Merge remote-tracking branch 'upstream/master' into easypassword
This commit is contained in:
commit
f4d8e0e20c
|
@ -33,6 +33,13 @@ jobs:
|
||||||
packageType: sdk
|
packageType: sdk
|
||||||
version: ${{ parameters.DotNetSdkVersion }}
|
version: ${{ parameters.DotNetSdkVersion }}
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@2
|
||||||
|
displayName: 'Install ABI CompatibilityChecker tool'
|
||||||
|
inputs:
|
||||||
|
command: custom
|
||||||
|
custom: tool
|
||||||
|
arguments: 'update compatibilitychecker -g'
|
||||||
|
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
displayName: "Download New Assembly Build Artifact"
|
displayName: "Download New Assembly Build Artifact"
|
||||||
inputs:
|
inputs:
|
||||||
|
@ -72,25 +79,11 @@ jobs:
|
||||||
overWrite: true
|
overWrite: true
|
||||||
flattenFolders: true
|
flattenFolders: true
|
||||||
|
|
||||||
- task: DownloadGitHubRelease@0
|
|
||||||
displayName: "Download ABI Compatibility Check Tool"
|
|
||||||
inputs:
|
|
||||||
connection: Jellyfin Release Download
|
|
||||||
userRepository: EraYaN/dotnet-compatibility
|
|
||||||
defaultVersionType: "latest"
|
|
||||||
itemPattern: "**-ci.zip"
|
|
||||||
downloadPath: "$(System.ArtifactsDirectory)"
|
|
||||||
|
|
||||||
- task: ExtractFiles@1
|
|
||||||
displayName: "Extract ABI Compatibility Check Tool"
|
|
||||||
inputs:
|
|
||||||
archiveFilePatterns: "$(System.ArtifactsDirectory)/*-ci.zip"
|
|
||||||
destinationFolder: $(System.ArtifactsDirectory)/tools
|
|
||||||
cleanDestinationFolder: true
|
|
||||||
|
|
||||||
# The `--warnings-only` switch will swallow the return code and not emit any errors.
|
# The `--warnings-only` switch will swallow the return code and not emit any errors.
|
||||||
- task: CmdLine@2
|
- task: DotNetCoreCLI@2
|
||||||
displayName: "Execute ABI Compatibility Check Tool"
|
displayName: 'Execute ABI Compatibility Check Tool'
|
||||||
inputs:
|
inputs:
|
||||||
script: "dotnet tools/CompatibilityCheckerCLI.dll current-release/$(AssemblyFileName) new-release/$(AssemblyFileName) --azure-pipelines --warnings-only"
|
command: custom
|
||||||
|
custom: compat
|
||||||
|
arguments: 'current-release/$(AssemblyFileName) new-release/$(AssemblyFileName) --azure-pipelines --warnings-only'
|
||||||
workingDirectory: $(System.ArtifactsDirectory)
|
workingDirectory: $(System.ArtifactsDirectory)
|
|
@ -1,6 +1,6 @@
|
||||||
parameters:
|
parameters:
|
||||||
LinuxImage: "ubuntu-latest"
|
LinuxImage: 'ubuntu-latest'
|
||||||
RestoreBuildProjects: "Jellyfin.Server/Jellyfin.Server.csproj"
|
RestoreBuildProjects: 'Jellyfin.Server/Jellyfin.Server.csproj'
|
||||||
DotNetSdkVersion: 3.1.100
|
DotNetSdkVersion: 3.1.100
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -13,7 +13,7 @@ jobs:
|
||||||
Debug:
|
Debug:
|
||||||
BuildConfiguration: Debug
|
BuildConfiguration: Debug
|
||||||
pool:
|
pool:
|
||||||
vmImage: "${{ parameters.LinuxImage }}"
|
vmImage: '${{ parameters.LinuxImage }}'
|
||||||
steps:
|
steps:
|
||||||
- checkout: self
|
- checkout: self
|
||||||
clean: true
|
clean: true
|
||||||
|
@ -21,7 +21,7 @@ jobs:
|
||||||
persistCredentials: true
|
persistCredentials: true
|
||||||
|
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
displayName: "Download Web Branch"
|
displayName: 'Download Web Branch'
|
||||||
condition: in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion')
|
condition: in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion')
|
||||||
inputs:
|
inputs:
|
||||||
path: '$(Agent.TempDirectory)'
|
path: '$(Agent.TempDirectory)'
|
||||||
|
@ -32,7 +32,7 @@ jobs:
|
||||||
runBranch: variables['Build.SourceBranch']
|
runBranch: variables['Build.SourceBranch']
|
||||||
|
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
displayName: "Download Web Target"
|
displayName: 'Download Web Target'
|
||||||
condition: eq(variables['Build.Reason'], 'PullRequest')
|
condition: eq(variables['Build.Reason'], 'PullRequest')
|
||||||
inputs:
|
inputs:
|
||||||
path: '$(Agent.TempDirectory)'
|
path: '$(Agent.TempDirectory)'
|
||||||
|
@ -43,51 +43,51 @@ jobs:
|
||||||
runBranch: variables['System.PullRequest.TargetBranch']
|
runBranch: variables['System.PullRequest.TargetBranch']
|
||||||
|
|
||||||
- task: ExtractFiles@1
|
- task: ExtractFiles@1
|
||||||
displayName: "Extract Web Client"
|
displayName: 'Extract Web Client'
|
||||||
inputs:
|
inputs:
|
||||||
archiveFilePatterns: '$(Agent.TempDirectory)/*.zip'
|
archiveFilePatterns: '$(Agent.TempDirectory)/*.zip'
|
||||||
destinationFolder: '$(Build.SourcesDirectory)/MediaBrowser.WebDashboard'
|
destinationFolder: '$(Build.SourcesDirectory)/MediaBrowser.WebDashboard'
|
||||||
cleanDestinationFolder: false
|
cleanDestinationFolder: false
|
||||||
|
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
displayName: "Update DotNet"
|
displayName: 'Update DotNet'
|
||||||
inputs:
|
inputs:
|
||||||
packageType: sdk
|
packageType: sdk
|
||||||
version: ${{ parameters.DotNetSdkVersion }}
|
version: ${{ parameters.DotNetSdkVersion }}
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
- task: DotNetCoreCLI@2
|
||||||
displayName: "Publish Server"
|
displayName: 'Publish Server'
|
||||||
inputs:
|
inputs:
|
||||||
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'
|
||||||
|
|
|
@ -45,6 +45,7 @@ jobs:
|
||||||
- task: SonarCloudPrepare@1
|
- task: SonarCloudPrepare@1
|
||||||
displayName: 'Prepare analysis on SonarCloud'
|
displayName: 'Prepare analysis on SonarCloud'
|
||||||
condition: eq(variables['ImageName'], 'ubuntu-latest')
|
condition: eq(variables['ImageName'], 'ubuntu-latest')
|
||||||
|
enabled: false
|
||||||
inputs:
|
inputs:
|
||||||
SonarCloud: 'Sonarcloud for Jellyfin'
|
SonarCloud: 'Sonarcloud for Jellyfin'
|
||||||
organization: 'jellyfin'
|
organization: 'jellyfin'
|
||||||
|
@ -63,14 +64,17 @@ jobs:
|
||||||
- task: SonarCloudAnalyze@1
|
- task: SonarCloudAnalyze@1
|
||||||
displayName: 'Run Code Analysis'
|
displayName: 'Run Code Analysis'
|
||||||
condition: eq(variables['ImageName'], 'ubuntu-latest')
|
condition: eq(variables['ImageName'], 'ubuntu-latest')
|
||||||
|
enabled: false
|
||||||
|
|
||||||
- task: SonarCloudPublish@1
|
- task: SonarCloudPublish@1
|
||||||
displayName: 'Publish Quality Gate Result'
|
displayName: 'Publish Quality Gate Result'
|
||||||
condition: eq(variables['ImageName'], 'ubuntu-latest')
|
condition: eq(variables['ImageName'], 'ubuntu-latest')
|
||||||
|
enabled: false
|
||||||
|
|
||||||
- task: Palmmedia.reportgenerator.reportgenerator-build-release-task.reportgenerator@4
|
- task: Palmmedia.reportgenerator.reportgenerator-build-release-task.reportgenerator@4
|
||||||
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) # !! THIS is for V1 only V2 will/should support merging
|
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) # !! THIS is for V1 only V2 will/should support merging
|
||||||
displayName: 'Run ReportGenerator'
|
displayName: 'Run ReportGenerator'
|
||||||
|
enabled: false
|
||||||
inputs:
|
inputs:
|
||||||
reports: "$(Agent.TempDirectory)/**/coverage.cobertura.xml"
|
reports: "$(Agent.TempDirectory)/**/coverage.cobertura.xml"
|
||||||
targetdir: "$(Agent.TempDirectory)/merged/"
|
targetdir: "$(Agent.TempDirectory)/merged/"
|
||||||
|
@ -80,10 +84,10 @@ jobs:
|
||||||
- task: PublishCodeCoverageResults@1
|
- task: PublishCodeCoverageResults@1
|
||||||
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) # !! THIS is for V1 only V2 will/should support merging
|
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) # !! THIS is for V1 only V2 will/should support merging
|
||||||
displayName: 'Publish Code Coverage'
|
displayName: 'Publish Code Coverage'
|
||||||
|
enabled: false
|
||||||
inputs:
|
inputs:
|
||||||
codeCoverageTool: "cobertura"
|
codeCoverageTool: "cobertura"
|
||||||
#summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml' # !!THIS IS FOR V2
|
#summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml' # !!THIS IS FOR V2
|
||||||
summaryFileLocation: "$(Agent.TempDirectory)/merged/**.xml"
|
summaryFileLocation: "$(Agent.TempDirectory)/merged/**.xml"
|
||||||
pathToSources: $(Build.SourcesDirectory)
|
pathToSources: $(Build.SourcesDirectory)
|
||||||
failIfCoverageEmpty: true
|
failIfCoverageEmpty: true
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ name: $(Date:yyyyMMdd)$(Rev:.r)
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
- name: TestProjects
|
- name: TestProjects
|
||||||
value: "tests/**/*Tests.csproj"
|
value: 'tests/**/*Tests.csproj'
|
||||||
- name: RestoreBuildProjects
|
- name: RestoreBuildProjects
|
||||||
value: "Jellyfin.Server/Jellyfin.Server.csproj"
|
value: 'Jellyfin.Server/Jellyfin.Server.csproj'
|
||||||
- name: DotNetSdkVersion
|
- name: DotNetSdkVersion
|
||||||
value: 3.1.100
|
value: 3.1.100
|
||||||
|
|
||||||
|
@ -17,17 +17,17 @@ trigger:
|
||||||
jobs:
|
jobs:
|
||||||
- template: azure-pipelines-main.yml
|
- template: azure-pipelines-main.yml
|
||||||
parameters:
|
parameters:
|
||||||
LinuxImage: "ubuntu-latest"
|
LinuxImage: 'ubuntu-latest'
|
||||||
RestoreBuildProjects: $(RestoreBuildProjects)
|
RestoreBuildProjects: $(RestoreBuildProjects)
|
||||||
|
|
||||||
- template: azure-pipelines-test.yml
|
- template: azure-pipelines-test.yml
|
||||||
parameters:
|
parameters:
|
||||||
ImageNames:
|
ImageNames:
|
||||||
Linux: "ubuntu-latest"
|
Linux: 'ubuntu-latest'
|
||||||
Windows: "windows-latest"
|
Windows: 'windows-latest'
|
||||||
macOS: "macos-latest"
|
macOS: 'macos-latest'
|
||||||
|
|
||||||
- template: azure-pipelines-compat.yml
|
- template: azure-pipelines-abi.yml
|
||||||
parameters:
|
parameters:
|
||||||
Packages:
|
Packages:
|
||||||
Naming:
|
Naming:
|
||||||
|
@ -42,4 +42,4 @@ jobs:
|
||||||
Common:
|
Common:
|
||||||
NugetPackageName: Jellyfin.Common
|
NugetPackageName: Jellyfin.Common
|
||||||
AssemblyFileName: MediaBrowser.Common.dll
|
AssemblyFileName: MediaBrowser.Common.dll
|
||||||
LinuxImage: "ubuntu-latest"
|
LinuxImage: 'ubuntu-latest'
|
||||||
|
|
9
.github/dependabot.yml
vendored
Normal file
9
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: nuget
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
||||||
|
time: '12:00'
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
|
|
@ -131,6 +131,7 @@
|
||||||
- [XVicarious](https://github.com/XVicarious)
|
- [XVicarious](https://github.com/XVicarious)
|
||||||
- [YouKnowBlom](https://github.com/YouKnowBlom)
|
- [YouKnowBlom](https://github.com/YouKnowBlom)
|
||||||
- [KristupasSavickas](https://github.com/KristupasSavickas)
|
- [KristupasSavickas](https://github.com/KristupasSavickas)
|
||||||
|
- [Pusta](https://github.com/pusta)
|
||||||
|
|
||||||
# Emby Contributors
|
# Emby Contributors
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace DvdLib.Ifo
|
||||||
public class Cell
|
public class Cell
|
||||||
{
|
{
|
||||||
public CellPlaybackInfo PlaybackInfo { get; private set; }
|
public CellPlaybackInfo PlaybackInfo { get; private set; }
|
||||||
|
|
||||||
public CellPositionInfo PositionInfo { get; private set; }
|
public CellPositionInfo PositionInfo { get; private set; }
|
||||||
|
|
||||||
internal void ParsePlayback(BinaryReader br)
|
internal void ParsePlayback(BinaryReader br)
|
||||||
|
|
|
@ -5,7 +5,9 @@ namespace DvdLib.Ifo
|
||||||
public class Chapter
|
public class Chapter
|
||||||
{
|
{
|
||||||
public ushort ProgramChainNumber { get; private set; }
|
public ushort ProgramChainNumber { get; private set; }
|
||||||
|
|
||||||
public ushort ProgramNumber { get; private set; }
|
public ushort ProgramNumber { get; private set; }
|
||||||
|
|
||||||
public uint ChapterNumber { get; private set; }
|
public uint ChapterNumber { get; private set; }
|
||||||
|
|
||||||
public Chapter(ushort pgcNum, ushort programNum, uint chapterNum)
|
public Chapter(ushort pgcNum, ushort programNum, uint chapterNum)
|
||||||
|
|
|
@ -117,12 +117,19 @@ namespace DvdLib.Ifo
|
||||||
uint chapNum = 1;
|
uint chapNum = 1;
|
||||||
vtsFs.Seek(baseAddr + offsets[titleNum], SeekOrigin.Begin);
|
vtsFs.Seek(baseAddr + offsets[titleNum], SeekOrigin.Begin);
|
||||||
var t = Titles.FirstOrDefault(vtst => vtst.IsVTSTitle(vtsNum, titleNum + 1));
|
var t = Titles.FirstOrDefault(vtst => vtst.IsVTSTitle(vtsNum, titleNum + 1));
|
||||||
if (t == null) continue;
|
if (t == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
t.Chapters.Add(new Chapter(vtsRead.ReadUInt16(), vtsRead.ReadUInt16(), chapNum));
|
t.Chapters.Add(new Chapter(vtsRead.ReadUInt16(), vtsRead.ReadUInt16(), chapNum));
|
||||||
if (titleNum + 1 < numTitles && vtsFs.Position == (baseAddr + offsets[titleNum + 1])) break;
|
if (titleNum + 1 < numTitles && vtsFs.Position == (baseAddr + offsets[titleNum + 1]))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
chapNum++;
|
chapNum++;
|
||||||
}
|
}
|
||||||
while (vtsFs.Position < (baseAddr + endaddr));
|
while (vtsFs.Position < (baseAddr + endaddr));
|
||||||
|
@ -147,7 +154,10 @@ namespace DvdLib.Ifo
|
||||||
uint vtsPgcOffset = vtsRead.ReadUInt32();
|
uint vtsPgcOffset = vtsRead.ReadUInt32();
|
||||||
|
|
||||||
var t = Titles.FirstOrDefault(vtst => vtst.IsVTSTitle(vtsNum, titleNum));
|
var t = Titles.FirstOrDefault(vtst => vtst.IsVTSTitle(vtsNum, titleNum));
|
||||||
if (t != null) t.AddPgc(vtsRead, startByte + vtsPgcOffset, entryPgc, pgcNum);
|
if (t != null)
|
||||||
|
{
|
||||||
|
t.AddPgc(vtsRead, startByte + vtsPgcOffset, entryPgc, pgcNum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,14 @@ namespace DvdLib.Ifo
|
||||||
Second = GetBCDValue(data[2]);
|
Second = GetBCDValue(data[2]);
|
||||||
Frames = GetBCDValue((byte)(data[3] & 0x3F));
|
Frames = GetBCDValue((byte)(data[3] & 0x3F));
|
||||||
|
|
||||||
if ((data[3] & 0x80) != 0) FrameRate = 30;
|
if ((data[3] & 0x80) != 0)
|
||||||
else if ((data[3] & 0x40) != 0) FrameRate = 25;
|
{
|
||||||
|
FrameRate = 30;
|
||||||
|
}
|
||||||
|
else if ((data[3] & 0x40) != 0)
|
||||||
|
{
|
||||||
|
FrameRate = 25;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte GetBCDValue(byte data)
|
private static byte GetBCDValue(byte data)
|
||||||
|
|
|
@ -22,7 +22,9 @@ namespace DvdLib.Ifo
|
||||||
public readonly List<Cell> Cells;
|
public readonly List<Cell> Cells;
|
||||||
|
|
||||||
public DvdTime PlaybackTime { get; private set; }
|
public DvdTime PlaybackTime { get; private set; }
|
||||||
|
|
||||||
public UserOperation ProhibitedUserOperations { get; private set; }
|
public UserOperation ProhibitedUserOperations { get; private set; }
|
||||||
|
|
||||||
public byte[] AudioStreamControl { get; private set; } // 8*2 entries
|
public byte[] AudioStreamControl { get; private set; } // 8*2 entries
|
||||||
public byte[] SubpictureStreamControl { get; private set; } // 32*4 entries
|
public byte[] SubpictureStreamControl { get; private set; } // 32*4 entries
|
||||||
|
|
||||||
|
@ -33,9 +35,11 @@ namespace DvdLib.Ifo
|
||||||
private ushort _goupProgramNumber;
|
private ushort _goupProgramNumber;
|
||||||
|
|
||||||
public ProgramPlaybackMode PlaybackMode { get; private set; }
|
public ProgramPlaybackMode PlaybackMode { get; private set; }
|
||||||
|
|
||||||
public uint ProgramCount { get; private set; }
|
public uint ProgramCount { get; private set; }
|
||||||
|
|
||||||
public byte StillTime { get; private set; }
|
public byte StillTime { get; private set; }
|
||||||
|
|
||||||
public byte[] Palette { get; private set; } // 16*4 entries
|
public byte[] Palette { get; private set; } // 16*4 entries
|
||||||
|
|
||||||
private ushort _commandTableOffset;
|
private ushort _commandTableOffset;
|
||||||
|
@ -71,8 +75,15 @@ namespace DvdLib.Ifo
|
||||||
|
|
||||||
StillTime = br.ReadByte();
|
StillTime = br.ReadByte();
|
||||||
byte pbMode = br.ReadByte();
|
byte pbMode = br.ReadByte();
|
||||||
if (pbMode == 0) PlaybackMode = ProgramPlaybackMode.Sequential;
|
if (pbMode == 0)
|
||||||
else PlaybackMode = ((pbMode & 0x80) == 0) ? ProgramPlaybackMode.Random : ProgramPlaybackMode.Shuffle;
|
{
|
||||||
|
PlaybackMode = ProgramPlaybackMode.Sequential;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlaybackMode = ((pbMode & 0x80) == 0) ? ProgramPlaybackMode.Random : ProgramPlaybackMode.Shuffle;
|
||||||
|
}
|
||||||
|
|
||||||
ProgramCount = (uint)(pbMode & 0x7F);
|
ProgramCount = (uint)(pbMode & 0x7F);
|
||||||
|
|
||||||
Palette = br.ReadBytes(64);
|
Palette = br.ReadBytes(64);
|
||||||
|
|
|
@ -8,8 +8,11 @@ namespace DvdLib.Ifo
|
||||||
public class Title
|
public class Title
|
||||||
{
|
{
|
||||||
public uint TitleNumber { get; private set; }
|
public uint TitleNumber { get; private set; }
|
||||||
|
|
||||||
public uint AngleCount { get; private set; }
|
public uint AngleCount { get; private set; }
|
||||||
|
|
||||||
public ushort ChapterCount { get; private set; }
|
public ushort ChapterCount { get; private set; }
|
||||||
|
|
||||||
public byte VideoTitleSetNumber { get; private set; }
|
public byte VideoTitleSetNumber { get; private set; }
|
||||||
|
|
||||||
private ushort _parentalManagementMask;
|
private ushort _parentalManagementMask;
|
||||||
|
@ -17,6 +20,7 @@ namespace DvdLib.Ifo
|
||||||
private uint _vtsStartSector; // relative to start of entire disk
|
private uint _vtsStartSector; // relative to start of entire disk
|
||||||
|
|
||||||
public ProgramChain EntryProgramChain { get; private set; }
|
public ProgramChain EntryProgramChain { get; private set; }
|
||||||
|
|
||||||
public readonly List<ProgramChain> ProgramChains;
|
public readonly List<ProgramChain> ProgramChains;
|
||||||
|
|
||||||
public readonly List<Chapter> Chapters;
|
public readonly List<Chapter> Chapters;
|
||||||
|
@ -55,7 +59,10 @@ namespace DvdLib.Ifo
|
||||||
var pgc = new ProgramChain(pgcNum);
|
var pgc = new ProgramChain(pgcNum);
|
||||||
pgc.ParseHeader(br);
|
pgc.ParseHeader(br);
|
||||||
ProgramChains.Add(pgc);
|
ProgramChains.Add(pgc);
|
||||||
if (entryPgc) EntryProgramChain = pgc;
|
if (entryPgc)
|
||||||
|
{
|
||||||
|
EntryProgramChain = pgc;
|
||||||
|
}
|
||||||
|
|
||||||
br.BaseStream.Seek(curPos, SeekOrigin.Begin);
|
br.BaseStream.Seek(curPos, SeekOrigin.Begin);
|
||||||
}
|
}
|
||||||
|
|
|
@ -466,12 +466,12 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
}
|
}
|
||||||
else if (search.SearchType == SearchType.Playlist)
|
else if (search.SearchType == SearchType.Playlist)
|
||||||
{
|
{
|
||||||
//items = items.OfType<Playlist>();
|
// items = items.OfType<Playlist>();
|
||||||
isFolder = true;
|
isFolder = true;
|
||||||
}
|
}
|
||||||
else if (search.SearchType == SearchType.MusicAlbum)
|
else if (search.SearchType == SearchType.MusicAlbum)
|
||||||
{
|
{
|
||||||
//items = items.OfType<MusicAlbum>();
|
// items = items.OfType<MusicAlbum>();
|
||||||
isFolder = true;
|
isFolder = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,7 +926,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
private QueryResult<ServerItem> GetMovieCollections(User user, InternalItemsQuery query)
|
private QueryResult<ServerItem> GetMovieCollections(User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.Recursive = true;
|
query.Recursive = true;
|
||||||
//query.Parent = parent;
|
// query.Parent = parent;
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(BoxSet).Name };
|
query.IncludeItemTypes = new[] { typeof(BoxSet).Name };
|
||||||
|
@ -1357,6 +1357,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
internal class ServerItem
|
internal class ServerItem
|
||||||
{
|
{
|
||||||
public BaseItem Item { get; set; }
|
public BaseItem Item { get; set; }
|
||||||
|
|
||||||
public StubType? StubType { get; set; }
|
public StubType? StubType { get; set; }
|
||||||
|
|
||||||
public ServerItem(BaseItem item)
|
public ServerItem(BaseItem item)
|
||||||
|
|
|
@ -98,21 +98,21 @@ namespace Emby.Dlna.Didl
|
||||||
{
|
{
|
||||||
using (var writer = XmlWriter.Create(builder, settings))
|
using (var writer = XmlWriter.Create(builder, settings))
|
||||||
{
|
{
|
||||||
//writer.WriteStartDocument();
|
// writer.WriteStartDocument();
|
||||||
|
|
||||||
writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL);
|
writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL);
|
||||||
|
|
||||||
writer.WriteAttributeString("xmlns", "dc", null, NS_DC);
|
writer.WriteAttributeString("xmlns", "dc", null, NS_DC);
|
||||||
writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA);
|
writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA);
|
||||||
writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP);
|
writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP);
|
||||||
//didl.SetAttribute("xmlns:sec", NS_SEC);
|
// didl.SetAttribute("xmlns:sec", NS_SEC);
|
||||||
|
|
||||||
WriteXmlRootAttributes(_profile, writer);
|
WriteXmlRootAttributes(_profile, writer);
|
||||||
|
|
||||||
WriteItemElement(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();
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
|
@ -705,13 +705,13 @@ namespace Emby.Dlna.Didl
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds fields used by both items and folders
|
/// Adds fields used by both items and folders.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void AddCommonFields(BaseItem item, StubType? itemStubType, BaseItem context, XmlWriter writer, Filter filter)
|
private void AddCommonFields(BaseItem item, StubType? itemStubType, BaseItem context, XmlWriter writer, Filter filter)
|
||||||
{
|
{
|
||||||
// Don't filter on dc:title because not all devices will include it in the filter
|
// Don't filter on dc:title because not all devices will include it in the filter
|
||||||
// MediaMonkey for example won't display content without a title
|
// MediaMonkey for example won't display content without a title
|
||||||
//if (filter.Contains("dc:title"))
|
// if (filter.Contains("dc:title"))
|
||||||
{
|
{
|
||||||
AddValue(writer, "dc", "title", GetDisplayName(item, itemStubType, context), NS_DC);
|
AddValue(writer, "dc", "title", GetDisplayName(item, itemStubType, context), NS_DC);
|
||||||
}
|
}
|
||||||
|
@ -750,7 +750,7 @@ namespace Emby.Dlna.Didl
|
||||||
AddValue(writer, "dc", "description", desc, NS_DC);
|
AddValue(writer, "dc", "description", desc, NS_DC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (filter.Contains("upnp:longDescription"))
|
// if (filter.Contains("upnp:longDescription"))
|
||||||
//{
|
//{
|
||||||
// if (!string.IsNullOrWhiteSpace(item.Overview))
|
// if (!string.IsNullOrWhiteSpace(item.Overview))
|
||||||
// {
|
// {
|
||||||
|
@ -765,6 +765,7 @@ namespace Emby.Dlna.Didl
|
||||||
{
|
{
|
||||||
AddValue(writer, "dc", "rating", item.OfficialRating, NS_DC);
|
AddValue(writer, "dc", "rating", item.OfficialRating, NS_DC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.Contains("upnp:rating"))
|
if (filter.Contains("upnp:rating"))
|
||||||
{
|
{
|
||||||
AddValue(writer, "upnp", "rating", item.OfficialRating, NS_UPNP);
|
AddValue(writer, "upnp", "rating", item.OfficialRating, NS_UPNP);
|
||||||
|
@ -1052,10 +1053,12 @@ namespace Emby.Dlna.Didl
|
||||||
{
|
{
|
||||||
return GetImageInfo(item, ImageType.Primary);
|
return GetImageInfo(item, ImageType.Primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.HasImage(ImageType.Thumb))
|
if (item.HasImage(ImageType.Thumb))
|
||||||
{
|
{
|
||||||
return GetImageInfo(item, ImageType.Thumb);
|
return GetImageInfo(item, ImageType.Thumb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.HasImage(ImageType.Backdrop))
|
if (item.HasImage(ImageType.Backdrop))
|
||||||
{
|
{
|
||||||
if (item is Channel)
|
if (item is Channel)
|
||||||
|
@ -1135,25 +1138,24 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
if (width == 0 || height == 0)
|
if (width == 0 || height == 0)
|
||||||
{
|
{
|
||||||
//_imageProcessor.GetImageSize(item, imageInfo);
|
// _imageProcessor.GetImageSize(item, imageInfo);
|
||||||
width = null;
|
width = null;
|
||||||
height = null;
|
height = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (width == -1 || height == -1)
|
else if (width == -1 || height == -1)
|
||||||
{
|
{
|
||||||
width = null;
|
width = null;
|
||||||
height = null;
|
height = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//try
|
// try
|
||||||
//{
|
//{
|
||||||
// var size = _imageProcessor.GetImageSize(imageInfo);
|
// var size = _imageProcessor.GetImageSize(imageInfo);
|
||||||
|
|
||||||
// width = size.Width;
|
// width = size.Width;
|
||||||
// height = size.Height;
|
// height = size.Height;
|
||||||
//}
|
//}
|
||||||
//catch
|
// catch
|
||||||
//{
|
//{
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -12,7 +12,6 @@ namespace Emby.Dlna.Didl
|
||||||
public Filter()
|
public Filter()
|
||||||
: this("*")
|
: this("*")
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Filter(string filter)
|
public Filter(string filter)
|
||||||
|
@ -26,7 +25,7 @@ namespace Emby.Dlna.Didl
|
||||||
{
|
{
|
||||||
// Don't bother with this. Some clients (media monkey) use the filter and then don't display very well when very little data comes back.
|
// Don't bother with this. Some clients (media monkey) use the filter and then don't display very well when very little data comes back.
|
||||||
return true;
|
return true;
|
||||||
//return _all || ListHelper.ContainsIgnoreCase(_fields, field);
|
// return _all || ListHelper.ContainsIgnoreCase(_fields, field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace Emby.Dlna
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
private readonly IXmlSerializer _xmlSerializer;
|
private readonly IXmlSerializer _xmlSerializer;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<DlnaManager> _logger;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private static readonly Assembly _assembly = typeof(DlnaManager).Assembly;
|
private static readonly Assembly _assembly = typeof(DlnaManager).Assembly;
|
||||||
|
@ -49,7 +49,7 @@ namespace Emby.Dlna
|
||||||
_xmlSerializer = xmlSerializer;
|
_xmlSerializer = xmlSerializer;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
_logger = loggerFactory.CreateLogger("Dlna");
|
_logger = loggerFactory.CreateLogger<DlnaManager>();
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,6 @@ namespace Emby.Dlna
|
||||||
.Select(i => i.Item2)
|
.Select(i => i.Item2)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceProfile GetDefaultProfile()
|
public DeviceProfile GetDefaultProfile()
|
||||||
|
@ -141,56 +140,74 @@ namespace Emby.Dlna
|
||||||
if (!string.IsNullOrEmpty(profileInfo.DeviceDescription))
|
if (!string.IsNullOrEmpty(profileInfo.DeviceDescription))
|
||||||
{
|
{
|
||||||
if (deviceInfo.DeviceDescription == null || !IsRegexMatch(deviceInfo.DeviceDescription, profileInfo.DeviceDescription))
|
if (deviceInfo.DeviceDescription == null || !IsRegexMatch(deviceInfo.DeviceDescription, profileInfo.DeviceDescription))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(profileInfo.FriendlyName))
|
if (!string.IsNullOrEmpty(profileInfo.FriendlyName))
|
||||||
{
|
{
|
||||||
if (deviceInfo.FriendlyName == null || !IsRegexMatch(deviceInfo.FriendlyName, profileInfo.FriendlyName))
|
if (deviceInfo.FriendlyName == null || !IsRegexMatch(deviceInfo.FriendlyName, profileInfo.FriendlyName))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(profileInfo.Manufacturer))
|
if (!string.IsNullOrEmpty(profileInfo.Manufacturer))
|
||||||
{
|
{
|
||||||
if (deviceInfo.Manufacturer == null || !IsRegexMatch(deviceInfo.Manufacturer, profileInfo.Manufacturer))
|
if (deviceInfo.Manufacturer == null || !IsRegexMatch(deviceInfo.Manufacturer, profileInfo.Manufacturer))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(profileInfo.ManufacturerUrl))
|
if (!string.IsNullOrEmpty(profileInfo.ManufacturerUrl))
|
||||||
{
|
{
|
||||||
if (deviceInfo.ManufacturerUrl == null || !IsRegexMatch(deviceInfo.ManufacturerUrl, profileInfo.ManufacturerUrl))
|
if (deviceInfo.ManufacturerUrl == null || !IsRegexMatch(deviceInfo.ManufacturerUrl, profileInfo.ManufacturerUrl))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(profileInfo.ModelDescription))
|
if (!string.IsNullOrEmpty(profileInfo.ModelDescription))
|
||||||
{
|
{
|
||||||
if (deviceInfo.ModelDescription == null || !IsRegexMatch(deviceInfo.ModelDescription, profileInfo.ModelDescription))
|
if (deviceInfo.ModelDescription == null || !IsRegexMatch(deviceInfo.ModelDescription, profileInfo.ModelDescription))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(profileInfo.ModelName))
|
if (!string.IsNullOrEmpty(profileInfo.ModelName))
|
||||||
{
|
{
|
||||||
if (deviceInfo.ModelName == null || !IsRegexMatch(deviceInfo.ModelName, profileInfo.ModelName))
|
if (deviceInfo.ModelName == null || !IsRegexMatch(deviceInfo.ModelName, profileInfo.ModelName))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(profileInfo.ModelNumber))
|
if (!string.IsNullOrEmpty(profileInfo.ModelNumber))
|
||||||
{
|
{
|
||||||
if (deviceInfo.ModelNumber == null || !IsRegexMatch(deviceInfo.ModelNumber, profileInfo.ModelNumber))
|
if (deviceInfo.ModelNumber == null || !IsRegexMatch(deviceInfo.ModelNumber, profileInfo.ModelNumber))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(profileInfo.ModelUrl))
|
if (!string.IsNullOrEmpty(profileInfo.ModelUrl))
|
||||||
{
|
{
|
||||||
if (deviceInfo.ModelUrl == null || !IsRegexMatch(deviceInfo.ModelUrl, profileInfo.ModelUrl))
|
if (deviceInfo.ModelUrl == null || !IsRegexMatch(deviceInfo.ModelUrl, profileInfo.ModelUrl))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(profileInfo.SerialNumber))
|
if (!string.IsNullOrEmpty(profileInfo.SerialNumber))
|
||||||
{
|
{
|
||||||
if (deviceInfo.SerialNumber == null || !IsRegexMatch(deviceInfo.SerialNumber, profileInfo.SerialNumber))
|
if (deviceInfo.SerialNumber == null || !IsRegexMatch(deviceInfo.SerialNumber, profileInfo.SerialNumber))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -251,7 +268,7 @@ namespace Emby.Dlna
|
||||||
return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase);
|
return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase);
|
||||||
case HeaderMatchType.Substring:
|
case HeaderMatchType.Substring:
|
||||||
var isMatch = value.ToString().IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1;
|
var isMatch = value.ToString().IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1;
|
||||||
//_logger.LogDebug("IsMatch-Substring value: {0} testValue: {1} isMatch: {2}", value, header.Value, isMatch);
|
// _logger.LogDebug("IsMatch-Substring value: {0} testValue: {1} isMatch: {2}", value, header.Value, isMatch);
|
||||||
return isMatch;
|
return isMatch;
|
||||||
case HeaderMatchType.Regex:
|
case HeaderMatchType.Regex:
|
||||||
return Regex.IsMatch(value, header.Value, RegexOptions.IgnoreCase);
|
return Regex.IsMatch(value, header.Value, RegexOptions.IgnoreCase);
|
||||||
|
@ -439,6 +456,7 @@ namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Profile is missing Id");
|
throw new ArgumentException("Profile is missing Id");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(profile.Name))
|
if (string.IsNullOrEmpty(profile.Name))
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Profile is missing Name");
|
throw new ArgumentException("Profile is missing Name");
|
||||||
|
@ -464,6 +482,7 @@ namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
_profiles[path] = new Tuple<InternalProfileInfo, DeviceProfile>(GetInternalProfileInfo(_fileSystem.GetFileInfo(path), type), profile);
|
_profiles[path] = new Tuple<InternalProfileInfo, DeviceProfile>(GetInternalProfileInfo(_fileSystem.GetFileInfo(path), type), profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
SerializeToXml(profile, path);
|
SerializeToXml(profile, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,7 +493,7 @@ namespace Emby.Dlna
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recreates the object using serialization, to ensure it's not a subclass.
|
/// Recreates the object using serialization, to ensure it's not a subclass.
|
||||||
/// If it's a subclass it may not serlialize properly to xml (different root element tag name)
|
/// If it's a subclass it may not serlialize properly to xml (different root element tag name).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="profile"></param>
|
/// <param name="profile"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
@ -493,6 +512,7 @@ namespace Emby.Dlna
|
||||||
class InternalProfileInfo
|
class InternalProfileInfo
|
||||||
{
|
{
|
||||||
internal DeviceProfileInfo Info { get; set; }
|
internal DeviceProfileInfo Info { get; set; }
|
||||||
|
|
||||||
internal string Path { get; set; }
|
internal string Path { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,9 +586,9 @@ namespace Emby.Dlna
|
||||||
new Foobar2000Profile(),
|
new Foobar2000Profile(),
|
||||||
new SharpSmartTvProfile(),
|
new SharpSmartTvProfile(),
|
||||||
new MediaMonkeyProfile(),
|
new MediaMonkeyProfile(),
|
||||||
//new Windows81Profile(),
|
// new Windows81Profile(),
|
||||||
//new WindowsMediaCenterProfile(),
|
// new WindowsMediaCenterProfile(),
|
||||||
//new WindowsPhoneProfile(),
|
// new WindowsPhoneProfile(),
|
||||||
new DirectTvProfile(),
|
new DirectTvProfile(),
|
||||||
new DishHopperJoeyProfile(),
|
new DishHopperJoeyProfile(),
|
||||||
new DefaultProfile(),
|
new DefaultProfile(),
|
||||||
|
|
|
@ -31,7 +31,8 @@ namespace Emby.Dlna.Eventing
|
||||||
public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl)
|
public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl)
|
||||||
{
|
{
|
||||||
var subscription = GetSubscription(subscriptionId, false);
|
var subscription = GetSubscription(subscriptionId, false);
|
||||||
|
if (subscription != null)
|
||||||
|
{
|
||||||
subscription.TimeoutSeconds = ParseTimeout(requestedTimeoutString) ?? 300;
|
subscription.TimeoutSeconds = ParseTimeout(requestedTimeoutString) ?? 300;
|
||||||
int timeoutSeconds = subscription.TimeoutSeconds;
|
int timeoutSeconds = subscription.TimeoutSeconds;
|
||||||
subscription.SubscriptionTime = DateTime.UtcNow;
|
subscription.SubscriptionTime = DateTime.UtcNow;
|
||||||
|
@ -45,6 +46,13 @@ namespace Emby.Dlna.Eventing
|
||||||
return GetEventSubscriptionResponse(subscriptionId, requestedTimeoutString, timeoutSeconds);
|
return GetEventSubscriptionResponse(subscriptionId, requestedTimeoutString, timeoutSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new EventSubscriptionResponse
|
||||||
|
{
|
||||||
|
Content = string.Empty,
|
||||||
|
ContentType = "text/plain"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl)
|
public EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl)
|
||||||
{
|
{
|
||||||
var timeout = ParseTimeout(requestedTimeoutString) ?? 300;
|
var timeout = ParseTimeout(requestedTimeoutString) ?? 300;
|
||||||
|
@ -150,6 +158,7 @@ namespace Emby.Dlna.Eventing
|
||||||
builder.Append("</" + key + ">");
|
builder.Append("</" + key + ">");
|
||||||
builder.Append("</e:property>");
|
builder.Append("</e:property>");
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Append("</e:propertyset>");
|
builder.Append("</e:propertyset>");
|
||||||
|
|
||||||
var options = new HttpRequestOptions
|
var options = new HttpRequestOptions
|
||||||
|
@ -169,7 +178,6 @@ namespace Emby.Dlna.Eventing
|
||||||
{
|
{
|
||||||
using (await _httpClient.SendAsync(options, new HttpMethod("NOTIFY")).ConfigureAwait(false))
|
using (await _httpClient.SendAsync(options, new HttpMethod("NOTIFY")).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
|
|
|
@ -7,10 +7,13 @@ namespace Emby.Dlna.Eventing
|
||||||
public class EventSubscription
|
public class EventSubscription
|
||||||
{
|
{
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
public string CallbackUrl { get; set; }
|
public string CallbackUrl { get; set; }
|
||||||
|
|
||||||
public string NotificationType { get; set; }
|
public string NotificationType { get; set; }
|
||||||
|
|
||||||
public DateTime SubscriptionTime { get; set; }
|
public DateTime SubscriptionTime { get; set; }
|
||||||
|
|
||||||
public int TimeoutSeconds { get; set; }
|
public int TimeoutSeconds { get; set; }
|
||||||
|
|
||||||
public long TriggerCount { get; set; }
|
public long TriggerCount { get; set; }
|
||||||
|
|
|
@ -33,10 +33,8 @@ namespace Emby.Dlna.Main
|
||||||
public class DlnaEntryPoint : IServerEntryPoint, IRunBeforeStartup
|
public class DlnaEntryPoint : IServerEntryPoint, IRunBeforeStartup
|
||||||
{
|
{
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<DlnaEntryPoint> _logger;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
|
|
||||||
private PlayToManager _manager;
|
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
@ -47,14 +45,13 @@ namespace Emby.Dlna.Main
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
private readonly IMediaEncoder _mediaEncoder;
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
|
|
||||||
private readonly IDeviceDiscovery _deviceDiscovery;
|
private readonly IDeviceDiscovery _deviceDiscovery;
|
||||||
|
|
||||||
private SsdpDevicePublisher _Publisher;
|
|
||||||
|
|
||||||
private readonly ISocketFactory _socketFactory;
|
private readonly ISocketFactory _socketFactory;
|
||||||
private readonly INetworkManager _networkManager;
|
private readonly INetworkManager _networkManager;
|
||||||
|
private readonly object _syncLock = new object();
|
||||||
|
|
||||||
|
private PlayToManager _manager;
|
||||||
|
private SsdpDevicePublisher _publisher;
|
||||||
private ISsdpCommunicationsServer _communicationsServer;
|
private ISsdpCommunicationsServer _communicationsServer;
|
||||||
|
|
||||||
internal IContentDirectory ContentDirectory { get; private set; }
|
internal IContentDirectory ContentDirectory { get; private set; }
|
||||||
|
@ -65,7 +62,8 @@ namespace Emby.Dlna.Main
|
||||||
|
|
||||||
public static DlnaEntryPoint Current;
|
public static DlnaEntryPoint Current;
|
||||||
|
|
||||||
public DlnaEntryPoint(IServerConfigurationManager config,
|
public DlnaEntryPoint(
|
||||||
|
IServerConfigurationManager config,
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
IServerApplicationHost appHost,
|
IServerApplicationHost appHost,
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
|
@ -99,7 +97,7 @@ namespace Emby.Dlna.Main
|
||||||
_mediaEncoder = mediaEncoder;
|
_mediaEncoder = mediaEncoder;
|
||||||
_socketFactory = socketFactory;
|
_socketFactory = socketFactory;
|
||||||
_networkManager = networkManager;
|
_networkManager = networkManager;
|
||||||
_logger = loggerFactory.CreateLogger("Dlna");
|
_logger = loggerFactory.CreateLogger<DlnaEntryPoint>();
|
||||||
|
|
||||||
ContentDirectory = new ContentDirectory.ContentDirectory(
|
ContentDirectory = new ContentDirectory.ContentDirectory(
|
||||||
dlnaManager,
|
dlnaManager,
|
||||||
|
@ -180,7 +178,7 @@ namespace Emby.Dlna.Main
|
||||||
var enableMultiSocketBinding = OperatingSystem.Id == OperatingSystemId.Windows ||
|
var enableMultiSocketBinding = OperatingSystem.Id == OperatingSystemId.Windows ||
|
||||||
OperatingSystem.Id == OperatingSystemId.Linux;
|
OperatingSystem.Id == OperatingSystemId.Linux;
|
||||||
|
|
||||||
_communicationsServer = new SsdpCommunicationsServer(_config, _socketFactory, _networkManager, _logger, enableMultiSocketBinding)
|
_communicationsServer = new SsdpCommunicationsServer(_socketFactory, _networkManager, _logger, enableMultiSocketBinding)
|
||||||
{
|
{
|
||||||
IsShared = true
|
IsShared = true
|
||||||
};
|
};
|
||||||
|
@ -231,20 +229,22 @@ namespace Emby.Dlna.Main
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_Publisher != null)
|
if (_publisher != null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_Publisher = new SsdpDevicePublisher(_communicationsServer, _networkManager, OperatingSystem.Name, Environment.OSVersion.VersionString, _config.GetDlnaConfiguration().SendOnlyMatchedHost);
|
_publisher = new SsdpDevicePublisher(_communicationsServer, _networkManager, OperatingSystem.Name, Environment.OSVersion.VersionString, _config.GetDlnaConfiguration().SendOnlyMatchedHost)
|
||||||
_Publisher.LogFunction = LogMessage;
|
{
|
||||||
_Publisher.SupportPnpRootDevice = false;
|
LogFunction = LogMessage,
|
||||||
|
SupportPnpRootDevice = false
|
||||||
|
};
|
||||||
|
|
||||||
await RegisterServerEndpoints().ConfigureAwait(false);
|
await RegisterServerEndpoints().ConfigureAwait(false);
|
||||||
|
|
||||||
_Publisher.StartBroadcastingAliveMessages(TimeSpan.FromSeconds(options.BlastAliveMessageIntervalSeconds));
|
_publisher.StartBroadcastingAliveMessages(TimeSpan.FromSeconds(options.BlastAliveMessageIntervalSeconds));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -266,6 +266,12 @@ namespace Emby.Dlna.Main
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Limit to LAN addresses only
|
||||||
|
if (!_networkManager.IsAddressInSubnets(address, true, true))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
|
var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
|
||||||
|
|
||||||
_logger.LogInformation("Registering publisher for {0} on {1}", fullService, address);
|
_logger.LogInformation("Registering publisher for {0} on {1}", fullService, address);
|
||||||
|
@ -275,7 +281,7 @@ namespace Emby.Dlna.Main
|
||||||
|
|
||||||
var device = new SsdpRootDevice
|
var device = new SsdpRootDevice
|
||||||
{
|
{
|
||||||
CacheLifetime = TimeSpan.FromSeconds(1800), //How long SSDP clients can cache this info.
|
CacheLifetime = TimeSpan.FromSeconds(1800), // How long SSDP clients can cache this info.
|
||||||
Location = uri, // Must point to the URL that serves your devices UPnP description document.
|
Location = uri, // Must point to the URL that serves your devices UPnP description document.
|
||||||
Address = address,
|
Address = address,
|
||||||
SubnetMask = _networkManager.GetLocalIpSubnetMask(address),
|
SubnetMask = _networkManager.GetLocalIpSubnetMask(address),
|
||||||
|
@ -287,13 +293,13 @@ namespace Emby.Dlna.Main
|
||||||
};
|
};
|
||||||
|
|
||||||
SetProperies(device, fullService);
|
SetProperies(device, fullService);
|
||||||
_Publisher.AddDevice(device);
|
_publisher.AddDevice(device);
|
||||||
|
|
||||||
var embeddedDevices = new[]
|
var embeddedDevices = new[]
|
||||||
{
|
{
|
||||||
"urn:schemas-upnp-org:service:ContentDirectory:1",
|
"urn:schemas-upnp-org:service:ContentDirectory:1",
|
||||||
"urn:schemas-upnp-org:service:ConnectionManager:1",
|
"urn:schemas-upnp-org:service:ConnectionManager:1",
|
||||||
//"urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1"
|
// "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1"
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var subDevice in embeddedDevices)
|
foreach (var subDevice in embeddedDevices)
|
||||||
|
@ -319,12 +325,13 @@ namespace Emby.Dlna.Main
|
||||||
{
|
{
|
||||||
guid = text.GetMD5();
|
guid = text.GetMD5();
|
||||||
}
|
}
|
||||||
|
|
||||||
return guid.ToString("N", CultureInfo.InvariantCulture);
|
return guid.ToString("N", CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetProperies(SsdpDevice device, string fullDeviceType)
|
private void SetProperies(SsdpDevice device, string fullDeviceType)
|
||||||
{
|
{
|
||||||
var service = fullDeviceType.Replace("urn:", string.Empty).Replace(":1", string.Empty);
|
var service = fullDeviceType.Replace("urn:", string.Empty, StringComparison.OrdinalIgnoreCase).Replace(":1", string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var serviceParts = service.Split(':');
|
var serviceParts = service.Split(':');
|
||||||
|
|
||||||
|
@ -335,7 +342,6 @@ namespace Emby.Dlna.Main
|
||||||
device.DeviceType = serviceParts[2];
|
device.DeviceType = serviceParts[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly object _syncLock = new object();
|
|
||||||
private void StartPlayToManager()
|
private void StartPlayToManager()
|
||||||
{
|
{
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
|
@ -347,7 +353,8 @@ namespace Emby.Dlna.Main
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_manager = new PlayToManager(_logger,
|
_manager = new PlayToManager(
|
||||||
|
_logger,
|
||||||
_sessionManager,
|
_sessionManager,
|
||||||
_libraryManager,
|
_libraryManager,
|
||||||
_userManager,
|
_userManager,
|
||||||
|
@ -386,6 +393,7 @@ namespace Emby.Dlna.Main
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error disposing PlayTo manager");
|
_logger.LogError(ex, "Error disposing PlayTo manager");
|
||||||
}
|
}
|
||||||
|
|
||||||
_manager = null;
|
_manager = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,11 +420,11 @@ namespace Emby.Dlna.Main
|
||||||
|
|
||||||
public void DisposeDevicePublisher()
|
public void DisposeDevicePublisher()
|
||||||
{
|
{
|
||||||
if (_Publisher != null)
|
if (_publisher != null)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Disposing SsdpDevicePublisher");
|
_logger.LogInformation("Disposing SsdpDevicePublisher");
|
||||||
_Publisher.Dispose();
|
_publisher.Dispose();
|
||||||
_Publisher = null;
|
_publisher = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
public class Device : IDisposable
|
public class Device : IDisposable
|
||||||
{
|
{
|
||||||
#region Fields & Properties
|
|
||||||
|
|
||||||
private Timer _timer;
|
private Timer _timer;
|
||||||
|
|
||||||
public DeviceInfo Properties { get; set; }
|
public DeviceInfo Properties { get; set; }
|
||||||
|
@ -37,6 +35,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
RefreshVolumeIfNeeded().GetAwaiter().GetResult();
|
RefreshVolumeIfNeeded().GetAwaiter().GetResult();
|
||||||
return _volume;
|
return _volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
set => _volume = value;
|
set => _volume = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,10 +51,10 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
public bool IsStopped => TransportState == TRANSPORTSTATE.STOPPED;
|
public bool IsStopped => TransportState == TRANSPORTSTATE.STOPPED;
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
|
||||||
public Action OnDeviceUnavailable { get; set; }
|
public Action OnDeviceUnavailable { get; set; }
|
||||||
|
@ -141,8 +140,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Commanding
|
|
||||||
|
|
||||||
public Task VolumeDown(CancellationToken cancellationToken)
|
public Task VolumeDown(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var sendVolume = Math.Max(Volume - 5, 0);
|
var sendVolume = Math.Max(Volume - 5, 0);
|
||||||
|
@ -211,7 +208,9 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
var command = rendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetMute");
|
var command = rendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetMute");
|
||||||
if (command == null)
|
if (command == null)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var service = GetServiceRenderingControl();
|
var service = GetServiceRenderingControl();
|
||||||
|
|
||||||
|
@ -232,7 +231,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets volume on a scale of 0-100
|
/// Sets volume on a scale of 0-100.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task SetVolume(int value, CancellationToken cancellationToken)
|
public async Task SetVolume(int value, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
@ -240,7 +239,9 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
var command = rendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetVolume");
|
var command = rendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetVolume");
|
||||||
if (command == null)
|
if (command == null)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var service = GetServiceRenderingControl();
|
var service = GetServiceRenderingControl();
|
||||||
|
|
||||||
|
@ -263,7 +264,9 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "Seek");
|
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "Seek");
|
||||||
if (command == null)
|
if (command == null)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var service = GetAvTransportService();
|
var service = GetAvTransportService();
|
||||||
|
|
||||||
|
@ -288,7 +291,9 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetAVTransportURI");
|
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetAVTransportURI");
|
||||||
if (command == null)
|
if (command == null)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var dictionary = new Dictionary<string, string>
|
var dictionary = new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
|
@ -401,11 +406,8 @@ namespace Emby.Dlna.PlayTo
|
||||||
RestartTimer(true);
|
RestartTimer(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Get data
|
|
||||||
|
|
||||||
private int _connectFailureCount;
|
private int _connectFailureCount;
|
||||||
|
|
||||||
private async void TimerCallback(object sender)
|
private async void TimerCallback(object sender)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
|
@ -458,7 +460,9 @@ namespace Emby.Dlna.PlayTo
|
||||||
_connectFailureCount = 0;
|
_connectFailureCount = 0;
|
||||||
|
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If we're not playing anything make sure we don't get data more often than neccessry to keep the Session alive
|
// If we're not playing anything make sure we don't get data more often than neccessry to keep the Session alive
|
||||||
if (transportState.Value == TRANSPORTSTATE.STOPPED)
|
if (transportState.Value == TRANSPORTSTATE.STOPPED)
|
||||||
|
@ -478,7 +482,9 @@ namespace Emby.Dlna.PlayTo
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_logger.LogError(ex, "Error updating device info for {DeviceName}", Properties.Name);
|
_logger.LogError(ex, "Error updating device info for {DeviceName}", Properties.Name);
|
||||||
|
|
||||||
|
@ -494,6 +500,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RestartTimerInactive();
|
RestartTimerInactive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -578,7 +585,9 @@ namespace Emby.Dlna.PlayTo
|
||||||
cancellationToken: cancellationToken).ConfigureAwait(false);
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (result == null || result.Document == null)
|
if (result == null || result.Document == null)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var valueNode = result.Document.Descendants(uPnpNamespaces.RenderingControl + "GetMuteResponse")
|
var valueNode = result.Document.Descendants(uPnpNamespaces.RenderingControl + "GetMuteResponse")
|
||||||
.Select(i => i.Element("CurrentMute"))
|
.Select(i => i.Element("CurrentMute"))
|
||||||
|
@ -750,7 +759,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
if (track == null)
|
if (track == null)
|
||||||
{
|
{
|
||||||
//If track is null, some vendors do this, use GetMediaInfo instead
|
// If track is null, some vendors do this, use GetMediaInfo instead
|
||||||
return (true, null);
|
return (true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,7 +803,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
catch (XmlException)
|
catch (XmlException)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// first try to add a root node with a dlna namesapce
|
// first try to add a root node with a dlna namesapce
|
||||||
|
@ -806,7 +814,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
catch (XmlException)
|
catch (XmlException)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// some devices send back invalid xml
|
// some devices send back invalid xml
|
||||||
|
@ -816,7 +823,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
catch (XmlException)
|
catch (XmlException)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -871,10 +877,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
return new string[4];
|
return new string[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region From XML
|
|
||||||
|
|
||||||
private async Task<TransportCommands> GetAVProtocolAsync(CancellationToken cancellationToken)
|
private async Task<TransportCommands> GetAVProtocolAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (AvCommands != null)
|
if (AvCommands != null)
|
||||||
|
@ -1069,8 +1071,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
return new Device(deviceProperties, httpClient, logger, config);
|
return new Device(deviceProperties, httpClient, logger, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||||
private static DeviceIcon CreateIcon(XElement element)
|
private static DeviceIcon CreateIcon(XElement element)
|
||||||
{
|
{
|
||||||
|
@ -1194,8 +1194,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IDisposable
|
|
||||||
|
|
||||||
bool _disposed;
|
bool _disposed;
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -1222,8 +1220,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return string.Format("{0} - {1}", Properties.Name, Properties.BaseUrl);
|
return string.Format("{0} - {1}", Properties.Name, Properties.BaseUrl);
|
||||||
|
|
|
@ -425,6 +425,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
|
await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await SeekAfterTransportChange(newPosition, CancellationToken.None).ConfigureAwait(false);
|
await SeekAfterTransportChange(newPosition, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,6 +714,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
throw new ArgumentException("Volume argument cannot be null");
|
throw new ArgumentException("Volume argument cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
@ -798,12 +800,15 @@ namespace Emby.Dlna.PlayTo
|
||||||
public int? SubtitleStreamIndex { get; set; }
|
public int? SubtitleStreamIndex { get; set; }
|
||||||
|
|
||||||
public string DeviceProfileId { get; set; }
|
public string DeviceProfileId { get; set; }
|
||||||
|
|
||||||
public string DeviceId { get; set; }
|
public string DeviceId { get; set; }
|
||||||
|
|
||||||
public string MediaSourceId { get; set; }
|
public string MediaSourceId { get; set; }
|
||||||
|
|
||||||
public string LiveStreamId { get; set; }
|
public string LiveStreamId { get; set; }
|
||||||
|
|
||||||
public BaseItem Item { get; set; }
|
public BaseItem Item { get; set; }
|
||||||
|
|
||||||
private MediaSourceInfo MediaSource;
|
private MediaSourceInfo MediaSource;
|
||||||
|
|
||||||
private IMediaSourceManager _mediaSourceManager;
|
private IMediaSourceManager _mediaSourceManager;
|
||||||
|
|
|
@ -78,9 +78,15 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
var info = e.Argument;
|
var info = e.Argument;
|
||||||
|
|
||||||
if (!info.Headers.TryGetValue("USN", out string usn)) usn = string.Empty;
|
if (!info.Headers.TryGetValue("USN", out string usn))
|
||||||
|
{
|
||||||
|
usn = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
if (!info.Headers.TryGetValue("NT", out string nt)) nt = string.Empty;
|
if (!info.Headers.TryGetValue("NT", out string nt))
|
||||||
|
{
|
||||||
|
nt = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
string location = info.Location.ToString();
|
string location = info.Location.ToString();
|
||||||
|
|
||||||
|
@ -88,7 +94,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1 &&
|
if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1 &&
|
||||||
nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1)
|
nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1)
|
||||||
{
|
{
|
||||||
//_logger.LogDebug("Upnp device {0} does not contain a MediaRenderer device (0).", location);
|
// _logger.LogDebug("Upnp device {0} does not contain a MediaRenderer device (0).", location);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +118,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -133,6 +138,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
usn = usn.Substring(index);
|
usn = usn.Substring(index);
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
index = usn.IndexOf("::", StringComparison.OrdinalIgnoreCase);
|
index = usn.IndexOf("::", StringComparison.OrdinalIgnoreCase);
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
{
|
{
|
||||||
|
@ -184,7 +190,8 @@ namespace Emby.Dlna.PlayTo
|
||||||
serverAddress = _appHost.GetLocalApiUrl(info.LocalIpAddress);
|
serverAddress = _appHost.GetLocalApiUrl(info.LocalIpAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
controller = new PlayToController(sessionInfo,
|
controller = new PlayToController(
|
||||||
|
sessionInfo,
|
||||||
_sessionManager,
|
_sessionManager,
|
||||||
_libraryManager,
|
_libraryManager,
|
||||||
_logger,
|
_logger,
|
||||||
|
@ -242,7 +249,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_sessionLock.Dispose();
|
_sessionLock.Dispose();
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
public class MediaChangedEventArgs : EventArgs
|
public class MediaChangedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public uBaseObject OldMediaInfo { get; set; }
|
public uBaseObject OldMediaInfo { get; set; }
|
||||||
|
|
||||||
public uBaseObject NewMediaInfo { get; set; }
|
public uBaseObject NewMediaInfo { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
using (await _httpClient.SendAsync(options, new HttpMethod("SUBSCRIBE")).ConfigureAwait(false))
|
using (await _httpClient.SendAsync(options, new HttpMethod("SUBSCRIBE")).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,10 +44,12 @@ namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
return MediaBrowser.Model.Entities.MediaType.Audio;
|
return MediaBrowser.Model.Entities.MediaType.Audio;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classType.IndexOf(MediaBrowser.Model.Entities.MediaType.Video, StringComparison.Ordinal) != -1)
|
if (classType.IndexOf(MediaBrowser.Model.Entities.MediaType.Video, StringComparison.Ordinal) != -1)
|
||||||
{
|
{
|
||||||
return MediaBrowser.Model.Entities.MediaType.Video;
|
return MediaBrowser.Model.Entities.MediaType.Video;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classType.IndexOf("image", StringComparison.Ordinal) != -1)
|
if (classType.IndexOf("image", StringComparison.Ordinal) != -1)
|
||||||
{
|
{
|
||||||
return MediaBrowser.Model.Entities.MediaType.Photo;
|
return MediaBrowser.Model.Entities.MediaType.Photo;
|
||||||
|
|
|
@ -134,6 +134,7 @@ namespace Emby.Dlna.Server
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.ToString(CultureInfo.InvariantCulture);
|
return c.ToString(CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,18 +158,22 @@ namespace Emby.Dlna.Server
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stringBuilder == null)
|
if (stringBuilder == null)
|
||||||
{
|
{
|
||||||
stringBuilder = new StringBuilder();
|
stringBuilder = new StringBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
stringBuilder.Append(str, num, num2 - num);
|
stringBuilder.Append(str, num, num2 - num);
|
||||||
stringBuilder.Append(GetEscapeSequence(str[num2]));
|
stringBuilder.Append(GetEscapeSequence(str[num2]));
|
||||||
num = num2 + 1;
|
num = num2 + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stringBuilder == null)
|
if (stringBuilder == null)
|
||||||
{
|
{
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
stringBuilder.Append(str, num, length - num);
|
stringBuilder.Append(str, num, length - num);
|
||||||
return stringBuilder.ToString();
|
return stringBuilder.ToString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Emby.Dlna.Service
|
||||||
private const string NS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/";
|
private const string NS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/";
|
||||||
|
|
||||||
protected IServerConfigurationManager Config { get; }
|
protected IServerConfigurationManager Config { get; }
|
||||||
|
|
||||||
protected ILogger Logger { get; }
|
protected ILogger Logger { get; }
|
||||||
|
|
||||||
protected BaseControlHandler(IServerConfigurationManager config, ILogger logger)
|
protected BaseControlHandler(IServerConfigurationManager config, ILogger logger)
|
||||||
|
@ -135,6 +136,7 @@ namespace Emby.Dlna.Service
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
await reader.SkipAsync().ConfigureAwait(false);
|
await reader.SkipAsync().ConfigureAwait(false);
|
||||||
|
@ -211,7 +213,9 @@ namespace Emby.Dlna.Service
|
||||||
private class ControlRequestInfo
|
private class ControlRequestInfo
|
||||||
{
|
{
|
||||||
public string LocalName { get; set; }
|
public string LocalName { get; set; }
|
||||||
|
|
||||||
public string NamespaceURI { get; set; }
|
public string NamespaceURI { get; set; }
|
||||||
|
|
||||||
public Dictionary<string, string> Headers { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
public Dictionary<string, string> Headers { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Emby.Dlna.Service
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
HttpClient = httpClient;
|
HttpClient = httpClient;
|
||||||
|
|
||||||
EventManager = new EventManager(Logger, HttpClient);
|
EventManager = new EventManager(logger, HttpClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventSubscriptionResponse CancelEventSubscription(string subscriptionId)
|
public EventSubscriptionResponse CancelEventSubscription(string subscriptionId)
|
||||||
|
|
|
@ -80,6 +80,7 @@ namespace Emby.Dlna.Service
|
||||||
{
|
{
|
||||||
builder.Append("<allowedValue>" + DescriptionXmlBuilder.Escape(allowedValue) + "</allowedValue>");
|
builder.Append("<allowedValue>" + DescriptionXmlBuilder.Escape(allowedValue) + "</allowedValue>");
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Append("</allowedValueList>");
|
builder.Append("</allowedValueList>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace Emby.Dlna.Ssdp
|
||||||
// (Optional) Set the filter so we only see notifications for devices we care about
|
// (Optional) Set the filter so we only see notifications for devices we care about
|
||||||
// (can be any search target value i.e device type, uuid value etc - any value that appears in the
|
// (can be any search target value i.e device type, uuid value etc - any value that appears in the
|
||||||
// DiscoverdSsdpDevice.NotificationType property or that is used with the searchTarget parameter of the Search method).
|
// DiscoverdSsdpDevice.NotificationType property or that is used with the searchTarget parameter of the Search method).
|
||||||
//_DeviceLocator.NotificationFilter = "upnp:rootdevice";
|
// _DeviceLocator.NotificationFilter = "upnp:rootdevice";
|
||||||
|
|
||||||
// Connect our event handler so we process devices as they are found
|
// Connect our event handler so we process devices as they are found
|
||||||
_deviceLocator.DeviceAvailable += OnDeviceLocatorDeviceAvailable;
|
_deviceLocator.DeviceAvailable += OnDeviceLocatorDeviceAvailable;
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Emby.Drawing
|
||||||
private static readonly HashSet<string> _transparentImageTypes
|
private static readonly HashSet<string> _transparentImageTypes
|
||||||
= new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".png", ".webp", ".gif" };
|
= new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".png", ".webp", ".gif" };
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<ImageProcessor> _logger;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IServerApplicationPaths _appPaths;
|
private readonly IServerApplicationPaths _appPaths;
|
||||||
private readonly IImageEncoder _imageEncoder;
|
private readonly IImageEncoder _imageEncoder;
|
||||||
|
@ -302,7 +302,7 @@ namespace Emby.Drawing
|
||||||
}
|
}
|
||||||
|
|
||||||
string path = info.Path;
|
string path = info.Path;
|
||||||
_logger.LogInformation("Getting image size for item {ItemType} {Path}", item.GetType().Name, path);
|
_logger.LogDebug("Getting image size for item {ItemType} {Path}", item.GetType().Name, path);
|
||||||
|
|
||||||
ImageDimensions size = GetImageDimensions(path);
|
ImageDimensions size = GetImageDimensions(path);
|
||||||
info.Width = size.Width;
|
info.Width = size.Width;
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace Emby.Naming.AudioBook
|
||||||
{
|
{
|
||||||
result.ChapterNumber = int.Parse(matches[0].Groups[0].Value);
|
result.ChapterNumber = int.Parse(matches[0].Groups[0].Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matches.Count > 1)
|
if (matches.Count > 1)
|
||||||
{
|
{
|
||||||
result.PartNumber = int.Parse(matches[matches.Count - 1].Groups[0].Value);
|
result.PartNumber = int.Parse(matches[matches.Count - 1].Groups[0].Value);
|
||||||
|
|
|
@ -5,17 +5,17 @@ namespace Emby.Naming.Common
|
||||||
public enum MediaType
|
public enum MediaType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The audio
|
/// The audio.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Audio = 0,
|
Audio = 0,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The photo
|
/// The photo.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Photo = 1,
|
Photo = 1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The video
|
/// The video.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Video = 2
|
Video = 2
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace Emby.Notifications
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class NotificationEntryPoint : IServerEntryPoint
|
public class NotificationEntryPoint : IServerEntryPoint
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<NotificationEntryPoint> _logger;
|
||||||
private readonly IActivityManager _activityManager;
|
private readonly IActivityManager _activityManager;
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
private readonly INotificationManager _notificationManager;
|
private readonly INotificationManager _notificationManager;
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Emby.Notifications
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class NotificationManager : INotificationManager
|
public class NotificationManager : INotificationManager
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<NotificationManager> _logger;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Emby.Photos
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PhotoProvider : ICustomMetadataProvider<Photo>, IForcedProvider, IHasItemChangeMonitor
|
public class PhotoProvider : ICustomMetadataProvider<Photo>, IForcedProvider, IHasItemChangeMonitor
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<PhotoProvider> _logger;
|
||||||
private readonly IImageProcessor _imageProcessor;
|
private readonly IImageProcessor _imageProcessor;
|
||||||
|
|
||||||
// These are causing taglib to hang
|
// These are causing taglib to hang
|
||||||
|
@ -104,7 +104,7 @@ namespace Emby.Photos
|
||||||
item.Overview = image.ImageTag.Comment;
|
item.Overview = image.ImageTag.Comment;
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(image.ImageTag.Title)
|
if (!string.IsNullOrWhiteSpace(image.ImageTag.Title)
|
||||||
&& !item.LockedFields.Contains(MetadataFields.Name))
|
&& !item.LockedFields.Contains(MetadataField.Name))
|
||||||
{
|
{
|
||||||
item.Name = image.ImageTag.Title;
|
item.Name = image.ImageTag.Title;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||||
CommonApplicationPaths = applicationPaths;
|
CommonApplicationPaths = applicationPaths;
|
||||||
XmlSerializer = xmlSerializer;
|
XmlSerializer = xmlSerializer;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
Logger = loggerFactory.CreateLogger(GetType().Name);
|
Logger = loggerFactory.CreateLogger<BaseConfigurationManager>();
|
||||||
|
|
||||||
UpdateCachePath();
|
UpdateCachePath();
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||||
/// Gets the logger.
|
/// Gets the logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The logger.</value>
|
/// <value>The logger.</value>
|
||||||
protected ILogger Logger { get; private set; }
|
protected ILogger<BaseConfigurationManager> Logger { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the XML serializer.
|
/// Gets the XML serializer.
|
||||||
|
|
|
@ -173,7 +173,7 @@ namespace Emby.Server.Implementations
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the logger.
|
/// Gets the logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected ILogger Logger { get; }
|
protected ILogger<ApplicationHost> Logger { get; }
|
||||||
|
|
||||||
private IPlugin[] _plugins;
|
private IPlugin[] _plugins;
|
||||||
|
|
||||||
|
@ -956,7 +956,7 @@ namespace Emby.Server.Implementations
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Notifies that the kernel that a change has been made that requires a restart
|
/// Notifies that the kernel that a change has been made that requires a restart.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void NotifyPendingRestart()
|
public void NotifyPendingRestart()
|
||||||
{
|
{
|
||||||
|
@ -1234,7 +1234,7 @@ namespace Emby.Server.Implementations
|
||||||
|
|
||||||
if (addresses.Count == 0)
|
if (addresses.Count == 0)
|
||||||
{
|
{
|
||||||
addresses.AddRange(_networkManager.GetLocalIpAddresses(ServerConfigurationManager.Configuration.IgnoreVirtualInterfaces));
|
addresses.AddRange(_networkManager.GetLocalIpAddresses());
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultList = new List<IPAddress>();
|
var resultList = new List<IPAddress>();
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.Browser
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var logger = appHost.Resolve<ILogger>();
|
var logger = appHost.Resolve<ILogger<IServerApplicationHost>>();
|
||||||
logger?.LogError(ex, "Failed to open browser window with URL {URL}", relativeUrl);
|
logger?.LogError(ex, "Failed to open browser window with URL {URL}", relativeUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace Emby.Server.Implementations.Channels
|
||||||
private readonly IUserDataManager _userDataManager;
|
private readonly IUserDataManager _userDataManager;
|
||||||
private readonly IDtoService _dtoService;
|
private readonly IDtoService _dtoService;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<ChannelManager> _logger;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
|
@ -1072,7 +1072,7 @@ namespace Emby.Server.Implementations.Channels
|
||||||
}
|
}
|
||||||
|
|
||||||
// was used for status
|
// was used for status
|
||||||
//if (!string.Equals(item.ExternalEtag ?? string.Empty, info.Etag ?? string.Empty, StringComparison.Ordinal))
|
// if (!string.Equals(item.ExternalEtag ?? string.Empty, info.Etag ?? string.Empty, StringComparison.Ordinal))
|
||||||
//{
|
//{
|
||||||
// item.ExternalEtag = info.Etag;
|
// item.ExternalEtag = info.Etag;
|
||||||
// forceUpdate = true;
|
// forceUpdate = true;
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Channels
|
||||||
public class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask
|
public class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask
|
||||||
{
|
{
|
||||||
private readonly IChannelManager _channelManager;
|
private readonly IChannelManager _channelManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<RefreshChannelsScheduledTask> _logger;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly ILibraryMonitor _iLibraryMonitor;
|
private readonly ILibraryMonitor _iLibraryMonitor;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<CollectionManager> _logger;
|
||||||
private readonly IProviderManager _providerManager;
|
private readonly IProviderManager _providerManager;
|
||||||
private readonly ILocalizationManager _localizationManager;
|
private readonly ILocalizationManager _localizationManager;
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
|
@ -57,7 +57,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_iLibraryMonitor = iLibraryMonitor;
|
_iLibraryMonitor = iLibraryMonitor;
|
||||||
_logger = loggerFactory.CreateLogger(nameof(CollectionManager));
|
_logger = loggerFactory.CreateLogger<CollectionManager>();
|
||||||
_providerManager = providerManager;
|
_providerManager = providerManager;
|
||||||
_localizationManager = localizationManager;
|
_localizationManager = localizationManager;
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
|
@ -371,7 +371,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
{
|
{
|
||||||
private readonly CollectionManager _collectionManager;
|
private readonly CollectionManager _collectionManager;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<CollectionManagerEntryPoint> _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="CollectionManagerEntryPoint"/> class.
|
/// Initializes a new instance of the <see cref="CollectionManagerEntryPoint"/> class.
|
||||||
|
|
|
@ -17,7 +17,6 @@ namespace Emby.Server.Implementations
|
||||||
{
|
{
|
||||||
{ HostWebClientKey, bool.TrueString },
|
{ HostWebClientKey, bool.TrueString },
|
||||||
{ HttpListenerHost.DefaultRedirectKey, "web/index.html" },
|
{ HttpListenerHost.DefaultRedirectKey, "web/index.html" },
|
||||||
{ InstallationManager.PluginManifestUrlKey, "https://repo.jellyfin.org/releases/plugin/manifest-stable.json" },
|
|
||||||
{ FfmpegProbeSizeKey, "1G" },
|
{ FfmpegProbeSizeKey, "1G" },
|
||||||
{ FfmpegAnalyzeDurationKey, "200M" },
|
{ FfmpegAnalyzeDurationKey, "200M" },
|
||||||
{ PlaylistsAllowDuplicatesKey, bool.TrueString }
|
{ PlaylistsAllowDuplicatesKey, bool.TrueString }
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
/// Initializes a new instance of the <see cref="BaseSqliteRepository"/> class.
|
/// Initializes a new instance of the <see cref="BaseSqliteRepository"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
protected BaseSqliteRepository(ILogger logger)
|
protected BaseSqliteRepository(ILogger<BaseSqliteRepository> logger)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
/// Gets the logger.
|
/// Gets the logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The logger.</value>
|
/// <value>The logger.</value>
|
||||||
protected ILogger Logger { get; }
|
protected ILogger<BaseSqliteRepository> Logger { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the default connection flags.
|
/// Gets the default connection flags.
|
||||||
|
@ -162,7 +162,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}, ReadTransactionMode);
|
}, ReadTransactionMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,12 +247,12 @@ namespace Emby.Server.Implementations.Data
|
||||||
public enum SynchronousMode
|
public enum SynchronousMode
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SQLite continues without syncing as soon as it has handed data off to the operating system
|
/// SQLite continues without syncing as soon as it has handed data off to the operating system.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Off = 0,
|
Off = 0,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SQLite database engine will still sync at the most critical moments
|
/// SQLite database engine will still sync at the most critical moments.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Normal = 1,
|
Normal = 1,
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
public class CleanDatabaseScheduledTask : ILibraryPostScanTask
|
public class CleanDatabaseScheduledTask : ILibraryPostScanTask
|
||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<CleanDatabaseScheduledTask> _logger;
|
||||||
|
|
||||||
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, ILogger<CleanDatabaseScheduledTask> logger)
|
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, ILogger<CleanDatabaseScheduledTask> logger)
|
||||||
{
|
{
|
||||||
|
@ -51,7 +51,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
_libraryManager.DeleteItem(item, new DeleteOptions
|
_libraryManager.DeleteItem(item, new DeleteOptions
|
||||||
{
|
{
|
||||||
DeleteFileLocation = false
|
DeleteFileLocation = false
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the connection to the database
|
/// Opens the connection to the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
private void InitializeInternal()
|
private void InitializeInternal()
|
||||||
|
@ -77,7 +77,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save the display preferences associated with an item in the repo
|
/// Save the display preferences associated with an item in the repo.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="displayPreferences">The display preferences.</param>
|
/// <param name="displayPreferences">The display preferences.</param>
|
||||||
/// <param name="userId">The user id.</param>
|
/// <param name="userId">The user id.</param>
|
||||||
|
@ -122,7 +122,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save all display preferences associated with a user in the repo
|
/// Save all display preferences associated with a user in the repo.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="displayPreferences">The display preferences.</param>
|
/// <param name="displayPreferences">The display preferences.</param>
|
||||||
/// <param name="userId">The user id.</param>
|
/// <param name="userId">The user id.</param>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -135,10 +135,12 @@ namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(userData));
|
throw new ArgumentNullException(nameof(userData));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (internalUserId <= 0)
|
if (internalUserId <= 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(internalUserId));
|
throw new ArgumentNullException(nameof(internalUserId));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(key))
|
if (string.IsNullOrEmpty(key))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(key));
|
throw new ArgumentNullException(nameof(key));
|
||||||
|
@ -153,6 +155,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(userData));
|
throw new ArgumentNullException(nameof(userData));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (internalUserId <= 0)
|
if (internalUserId <= 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(internalUserId));
|
throw new ArgumentNullException(nameof(internalUserId));
|
||||||
|
@ -235,7 +238,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Persist all user data for the specified user
|
/// Persist all user data for the specified user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void PersistAllUserData(long internalUserId, UserItemData[] userDataList, CancellationToken cancellationToken)
|
private void PersistAllUserData(long internalUserId, UserItemData[] userDataList, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
@ -309,7 +312,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return all user-data associated with the given user
|
/// Return all user-data associated with the given user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="internalUserId"></param>
|
/// <param name="internalUserId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
@ -339,7 +342,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read a row from the specified reader into the provided userData object
|
/// Read a row from the specified reader into the provided userData object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader"></param>
|
/// <param name="reader"></param>
|
||||||
private UserItemData ReadRow(IReadOnlyList<IResultSetValue> reader)
|
private UserItemData ReadRow(IReadOnlyList<IResultSetValue> reader)
|
||||||
|
@ -347,7 +350,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
var userData = new UserItemData();
|
var userData = new UserItemData();
|
||||||
|
|
||||||
userData.Key = reader[0].ToString();
|
userData.Key = reader[0].ToString();
|
||||||
//userData.UserId = reader[1].ReadGuidFromBlob();
|
// userData.UserId = reader[1].ReadGuidFromBlob();
|
||||||
|
|
||||||
if (reader[2].SQLiteType != SQLiteType.Null)
|
if (reader[2].SQLiteType != SQLiteType.Null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Emby.Server.Implementations.Devices
|
||||||
public class DeviceId
|
public class DeviceId
|
||||||
{
|
{
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<DeviceId> _logger;
|
||||||
|
|
||||||
private readonly object _syncLock = new object();
|
private readonly object _syncLock = new object();
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ namespace Emby.Server.Implementations.Devices
|
||||||
public DeviceId(IApplicationPaths appPaths, ILoggerFactory loggerFactory)
|
public DeviceId(IApplicationPaths appPaths, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
_logger = loggerFactory.CreateLogger("SystemId");
|
_logger = loggerFactory.CreateLogger<DeviceId>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Value => _id ?? (_id = GetDeviceId());
|
public string Value => _id ?? (_id = GetDeviceId());
|
||||||
|
|
|
@ -112,7 +112,7 @@ namespace Emby.Server.Implementations.Devices
|
||||||
{
|
{
|
||||||
IEnumerable<AuthenticationInfo> sessions = _authRepo.Get(new AuthenticationInfoQuery
|
IEnumerable<AuthenticationInfo> sessions = _authRepo.Get(new AuthenticationInfoQuery
|
||||||
{
|
{
|
||||||
//UserId = query.UserId
|
// UserId = query.UserId
|
||||||
HasUser = true
|
HasUser = true
|
||||||
}).Items;
|
}).Items;
|
||||||
|
|
||||||
|
@ -169,6 +169,7 @@ namespace Emby.Server.Implementations.Devices
|
||||||
{
|
{
|
||||||
throw new ArgumentException("user not found");
|
throw new ArgumentException("user not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(deviceId))
|
if (string.IsNullOrEmpty(deviceId))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(deviceId));
|
throw new ArgumentNullException(nameof(deviceId));
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
{
|
{
|
||||||
public class DtoService : IDtoService
|
public class DtoService : IDtoService
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<DtoService> _logger;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IUserDataManager _userDataRepository;
|
private readonly IUserDataManager _userDataRepository;
|
||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
|
@ -74,7 +74,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts a BaseItem to a DTOBaseItem
|
/// Converts a BaseItem to a DTOBaseItem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <param name="fields">The fields.</param>
|
/// <param name="fields">The fields.</param>
|
||||||
|
@ -277,6 +277,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
dto.EpisodeTitle = dto.Name;
|
dto.EpisodeTitle = dto.Name;
|
||||||
dto.Name = dto.SeriesName;
|
dto.Name = dto.SeriesName;
|
||||||
}
|
}
|
||||||
|
|
||||||
liveTvManager.AddInfoToRecordingDto(item, dto, activeRecording, user);
|
liveTvManager.AddInfoToRecordingDto(item, dto, activeRecording, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +293,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var containers = container.Split(new[] { ',' });
|
var containers = container.Split(new[] { ',' });
|
||||||
if (containers.Length < 2)
|
if (containers.Length < 2)
|
||||||
{
|
{
|
||||||
|
@ -406,7 +408,6 @@ namespace Emby.Server.Implementations.Dto
|
||||||
dto.DateLastMediaAdded = folder.DateLastMediaAdded;
|
dto.DateLastMediaAdded = folder.DateLastMediaAdded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (options.EnableUserData)
|
if (options.EnableUserData)
|
||||||
|
@ -443,7 +444,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets client-side Id of a server-side BaseItem
|
/// Gets client-side Id of a server-side BaseItem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
|
@ -457,6 +458,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
{
|
{
|
||||||
dto.SeriesName = item.SeriesName;
|
dto.SeriesName = item.SeriesName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetPhotoProperties(BaseItemDto dto, Photo item)
|
private static void SetPhotoProperties(BaseItemDto dto, Photo item)
|
||||||
{
|
{
|
||||||
dto.CameraMake = item.CameraMake;
|
dto.CameraMake = item.CameraMake;
|
||||||
|
@ -538,7 +540,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attaches People DTO's to a DTOBaseItem
|
/// Attaches People DTO's to a DTOBaseItem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dto">The dto.</param>
|
/// <param name="dto">The dto.</param>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
|
@ -555,22 +557,27 @@ namespace Emby.Server.Implementations.Dto
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.IsType(PersonType.GuestStar))
|
if (i.IsType(PersonType.GuestStar))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.IsType(PersonType.Director))
|
if (i.IsType(PersonType.Director))
|
||||||
{
|
{
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.IsType(PersonType.Writer))
|
if (i.IsType(PersonType.Writer))
|
||||||
{
|
{
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.IsType(PersonType.Producer))
|
if (i.IsType(PersonType.Producer))
|
||||||
{
|
{
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.IsType(PersonType.Composer))
|
if (i.IsType(PersonType.Composer))
|
||||||
{
|
{
|
||||||
return 4;
|
return 4;
|
||||||
|
@ -594,7 +601,6 @@ namespace Emby.Server.Implementations.Dto
|
||||||
_logger.LogError(ex, "Error getting person {Name}", c);
|
_logger.LogError(ex, "Error getting person {Name}", c);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}).Where(i => i != null)
|
}).Where(i => i != null)
|
||||||
.GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
|
.GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
|
||||||
.Select(x => x.First())
|
.Select(x => x.First())
|
||||||
|
@ -615,6 +621,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
{
|
{
|
||||||
baseItemPerson.PrimaryImageTag = GetTagAndFillBlurhash(dto, entity, ImageType.Primary);
|
baseItemPerson.PrimaryImageTag = GetTagAndFillBlurhash(dto, entity, ImageType.Primary);
|
||||||
baseItemPerson.Id = entity.Id.ToString("N", CultureInfo.InvariantCulture);
|
baseItemPerson.Id = entity.Id.ToString("N", CultureInfo.InvariantCulture);
|
||||||
|
baseItemPerson.ImageBlurHashes = dto.ImageBlurHashes;
|
||||||
list.Add(baseItemPerson);
|
list.Add(baseItemPerson);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -727,7 +734,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets simple property values on a DTOBaseItem
|
/// Sets simple property values on a DTOBaseItem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dto">The dto.</param>
|
/// <param name="dto">The dto.</param>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
|
@ -947,7 +954,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
dto.AlbumPrimaryImageTag = GetTagAndFillBlurhash(dto, albumParent, ImageType.Primary);
|
dto.AlbumPrimaryImageTag = GetTagAndFillBlurhash(dto, albumParent, ImageType.Primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (options.ContainsField(ItemFields.MediaSourceCount))
|
// if (options.ContainsField(ItemFields.MediaSourceCount))
|
||||||
//{
|
//{
|
||||||
// Songs always have one
|
// Songs always have one
|
||||||
//}
|
//}
|
||||||
|
@ -957,13 +964,13 @@ namespace Emby.Server.Implementations.Dto
|
||||||
{
|
{
|
||||||
dto.Artists = hasArtist.Artists;
|
dto.Artists = hasArtist.Artists;
|
||||||
|
|
||||||
//var artistItems = _libraryManager.GetArtists(new InternalItemsQuery
|
// var artistItems = _libraryManager.GetArtists(new InternalItemsQuery
|
||||||
//{
|
//{
|
||||||
// EnableTotalRecordCount = false,
|
// EnableTotalRecordCount = false,
|
||||||
// ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) }
|
// ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) }
|
||||||
//});
|
//});
|
||||||
|
|
||||||
//dto.ArtistItems = artistItems.Items
|
// dto.ArtistItems = artistItems.Items
|
||||||
// .Select(i =>
|
// .Select(i =>
|
||||||
// {
|
// {
|
||||||
// var artist = i.Item1;
|
// var artist = i.Item1;
|
||||||
|
@ -976,7 +983,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
// .ToList();
|
// .ToList();
|
||||||
|
|
||||||
// Include artists that are not in the database yet, e.g., just added via metadata editor
|
// Include artists that are not in the database yet, e.g., just added via metadata editor
|
||||||
//var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList();
|
// var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList();
|
||||||
dto.ArtistItems = hasArtist.Artists
|
dto.ArtistItems = hasArtist.Artists
|
||||||
//.Except(foundArtists, new DistinctNameComparer())
|
//.Except(foundArtists, new DistinctNameComparer())
|
||||||
.Select(i =>
|
.Select(i =>
|
||||||
|
@ -1001,7 +1008,6 @@ namespace Emby.Server.Implementations.Dto
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}).Where(i => i != null).ToArray();
|
}).Where(i => i != null).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1010,13 +1016,13 @@ namespace Emby.Server.Implementations.Dto
|
||||||
{
|
{
|
||||||
dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault();
|
dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault();
|
||||||
|
|
||||||
//var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery
|
// var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery
|
||||||
//{
|
//{
|
||||||
// EnableTotalRecordCount = false,
|
// EnableTotalRecordCount = false,
|
||||||
// ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) }
|
// ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) }
|
||||||
//});
|
//});
|
||||||
|
|
||||||
//dto.AlbumArtists = artistItems.Items
|
// dto.AlbumArtists = artistItems.Items
|
||||||
// .Select(i =>
|
// .Select(i =>
|
||||||
// {
|
// {
|
||||||
// var artist = i.Item1;
|
// var artist = i.Item1;
|
||||||
|
@ -1052,7 +1058,6 @@ namespace Emby.Server.Implementations.Dto
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}).Where(i => i != null).ToArray();
|
}).Where(i => i != null).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1166,7 +1171,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
|
|
||||||
// this block will add the series poster for episodes without a poster
|
// this block will add the series poster for episodes without a poster
|
||||||
// TODO maybe remove the if statement entirely
|
// TODO maybe remove the if statement entirely
|
||||||
//if (options.ContainsField(ItemFields.SeriesPrimaryImage))
|
// if (options.ContainsField(ItemFields.SeriesPrimaryImage))
|
||||||
{
|
{
|
||||||
episodeSeries = episodeSeries ?? episode.Series;
|
episodeSeries = episodeSeries ?? episode.Series;
|
||||||
if (episodeSeries != null)
|
if (episodeSeries != null)
|
||||||
|
@ -1212,7 +1217,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
|
|
||||||
// this block will add the series poster for seasons without a poster
|
// this block will add the series poster for seasons without a poster
|
||||||
// TODO maybe remove the if statement entirely
|
// TODO maybe remove the if statement entirely
|
||||||
//if (options.ContainsField(ItemFields.SeriesPrimaryImage))
|
// if (options.ContainsField(ItemFields.SeriesPrimaryImage))
|
||||||
{
|
{
|
||||||
series = series ?? season.Series;
|
series = series ?? season.Series;
|
||||||
if (series != null)
|
if (series != null)
|
||||||
|
@ -1350,6 +1355,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
dto.ParentLogoImageTag = GetTagAndFillBlurhash(dto, parent, image);
|
dto.ParentLogoImageTag = GetTagAndFillBlurhash(dto, parent, image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (artLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && dto.ParentArtItemId == null)
|
if (artLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && dto.ParentArtItemId == null)
|
||||||
{
|
{
|
||||||
var image = allImages.FirstOrDefault(i => i.Type == ImageType.Art);
|
var image = allImages.FirstOrDefault(i => i.Type == ImageType.Art);
|
||||||
|
@ -1360,6 +1366,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
dto.ParentArtImageTag = GetTagAndFillBlurhash(dto, parent, image);
|
dto.ParentArtImageTag = GetTagAndFillBlurhash(dto, parent, image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId == null || parent is Series) && !(parent is ICollectionFolder) && !(parent is UserView))
|
if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId == null || parent is Series) && !(parent is ICollectionFolder) && !(parent is UserView))
|
||||||
{
|
{
|
||||||
var image = allImages.FirstOrDefault(i => i.Type == ImageType.Thumb);
|
var image = allImages.FirstOrDefault(i => i.Type == ImageType.Thumb);
|
||||||
|
@ -1370,6 +1377,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
dto.ParentThumbImageTag = GetTagAndFillBlurhash(dto, parent, image);
|
dto.ParentThumbImageTag = GetTagAndFillBlurhash(dto, parent, image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backdropLimit > 0 && !((dto.BackdropImageTags != null && dto.BackdropImageTags.Length > 0) || (dto.ParentBackdropImageTags != null && dto.ParentBackdropImageTags.Length > 0)))
|
if (backdropLimit > 0 && !((dto.BackdropImageTags != null && dto.BackdropImageTags.Length > 0) || (dto.ParentBackdropImageTags != null && dto.ParentBackdropImageTags.Length > 0)))
|
||||||
{
|
{
|
||||||
var images = allImages.Where(i => i.Type == ImageType.Backdrop).Take(backdropLimit).ToList();
|
var images = allImages.Where(i => i.Type == ImageType.Backdrop).Take(backdropLimit).ToList();
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="IPNetwork2" Version="2.4.0.126" />
|
<PackageReference Include="IPNetwork2" Version="2.5.211" />
|
||||||
<PackageReference Include="Jellyfin.XmlTv" Version="10.4.3" />
|
<PackageReference Include="Jellyfin.XmlTv" Version="10.4.3" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
|
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
|
||||||
|
@ -34,14 +34,14 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
|
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.4" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.4" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.4" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.4" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.5" />
|
||||||
<PackageReference Include="Mono.Nat" Version="2.0.1" />
|
<PackageReference Include="Mono.Nat" Version="2.0.1" />
|
||||||
<PackageReference Include="prometheus-net.DotNetRuntime" Version="3.3.1" />
|
<PackageReference Include="prometheus-net.DotNetRuntime" Version="3.3.1" />
|
||||||
<PackageReference Include="ServiceStack.Text.Core" Version="5.8.0" />
|
<PackageReference Include="ServiceStack.Text.Core" Version="5.9.0" />
|
||||||
<PackageReference Include="sharpcompress" Version="0.25.0" />
|
<PackageReference Include="sharpcompress" Version="0.25.1" />
|
||||||
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />
|
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />
|
||||||
<PackageReference Include="DotNet.Glob" Version="3.0.9" />
|
<PackageReference Include="DotNet.Glob" Version="3.0.9" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
public class ExternalPortForwarding : IServerEntryPoint
|
public class ExternalPortForwarding : IServerEntryPoint
|
||||||
{
|
{
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<ExternalPortForwarding> _logger;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IDeviceDiscovery _deviceDiscovery;
|
private readonly IDeviceDiscovery _deviceDiscovery;
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
|
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<LibraryChangedNotifier> _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The library changed sync lock.
|
/// The library changed sync lock.
|
||||||
|
@ -132,7 +132,6 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
private readonly ILiveTvManager _liveTvManager;
|
private readonly ILiveTvManager _liveTvManager;
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<RecordingNotifier> _logger;
|
||||||
|
|
||||||
public RecordingNotifier(
|
public RecordingNotifier(
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
|
|
|
@ -159,7 +159,6 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +174,6 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger.
|
/// The logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<UdpServerEntryPoint> _logger;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly IConfiguration _config;
|
private readonly IConfiguration _config;
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_config = configuration;
|
_config = configuration;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class HttpClientManager : IHttpClient
|
public class HttpClientManager : IHttpClient
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<HttpClientManager> _logger;
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IApplicationHost _appHost;
|
private readonly IApplicationHost _appHost;
|
||||||
|
@ -140,7 +140,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
||||||
=> SendAsync(options, HttpMethod.Get);
|
=> SendAsync(options, HttpMethod.Get);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a GET request and returns the resulting stream
|
/// Performs a GET request and returns the resulting stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <returns>Task{Stream}.</returns>
|
/// <returns>Task{Stream}.</returns>
|
||||||
|
|
|
@ -32,12 +32,12 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _options
|
/// The _options.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IDictionary<string, string> _options = new Dictionary<string, string>();
|
private readonly IDictionary<string, string> _options = new Dictionary<string, string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _requested ranges
|
/// The _requested ranges.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<KeyValuePair<long, long?>> _requestedRanges;
|
private List<KeyValuePair<long, long?>> _requestedRanges;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string DefaultRedirectKey = "HttpListenerHost:DefaultRedirectPath";
|
public const string DefaultRedirectKey = "HttpListenerHost:DefaultRedirectPath";
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<HttpListenerHost> _logger;
|
||||||
private readonly ILoggerFactory _loggerFactory;
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly INetworkManager _networkManager;
|
private readonly INetworkManager _networkManager;
|
||||||
|
@ -230,7 +230,9 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
|
|
||||||
httpRes.StatusCode = statusCode;
|
httpRes.StatusCode = statusCode;
|
||||||
|
|
||||||
var errContent = NormalizeExceptionMessage(ex) ?? string.Empty;
|
var errContent = _hostEnvironment.IsDevelopment()
|
||||||
|
? (NormalizeExceptionMessage(ex) ?? string.Empty)
|
||||||
|
: "Error processing request.";
|
||||||
httpRes.ContentType = "text/plain";
|
httpRes.ContentType = "text/plain";
|
||||||
httpRes.ContentLength = errContent.Length;
|
httpRes.ContentLength = errContent.Length;
|
||||||
await httpRes.WriteAsync(errContent).ConfigureAwait(false);
|
await httpRes.WriteAsync(errContent).ConfigureAwait(false);
|
||||||
|
@ -397,7 +399,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
var response = context.Response;
|
var response = context.Response;
|
||||||
var localPath = context.Request.Path.ToString();
|
var localPath = context.Request.Path.ToString();
|
||||||
|
|
||||||
var req = new WebSocketSharpRequest(request, response, request.Path, _logger);
|
var req = new WebSocketSharpRequest(request, response, request.Path);
|
||||||
return RequestHandler(req, request.GetDisplayUrl(), request.Host.ToString(), localPath, context.RequestAborted);
|
return RequestHandler(req, request.GetDisplayUrl(), request.Host.ToString(), localPath, context.RequestAborted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,6 +453,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
{
|
{
|
||||||
httpRes.Headers.Add(key, value);
|
httpRes.Headers.Add(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
httpRes.ContentType = "text/plain";
|
httpRes.ContentType = "text/plain";
|
||||||
await httpRes.WriteAsync(string.Empty, cancellationToken).ConfigureAwait(false);
|
await httpRes.WriteAsync(string.Empty, cancellationToken).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
|
@ -589,7 +592,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the default CORS headers
|
/// Get the default CORS headers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="req"></param>
|
/// <param name="req"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger.
|
/// The logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<HttpResultFactory> _logger;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
private readonly IStreamHelper _streamHelper;
|
private readonly IStreamHelper _streamHelper;
|
||||||
|
@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
_streamHelper = streamHelper;
|
_streamHelper = streamHelper;
|
||||||
_logger = loggerfactory.CreateLogger("HttpResultFactory");
|
_logger = loggerfactory.CreateLogger<HttpResultFactory>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -426,7 +426,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, StaticResultOptions options)
|
private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, StaticResultOptions options)
|
||||||
{
|
{
|
||||||
bool noCache = (requestContext.Headers[HeaderNames.CacheControl].ToString()).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;
|
bool noCache = requestContext.Headers[HeaderNames.CacheControl].ToString().IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;
|
||||||
AddCachingHeaders(responseHeaders, options.CacheDuration, noCache, options.DateLastModified);
|
AddCachingHeaders(responseHeaders, options.CacheDuration, noCache, options.DateLastModified);
|
||||||
|
|
||||||
if (!noCache)
|
if (!noCache)
|
||||||
|
@ -580,7 +580,6 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
}
|
}
|
||||||
catch (NotSupportedException)
|
catch (NotSupportedException)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,7 +692,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that
|
/// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="date">The date.</param>
|
/// <param name="date">The date.</param>
|
||||||
/// <returns>DateTime.</returns>
|
/// <returns>DateTime.</returns>
|
||||||
|
|
|
@ -20,31 +20,37 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The source stream.</value>
|
/// <value>The source stream.</value>
|
||||||
private Stream SourceStream { get; set; }
|
private Stream SourceStream { get; set; }
|
||||||
|
|
||||||
private string RangeHeader { get; set; }
|
private string RangeHeader { get; set; }
|
||||||
|
|
||||||
private bool IsHeadRequest { get; set; }
|
private bool IsHeadRequest { get; set; }
|
||||||
|
|
||||||
private long RangeStart { get; set; }
|
private long RangeStart { get; set; }
|
||||||
|
|
||||||
private long RangeEnd { get; set; }
|
private long RangeEnd { get; set; }
|
||||||
|
|
||||||
private long RangeLength { get; set; }
|
private long RangeLength { get; set; }
|
||||||
|
|
||||||
private long TotalContentLength { get; set; }
|
private long TotalContentLength { get; set; }
|
||||||
|
|
||||||
public Action OnComplete { get; set; }
|
public Action OnComplete { get; set; }
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
private const int BufferSize = 81920;
|
private const int BufferSize = 81920;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _options
|
/// The _options.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Dictionary<string, string> _options = new Dictionary<string, string>();
|
private readonly Dictionary<string, string> _options = new Dictionary<string, string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The us culture
|
/// The us culture.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Additional HTTP Headers
|
/// Additional HTTP Headers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The headers.</value>
|
/// <value>The headers.</value>
|
||||||
public IDictionary<string, string> Headers => _options;
|
public IDictionary<string, string> Headers => _options;
|
||||||
|
@ -110,7 +116,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _requested ranges
|
/// The _requested ranges.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<KeyValuePair<long, long?>> _requestedRanges;
|
private List<KeyValuePair<long, long?>> _requestedRanges;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -139,6 +145,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
{
|
{
|
||||||
start = long.Parse(vals[0], UsCulture);
|
start = long.Parse(vals[0], UsCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(vals[1]))
|
if (!string.IsNullOrEmpty(vals[1]))
|
||||||
{
|
{
|
||||||
end = long.Parse(vals[1], UsCulture);
|
end = long.Parse(vals[1], UsCulture);
|
||||||
|
|
|
@ -41,11 +41,11 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
res.Headers.Add(key, value);
|
res.Headers.Add(key, value);
|
||||||
}
|
}
|
||||||
// Try to prevent compatibility view
|
// Try to prevent compatibility view
|
||||||
res.Headers["Access-Control-Allow-Headers"] = ("Accept, Accept-Language, Authorization, Cache-Control, " +
|
res.Headers["Access-Control-Allow-Headers"] = "Accept, Accept-Language, Authorization, Cache-Control, " +
|
||||||
"Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, " +
|
"Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, " +
|
||||||
"Content-Type, Cookie, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, " +
|
"Content-Type, Cookie, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, " +
|
||||||
"Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, " +
|
"Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, " +
|
||||||
"X-Emby-Authorization");
|
"X-Emby-Authorization";
|
||||||
|
|
||||||
if (dto is Exception exception)
|
if (dto is Exception exception)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Authentication;
|
|
||||||
using Emby.Server.Implementations.SocketSharp;
|
using Emby.Server.Implementations.SocketSharp;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Controller.Authentication;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Controller.Security;
|
using MediaBrowser.Controller.Security;
|
||||||
|
@ -46,11 +46,27 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
|
|
||||||
public User Authenticate(HttpRequest request, IAuthenticationAttributes authAttributes)
|
public User Authenticate(HttpRequest request, IAuthenticationAttributes authAttributes)
|
||||||
{
|
{
|
||||||
var req = new WebSocketSharpRequest(request, null, request.Path, _logger);
|
var req = new WebSocketSharpRequest(request, null, request.Path);
|
||||||
var user = ValidateUser(req, authAttributes);
|
var user = ValidateUser(req, authAttributes);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AuthorizationInfo Authenticate(HttpRequest request)
|
||||||
|
{
|
||||||
|
var auth = _authorizationContext.GetAuthorizationInfo(request);
|
||||||
|
if (auth?.User == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auth.User.HasPermission(PermissionKind.IsDisabled))
|
||||||
|
{
|
||||||
|
throw new SecurityException("User account has been disabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return auth;
|
||||||
|
}
|
||||||
|
|
||||||
private User ValidateUser(IRequest request, IAuthenticationAttributes authAttribtues)
|
private User ValidateUser(IRequest request, IAuthenticationAttributes authAttribtues)
|
||||||
{
|
{
|
||||||
// This code is executed before the service
|
// This code is executed before the service
|
||||||
|
@ -140,6 +156,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authAttribtues.AllowLocalOnly && request.IsLocal)
|
if (authAttribtues.AllowLocalOnly && request.IsLocal)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -225,7 +242,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
throw new AuthenticationException("Access token is invalid or expired.");
|
throw new AuthenticationException("Access token is invalid or expired.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (!string.IsNullOrEmpty(info.UserId))
|
// if (!string.IsNullOrEmpty(info.UserId))
|
||||||
//{
|
//{
|
||||||
// var user = _userManager.GetUserById(info.UserId);
|
// var user = _userManager.GetUserById(info.UserId);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Controller.Security;
|
using MediaBrowser.Controller.Security;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.HttpServer.Security
|
namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
|
@ -38,6 +39,14 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
return GetAuthorization(requestContext);
|
return GetAuthorization(requestContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AuthorizationInfo GetAuthorizationInfo(HttpRequest requestContext)
|
||||||
|
{
|
||||||
|
var auth = GetAuthorizationDictionary(requestContext);
|
||||||
|
var (authInfo, _) =
|
||||||
|
GetAuthorizationInfoFromDictionary(auth, requestContext.Headers, requestContext.Query);
|
||||||
|
return authInfo;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authorization.
|
/// Gets the authorization.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -46,7 +55,23 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
private AuthorizationInfo GetAuthorization(IRequest httpReq)
|
private AuthorizationInfo GetAuthorization(IRequest httpReq)
|
||||||
{
|
{
|
||||||
var auth = GetAuthorizationDictionary(httpReq);
|
var auth = GetAuthorizationDictionary(httpReq);
|
||||||
|
var (authInfo, originalAuthInfo) =
|
||||||
|
GetAuthorizationInfoFromDictionary(auth, httpReq.Headers, httpReq.QueryString);
|
||||||
|
|
||||||
|
if (originalAuthInfo != null)
|
||||||
|
{
|
||||||
|
httpReq.Items["OriginalAuthenticationInfo"] = originalAuthInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpReq.Items["AuthorizationInfo"] = authInfo;
|
||||||
|
return authInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private (AuthorizationInfo authInfo, AuthenticationInfo originalAuthenticationInfo) GetAuthorizationInfoFromDictionary(
|
||||||
|
in Dictionary<string, string> auth,
|
||||||
|
in IHeaderDictionary headers,
|
||||||
|
in IQueryCollection queryString)
|
||||||
|
{
|
||||||
string deviceId = null;
|
string deviceId = null;
|
||||||
string device = null;
|
string device = null;
|
||||||
string client = null;
|
string client = null;
|
||||||
|
@ -64,19 +89,20 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(token))
|
if (string.IsNullOrEmpty(token))
|
||||||
{
|
{
|
||||||
token = httpReq.Headers["X-Emby-Token"];
|
token = headers["X-Emby-Token"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(token))
|
if (string.IsNullOrEmpty(token))
|
||||||
{
|
{
|
||||||
token = httpReq.Headers["X-MediaBrowser-Token"];
|
token = headers["X-MediaBrowser-Token"];
|
||||||
}
|
|
||||||
if (string.IsNullOrEmpty(token))
|
|
||||||
{
|
|
||||||
token = httpReq.QueryString["api_key"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var info = new AuthorizationInfo
|
if (string.IsNullOrEmpty(token))
|
||||||
|
{
|
||||||
|
token = queryString["api_key"];
|
||||||
|
}
|
||||||
|
|
||||||
|
var authInfo = new AuthorizationInfo
|
||||||
{
|
{
|
||||||
Client = client,
|
Client = client,
|
||||||
Device = device,
|
Device = device,
|
||||||
|
@ -85,6 +111,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
Token = token
|
Token = token
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AuthenticationInfo originalAuthenticationInfo = null;
|
||||||
if (!string.IsNullOrWhiteSpace(token))
|
if (!string.IsNullOrWhiteSpace(token))
|
||||||
{
|
{
|
||||||
var result = _authRepo.Get(new AuthenticationInfoQuery
|
var result = _authRepo.Get(new AuthenticationInfoQuery
|
||||||
|
@ -92,81 +119,77 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
AccessToken = token
|
AccessToken = token
|
||||||
});
|
});
|
||||||
|
|
||||||
var tokenInfo = result.Items.Count > 0 ? result.Items[0] : null;
|
originalAuthenticationInfo = result.Items.Count > 0 ? result.Items[0] : null;
|
||||||
|
|
||||||
if (tokenInfo != null)
|
if (originalAuthenticationInfo != null)
|
||||||
{
|
{
|
||||||
var updateToken = false;
|
var updateToken = false;
|
||||||
|
|
||||||
// TODO: Remove these checks for IsNullOrWhiteSpace
|
// TODO: Remove these checks for IsNullOrWhiteSpace
|
||||||
if (string.IsNullOrWhiteSpace(info.Client))
|
if (string.IsNullOrWhiteSpace(authInfo.Client))
|
||||||
{
|
{
|
||||||
info.Client = tokenInfo.AppName;
|
authInfo.Client = originalAuthenticationInfo.AppName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(info.DeviceId))
|
if (string.IsNullOrWhiteSpace(authInfo.DeviceId))
|
||||||
{
|
{
|
||||||
info.DeviceId = tokenInfo.DeviceId;
|
authInfo.DeviceId = originalAuthenticationInfo.DeviceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary. TODO - allow clients to specify that the token has been shared with a casting device
|
// Temporary. TODO - allow clients to specify that the token has been shared with a casting device
|
||||||
var allowTokenInfoUpdate = info.Client == null || info.Client.IndexOf("chromecast", StringComparison.OrdinalIgnoreCase) == -1;
|
var allowTokenInfoUpdate = authInfo.Client == null || authInfo.Client.IndexOf("chromecast", StringComparison.OrdinalIgnoreCase) == -1;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(info.Device))
|
if (string.IsNullOrWhiteSpace(authInfo.Device))
|
||||||
{
|
{
|
||||||
info.Device = tokenInfo.DeviceName;
|
authInfo.Device = originalAuthenticationInfo.DeviceName;
|
||||||
}
|
}
|
||||||
|
else if (!string.Equals(authInfo.Device, originalAuthenticationInfo.DeviceName, StringComparison.OrdinalIgnoreCase))
|
||||||
else if (!string.Equals(info.Device, tokenInfo.DeviceName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
if (allowTokenInfoUpdate)
|
if (allowTokenInfoUpdate)
|
||||||
{
|
{
|
||||||
updateToken = true;
|
updateToken = true;
|
||||||
tokenInfo.DeviceName = info.Device;
|
originalAuthenticationInfo.DeviceName = authInfo.Device;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(info.Version))
|
if (string.IsNullOrWhiteSpace(authInfo.Version))
|
||||||
{
|
{
|
||||||
info.Version = tokenInfo.AppVersion;
|
authInfo.Version = originalAuthenticationInfo.AppVersion;
|
||||||
}
|
}
|
||||||
else if (!string.Equals(info.Version, tokenInfo.AppVersion, StringComparison.OrdinalIgnoreCase))
|
else if (!string.Equals(authInfo.Version, originalAuthenticationInfo.AppVersion, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (allowTokenInfoUpdate)
|
if (allowTokenInfoUpdate)
|
||||||
{
|
{
|
||||||
updateToken = true;
|
updateToken = true;
|
||||||
tokenInfo.AppVersion = info.Version;
|
originalAuthenticationInfo.AppVersion = authInfo.Version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((DateTime.UtcNow - tokenInfo.DateLastActivity).TotalMinutes > 3)
|
if ((DateTime.UtcNow - originalAuthenticationInfo.DateLastActivity).TotalMinutes > 3)
|
||||||
{
|
{
|
||||||
tokenInfo.DateLastActivity = DateTime.UtcNow;
|
originalAuthenticationInfo.DateLastActivity = DateTime.UtcNow;
|
||||||
updateToken = true;
|
updateToken = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tokenInfo.UserId.Equals(Guid.Empty))
|
if (!originalAuthenticationInfo.UserId.Equals(Guid.Empty))
|
||||||
{
|
{
|
||||||
info.User = _userManager.GetUserById(tokenInfo.UserId);
|
authInfo.User = _userManager.GetUserById(originalAuthenticationInfo.UserId);
|
||||||
|
|
||||||
if (info.User != null && !string.Equals(info.User.Username, tokenInfo.UserName, StringComparison.OrdinalIgnoreCase))
|
if (authInfo.User != null && !string.Equals(authInfo.User.Username, originalAuthenticationInfo.UserName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
tokenInfo.UserName = info.User.Username;
|
originalAuthenticationInfo.UserName = authInfo.User.Username;
|
||||||
updateToken = true;
|
updateToken = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateToken)
|
if (updateToken)
|
||||||
{
|
{
|
||||||
_authRepo.Update(tokenInfo);
|
_authRepo.Update(originalAuthenticationInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
httpReq.Items["OriginalAuthenticationInfo"] = tokenInfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
httpReq.Items["AuthorizationInfo"] = info;
|
return (authInfo, originalAuthenticationInfo);
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -186,6 +209,23 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
return GetAuthorization(auth);
|
return GetAuthorization(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the auth.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpReq">The HTTP req.</param>
|
||||||
|
/// <returns>Dictionary{System.StringSystem.String}.</returns>
|
||||||
|
private Dictionary<string, string> GetAuthorizationDictionary(HttpRequest httpReq)
|
||||||
|
{
|
||||||
|
var auth = httpReq.Headers["X-Emby-Authorization"];
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(auth))
|
||||||
|
{
|
||||||
|
auth = httpReq.Headers[HeaderNames.Authorization];
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetAuthorization(auth);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authorization.
|
/// Gets the authorization.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger.
|
/// The logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<WebSocketConnection> _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The json serializer options.
|
/// The json serializer options.
|
||||||
|
@ -234,8 +234,10 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
private Task SendKeepAliveResponse()
|
private Task SendKeepAliveResponse()
|
||||||
{
|
{
|
||||||
LastKeepAliveDate = DateTime.UtcNow;
|
LastKeepAliveDate = DateTime.UtcNow;
|
||||||
return SendAsync(new WebSocketMessage<string>
|
return SendAsync(
|
||||||
|
new WebSocketMessage<string>
|
||||||
{
|
{
|
||||||
|
MessageId = Guid.NewGuid(),
|
||||||
MessageType = "KeepAlive"
|
MessageType = "KeepAlive"
|
||||||
}, CancellationToken.None);
|
}, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Emby.Server.Implementations.IO
|
||||||
{
|
{
|
||||||
public class LibraryMonitor : ILibraryMonitor
|
public class LibraryMonitor : ILibraryMonitor
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<LibraryMonitor> _logger;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IServerConfigurationManager _configurationManager;
|
private readonly IServerConfigurationManager _configurationManager;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
@ -266,7 +266,6 @@ namespace Emby.Server.Implementations.IO
|
||||||
{
|
{
|
||||||
DisposeWatcher(newWatcher, false);
|
DisposeWatcher(newWatcher, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -393,7 +392,6 @@ namespace Emby.Server.Implementations.IO
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
monitorPath = false;
|
monitorPath = false;
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Emby.Server.Implementations.IO
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ManagedFileSystem : IFileSystem
|
public class ManagedFileSystem : IFileSystem
|
||||||
{
|
{
|
||||||
protected ILogger Logger;
|
protected ILogger<ManagedFileSystem> Logger;
|
||||||
|
|
||||||
private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
|
private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
|
||||||
private readonly string _tempPath;
|
private readonly string _tempPath;
|
||||||
|
@ -237,7 +237,7 @@ namespace Emby.Server.Implementations.IO
|
||||||
{
|
{
|
||||||
result.IsDirectory = info is DirectoryInfo || (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory;
|
result.IsDirectory = info is DirectoryInfo || (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory;
|
||||||
|
|
||||||
//if (!result.IsDirectory)
|
// if (!result.IsDirectory)
|
||||||
//{
|
//{
|
||||||
// result.IsHidden = (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
|
// result.IsHidden = (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
|
||||||
//}
|
//}
|
||||||
|
@ -628,6 +628,7 @@ namespace Emby.Server.Implementations.IO
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
|
return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -682,6 +683,7 @@ namespace Emby.Server.Implementations.IO
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
|
return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,6 @@ namespace Emby.Server.Implementations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string RestartArgs { get; }
|
string RestartArgs { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the value of the --plugin-manifest-url command line option.
|
|
||||||
/// </summary>
|
|
||||||
string PluginManifestUrl { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the value of the --published-server-url command line option.
|
/// Gets the value of the --published-server-url command line option.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -71,7 +71,6 @@ namespace Emby.Server.Implementations.Images
|
||||||
new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)
|
new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)
|
||||||
},
|
},
|
||||||
IncludeItemTypes = includeItemTypes
|
IncludeItemTypes = includeItemTypes
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,6 @@ namespace Emby.Server.Implementations.Images
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
}).GroupBy(x => x.Id)
|
}).GroupBy(x => x.Id)
|
||||||
.Select(x => x.First());
|
.Select(x => x.First());
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ using MediaBrowser.Model.IO;
|
||||||
namespace Emby.Server.Implementations.Library
|
namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides the core resolver ignore rules
|
/// Provides the core resolver ignore rules.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CoreResolutionIgnoreRule : IResolverIgnoreRule
|
public class CoreResolutionIgnoreRule : IResolverIgnoreRule
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,11 +12,13 @@ namespace Emby.Server.Implementations.Library
|
||||||
public class ExclusiveLiveStream : ILiveStream
|
public class ExclusiveLiveStream : ILiveStream
|
||||||
{
|
{
|
||||||
public int ConsumerCount { get; set; }
|
public int ConsumerCount { get; set; }
|
||||||
|
|
||||||
public string OriginalStreamId { get; set; }
|
public string OriginalStreamId { get; set; }
|
||||||
|
|
||||||
public string TunerHostId => null;
|
public string TunerHostId => null;
|
||||||
|
|
||||||
public bool EnableStreamSharing { get; set; }
|
public bool EnableStreamSharing { get; set; }
|
||||||
|
|
||||||
public MediaSourceInfo MediaSource { get; set; }
|
public MediaSourceInfo MediaSource { get; set; }
|
||||||
|
|
||||||
public string UniqueId { get; private set; }
|
public string UniqueId { get; private set; }
|
||||||
|
|
|
@ -4,12 +4,12 @@ using DotNet.Globbing;
|
||||||
namespace Emby.Server.Implementations.Library
|
namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Glob patterns for files to ignore
|
/// Glob patterns for files to ignore.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class IgnorePatterns
|
public static class IgnorePatterns
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Files matching these glob patterns will be ignored
|
/// Files matching these glob patterns will be ignored.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string[] Patterns = new string[]
|
public static readonly string[] Patterns = new string[]
|
||||||
{
|
{
|
||||||
|
@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
private static readonly Glob[] _globs = Patterns.Select(p => Glob.Parse(p, _globOptions)).ToArray();
|
private static readonly Glob[] _globs = Patterns.Select(p => Glob.Parse(p, _globOptions)).ToArray();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns true if the supplied path should be ignored
|
/// Returns true if the supplied path should be ignored.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool ShouldIgnore(string path)
|
public static bool ShouldIgnore(string path)
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LibraryManager : ILibraryManager
|
public class LibraryManager : ILibraryManager
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<LibraryManager> _logger;
|
||||||
private readonly ITaskManager _taskManager;
|
private readonly ITaskManager _taskManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IUserDataManager _userDataRepository;
|
private readonly IUserDataManager _userDataRepository;
|
||||||
|
@ -97,13 +97,13 @@ namespace Emby.Server.Implementations.Library
|
||||||
private IIntroProvider[] IntroProviders { get; set; }
|
private IIntroProvider[] IntroProviders { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the list of entity resolution ignore rules
|
/// Gets or sets the list of entity resolution ignore rules.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The entity resolution ignore rules.</value>
|
/// <value>The entity resolution ignore rules.</value>
|
||||||
private IResolverIgnoreRule[] EntityResolutionIgnoreRules { get; set; }
|
private IResolverIgnoreRule[] EntityResolutionIgnoreRules { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the list of currently registered entity resolvers
|
/// Gets or sets the list of currently registered entity resolvers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The entity resolvers enumerable.</value>
|
/// <value>The entity resolvers enumerable.</value>
|
||||||
private IItemResolver[] EntityResolvers { get; set; }
|
private IItemResolver[] EntityResolvers { get; set; }
|
||||||
|
@ -136,7 +136,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="LibraryManager" /> class.
|
/// Initializes a new instance of the <see cref="LibraryManager" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="appHost">The application host</param>
|
/// <param name="appHost">The application host.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="taskManager">The task manager.</param>
|
/// <param name="taskManager">The task manager.</param>
|
||||||
/// <param name="userManager">The user manager.</param>
|
/// <param name="userManager">The user manager.</param>
|
||||||
|
@ -209,12 +209,12 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _root folder
|
/// The _root folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private volatile AggregateFolder _rootFolder;
|
private volatile AggregateFolder _rootFolder;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _root folder sync lock
|
/// The _root folder sync lock.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly object _rootFolderSyncLock = new object();
|
private readonly object _rootFolderSyncLock = new object();
|
||||||
|
|
||||||
|
@ -514,8 +514,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
return key.GetMD5();
|
return key.GetMD5();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null)
|
public BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null, bool allowIgnorePath = true)
|
||||||
=> ResolvePath(fileInfo, new DirectoryService(_fileSystem), null, parent);
|
=> ResolvePath(fileInfo, new DirectoryService(_fileSystem), null, parent, allowIgnorePath: allowIgnorePath);
|
||||||
|
|
||||||
private BaseItem ResolvePath(
|
private BaseItem ResolvePath(
|
||||||
FileSystemMetadata fileInfo,
|
FileSystemMetadata fileInfo,
|
||||||
|
@ -523,7 +523,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
IItemResolver[] resolvers,
|
IItemResolver[] resolvers,
|
||||||
Folder parent = null,
|
Folder parent = null,
|
||||||
string collectionType = null,
|
string collectionType = null,
|
||||||
LibraryOptions libraryOptions = null)
|
LibraryOptions libraryOptions = null,
|
||||||
|
bool allowIgnorePath = true)
|
||||||
{
|
{
|
||||||
if (fileInfo == null)
|
if (fileInfo == null)
|
||||||
{
|
{
|
||||||
|
@ -547,7 +548,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return null if ignore rules deem that we should do so
|
// Return null if ignore rules deem that we should do so
|
||||||
if (IgnoreFile(args.FileInfo, args.Parent))
|
if (allowIgnorePath && IgnoreFile(args.FileInfo, args.Parent))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -626,7 +627,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether a path should be ignored based on its contents - called after the contents have been read
|
/// Determines whether a path should be ignored based on its contents - called after the contents have been read.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">The args.</param>
|
/// <param name="args">The args.</param>
|
||||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||||
|
@ -711,7 +712,9 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
Directory.CreateDirectory(rootFolderPath);
|
Directory.CreateDirectory(rootFolderPath);
|
||||||
|
|
||||||
var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? ((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath))).DeepCopy<Folder, AggregateFolder>();
|
var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ??
|
||||||
|
((Folder) ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath), allowIgnorePath: false))
|
||||||
|
.DeepCopy<Folder, AggregateFolder>();
|
||||||
|
|
||||||
// In case program data folder was moved
|
// In case program data folder was moved
|
||||||
if (!string.Equals(rootFolder.Path, rootFolderPath, StringComparison.Ordinal))
|
if (!string.Equals(rootFolder.Path, rootFolderPath, StringComparison.Ordinal))
|
||||||
|
@ -792,7 +795,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
if (tmpItem == null)
|
if (tmpItem == null)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Creating new userRootFolder with DeepCopy");
|
_logger.LogDebug("Creating new userRootFolder with DeepCopy");
|
||||||
tmpItem = ((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(userRootPath))).DeepCopy<Folder, UserRootFolder>();
|
tmpItem = ((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(userRootPath), allowIgnorePath: false)).DeepCopy<Folder, UserRootFolder>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case program data folder was moved
|
// In case program data folder was moved
|
||||||
|
@ -906,7 +909,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Genre
|
/// Gets a Genre.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name.</param>
|
/// <param name="name">The name.</param>
|
||||||
/// <returns>Task{Genre}.</returns>
|
/// <returns>Task{Genre}.</returns>
|
||||||
|
@ -987,7 +990,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reloads the root media folder
|
/// Reloads the root media folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="progress">The progress.</param>
|
/// <param name="progress">The progress.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
@ -1790,7 +1793,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
/// Creates the items.
|
/// Creates the items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <param name="parent">The parent item</param>
|
/// <param name="parent">The parent item.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
public void CreateItems(IEnumerable<BaseItem> items, BaseItem parent, CancellationToken cancellationToken)
|
public void CreateItems(IEnumerable<BaseItem> items, BaseItem parent, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
@ -2592,7 +2595,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
Anime series don't generally have a season in their file name, however,
|
Anime series don't generally have a season in their file name, however,
|
||||||
tvdb needs a season to correctly get the metadata.
|
tvdb needs a season to correctly get the metadata.
|
||||||
Hence, a null season needs to be filled with something. */
|
Hence, a null season needs to be filled with something. */
|
||||||
//FIXME perhaps this would be better for tvdb parser to ask for season 1 if no season is specified
|
// FIXME perhaps this would be better for tvdb parser to ask for season 1 if no season is specified
|
||||||
episode.ParentIndexNumber = 1;
|
episode.ParentIndexNumber = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2781,10 +2784,12 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(path));
|
throw new ArgumentNullException(nameof(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(from))
|
if (string.IsNullOrWhiteSpace(from))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(from));
|
throw new ArgumentNullException(nameof(from));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(to))
|
if (string.IsNullOrWhiteSpace(to))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(to));
|
throw new ArgumentNullException(nameof(to));
|
||||||
|
@ -2858,7 +2863,6 @@ namespace Emby.Server.Implementations.Library
|
||||||
_logger.LogError(ex, "Error getting person");
|
_logger.LogError(ex, "Error getting person");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}).Where(i => i != null).ToList();
|
}).Where(i => i != null).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2893,7 +2897,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
|
if (ex.StatusCode.HasValue
|
||||||
|
&& (ex.StatusCode.Value == HttpStatusCode.NotFound || ex.StatusCode.Value == HttpStatusCode.Forbidden))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2988,7 +2993,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
private static bool ValidateNetworkPath(string path)
|
private static bool ValidateNetworkPath(string path)
|
||||||
{
|
{
|
||||||
//if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
// if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||||
//{
|
//{
|
||||||
// // We can't validate protocol-based paths, so just allow them
|
// // We can't validate protocol-based paths, so just allow them
|
||||||
// if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1)
|
// if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1)
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
mediaInfo = _json.DeserializeFromFile<MediaInfo>(cacheFilePath);
|
mediaInfo = _json.DeserializeFromFile<MediaInfo>(cacheFilePath);
|
||||||
|
|
||||||
//_logger.LogDebug("Found cached media info");
|
// _logger.LogDebug("Found cached media info");
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -85,7 +85,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
|
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
|
||||||
_json.SerializeToFile(mediaInfo, cacheFilePath);
|
_json.SerializeToFile(mediaInfo, cacheFilePath);
|
||||||
|
|
||||||
//_logger.LogDebug("Saved media info to {0}", cacheFilePath);
|
// _logger.LogDebug("Saved media info to {0}", cacheFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,17 +148,14 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
videoStream.BitRate = 30000000;
|
videoStream.BitRate = 30000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (width >= 1900)
|
else if (width >= 1900)
|
||||||
{
|
{
|
||||||
videoStream.BitRate = 20000000;
|
videoStream.BitRate = 20000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (width >= 1200)
|
else if (width >= 1200)
|
||||||
{
|
{
|
||||||
videoStream.BitRate = 8000000;
|
videoStream.BitRate = 8000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (width >= 700)
|
else if (width >= 700)
|
||||||
{
|
{
|
||||||
videoStream.BitRate = 2000000;
|
videoStream.BitRate = 2000000;
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<MediaSourceManager> _logger;
|
||||||
private readonly IUserDataManager _userDataManager;
|
private readonly IUserDataManager _userDataManager;
|
||||||
private readonly IMediaEncoder _mediaEncoder;
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
private readonly ILocalizationManager _localizationManager;
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
@ -205,22 +205,27 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
return MediaProtocol.Rtsp;
|
return MediaProtocol.Rtsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.StartsWith("Rtmp", StringComparison.OrdinalIgnoreCase))
|
if (path.StartsWith("Rtmp", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return MediaProtocol.Rtmp;
|
return MediaProtocol.Rtmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.StartsWith("Http", StringComparison.OrdinalIgnoreCase))
|
if (path.StartsWith("Http", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return MediaProtocol.Http;
|
return MediaProtocol.Http;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.StartsWith("rtp", StringComparison.OrdinalIgnoreCase))
|
if (path.StartsWith("rtp", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return MediaProtocol.Rtp;
|
return MediaProtocol.Rtp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.StartsWith("ftp", StringComparison.OrdinalIgnoreCase))
|
if (path.StartsWith("ftp", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return MediaProtocol.Ftp;
|
return MediaProtocol.Ftp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
|
if (path.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return MediaProtocol.Udp;
|
return MediaProtocol.Udp;
|
||||||
|
@ -436,7 +441,6 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
|
}).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
|
||||||
.ThenByDescending(i =>
|
.ThenByDescending(i =>
|
||||||
{
|
{
|
||||||
|
@ -620,7 +624,6 @@ namespace Emby.Server.Implementations.Library
|
||||||
MediaSource = mediaSource,
|
MediaSource = mediaSource,
|
||||||
ExtractChapters = false,
|
ExtractChapters = false,
|
||||||
MediaType = DlnaProfileType.Video
|
MediaType = DlnaProfileType.Video
|
||||||
|
|
||||||
}, cancellationToken).ConfigureAwait(false);
|
}, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
mediaSource.MediaStreams = info.MediaStreams;
|
mediaSource.MediaStreams = info.MediaStreams;
|
||||||
|
@ -646,7 +649,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
mediaInfo = _jsonSerializer.DeserializeFromFile<MediaInfo>(cacheFilePath);
|
mediaInfo = _jsonSerializer.DeserializeFromFile<MediaInfo>(cacheFilePath);
|
||||||
|
|
||||||
//_logger.LogDebug("Found cached media info");
|
// _logger.LogDebug("Found cached media info");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -682,7 +685,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
|
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
|
||||||
_jsonSerializer.SerializeToFile(mediaInfo, cacheFilePath);
|
_jsonSerializer.SerializeToFile(mediaInfo, cacheFilePath);
|
||||||
|
|
||||||
//_logger.LogDebug("Saved media info to {0}", cacheFilePath);
|
// _logger.LogDebug("Saved media info to {0}", cacheFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,17 +751,14 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
videoStream.BitRate = 30000000;
|
videoStream.BitRate = 30000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (width >= 1900)
|
else if (width >= 1900)
|
||||||
{
|
{
|
||||||
videoStream.BitRate = 20000000;
|
videoStream.BitRate = 20000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (width >= 1200)
|
else if (width >= 1200)
|
||||||
{
|
{
|
||||||
videoStream.BitRate = 8000000;
|
videoStream.BitRate = 8000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (width >= 700)
|
else if (width >= 700)
|
||||||
{
|
{
|
||||||
videoStream.BitRate = 2000000;
|
videoStream.BitRate = 2000000;
|
||||||
|
|
|
@ -107,7 +107,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ensures DateCreated and DateModified have values
|
/// Ensures DateCreated and DateModified have values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fileSystem">The file system.</param>
|
/// <param name="fileSystem">The file system.</param>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
|
|
|
@ -209,8 +209,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||||
Name = parseName ?
|
Name = parseName ?
|
||||||
resolvedItem.Name :
|
resolvedItem.Name :
|
||||||
Path.GetFileNameWithoutExtension(firstMedia.Path),
|
Path.GetFileNameWithoutExtension(firstMedia.Path),
|
||||||
//AdditionalParts = resolvedItem.Files.Skip(1).Select(i => i.Path).ToArray(),
|
// AdditionalParts = resolvedItem.Files.Skip(1).Select(i => i.Path).ToArray(),
|
||||||
//LocalAlternateVersions = resolvedItem.AlternateVersions.Select(i => i.Path).ToArray()
|
// LocalAlternateVersions = resolvedItem.AlternateVersions.Select(i => i.Path).ToArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
result.Items.Add(libraryItem);
|
result.Items.Add(libraryItem);
|
||||||
|
|
|
@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||||
// Args points to an album if parent is an Artist folder or it directly contains music
|
// Args points to an album if parent is an Artist folder or it directly contains music
|
||||||
if (args.IsDirectory)
|
if (args.IsDirectory)
|
||||||
{
|
{
|
||||||
// if (args.Parent is MusicArtist) return true; //saves us from testing children twice
|
// if (args.Parent is MusicArtist) return true; // saves us from testing children twice
|
||||||
if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, _libraryManager))
|
if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, _libraryManager))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -109,7 +109,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||||
IEnumerable<FileSystemMetadata> list,
|
IEnumerable<FileSystemMetadata> list,
|
||||||
bool allowSubfolders,
|
bool allowSubfolders,
|
||||||
IDirectoryService directoryService,
|
IDirectoryService directoryService,
|
||||||
ILogger logger,
|
ILogger<MusicAlbumResolver> logger,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
|
|
|
@ -292,7 +292,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
//var blurayExtensions = new[]
|
// var blurayExtensions = new[]
|
||||||
//{
|
//{
|
||||||
// ".mts",
|
// ".mts",
|
||||||
// ".m2ts",
|
// ".m2ts",
|
||||||
|
@ -300,7 +300,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
||||||
// ".mpls"
|
// ".mpls"
|
||||||
//};
|
//};
|
||||||
|
|
||||||
//return directoryService.GetFiles(fullPath).Any(i => blurayExtensions.Contains(i.Extension ?? string.Empty, StringComparer.OrdinalIgnoreCase));
|
// return directoryService.GetFiles(fullPath).Any(i => blurayExtensions.Contains(i.Extension ?? string.Empty, StringComparer.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books
|
||||||
|
|
||||||
// Only process items that are in a collection folder containing books
|
// Only process items that are in a collection folder containing books
|
||||||
if (!string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (args.IsDirectory)
|
if (args.IsDirectory)
|
||||||
{
|
{
|
||||||
|
@ -55,7 +57,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books
|
||||||
|
|
||||||
// Don't return a Book if there is more (or less) than one document in the directory
|
// Don't return a Book if there is more (or less) than one document in the directory
|
||||||
if (bookFiles.Count != 1)
|
if (bookFiles.Count != 1)
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return new Book
|
return new Book
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
||||||
public virtual ResolverPriority Priority => ResolverPriority.First;
|
public virtual ResolverPriority Priority => ResolverPriority.First;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets initial values on the newly resolved item
|
/// Sets initial values on the newly resolved item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <param name="args">The args.</param>
|
/// <param name="args">The args.</param>
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(id))
|
if (!string.IsNullOrEmpty(id))
|
||||||
{
|
{
|
||||||
item.SetProviderId(MetadataProviders.Tmdb, id);
|
item.SetProviderId(MetadataProvider.Tmdb, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,7 +350,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(tmdbid))
|
if (!string.IsNullOrWhiteSpace(tmdbid))
|
||||||
{
|
{
|
||||||
item.SetProviderId(MetadataProviders.Tmdb, tmdbid);
|
item.SetProviderId(MetadataProvider.Tmdb, tmdbid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +361,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(imdbid))
|
if (!string.IsNullOrWhiteSpace(imdbid))
|
||||||
{
|
{
|
||||||
item.SetProviderId(MetadataProviders.Imdb, imdbid);
|
item.SetProviderId(MetadataProvider.Imdb, imdbid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,10 +41,12 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
||||||
{
|
{
|
||||||
return new AggregateFolder();
|
return new AggregateFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(args.Path, _appPaths.DefaultUserViewsPath, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(args.Path, _appPaths.DefaultUserViewsPath, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return new UserRootFolder(); //if we got here and still a root - must be user root
|
return new UserRootFolder(); // if we got here and still a root - must be user root
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.IsVf)
|
if (args.IsVf)
|
||||||
{
|
{
|
||||||
return new CollectionFolder
|
return new CollectionFolder
|
||||||
|
@ -73,7 +75,6 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
.Select(i => _fileSystem.GetFileNameWithoutExtension(i))
|
.Select(i => _fileSystem.GetFileNameWithoutExtension(i))
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
|
@ -55,6 +55,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||||
episode.SeriesId = series.Id;
|
episode.SeriesId = series.Id;
|
||||||
episode.SeriesName = series.Name;
|
episode.SeriesName = series.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (season != null)
|
if (season != null)
|
||||||
{
|
{
|
||||||
episode.SeasonId = season.Id;
|
episode.SeasonId = season.Id;
|
||||||
|
|
|
@ -16,15 +16,15 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<SeasonResolver> _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SeasonResolver"/> class.
|
/// Initializes a new instance of the <see cref="SeasonResolver"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="config">The config.</param>
|
/// <param name="config">The config.</param>
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="localization">The localization</param>
|
/// <param name="localization">The localization.</param>
|
||||||
/// <param name="logger">The logger</param>
|
/// <param name="logger">The logger.</param>
|
||||||
public SeasonResolver(
|
public SeasonResolver(
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
|
@ -94,7 +94,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||||
_localization.GetLocalizedString("NameSeasonNumber"),
|
_localization.GetLocalizedString("NameSeasonNumber"),
|
||||||
seasonNumber,
|
seasonNumber,
|
||||||
args.GetLibraryOptions().PreferredMetadataLanguage);
|
args.GetLibraryOptions().PreferredMetadataLanguage);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return season;
|
return season;
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||||
public class SeriesResolver : FolderResolver<Series>
|
public class SeriesResolver : FolderResolver<Series>
|
||||||
{
|
{
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<SeriesResolver> _logger;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||||
var collectionType = args.GetCollectionType();
|
var collectionType = args.GetCollectionType();
|
||||||
if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
//if (args.ContainsFileSystemEntryByName("tvshow.nfo"))
|
// if (args.ContainsFileSystemEntryByName("tvshow.nfo"))
|
||||||
//{
|
//{
|
||||||
// return new Series
|
// return new Series
|
||||||
// {
|
// {
|
||||||
|
@ -119,7 +119,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||||
IEnumerable<FileSystemMetadata> fileSystemChildren,
|
IEnumerable<FileSystemMetadata> fileSystemChildren,
|
||||||
IDirectoryService directoryService,
|
IDirectoryService directoryService,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILogger logger,
|
ILogger<SeriesResolver> logger,
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
bool isTvContentType)
|
bool isTvContentType)
|
||||||
{
|
{
|
||||||
|
@ -217,7 +217,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(id))
|
if (!string.IsNullOrEmpty(id))
|
||||||
{
|
{
|
||||||
item.SetProviderId(MetadataProviders.Tvdb, id);
|
item.SetProviderId(MetadataProvider.Tvdb, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
public class SearchEngine : ISearchEngine
|
public class SearchEngine : ISearchEngine
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<SearchEngine> _logger;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
|
|
||||||
|
@ -194,6 +194,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
searchQuery.AncestorIds = new[] { searchQuery.ParentId };
|
searchQuery.AncestorIds = new[] { searchQuery.ParentId };
|
||||||
}
|
}
|
||||||
|
|
||||||
searchQuery.ParentId = Guid.Empty;
|
searchQuery.ParentId = Guid.Empty;
|
||||||
searchQuery.IncludeItemsByName = true;
|
searchQuery.IncludeItemsByName = true;
|
||||||
searchQuery.IncludeItemTypes = Array.Empty<string>();
|
searchQuery.IncludeItemTypes = Array.Empty<string>();
|
||||||
|
@ -207,7 +208,6 @@ namespace Emby.Server.Implementations.Library
|
||||||
return mediaItems.Select(i => new SearchHintInfo
|
return mediaItems.Select(i => new SearchHintInfo
|
||||||
{
|
{
|
||||||
Item = i
|
Item = i
|
||||||
|
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Book = MediaBrowser.Controller.Entities.Book;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Library
|
namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
|
@ -27,7 +28,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
private readonly ConcurrentDictionary<string, UserItemData> _userData =
|
private readonly ConcurrentDictionary<string, UserItemData> _userData =
|
||||||
new ConcurrentDictionary<string, UserItemData>(StringComparer.OrdinalIgnoreCase);
|
new ConcurrentDictionary<string, UserItemData>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<UserDataManager> _logger;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IUserDataRepository _repository;
|
private readonly IUserDataRepository _repository;
|
||||||
|
@ -102,7 +103,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieve all user data for the given user
|
/// Retrieve all user data for the given user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId"></param>
|
/// <param name="userId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
@ -187,7 +188,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts a UserItemData to a DTOUserItemData
|
/// Converts a UserItemData to a DTOUserItemData.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data">The data.</param>
|
/// <param name="data">The data.</param>
|
||||||
/// <returns>DtoUserItemData.</returns>
|
/// <returns>DtoUserItemData.</returns>
|
||||||
|
@ -241,7 +242,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
// Enforce MinResumeDuration
|
// Enforce MinResumeDuration
|
||||||
var durationSeconds = TimeSpan.FromTicks(runtimeTicks).TotalSeconds;
|
var durationSeconds = TimeSpan.FromTicks(runtimeTicks).TotalSeconds;
|
||||||
if (durationSeconds < _config.Configuration.MinResumeDurationSeconds)
|
if (durationSeconds < _config.Configuration.MinResumeDurationSeconds && !(item is Book))
|
||||||
{
|
{
|
||||||
positionTicks = 0;
|
positionTicks = 0;
|
||||||
data.Played = playedToCompletion = true;
|
data.Played = playedToCompletion = true;
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// The _library manager.
|
/// The _library manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<ArtistsValidator> _logger;
|
||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public ArtistsPostScanTask(
|
public ArtistsPostScanTask(
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
ILogger<ArtistsPostScanTask> logger,
|
ILogger<ArtistsValidator> logger,
|
||||||
IItemRepository itemRepo)
|
IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger.
|
/// The logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<ArtistsValidator> _logger;
|
||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -33,7 +33,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public ArtistsValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
public ArtistsValidator(ILibraryManager libraryManager, ILogger<ArtistsValidator> logger, IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -98,7 +98,6 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
_libraryManager.DeleteItem(item, new DeleteOptions
|
_libraryManager.DeleteItem(item, new DeleteOptions
|
||||||
{
|
{
|
||||||
DeleteFileLocation = false
|
DeleteFileLocation = false
|
||||||
|
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// The _library manager.
|
/// The _library manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<GenresValidator> _logger;
|
||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public GenresPostScanTask(
|
public GenresPostScanTask(
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
ILogger<GenresPostScanTask> logger,
|
ILogger<GenresValidator> logger,
|
||||||
IItemRepository itemRepo)
|
IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger.
|
/// The logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<GenresValidator> _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="GenresValidator"/> class.
|
/// Initializes a new instance of the <see cref="GenresValidator"/> class.
|
||||||
|
@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public GenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
public GenresValidator(ILibraryManager libraryManager, ILogger<GenresValidator> logger, IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// The library manager.
|
/// The library manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<MusicGenresValidator> _logger;
|
||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public MusicGenresPostScanTask(
|
public MusicGenresPostScanTask(
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
ILogger<MusicGenresPostScanTask> logger,
|
ILogger<MusicGenresValidator> logger,
|
||||||
IItemRepository itemRepo)
|
IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger.
|
/// The logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<MusicGenresValidator> _logger;
|
||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public MusicGenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
public MusicGenresValidator(ILibraryManager libraryManager, ILogger<MusicGenresValidator> logger, IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<StudiosValidator> _logger;
|
||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public StudiosPostScanTask(
|
public StudiosPostScanTask(
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
ILogger<StudiosPostScanTask> logger,
|
ILogger<StudiosValidator> logger,
|
||||||
IItemRepository itemRepo)
|
IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger.
|
/// The logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<StudiosValidator> _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="StudiosValidator" /> class.
|
/// Initializes a new instance of the <see cref="StudiosValidator" /> class.
|
||||||
|
@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public StudiosValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
public StudiosValidator(ILibraryManager libraryManager, ILogger<StudiosValidator> logger, IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -92,7 +92,6 @@ namespace Emby.Server.Implementations.Library.Validators
|
||||||
_libraryManager.DeleteItem(item, new DeleteOptions
|
_libraryManager.DeleteItem(item, new DeleteOptions
|
||||||
{
|
{
|
||||||
DeleteFileLocation = false
|
DeleteFileLocation = false
|
||||||
|
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
private const int TunerDiscoveryDurationMs = 3000;
|
private const int TunerDiscoveryDurationMs = 3000;
|
||||||
|
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger<EmbyTV> _logger;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
|
@ -1547,7 +1547,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
IsFolder = false,
|
IsFolder = false,
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
DtoOptions = new DtoOptions(true)
|
DtoOptions = new DtoOptions(true)
|
||||||
|
|
||||||
})
|
})
|
||||||
.Where(i => i.IsFileProtocol && File.Exists(i.Path))
|
.Where(i => i.IsFileProtocol && File.Exists(i.Path))
|
||||||
.Skip(seriesTimer.KeepUpTo - 1)
|
.Skip(seriesTimer.KeepUpTo - 1)
|
||||||
|
@ -1893,22 +1892,22 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
writer.WriteStartDocument(true);
|
writer.WriteStartDocument(true);
|
||||||
writer.WriteStartElement("tvshow");
|
writer.WriteStartElement("tvshow");
|
||||||
string id;
|
string id;
|
||||||
if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id))
|
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), out id))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("id", id);
|
writer.WriteElementString("id", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id))
|
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out id))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("imdb_id", id);
|
writer.WriteElementString("imdb_id", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Tmdb.ToString(), out id))
|
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tmdb.ToString(), out id))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("tmdbid", id);
|
writer.WriteElementString("tmdbid", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Zap2It.ToString(), out id))
|
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Zap2It.ToString(), out id))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("zap2itid", id);
|
writer.WriteElementString("zap2itid", id);
|
||||||
}
|
}
|
||||||
|
@ -2075,14 +2074,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
writer.WriteElementString("credits", person);
|
writer.WriteElementString("credits", person);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tmdbCollection = item.GetProviderId(MetadataProviders.TmdbCollection);
|
var tmdbCollection = item.GetProviderId(MetadataProvider.TmdbCollection);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tmdbCollection))
|
if (!string.IsNullOrEmpty(tmdbCollection))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("collectionnumber", tmdbCollection);
|
writer.WriteElementString("collectionnumber", tmdbCollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
var imdb = item.GetProviderId(MetadataProviders.Imdb);
|
var imdb = item.GetProviderId(MetadataProvider.Imdb);
|
||||||
if (!string.IsNullOrEmpty(imdb))
|
if (!string.IsNullOrEmpty(imdb))
|
||||||
{
|
{
|
||||||
if (!isSeriesEpisode)
|
if (!isSeriesEpisode)
|
||||||
|
@ -2096,7 +2095,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
lockData = false;
|
lockData = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tvdb = item.GetProviderId(MetadataProviders.Tvdb);
|
var tvdb = item.GetProviderId(MetadataProvider.Tvdb);
|
||||||
if (!string.IsNullOrEmpty(tvdb))
|
if (!string.IsNullOrEmpty(tvdb))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("tvdbid", tvdb);
|
writer.WriteElementString("tvdbid", tvdb);
|
||||||
|
@ -2105,7 +2104,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
lockData = false;
|
lockData = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tmdb = item.GetProviderId(MetadataProviders.Tmdb);
|
var tmdb = item.GetProviderId(MetadataProvider.Tmdb);
|
||||||
if (!string.IsNullOrEmpty(tmdb))
|
if (!string.IsNullOrEmpty(tmdb))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("tmdbid", tmdb);
|
writer.WriteElementString("tmdbid", tmdb);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user