mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-07 11:57:55 +02:00
commit
5b55997984
127 changed files with 819 additions and 7031 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
@ -10,7 +10,7 @@
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "build",
|
"preLaunchTask": "build",
|
||||||
// If you have changed target frameworks, make sure to update the program path.
|
// If you have changed target frameworks, make sure to update the program path.
|
||||||
"program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/netcoreapp3.0/jellyfin.dll",
|
"program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/netcoreapp3.1/jellyfin.dll",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}/Jellyfin.Server",
|
"cwd": "${workspaceFolder}/Jellyfin.Server",
|
||||||
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
|
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\SharedVersion.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
|
@ -1,33 +0,0 @@
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
class BDInfoSettings
|
|
||||||
{
|
|
||||||
public static bool GenerateStreamDiagnostics => true;
|
|
||||||
|
|
||||||
public static bool EnableSSIF => true;
|
|
||||||
|
|
||||||
public static bool AutosaveReport => false;
|
|
||||||
|
|
||||||
public static bool GenerateFrameDataFile => false;
|
|
||||||
|
|
||||||
public static bool FilterLoopingPlaylists => true;
|
|
||||||
|
|
||||||
public static bool FilterShortPlaylists => false;
|
|
||||||
|
|
||||||
public static int FilterShortPlaylistsValue => 0;
|
|
||||||
|
|
||||||
public static bool UseImagePrefix => false;
|
|
||||||
|
|
||||||
public static string UseImagePrefixValue => null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Setting this to false throws an IComparer error on some discs.
|
|
||||||
/// </summary>
|
|
||||||
public static bool KeepStreamOrder => true;
|
|
||||||
|
|
||||||
public static bool GenerateTextSummary => false;
|
|
||||||
|
|
||||||
public static string LastPath => string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
449
BDInfo/BDROM.cs
449
BDInfo/BDROM.cs
|
@ -1,449 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public class BDROM
|
|
||||||
{
|
|
||||||
public FileSystemMetadata DirectoryRoot = null;
|
|
||||||
public FileSystemMetadata DirectoryBDMV = null;
|
|
||||||
public FileSystemMetadata DirectoryBDJO = null;
|
|
||||||
public FileSystemMetadata DirectoryCLIPINF = null;
|
|
||||||
public FileSystemMetadata DirectoryPLAYLIST = null;
|
|
||||||
public FileSystemMetadata DirectorySNP = null;
|
|
||||||
public FileSystemMetadata DirectorySSIF = null;
|
|
||||||
public FileSystemMetadata DirectorySTREAM = null;
|
|
||||||
|
|
||||||
public string VolumeLabel = null;
|
|
||||||
public ulong Size = 0;
|
|
||||||
public bool IsBDPlus = false;
|
|
||||||
public bool IsBDJava = false;
|
|
||||||
public bool IsDBOX = false;
|
|
||||||
public bool IsPSP = false;
|
|
||||||
public bool Is3D = false;
|
|
||||||
public bool Is50Hz = false;
|
|
||||||
|
|
||||||
private readonly IFileSystem _fileSystem;
|
|
||||||
|
|
||||||
public Dictionary<string, TSPlaylistFile> PlaylistFiles =
|
|
||||||
new Dictionary<string, TSPlaylistFile>();
|
|
||||||
public Dictionary<string, TSStreamClipFile> StreamClipFiles =
|
|
||||||
new Dictionary<string, TSStreamClipFile>();
|
|
||||||
public Dictionary<string, TSStreamFile> StreamFiles =
|
|
||||||
new Dictionary<string, TSStreamFile>();
|
|
||||||
public Dictionary<string, TSInterleavedFile> InterleavedFiles =
|
|
||||||
new Dictionary<string, TSInterleavedFile>();
|
|
||||||
|
|
||||||
public delegate bool OnStreamClipFileScanError(
|
|
||||||
TSStreamClipFile streamClipFile, Exception ex);
|
|
||||||
|
|
||||||
public event OnStreamClipFileScanError StreamClipFileScanError;
|
|
||||||
|
|
||||||
public delegate bool OnStreamFileScanError(
|
|
||||||
TSStreamFile streamClipFile, Exception ex);
|
|
||||||
|
|
||||||
public event OnStreamFileScanError StreamFileScanError;
|
|
||||||
|
|
||||||
public delegate bool OnPlaylistFileScanError(
|
|
||||||
TSPlaylistFile playlistFile, Exception ex);
|
|
||||||
|
|
||||||
public event OnPlaylistFileScanError PlaylistFileScanError;
|
|
||||||
|
|
||||||
public BDROM(string path, IFileSystem fileSystem)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(path))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
_fileSystem = fileSystem;
|
|
||||||
//
|
|
||||||
// Locate BDMV directories.
|
|
||||||
//
|
|
||||||
|
|
||||||
DirectoryBDMV =
|
|
||||||
GetDirectoryBDMV(path);
|
|
||||||
|
|
||||||
if (DirectoryBDMV == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Unable to locate BD structure.");
|
|
||||||
}
|
|
||||||
|
|
||||||
DirectoryRoot =
|
|
||||||
_fileSystem.GetDirectoryInfo(Path.GetDirectoryName(DirectoryBDMV.FullName));
|
|
||||||
DirectoryBDJO =
|
|
||||||
GetDirectory("BDJO", DirectoryBDMV, 0);
|
|
||||||
DirectoryCLIPINF =
|
|
||||||
GetDirectory("CLIPINF", DirectoryBDMV, 0);
|
|
||||||
DirectoryPLAYLIST =
|
|
||||||
GetDirectory("PLAYLIST", DirectoryBDMV, 0);
|
|
||||||
DirectorySNP =
|
|
||||||
GetDirectory("SNP", DirectoryRoot, 0);
|
|
||||||
DirectorySTREAM =
|
|
||||||
GetDirectory("STREAM", DirectoryBDMV, 0);
|
|
||||||
DirectorySSIF =
|
|
||||||
GetDirectory("SSIF", DirectorySTREAM, 0);
|
|
||||||
|
|
||||||
if (DirectoryCLIPINF == null
|
|
||||||
|| DirectoryPLAYLIST == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Unable to locate BD structure.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize basic disc properties.
|
|
||||||
//
|
|
||||||
|
|
||||||
VolumeLabel = GetVolumeLabel(DirectoryRoot);
|
|
||||||
Size = (ulong)GetDirectorySize(DirectoryRoot);
|
|
||||||
|
|
||||||
if (null != GetDirectory("BDSVM", DirectoryRoot, 0))
|
|
||||||
{
|
|
||||||
IsBDPlus = true;
|
|
||||||
}
|
|
||||||
if (null != GetDirectory("SLYVM", DirectoryRoot, 0))
|
|
||||||
{
|
|
||||||
IsBDPlus = true;
|
|
||||||
}
|
|
||||||
if (null != GetDirectory("ANYVM", DirectoryRoot, 0))
|
|
||||||
{
|
|
||||||
IsBDPlus = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DirectoryBDJO != null &&
|
|
||||||
_fileSystem.GetFilePaths(DirectoryBDJO.FullName).Any())
|
|
||||||
{
|
|
||||||
IsBDJava = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DirectorySNP != null &&
|
|
||||||
GetFilePaths(DirectorySNP.FullName, ".mnv").Any())
|
|
||||||
{
|
|
||||||
IsPSP = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DirectorySSIF != null &&
|
|
||||||
_fileSystem.GetFilePaths(DirectorySSIF.FullName).Any())
|
|
||||||
{
|
|
||||||
Is3D = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (File.Exists(Path.Combine(DirectoryRoot.FullName, "FilmIndex.xml")))
|
|
||||||
{
|
|
||||||
IsDBOX = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize file lists.
|
|
||||||
//
|
|
||||||
|
|
||||||
if (DirectoryPLAYLIST != null)
|
|
||||||
{
|
|
||||||
FileSystemMetadata[] files = GetFiles(DirectoryPLAYLIST.FullName, ".mpls").ToArray();
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
PlaylistFiles.Add(
|
|
||||||
file.Name.ToUpper(), new TSPlaylistFile(this, file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DirectorySTREAM != null)
|
|
||||||
{
|
|
||||||
FileSystemMetadata[] files = GetFiles(DirectorySTREAM.FullName, ".m2ts").ToArray();
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
StreamFiles.Add(
|
|
||||||
file.Name.ToUpper(), new TSStreamFile(file, _fileSystem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DirectoryCLIPINF != null)
|
|
||||||
{
|
|
||||||
FileSystemMetadata[] files = GetFiles(DirectoryCLIPINF.FullName, ".clpi").ToArray();
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
StreamClipFiles.Add(
|
|
||||||
file.Name.ToUpper(), new TSStreamClipFile(file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DirectorySSIF != null)
|
|
||||||
{
|
|
||||||
FileSystemMetadata[] files = GetFiles(DirectorySSIF.FullName, ".ssif").ToArray();
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
InterleavedFiles.Add(
|
|
||||||
file.Name.ToUpper(), new TSInterleavedFile(file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<FileSystemMetadata> GetFiles(string path, string extension)
|
|
||||||
{
|
|
||||||
return _fileSystem.GetFiles(path, new[] { extension }, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<string> GetFilePaths(string path, string extension)
|
|
||||||
{
|
|
||||||
return _fileSystem.GetFilePaths(path, new[] { extension }, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Scan()
|
|
||||||
{
|
|
||||||
foreach (var streamClipFile in StreamClipFiles.Values)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
streamClipFile.Scan();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (StreamClipFileScanError != null)
|
|
||||||
{
|
|
||||||
if (StreamClipFileScanError(streamClipFile, ex))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var streamFile in StreamFiles.Values)
|
|
||||||
{
|
|
||||||
string ssifName = Path.GetFileNameWithoutExtension(streamFile.Name) + ".SSIF";
|
|
||||||
if (InterleavedFiles.ContainsKey(ssifName))
|
|
||||||
{
|
|
||||||
streamFile.InterleavedFile = InterleavedFiles[ssifName];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TSStreamFile[] streamFiles = new TSStreamFile[StreamFiles.Count];
|
|
||||||
StreamFiles.Values.CopyTo(streamFiles, 0);
|
|
||||||
Array.Sort(streamFiles, CompareStreamFiles);
|
|
||||||
|
|
||||||
foreach (var playlistFile in PlaylistFiles.Values)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
playlistFile.Scan(StreamFiles, StreamClipFiles);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (PlaylistFileScanError != null)
|
|
||||||
{
|
|
||||||
if (PlaylistFileScanError(playlistFile, ex))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var streamFile in streamFiles)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var playlists = new List<TSPlaylistFile>();
|
|
||||||
foreach (var playlist in PlaylistFiles.Values)
|
|
||||||
{
|
|
||||||
foreach (var streamClip in playlist.StreamClips)
|
|
||||||
{
|
|
||||||
if (streamClip.Name == streamFile.Name)
|
|
||||||
{
|
|
||||||
playlists.Add(playlist);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
streamFile.Scan(playlists, false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (StreamFileScanError != null)
|
|
||||||
{
|
|
||||||
if (StreamFileScanError(streamFile, ex))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var playlistFile in PlaylistFiles.Values)
|
|
||||||
{
|
|
||||||
playlistFile.Initialize();
|
|
||||||
if (!Is50Hz)
|
|
||||||
{
|
|
||||||
foreach (var videoStream in playlistFile.VideoStreams)
|
|
||||||
{
|
|
||||||
if (videoStream.FrameRate == TSFrameRate.FRAMERATE_25 ||
|
|
||||||
videoStream.FrameRate == TSFrameRate.FRAMERATE_50)
|
|
||||||
{
|
|
||||||
Is50Hz = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private FileSystemMetadata GetDirectoryBDMV(
|
|
||||||
string path)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(path))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
FileSystemMetadata dir = _fileSystem.GetDirectoryInfo(path);
|
|
||||||
|
|
||||||
while (dir != null)
|
|
||||||
{
|
|
||||||
if (string.Equals(dir.Name, "BDMV", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
var parentFolder = Path.GetDirectoryName(dir.FullName);
|
|
||||||
if (string.IsNullOrEmpty(parentFolder))
|
|
||||||
{
|
|
||||||
dir = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dir = _fileSystem.GetDirectoryInfo(parentFolder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetDirectory("BDMV", _fileSystem.GetDirectoryInfo(path), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private FileSystemMetadata GetDirectory(
|
|
||||||
string name,
|
|
||||||
FileSystemMetadata dir,
|
|
||||||
int searchDepth)
|
|
||||||
{
|
|
||||||
if (dir != null)
|
|
||||||
{
|
|
||||||
FileSystemMetadata[] children = _fileSystem.GetDirectories(dir.FullName).ToArray();
|
|
||||||
foreach (var child in children)
|
|
||||||
{
|
|
||||||
if (string.Equals(child.Name, name, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (searchDepth > 0)
|
|
||||||
{
|
|
||||||
foreach (var child in children)
|
|
||||||
{
|
|
||||||
GetDirectory(
|
|
||||||
name, child, searchDepth - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long GetDirectorySize(FileSystemMetadata directoryInfo)
|
|
||||||
{
|
|
||||||
long size = 0;
|
|
||||||
|
|
||||||
//if (!ExcludeDirs.Contains(directoryInfo.Name.ToUpper())) // TODO: Keep?
|
|
||||||
{
|
|
||||||
FileSystemMetadata[] pathFiles = _fileSystem.GetFiles(directoryInfo.FullName).ToArray();
|
|
||||||
foreach (var pathFile in pathFiles)
|
|
||||||
{
|
|
||||||
if (pathFile.Extension.ToUpper() == ".SSIF")
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
size += pathFile.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileSystemMetadata[] pathChildren = _fileSystem.GetDirectories(directoryInfo.FullName).ToArray();
|
|
||||||
foreach (var pathChild in pathChildren)
|
|
||||||
{
|
|
||||||
size += GetDirectorySize(pathChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetVolumeLabel(FileSystemMetadata dir)
|
|
||||||
{
|
|
||||||
return dir.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CompareStreamFiles(
|
|
||||||
TSStreamFile x,
|
|
||||||
TSStreamFile y)
|
|
||||||
{
|
|
||||||
// TODO: Use interleaved file sizes
|
|
||||||
|
|
||||||
if ((x == null || x.FileInfo == null) && (y == null || y.FileInfo == null))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if ((x == null || x.FileInfo == null) && (y != null && y.FileInfo != null))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if ((x != null && x.FileInfo != null) && (y == null || y.FileInfo == null))
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (x.FileInfo.Length > y.FileInfo.Length)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (y.FileInfo.Length > x.FileInfo.Length)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,493 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public abstract class LanguageCodes
|
|
||||||
{
|
|
||||||
public static string GetName(string code)
|
|
||||||
{
|
|
||||||
switch (code)
|
|
||||||
{
|
|
||||||
case "abk": return "Abkhazian";
|
|
||||||
case "ace": return "Achinese";
|
|
||||||
case "ach": return "Acoli";
|
|
||||||
case "ada": return "Adangme";
|
|
||||||
case "aar": return "Afar";
|
|
||||||
case "afh": return "Afrihili";
|
|
||||||
case "afr": return "Afrikaans";
|
|
||||||
case "afa": return "Afro-Asiatic (Other)";
|
|
||||||
case "aka": return "Akan";
|
|
||||||
case "akk": return "Akkadian";
|
|
||||||
case "alb": return "Albanian";
|
|
||||||
case "sqi": return "Albanian";
|
|
||||||
case "ale": return "Aleut";
|
|
||||||
case "alg": return "Algonquian languages";
|
|
||||||
case "tut": return "Altaic (Other)";
|
|
||||||
case "amh": return "Amharic";
|
|
||||||
case "apa": return "Apache languages";
|
|
||||||
case "ara": return "Arabic";
|
|
||||||
case "arc": return "Aramaic";
|
|
||||||
case "arp": return "Arapaho";
|
|
||||||
case "arn": return "Araucanian";
|
|
||||||
case "arw": return "Arawak";
|
|
||||||
case "arm": return "Armenian";
|
|
||||||
case "hye": return "Armenian";
|
|
||||||
case "art": return "Artificial (Other)";
|
|
||||||
case "asm": return "Assamese";
|
|
||||||
case "ath": return "Athapascan languages";
|
|
||||||
case "aus": return "Australian languages";
|
|
||||||
case "map": return "Austronesian (Other)";
|
|
||||||
case "ava": return "Avaric";
|
|
||||||
case "ave": return "Avestan";
|
|
||||||
case "awa": return "Awadhi";
|
|
||||||
case "aym": return "Aymara";
|
|
||||||
case "aze": return "Azerbaijani";
|
|
||||||
case "ban": return "Balinese";
|
|
||||||
case "bat": return "Baltic (Other)";
|
|
||||||
case "bal": return "Baluchi";
|
|
||||||
case "bam": return "Bambara";
|
|
||||||
case "bai": return "Bamileke languages";
|
|
||||||
case "bad": return "Banda";
|
|
||||||
case "bnt": return "Bantu (Other)";
|
|
||||||
case "bas": return "Basa";
|
|
||||||
case "bak": return "Bashkir";
|
|
||||||
case "baq": return "Basque";
|
|
||||||
case "eus": return "Basque";
|
|
||||||
case "btk": return "Batak (Indonesia)";
|
|
||||||
case "bej": return "Beja";
|
|
||||||
case "bel": return "Belarusian";
|
|
||||||
case "bem": return "Bemba";
|
|
||||||
case "ben": return "Bengali";
|
|
||||||
case "ber": return "Berber (Other)";
|
|
||||||
case "bho": return "Bhojpuri";
|
|
||||||
case "bih": return "Bihari";
|
|
||||||
case "bik": return "Bikol";
|
|
||||||
case "bin": return "Bini";
|
|
||||||
case "bis": return "Bislama";
|
|
||||||
case "bos": return "Bosnian";
|
|
||||||
case "bra": return "Braj";
|
|
||||||
case "bre": return "Breton";
|
|
||||||
case "bug": return "Buginese";
|
|
||||||
case "bul": return "Bulgarian";
|
|
||||||
case "bua": return "Buriat";
|
|
||||||
case "bur": return "Burmese";
|
|
||||||
case "mya": return "Burmese";
|
|
||||||
case "cad": return "Caddo";
|
|
||||||
case "car": return "Carib";
|
|
||||||
case "cat": return "Catalan";
|
|
||||||
case "cau": return "Caucasian (Other)";
|
|
||||||
case "ceb": return "Cebuano";
|
|
||||||
case "cel": return "Celtic (Other)";
|
|
||||||
case "cai": return "Central American Indian (Other)";
|
|
||||||
case "chg": return "Chagatai";
|
|
||||||
case "cmc": return "Chamic languages";
|
|
||||||
case "cha": return "Chamorro";
|
|
||||||
case "che": return "Chechen";
|
|
||||||
case "chr": return "Cherokee";
|
|
||||||
case "chy": return "Cheyenne";
|
|
||||||
case "chb": return "Chibcha";
|
|
||||||
case "chi": return "Chinese";
|
|
||||||
case "zho": return "Chinese";
|
|
||||||
case "chn": return "Chinook jargon";
|
|
||||||
case "chp": return "Chipewyan";
|
|
||||||
case "cho": return "Choctaw";
|
|
||||||
case "chu": return "Church Slavic";
|
|
||||||
case "chk": return "Chuukese";
|
|
||||||
case "chv": return "Chuvash";
|
|
||||||
case "cop": return "Coptic";
|
|
||||||
case "cor": return "Cornish";
|
|
||||||
case "cos": return "Corsican";
|
|
||||||
case "cre": return "Cree";
|
|
||||||
case "mus": return "Creek";
|
|
||||||
case "crp": return "Creoles and pidgins (Other)";
|
|
||||||
case "cpe": return "Creoles and pidgins,";
|
|
||||||
case "cpf": return "Creoles and pidgins,";
|
|
||||||
case "cpp": return "Creoles and pidgins,";
|
|
||||||
case "scr": return "Croatian";
|
|
||||||
case "hrv": return "Croatian";
|
|
||||||
case "cus": return "Cushitic (Other)";
|
|
||||||
case "cze": return "Czech";
|
|
||||||
case "ces": return "Czech";
|
|
||||||
case "dak": return "Dakota";
|
|
||||||
case "dan": return "Danish";
|
|
||||||
case "day": return "Dayak";
|
|
||||||
case "del": return "Delaware";
|
|
||||||
case "din": return "Dinka";
|
|
||||||
case "div": return "Divehi";
|
|
||||||
case "doi": return "Dogri";
|
|
||||||
case "dgr": return "Dogrib";
|
|
||||||
case "dra": return "Dravidian (Other)";
|
|
||||||
case "dua": return "Duala";
|
|
||||||
case "dut": return "Dutch";
|
|
||||||
case "nld": return "Dutch";
|
|
||||||
case "dum": return "Dutch, Middle (ca. 1050-1350)";
|
|
||||||
case "dyu": return "Dyula";
|
|
||||||
case "dzo": return "Dzongkha";
|
|
||||||
case "efi": return "Efik";
|
|
||||||
case "egy": return "Egyptian (Ancient)";
|
|
||||||
case "eka": return "Ekajuk";
|
|
||||||
case "elx": return "Elamite";
|
|
||||||
case "eng": return "English";
|
|
||||||
case "enm": return "English, Middle (1100-1500)";
|
|
||||||
case "ang": return "English, Old (ca.450-1100)";
|
|
||||||
case "epo": return "Esperanto";
|
|
||||||
case "est": return "Estonian";
|
|
||||||
case "ewe": return "Ewe";
|
|
||||||
case "ewo": return "Ewondo";
|
|
||||||
case "fan": return "Fang";
|
|
||||||
case "fat": return "Fanti";
|
|
||||||
case "fao": return "Faroese";
|
|
||||||
case "fij": return "Fijian";
|
|
||||||
case "fin": return "Finnish";
|
|
||||||
case "fiu": return "Finno-Ugrian (Other)";
|
|
||||||
case "fon": return "Fon";
|
|
||||||
case "fre": return "French";
|
|
||||||
case "fra": return "French";
|
|
||||||
case "frm": return "French, Middle (ca.1400-1600)";
|
|
||||||
case "fro": return "French, Old (842-ca.1400)";
|
|
||||||
case "fry": return "Frisian";
|
|
||||||
case "fur": return "Friulian";
|
|
||||||
case "ful": return "Fulah";
|
|
||||||
case "gaa": return "Ga";
|
|
||||||
case "glg": return "Gallegan";
|
|
||||||
case "lug": return "Ganda";
|
|
||||||
case "gay": return "Gayo";
|
|
||||||
case "gba": return "Gbaya";
|
|
||||||
case "gez": return "Geez";
|
|
||||||
case "geo": return "Georgian";
|
|
||||||
case "kat": return "Georgian";
|
|
||||||
case "ger": return "German";
|
|
||||||
case "deu": return "German";
|
|
||||||
case "nds": return "Saxon";
|
|
||||||
case "gmh": return "German, Middle High (ca.1050-1500)";
|
|
||||||
case "goh": return "German, Old High (ca.750-1050)";
|
|
||||||
case "gem": return "Germanic (Other)";
|
|
||||||
case "gil": return "Gilbertese";
|
|
||||||
case "gon": return "Gondi";
|
|
||||||
case "gor": return "Gorontalo";
|
|
||||||
case "got": return "Gothic";
|
|
||||||
case "grb": return "Grebo";
|
|
||||||
case "grc": return "Greek, Ancient (to 1453)";
|
|
||||||
case "gre": return "Greek";
|
|
||||||
case "ell": return "Greek";
|
|
||||||
case "grn": return "Guarani";
|
|
||||||
case "guj": return "Gujarati";
|
|
||||||
case "gwi": return "Gwich´in";
|
|
||||||
case "hai": return "Haida";
|
|
||||||
case "hau": return "Hausa";
|
|
||||||
case "haw": return "Hawaiian";
|
|
||||||
case "heb": return "Hebrew";
|
|
||||||
case "her": return "Herero";
|
|
||||||
case "hil": return "Hiligaynon";
|
|
||||||
case "him": return "Himachali";
|
|
||||||
case "hin": return "Hindi";
|
|
||||||
case "hmo": return "Hiri Motu";
|
|
||||||
case "hit": return "Hittite";
|
|
||||||
case "hmn": return "Hmong";
|
|
||||||
case "hun": return "Hungarian";
|
|
||||||
case "hup": return "Hupa";
|
|
||||||
case "iba": return "Iban";
|
|
||||||
case "ice": return "Icelandic";
|
|
||||||
case "isl": return "Icelandic";
|
|
||||||
case "ibo": return "Igbo";
|
|
||||||
case "ijo": return "Ijo";
|
|
||||||
case "ilo": return "Iloko";
|
|
||||||
case "inc": return "Indic (Other)";
|
|
||||||
case "ine": return "Indo-European (Other)";
|
|
||||||
case "ind": return "Indonesian";
|
|
||||||
case "ina": return "Interlingua (International";
|
|
||||||
case "ile": return "Interlingue";
|
|
||||||
case "iku": return "Inuktitut";
|
|
||||||
case "ipk": return "Inupiaq";
|
|
||||||
case "ira": return "Iranian (Other)";
|
|
||||||
case "gle": return "Irish";
|
|
||||||
case "mga": return "Irish, Middle (900-1200)";
|
|
||||||
case "sga": return "Irish, Old (to 900)";
|
|
||||||
case "iro": return "Iroquoian languages";
|
|
||||||
case "ita": return "Italian";
|
|
||||||
case "jpn": return "Japanese";
|
|
||||||
case "jav": return "Javanese";
|
|
||||||
case "jrb": return "Judeo-Arabic";
|
|
||||||
case "jpr": return "Judeo-Persian";
|
|
||||||
case "kab": return "Kabyle";
|
|
||||||
case "kac": return "Kachin";
|
|
||||||
case "kal": return "Kalaallisut";
|
|
||||||
case "kam": return "Kamba";
|
|
||||||
case "kan": return "Kannada";
|
|
||||||
case "kau": return "Kanuri";
|
|
||||||
case "kaa": return "Kara-Kalpak";
|
|
||||||
case "kar": return "Karen";
|
|
||||||
case "kas": return "Kashmiri";
|
|
||||||
case "kaw": return "Kawi";
|
|
||||||
case "kaz": return "Kazakh";
|
|
||||||
case "kha": return "Khasi";
|
|
||||||
case "khm": return "Khmer";
|
|
||||||
case "khi": return "Khoisan (Other)";
|
|
||||||
case "kho": return "Khotanese";
|
|
||||||
case "kik": return "Kikuyu";
|
|
||||||
case "kmb": return "Kimbundu";
|
|
||||||
case "kin": return "Kinyarwanda";
|
|
||||||
case "kir": return "Kirghiz";
|
|
||||||
case "kom": return "Komi";
|
|
||||||
case "kon": return "Kongo";
|
|
||||||
case "kok": return "Konkani";
|
|
||||||
case "kor": return "Korean";
|
|
||||||
case "kos": return "Kosraean";
|
|
||||||
case "kpe": return "Kpelle";
|
|
||||||
case "kro": return "Kru";
|
|
||||||
case "kua": return "Kuanyama";
|
|
||||||
case "kum": return "Kumyk";
|
|
||||||
case "kur": return "Kurdish";
|
|
||||||
case "kru": return "Kurukh";
|
|
||||||
case "kut": return "Kutenai";
|
|
||||||
case "lad": return "Ladino";
|
|
||||||
case "lah": return "Lahnda";
|
|
||||||
case "lam": return "Lamba";
|
|
||||||
case "lao": return "Lao";
|
|
||||||
case "lat": return "Latin";
|
|
||||||
case "lav": return "Latvian";
|
|
||||||
case "ltz": return "Letzeburgesch";
|
|
||||||
case "lez": return "Lezghian";
|
|
||||||
case "lin": return "Lingala";
|
|
||||||
case "lit": return "Lithuanian";
|
|
||||||
case "loz": return "Lozi";
|
|
||||||
case "lub": return "Luba-Katanga";
|
|
||||||
case "lua": return "Luba-Lulua";
|
|
||||||
case "lui": return "Luiseno";
|
|
||||||
case "lun": return "Lunda";
|
|
||||||
case "luo": return "Luo (Kenya and Tanzania)";
|
|
||||||
case "lus": return "Lushai";
|
|
||||||
case "mac": return "Macedonian";
|
|
||||||
case "mkd": return "Macedonian";
|
|
||||||
case "mad": return "Madurese";
|
|
||||||
case "mag": return "Magahi";
|
|
||||||
case "mai": return "Maithili";
|
|
||||||
case "mak": return "Makasar";
|
|
||||||
case "mlg": return "Malagasy";
|
|
||||||
case "may": return "Malay";
|
|
||||||
case "msa": return "Malay";
|
|
||||||
case "mal": return "Malayalam";
|
|
||||||
case "mlt": return "Maltese";
|
|
||||||
case "mnc": return "Manchu";
|
|
||||||
case "mdr": return "Mandar";
|
|
||||||
case "man": return "Mandingo";
|
|
||||||
case "mni": return "Manipuri";
|
|
||||||
case "mno": return "Manobo languages";
|
|
||||||
case "glv": return "Manx";
|
|
||||||
case "mao": return "Maori";
|
|
||||||
case "mri": return "Maori";
|
|
||||||
case "mar": return "Marathi";
|
|
||||||
case "chm": return "Mari";
|
|
||||||
case "mah": return "Marshall";
|
|
||||||
case "mwr": return "Marwari";
|
|
||||||
case "mas": return "Masai";
|
|
||||||
case "myn": return "Mayan languages";
|
|
||||||
case "men": return "Mende";
|
|
||||||
case "mic": return "Micmac";
|
|
||||||
case "min": return "Minangkabau";
|
|
||||||
case "mis": return "Miscellaneous languages";
|
|
||||||
case "moh": return "Mohawk";
|
|
||||||
case "mol": return "Moldavian";
|
|
||||||
case "mkh": return "Mon-Khmer (Other)";
|
|
||||||
case "lol": return "Mongo";
|
|
||||||
case "mon": return "Mongolian";
|
|
||||||
case "mos": return "Mossi";
|
|
||||||
case "mul": return "Multiple languages";
|
|
||||||
case "mun": return "Munda languages";
|
|
||||||
case "nah": return "Nahuatl";
|
|
||||||
case "nau": return "Nauru";
|
|
||||||
case "nav": return "Navajo";
|
|
||||||
case "nde": return "Ndebele, North";
|
|
||||||
case "nbl": return "Ndebele, South";
|
|
||||||
case "ndo": return "Ndonga";
|
|
||||||
case "nep": return "Nepali";
|
|
||||||
case "new": return "Newari";
|
|
||||||
case "nia": return "Nias";
|
|
||||||
case "nic": return "Niger-Kordofanian (Other)";
|
|
||||||
case "ssa": return "Nilo-Saharan (Other)";
|
|
||||||
case "niu": return "Niuean";
|
|
||||||
case "non": return "Norse, Old";
|
|
||||||
case "nai": return "North American Indian (Other)";
|
|
||||||
case "sme": return "Northern Sami";
|
|
||||||
case "nor": return "Norwegian";
|
|
||||||
case "nob": return "Norwegian Bokmål";
|
|
||||||
case "nno": return "Norwegian Nynorsk";
|
|
||||||
case "nub": return "Nubian languages";
|
|
||||||
case "nym": return "Nyamwezi";
|
|
||||||
case "nya": return "Nyanja";
|
|
||||||
case "nyn": return "Nyankole";
|
|
||||||
case "nyo": return "Nyoro";
|
|
||||||
case "nzi": return "Nzima";
|
|
||||||
case "oci": return "Occitan";
|
|
||||||
case "oji": return "Ojibwa";
|
|
||||||
case "ori": return "Oriya";
|
|
||||||
case "orm": return "Oromo";
|
|
||||||
case "osa": return "Osage";
|
|
||||||
case "oss": return "Ossetian";
|
|
||||||
case "oto": return "Otomian languages";
|
|
||||||
case "pal": return "Pahlavi";
|
|
||||||
case "pau": return "Palauan";
|
|
||||||
case "pli": return "Pali";
|
|
||||||
case "pam": return "Pampanga";
|
|
||||||
case "pag": return "Pangasinan";
|
|
||||||
case "pan": return "Panjabi";
|
|
||||||
case "pap": return "Papiamento";
|
|
||||||
case "paa": return "Papuan (Other)";
|
|
||||||
case "per": return "Persian";
|
|
||||||
case "fas": return "Persian";
|
|
||||||
case "peo": return "Persian, Old (ca.600-400 B.C.)";
|
|
||||||
case "phi": return "Philippine (Other)";
|
|
||||||
case "phn": return "Phoenician";
|
|
||||||
case "pon": return "Pohnpeian";
|
|
||||||
case "pol": return "Polish";
|
|
||||||
case "por": return "Portuguese";
|
|
||||||
case "pra": return "Prakrit languages";
|
|
||||||
case "pro": return "Provençal";
|
|
||||||
case "pus": return "Pushto";
|
|
||||||
case "que": return "Quechua";
|
|
||||||
case "roh": return "Raeto-Romance";
|
|
||||||
case "raj": return "Rajasthani";
|
|
||||||
case "rap": return "Rapanui";
|
|
||||||
case "rar": return "Rarotongan";
|
|
||||||
case "roa": return "Romance (Other)";
|
|
||||||
case "rum": return "Romanian";
|
|
||||||
case "ron": return "Romanian";
|
|
||||||
case "rom": return "Romany";
|
|
||||||
case "run": return "Rundi";
|
|
||||||
case "rus": return "Russian";
|
|
||||||
case "sal": return "Salishan languages";
|
|
||||||
case "sam": return "Samaritan Aramaic";
|
|
||||||
case "smi": return "Sami languages (Other)";
|
|
||||||
case "smo": return "Samoan";
|
|
||||||
case "sad": return "Sandawe";
|
|
||||||
case "sag": return "Sango";
|
|
||||||
case "san": return "Sanskrit";
|
|
||||||
case "sat": return "Santali";
|
|
||||||
case "srd": return "Sardinian";
|
|
||||||
case "sas": return "Sasak";
|
|
||||||
case "sco": return "Scots";
|
|
||||||
case "gla": return "Gaelic";
|
|
||||||
case "sel": return "Selkup";
|
|
||||||
case "sem": return "Semitic (Other)";
|
|
||||||
case "scc": return "Serbian";
|
|
||||||
case "srp": return "Serbian";
|
|
||||||
case "srr": return "Serer";
|
|
||||||
case "shn": return "Shan";
|
|
||||||
case "sna": return "Shona";
|
|
||||||
case "sid": return "Sidamo";
|
|
||||||
case "sgn": return "Sign languages";
|
|
||||||
case "bla": return "Siksika";
|
|
||||||
case "snd": return "Sindhi";
|
|
||||||
case "sin": return "Sinhalese";
|
|
||||||
case "sit": return "Sino-Tibetan (Other)";
|
|
||||||
case "sio": return "Siouan languages";
|
|
||||||
case "den": return "Slave (Athapascan)";
|
|
||||||
case "sla": return "Slavic (Other)";
|
|
||||||
case "slo": return "Slovak";
|
|
||||||
case "slk": return "Slovak";
|
|
||||||
case "slv": return "Slovenian";
|
|
||||||
case "sog": return "Sogdian";
|
|
||||||
case "som": return "Somali";
|
|
||||||
case "son": return "Songhai";
|
|
||||||
case "snk": return "Soninke";
|
|
||||||
case "wen": return "Sorbian languages";
|
|
||||||
case "nso": return "Sotho, Northern";
|
|
||||||
case "sot": return "Sotho, Southern";
|
|
||||||
case "sai": return "South American Indian (Other)";
|
|
||||||
case "spa": return "Spanish";
|
|
||||||
case "suk": return "Sukuma";
|
|
||||||
case "sux": return "Sumerian";
|
|
||||||
case "sun": return "Sundanese";
|
|
||||||
case "sus": return "Susu";
|
|
||||||
case "swa": return "Swahili";
|
|
||||||
case "ssw": return "Swati";
|
|
||||||
case "swe": return "Swedish";
|
|
||||||
case "syr": return "Syriac";
|
|
||||||
case "tgl": return "Tagalog";
|
|
||||||
case "tah": return "Tahitian";
|
|
||||||
case "tai": return "Tai (Other)";
|
|
||||||
case "tgk": return "Tajik";
|
|
||||||
case "tmh": return "Tamashek";
|
|
||||||
case "tam": return "Tamil";
|
|
||||||
case "tat": return "Tatar";
|
|
||||||
case "tel": return "Telugu";
|
|
||||||
case "ter": return "Tereno";
|
|
||||||
case "tet": return "Tetum";
|
|
||||||
case "tha": return "Thai";
|
|
||||||
case "tib": return "Tibetan";
|
|
||||||
case "bod": return "Tibetan";
|
|
||||||
case "tig": return "Tigre";
|
|
||||||
case "tir": return "Tigrinya";
|
|
||||||
case "tem": return "Timne";
|
|
||||||
case "tiv": return "Tiv";
|
|
||||||
case "tli": return "Tlingit";
|
|
||||||
case "tpi": return "Tok Pisin";
|
|
||||||
case "tkl": return "Tokelau";
|
|
||||||
case "tog": return "Tonga (Nyasa)";
|
|
||||||
case "ton": return "Tonga (Tonga Islands)";
|
|
||||||
case "tsi": return "Tsimshian";
|
|
||||||
case "tso": return "Tsonga";
|
|
||||||
case "tsn": return "Tswana";
|
|
||||||
case "tum": return "Tumbuka";
|
|
||||||
case "tur": return "Turkish";
|
|
||||||
case "ota": return "Turkish, Ottoman (1500-1928)";
|
|
||||||
case "tuk": return "Turkmen";
|
|
||||||
case "tvl": return "Tuvalu";
|
|
||||||
case "tyv": return "Tuvinian";
|
|
||||||
case "twi": return "Twi";
|
|
||||||
case "uga": return "Ugaritic";
|
|
||||||
case "uig": return "Uighur";
|
|
||||||
case "ukr": return "Ukrainian";
|
|
||||||
case "umb": return "Umbundu";
|
|
||||||
case "und": return "Undetermined";
|
|
||||||
case "urd": return "Urdu";
|
|
||||||
case "uzb": return "Uzbek";
|
|
||||||
case "vai": return "Vai";
|
|
||||||
case "ven": return "Venda";
|
|
||||||
case "vie": return "Vietnamese";
|
|
||||||
case "vol": return "Volapük";
|
|
||||||
case "vot": return "Votic";
|
|
||||||
case "wak": return "Wakashan languages";
|
|
||||||
case "wal": return "Walamo";
|
|
||||||
case "war": return "Waray";
|
|
||||||
case "was": return "Washo";
|
|
||||||
case "wel": return "Welsh";
|
|
||||||
case "cym": return "Welsh";
|
|
||||||
case "wol": return "Wolof";
|
|
||||||
case "xho": return "Xhosa";
|
|
||||||
case "sah": return "Yakut";
|
|
||||||
case "yao": return "Yao";
|
|
||||||
case "yap": return "Yapese";
|
|
||||||
case "yid": return "Yiddish";
|
|
||||||
case "yor": return "Yoruba";
|
|
||||||
case "ypk": return "Yupik languages";
|
|
||||||
case "znd": return "Zande";
|
|
||||||
case "zap": return "Zapotec";
|
|
||||||
case "zen": return "Zenaga";
|
|
||||||
case "zha": return "Zhuang";
|
|
||||||
case "zul": return "Zulu";
|
|
||||||
case "zun": return "Zuni";
|
|
||||||
|
|
||||||
default: return code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
using System.Reflection;
|
|
||||||
using System.Resources;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("BDInfo")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("Jellyfin Project")]
|
|
||||||
[assembly: AssemblyProduct("Jellyfin Server")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © 2016 CinemaSquid. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: NeutralResourcesLanguage("en")]
|
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||||
// to COM components. If you need to access a type in this assembly from
|
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||||
[assembly: ComVisible(false)]
|
|
|
@ -1,5 +0,0 @@
|
||||||
The source is taken from the BDRom folder of this project:
|
|
||||||
|
|
||||||
http://www.cinemasquid.com/blu-ray/tools/bdinfo
|
|
||||||
|
|
||||||
BDInfoSettings was taken from the FormSettings class, and changed so that the settings all return defaults.
|
|
|
@ -1,309 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
#undef DEBUG
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public abstract class TSCodecAC3
|
|
||||||
{
|
|
||||||
private static byte[] eac3_blocks = new byte[] { 1, 2, 3, 6 };
|
|
||||||
|
|
||||||
public static void Scan(
|
|
||||||
TSAudioStream stream,
|
|
||||||
TSStreamBuffer buffer,
|
|
||||||
ref string tag)
|
|
||||||
{
|
|
||||||
if (stream.IsInitialized) return;
|
|
||||||
|
|
||||||
byte[] sync = buffer.ReadBytes(2);
|
|
||||||
if (sync == null ||
|
|
||||||
sync[0] != 0x0B ||
|
|
||||||
sync[1] != 0x77)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sr_code = 0;
|
|
||||||
int frame_size = 0;
|
|
||||||
int frame_size_code = 0;
|
|
||||||
int channel_mode = 0;
|
|
||||||
int lfe_on = 0;
|
|
||||||
int dial_norm = 0;
|
|
||||||
int num_blocks = 0;
|
|
||||||
|
|
||||||
byte[] hdr = buffer.ReadBytes(4);
|
|
||||||
int bsid = (hdr[3] & 0xF8) >> 3;
|
|
||||||
buffer.Seek(-4, SeekOrigin.Current);
|
|
||||||
if (bsid <= 10)
|
|
||||||
{
|
|
||||||
byte[] crc = buffer.ReadBytes(2);
|
|
||||||
sr_code = buffer.ReadBits(2);
|
|
||||||
frame_size_code = buffer.ReadBits(6);
|
|
||||||
bsid = buffer.ReadBits(5);
|
|
||||||
int bsmod = buffer.ReadBits(3);
|
|
||||||
|
|
||||||
channel_mode = buffer.ReadBits(3);
|
|
||||||
int cmixlev = 0;
|
|
||||||
if (((channel_mode & 0x1) > 0) && (channel_mode != 0x1))
|
|
||||||
{
|
|
||||||
cmixlev = buffer.ReadBits(2);
|
|
||||||
}
|
|
||||||
int surmixlev = 0;
|
|
||||||
if ((channel_mode & 0x4) > 0)
|
|
||||||
{
|
|
||||||
surmixlev = buffer.ReadBits(2);
|
|
||||||
}
|
|
||||||
int dsurmod = 0;
|
|
||||||
if (channel_mode == 0x2)
|
|
||||||
{
|
|
||||||
dsurmod = buffer.ReadBits(2);
|
|
||||||
if (dsurmod == 0x2)
|
|
||||||
{
|
|
||||||
stream.AudioMode = TSAudioMode.Surround;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lfe_on = buffer.ReadBits(1);
|
|
||||||
dial_norm = buffer.ReadBits(5);
|
|
||||||
int compr = 0;
|
|
||||||
if (1 == buffer.ReadBits(1))
|
|
||||||
{
|
|
||||||
compr = buffer.ReadBits(8);
|
|
||||||
}
|
|
||||||
int langcod = 0;
|
|
||||||
if (1 == buffer.ReadBits(1))
|
|
||||||
{
|
|
||||||
langcod = buffer.ReadBits(8);
|
|
||||||
}
|
|
||||||
int mixlevel = 0;
|
|
||||||
int roomtyp = 0;
|
|
||||||
if (1 == buffer.ReadBits(1))
|
|
||||||
{
|
|
||||||
mixlevel = buffer.ReadBits(5);
|
|
||||||
roomtyp = buffer.ReadBits(2);
|
|
||||||
}
|
|
||||||
if (channel_mode == 0)
|
|
||||||
{
|
|
||||||
int dialnorm2 = buffer.ReadBits(5);
|
|
||||||
int compr2 = 0;
|
|
||||||
if (1 == buffer.ReadBits(1))
|
|
||||||
{
|
|
||||||
compr2 = buffer.ReadBits(8);
|
|
||||||
}
|
|
||||||
int langcod2 = 0;
|
|
||||||
if (1 == buffer.ReadBits(1))
|
|
||||||
{
|
|
||||||
langcod2 = buffer.ReadBits(8);
|
|
||||||
}
|
|
||||||
int mixlevel2 = 0;
|
|
||||||
int roomtyp2 = 0;
|
|
||||||
if (1 == buffer.ReadBits(1))
|
|
||||||
{
|
|
||||||
mixlevel2 = buffer.ReadBits(5);
|
|
||||||
roomtyp2 = buffer.ReadBits(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int copyrightb = buffer.ReadBits(1);
|
|
||||||
int origbs = buffer.ReadBits(1);
|
|
||||||
if (bsid == 6)
|
|
||||||
{
|
|
||||||
if (1 == buffer.ReadBits(1))
|
|
||||||
{
|
|
||||||
int dmixmod = buffer.ReadBits(2);
|
|
||||||
int ltrtcmixlev = buffer.ReadBits(3);
|
|
||||||
int ltrtsurmixlev = buffer.ReadBits(3);
|
|
||||||
int lorocmixlev = buffer.ReadBits(3);
|
|
||||||
int lorosurmixlev = buffer.ReadBits(3);
|
|
||||||
}
|
|
||||||
if (1 == buffer.ReadBits(1))
|
|
||||||
{
|
|
||||||
int dsurexmod = buffer.ReadBits(2);
|
|
||||||
int dheadphonmod = buffer.ReadBits(2);
|
|
||||||
if (dheadphonmod == 0x2)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
int adconvtyp = buffer.ReadBits(1);
|
|
||||||
int xbsi2 = buffer.ReadBits(8);
|
|
||||||
int encinfo = buffer.ReadBits(1);
|
|
||||||
if (dsurexmod == 2)
|
|
||||||
{
|
|
||||||
stream.AudioMode = TSAudioMode.Extended;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int frame_type = buffer.ReadBits(2);
|
|
||||||
int substreamid = buffer.ReadBits(3);
|
|
||||||
frame_size = (buffer.ReadBits(11) + 1) << 1;
|
|
||||||
|
|
||||||
sr_code = buffer.ReadBits(2);
|
|
||||||
if (sr_code == 3)
|
|
||||||
{
|
|
||||||
sr_code = buffer.ReadBits(2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
num_blocks = buffer.ReadBits(2);
|
|
||||||
}
|
|
||||||
channel_mode = buffer.ReadBits(3);
|
|
||||||
lfe_on = buffer.ReadBits(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (channel_mode)
|
|
||||||
{
|
|
||||||
case 0: // 1+1
|
|
||||||
stream.ChannelCount = 2;
|
|
||||||
if (stream.AudioMode == TSAudioMode.Unknown)
|
|
||||||
{
|
|
||||||
stream.AudioMode = TSAudioMode.DualMono;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1: // 1/0
|
|
||||||
stream.ChannelCount = 1;
|
|
||||||
break;
|
|
||||||
case 2: // 2/0
|
|
||||||
stream.ChannelCount = 2;
|
|
||||||
if (stream.AudioMode == TSAudioMode.Unknown)
|
|
||||||
{
|
|
||||||
stream.AudioMode = TSAudioMode.Stereo;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3: // 3/0
|
|
||||||
stream.ChannelCount = 3;
|
|
||||||
break;
|
|
||||||
case 4: // 2/1
|
|
||||||
stream.ChannelCount = 3;
|
|
||||||
break;
|
|
||||||
case 5: // 3/1
|
|
||||||
stream.ChannelCount = 4;
|
|
||||||
break;
|
|
||||||
case 6: // 2/2
|
|
||||||
stream.ChannelCount = 4;
|
|
||||||
break;
|
|
||||||
case 7: // 3/2
|
|
||||||
stream.ChannelCount = 5;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stream.ChannelCount = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (sr_code)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
stream.SampleRate = 48000;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
stream.SampleRate = 44100;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
stream.SampleRate = 32000;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stream.SampleRate = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bsid <= 10)
|
|
||||||
{
|
|
||||||
switch (frame_size_code >> 1)
|
|
||||||
{
|
|
||||||
case 18:
|
|
||||||
stream.BitRate = 640000;
|
|
||||||
break;
|
|
||||||
case 17:
|
|
||||||
stream.BitRate = 576000;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
stream.BitRate = 512000;
|
|
||||||
break;
|
|
||||||
case 15:
|
|
||||||
stream.BitRate = 448000;
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
stream.BitRate = 384000;
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
stream.BitRate = 320000;
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
stream.BitRate = 256000;
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
stream.BitRate = 224000;
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
stream.BitRate = 192000;
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
stream.BitRate = 160000;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
stream.BitRate = 128000;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
stream.BitRate = 112000;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
stream.BitRate = 96000;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
stream.BitRate = 80000;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
stream.BitRate = 64000;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
stream.BitRate = 56000;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
stream.BitRate = 48000;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
stream.BitRate = 40000;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
stream.BitRate = 32000;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stream.BitRate = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream.BitRate = (long)
|
|
||||||
(4.0 * frame_size * stream.SampleRate / (num_blocks * 256));
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.LFE = lfe_on;
|
|
||||||
if (stream.StreamType != TSStreamType.AC3_PLUS_AUDIO &&
|
|
||||||
stream.StreamType != TSStreamType.AC3_PLUS_SECONDARY_AUDIO)
|
|
||||||
{
|
|
||||||
stream.DialNorm = dial_norm - 31;
|
|
||||||
}
|
|
||||||
stream.IsVBR = false;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,148 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public abstract class TSCodecAVC
|
|
||||||
{
|
|
||||||
public static void Scan(
|
|
||||||
TSVideoStream stream,
|
|
||||||
TSStreamBuffer buffer,
|
|
||||||
ref string tag)
|
|
||||||
{
|
|
||||||
uint parse = 0;
|
|
||||||
byte accessUnitDelimiterParse = 0;
|
|
||||||
byte sequenceParameterSetParse = 0;
|
|
||||||
string profile = null;
|
|
||||||
string level = null;
|
|
||||||
byte constraintSet0Flag = 0;
|
|
||||||
byte constraintSet1Flag = 0;
|
|
||||||
byte constraintSet2Flag = 0;
|
|
||||||
byte constraintSet3Flag = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < buffer.Length; i++)
|
|
||||||
{
|
|
||||||
parse = (parse << 8) + buffer.ReadByte();
|
|
||||||
|
|
||||||
if (parse == 0x00000109)
|
|
||||||
{
|
|
||||||
accessUnitDelimiterParse = 1;
|
|
||||||
}
|
|
||||||
else if (accessUnitDelimiterParse > 0)
|
|
||||||
{
|
|
||||||
--accessUnitDelimiterParse;
|
|
||||||
if (accessUnitDelimiterParse == 0)
|
|
||||||
{
|
|
||||||
switch ((parse & 0xFF) >> 5)
|
|
||||||
{
|
|
||||||
case 0: // I
|
|
||||||
case 3: // SI
|
|
||||||
case 5: // I, SI
|
|
||||||
tag = "I";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // I, P
|
|
||||||
case 4: // SI, SP
|
|
||||||
case 6: // I, SI, P, SP
|
|
||||||
tag = "P";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: // I, P, B
|
|
||||||
case 7: // I, SI, P, SP, B
|
|
||||||
tag = "B";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (stream.IsInitialized) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (parse == 0x00000127 || parse == 0x00000167)
|
|
||||||
{
|
|
||||||
sequenceParameterSetParse = 3;
|
|
||||||
}
|
|
||||||
else if (sequenceParameterSetParse > 0)
|
|
||||||
{
|
|
||||||
--sequenceParameterSetParse;
|
|
||||||
switch (sequenceParameterSetParse)
|
|
||||||
{
|
|
||||||
case 2:
|
|
||||||
switch (parse & 0xFF)
|
|
||||||
{
|
|
||||||
case 66:
|
|
||||||
profile = "Baseline Profile";
|
|
||||||
break;
|
|
||||||
case 77:
|
|
||||||
profile = "Main Profile";
|
|
||||||
break;
|
|
||||||
case 88:
|
|
||||||
profile = "Extended Profile";
|
|
||||||
break;
|
|
||||||
case 100:
|
|
||||||
profile = "High Profile";
|
|
||||||
break;
|
|
||||||
case 110:
|
|
||||||
profile = "High 10 Profile";
|
|
||||||
break;
|
|
||||||
case 122:
|
|
||||||
profile = "High 4:2:2 Profile";
|
|
||||||
break;
|
|
||||||
case 144:
|
|
||||||
profile = "High 4:4:4 Profile";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
profile = "Unknown Profile";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
constraintSet0Flag = (byte)
|
|
||||||
((parse & 0x80) >> 7);
|
|
||||||
constraintSet1Flag = (byte)
|
|
||||||
((parse & 0x40) >> 6);
|
|
||||||
constraintSet2Flag = (byte)
|
|
||||||
((parse & 0x20) >> 5);
|
|
||||||
constraintSet3Flag = (byte)
|
|
||||||
((parse & 0x10) >> 4);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
byte b = (byte)(parse & 0xFF);
|
|
||||||
if (b == 11 && constraintSet3Flag == 1)
|
|
||||||
{
|
|
||||||
level = "1b";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
level = string.Format(
|
|
||||||
"{0:D}.{1:D}",
|
|
||||||
b / 10, (b - ((b / 10) * 10)));
|
|
||||||
}
|
|
||||||
stream.EncodingProfile = string.Format(
|
|
||||||
"{0} {1}", profile, level);
|
|
||||||
stream.IsVBR = true;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,159 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public abstract class TSCodecDTS
|
|
||||||
{
|
|
||||||
private static int[] dca_sample_rates =
|
|
||||||
{
|
|
||||||
0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0,
|
|
||||||
12000, 24000, 48000, 96000, 192000
|
|
||||||
};
|
|
||||||
|
|
||||||
private static int[] dca_bit_rates =
|
|
||||||
{
|
|
||||||
32000, 56000, 64000, 96000, 112000, 128000,
|
|
||||||
192000, 224000, 256000, 320000, 384000,
|
|
||||||
448000, 512000, 576000, 640000, 768000,
|
|
||||||
896000, 1024000, 1152000, 1280000, 1344000,
|
|
||||||
1408000, 1411200, 1472000, 1509000, 1920000,
|
|
||||||
2048000, 3072000, 3840000, 1/*open*/, 2/*variable*/, 3/*lossless*/
|
|
||||||
};
|
|
||||||
|
|
||||||
private static int[] dca_channels =
|
|
||||||
{
|
|
||||||
1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8
|
|
||||||
};
|
|
||||||
|
|
||||||
private static int[] dca_bits_per_sample =
|
|
||||||
{
|
|
||||||
16, 16, 20, 20, 0, 24, 24
|
|
||||||
};
|
|
||||||
|
|
||||||
public static void Scan(
|
|
||||||
TSAudioStream stream,
|
|
||||||
TSStreamBuffer buffer,
|
|
||||||
long bitrate,
|
|
||||||
ref string tag)
|
|
||||||
{
|
|
||||||
if (stream.IsInitialized) return;
|
|
||||||
|
|
||||||
bool syncFound = false;
|
|
||||||
uint sync = 0;
|
|
||||||
for (int i = 0; i < buffer.Length; i++)
|
|
||||||
{
|
|
||||||
sync = (sync << 8) + buffer.ReadByte();
|
|
||||||
if (sync == 0x7FFE8001)
|
|
||||||
{
|
|
||||||
syncFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!syncFound) return;
|
|
||||||
|
|
||||||
int frame_type = buffer.ReadBits(1);
|
|
||||||
int samples_deficit = buffer.ReadBits(5);
|
|
||||||
int crc_present = buffer.ReadBits(1);
|
|
||||||
int sample_blocks = buffer.ReadBits(7);
|
|
||||||
int frame_size = buffer.ReadBits(14);
|
|
||||||
if (frame_size < 95)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int amode = buffer.ReadBits(6);
|
|
||||||
int sample_rate = buffer.ReadBits(4);
|
|
||||||
if (sample_rate < 0 || sample_rate >= dca_sample_rates.Length)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int bit_rate = buffer.ReadBits(5);
|
|
||||||
if (bit_rate < 0 || bit_rate >= dca_bit_rates.Length)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int downmix = buffer.ReadBits(1);
|
|
||||||
int dynrange = buffer.ReadBits(1);
|
|
||||||
int timestamp = buffer.ReadBits(1);
|
|
||||||
int aux_data = buffer.ReadBits(1);
|
|
||||||
int hdcd = buffer.ReadBits(1);
|
|
||||||
int ext_descr = buffer.ReadBits(3);
|
|
||||||
int ext_coding = buffer.ReadBits(1);
|
|
||||||
int aspf = buffer.ReadBits(1);
|
|
||||||
int lfe = buffer.ReadBits(2);
|
|
||||||
int predictor_history = buffer.ReadBits(1);
|
|
||||||
if (crc_present == 1)
|
|
||||||
{
|
|
||||||
int crc = buffer.ReadBits(16);
|
|
||||||
}
|
|
||||||
int multirate_inter = buffer.ReadBits(1);
|
|
||||||
int version = buffer.ReadBits(4);
|
|
||||||
int copy_history = buffer.ReadBits(2);
|
|
||||||
int source_pcm_res = buffer.ReadBits(3);
|
|
||||||
int front_sum = buffer.ReadBits(1);
|
|
||||||
int surround_sum = buffer.ReadBits(1);
|
|
||||||
int dialog_norm = buffer.ReadBits(4);
|
|
||||||
if (source_pcm_res < 0 || source_pcm_res >= dca_bits_per_sample.Length)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int subframes = buffer.ReadBits(4);
|
|
||||||
int total_channels = buffer.ReadBits(3) + 1 + ext_coding;
|
|
||||||
|
|
||||||
stream.SampleRate = dca_sample_rates[sample_rate];
|
|
||||||
stream.ChannelCount = total_channels;
|
|
||||||
stream.LFE = (lfe > 0 ? 1 : 0);
|
|
||||||
stream.BitDepth = dca_bits_per_sample[source_pcm_res];
|
|
||||||
stream.DialNorm = -dialog_norm;
|
|
||||||
if ((source_pcm_res & 0x1) == 0x1)
|
|
||||||
{
|
|
||||||
stream.AudioMode = TSAudioMode.Extended;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.BitRate = (uint)dca_bit_rates[bit_rate];
|
|
||||||
switch (stream.BitRate)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
if (bitrate > 0)
|
|
||||||
{
|
|
||||||
stream.BitRate = bitrate;
|
|
||||||
stream.IsVBR = false;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream.BitRate = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
stream.IsVBR = true;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
stream.IsVBR = false;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,246 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public abstract class TSCodecDTSHD
|
|
||||||
{
|
|
||||||
private static int[] SampleRates = new int[]
|
|
||||||
{ 0x1F40, 0x3E80, 0x7D00, 0x0FA00, 0x1F400, 0x5622, 0x0AC44, 0x15888, 0x2B110, 0x56220, 0x2EE0, 0x5DC0, 0x0BB80, 0x17700, 0x2EE00, 0x5DC00 };
|
|
||||||
|
|
||||||
public static void Scan(
|
|
||||||
TSAudioStream stream,
|
|
||||||
TSStreamBuffer buffer,
|
|
||||||
long bitrate,
|
|
||||||
ref string tag)
|
|
||||||
{
|
|
||||||
if (stream.IsInitialized &&
|
|
||||||
(stream.StreamType == TSStreamType.DTS_HD_SECONDARY_AUDIO ||
|
|
||||||
(stream.CoreStream != null &&
|
|
||||||
stream.CoreStream.IsInitialized))) return;
|
|
||||||
|
|
||||||
bool syncFound = false;
|
|
||||||
uint sync = 0;
|
|
||||||
for (int i = 0; i < buffer.Length; i++)
|
|
||||||
{
|
|
||||||
sync = (sync << 8) + buffer.ReadByte();
|
|
||||||
if (sync == 0x64582025)
|
|
||||||
{
|
|
||||||
syncFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!syncFound)
|
|
||||||
{
|
|
||||||
tag = "CORE";
|
|
||||||
if (stream.CoreStream == null)
|
|
||||||
{
|
|
||||||
stream.CoreStream = new TSAudioStream();
|
|
||||||
stream.CoreStream.StreamType = TSStreamType.DTS_AUDIO;
|
|
||||||
}
|
|
||||||
if (!stream.CoreStream.IsInitialized)
|
|
||||||
{
|
|
||||||
buffer.BeginRead();
|
|
||||||
TSCodecDTS.Scan(stream.CoreStream, buffer, bitrate, ref tag);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tag = "HD";
|
|
||||||
int temp1 = buffer.ReadBits(8);
|
|
||||||
int nuSubStreamIndex = buffer.ReadBits(2);
|
|
||||||
int nuExtSSHeaderSize = 0;
|
|
||||||
int nuExtSSFSize = 0;
|
|
||||||
int bBlownUpHeader = buffer.ReadBits(1);
|
|
||||||
if (1 == bBlownUpHeader)
|
|
||||||
{
|
|
||||||
nuExtSSHeaderSize = buffer.ReadBits(12) + 1;
|
|
||||||
nuExtSSFSize = buffer.ReadBits(20) + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nuExtSSHeaderSize = buffer.ReadBits(8) + 1;
|
|
||||||
nuExtSSFSize = buffer.ReadBits(16) + 1;
|
|
||||||
}
|
|
||||||
int nuNumAudioPresent = 1;
|
|
||||||
int nuNumAssets = 1;
|
|
||||||
int bStaticFieldsPresent = buffer.ReadBits(1);
|
|
||||||
if (1 == bStaticFieldsPresent)
|
|
||||||
{
|
|
||||||
int nuRefClockCode = buffer.ReadBits(2);
|
|
||||||
int nuExSSFrameDurationCode = buffer.ReadBits(3) + 1;
|
|
||||||
long nuTimeStamp = 0;
|
|
||||||
if (1 == buffer.ReadBits(1))
|
|
||||||
{
|
|
||||||
nuTimeStamp = (buffer.ReadBits(18) << 18) + buffer.ReadBits(18);
|
|
||||||
}
|
|
||||||
nuNumAudioPresent = buffer.ReadBits(3) + 1;
|
|
||||||
nuNumAssets = buffer.ReadBits(3) + 1;
|
|
||||||
int[] nuActiveExSSMask = new int[nuNumAudioPresent];
|
|
||||||
for (int i = 0; i < nuNumAudioPresent; i++)
|
|
||||||
{
|
|
||||||
nuActiveExSSMask[i] = buffer.ReadBits(nuSubStreamIndex + 1); //?
|
|
||||||
}
|
|
||||||
for (int i = 0; i < nuNumAudioPresent; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < nuSubStreamIndex + 1; j++)
|
|
||||||
{
|
|
||||||
if (((j + 1) % 2) == 1)
|
|
||||||
{
|
|
||||||
int mask = buffer.ReadBits(8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (1 == buffer.ReadBits(1))
|
|
||||||
{
|
|
||||||
int nuMixMetadataAdjLevel = buffer.ReadBits(2);
|
|
||||||
int nuBits4MixOutMask = buffer.ReadBits(2) * 4 + 4;
|
|
||||||
int nuNumMixOutConfigs = buffer.ReadBits(2) + 1;
|
|
||||||
int[] nuMixOutChMask = new int[nuNumMixOutConfigs];
|
|
||||||
for (int i = 0; i < nuNumMixOutConfigs; i++)
|
|
||||||
{
|
|
||||||
nuMixOutChMask[i] = buffer.ReadBits(nuBits4MixOutMask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int[] AssetSizes = new int[nuNumAssets];
|
|
||||||
for (int i = 0; i < nuNumAssets; i++)
|
|
||||||
{
|
|
||||||
if (1 == bBlownUpHeader)
|
|
||||||
{
|
|
||||||
AssetSizes[i] = buffer.ReadBits(20) + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AssetSizes[i] = buffer.ReadBits(16) + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < nuNumAssets; i++)
|
|
||||||
{
|
|
||||||
long bufferPosition = buffer.Position;
|
|
||||||
int nuAssetDescriptorFSIZE = buffer.ReadBits(9) + 1;
|
|
||||||
int DescriptorDataForAssetIndex = buffer.ReadBits(3);
|
|
||||||
if (1 == bStaticFieldsPresent)
|
|
||||||
{
|
|
||||||
int AssetTypeDescrPresent = buffer.ReadBits(1);
|
|
||||||
if (1 == AssetTypeDescrPresent)
|
|
||||||
{
|
|
||||||
int AssetTypeDescriptor = buffer.ReadBits(4);
|
|
||||||
}
|
|
||||||
int LanguageDescrPresent = buffer.ReadBits(1);
|
|
||||||
if (1 == LanguageDescrPresent)
|
|
||||||
{
|
|
||||||
int LanguageDescriptor = buffer.ReadBits(24);
|
|
||||||
}
|
|
||||||
int bInfoTextPresent = buffer.ReadBits(1);
|
|
||||||
if (1 == bInfoTextPresent)
|
|
||||||
{
|
|
||||||
int nuInfoTextByteSize = buffer.ReadBits(10) + 1;
|
|
||||||
int[] InfoText = new int[nuInfoTextByteSize];
|
|
||||||
for (int j = 0; j < nuInfoTextByteSize; j++)
|
|
||||||
{
|
|
||||||
InfoText[j] = buffer.ReadBits(8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int nuBitResolution = buffer.ReadBits(5) + 1;
|
|
||||||
int nuMaxSampleRate = buffer.ReadBits(4);
|
|
||||||
int nuTotalNumChs = buffer.ReadBits(8) + 1;
|
|
||||||
int bOne2OneMapChannels2Speakers = buffer.ReadBits(1);
|
|
||||||
int nuSpkrActivityMask = 0;
|
|
||||||
if (1 == bOne2OneMapChannels2Speakers)
|
|
||||||
{
|
|
||||||
int bEmbeddedStereoFlag = 0;
|
|
||||||
if (nuTotalNumChs > 2)
|
|
||||||
{
|
|
||||||
bEmbeddedStereoFlag = buffer.ReadBits(1);
|
|
||||||
}
|
|
||||||
int bEmbeddedSixChFlag = 0;
|
|
||||||
if (nuTotalNumChs > 6)
|
|
||||||
{
|
|
||||||
bEmbeddedSixChFlag = buffer.ReadBits(1);
|
|
||||||
}
|
|
||||||
int bSpkrMaskEnabled = buffer.ReadBits(1);
|
|
||||||
int nuNumBits4SAMask = 0;
|
|
||||||
if (1 == bSpkrMaskEnabled)
|
|
||||||
{
|
|
||||||
nuNumBits4SAMask = buffer.ReadBits(2);
|
|
||||||
nuNumBits4SAMask = nuNumBits4SAMask * 4 + 4;
|
|
||||||
nuSpkrActivityMask = buffer.ReadBits(nuNumBits4SAMask);
|
|
||||||
}
|
|
||||||
// TODO...
|
|
||||||
}
|
|
||||||
stream.SampleRate = SampleRates[nuMaxSampleRate];
|
|
||||||
stream.BitDepth = nuBitResolution;
|
|
||||||
|
|
||||||
stream.LFE = 0;
|
|
||||||
if ((nuSpkrActivityMask & 0x8) == 0x8)
|
|
||||||
{
|
|
||||||
++stream.LFE;
|
|
||||||
}
|
|
||||||
if ((nuSpkrActivityMask & 0x1000) == 0x1000)
|
|
||||||
{
|
|
||||||
++stream.LFE;
|
|
||||||
}
|
|
||||||
stream.ChannelCount = nuTotalNumChs - stream.LFE;
|
|
||||||
}
|
|
||||||
if (nuNumAssets > 1)
|
|
||||||
{
|
|
||||||
// TODO...
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
if (stream.CoreStream != null)
|
|
||||||
{
|
|
||||||
var coreStream = (TSAudioStream)stream.CoreStream;
|
|
||||||
if (coreStream.AudioMode == TSAudioMode.Extended &&
|
|
||||||
stream.ChannelCount == 5)
|
|
||||||
{
|
|
||||||
stream.AudioMode = TSAudioMode.Extended;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if (coreStream.DialNorm != 0)
|
|
||||||
{
|
|
||||||
stream.DialNorm = coreStream.DialNorm;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stream.StreamType == TSStreamType.DTS_HD_MASTER_AUDIO)
|
|
||||||
{
|
|
||||||
stream.IsVBR = true;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
}
|
|
||||||
else if (bitrate > 0)
|
|
||||||
{
|
|
||||||
stream.IsVBR = false;
|
|
||||||
stream.BitRate = bitrate;
|
|
||||||
if (stream.CoreStream != null)
|
|
||||||
{
|
|
||||||
stream.BitRate += stream.CoreStream.BitRate;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
}
|
|
||||||
stream.IsInitialized = (stream.BitRate > 0 ? true : false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,123 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public abstract class TSCodecLPCM
|
|
||||||
{
|
|
||||||
public static void Scan(
|
|
||||||
TSAudioStream stream,
|
|
||||||
TSStreamBuffer buffer,
|
|
||||||
ref string tag)
|
|
||||||
{
|
|
||||||
if (stream.IsInitialized) return;
|
|
||||||
|
|
||||||
byte[] header = buffer.ReadBytes(4);
|
|
||||||
int flags = (header[2] << 8) + header[3];
|
|
||||||
|
|
||||||
switch ((flags & 0xF000) >> 12)
|
|
||||||
{
|
|
||||||
case 1: // 1/0/0
|
|
||||||
stream.ChannelCount = 1;
|
|
||||||
stream.LFE = 0;
|
|
||||||
break;
|
|
||||||
case 3: // 2/0/0
|
|
||||||
stream.ChannelCount = 2;
|
|
||||||
stream.LFE = 0;
|
|
||||||
break;
|
|
||||||
case 4: // 3/0/0
|
|
||||||
stream.ChannelCount = 3;
|
|
||||||
stream.LFE = 0;
|
|
||||||
break;
|
|
||||||
case 5: // 2/1/0
|
|
||||||
stream.ChannelCount = 3;
|
|
||||||
stream.LFE = 0;
|
|
||||||
break;
|
|
||||||
case 6: // 3/1/0
|
|
||||||
stream.ChannelCount = 4;
|
|
||||||
stream.LFE = 0;
|
|
||||||
break;
|
|
||||||
case 7: // 2/2/0
|
|
||||||
stream.ChannelCount = 4;
|
|
||||||
stream.LFE = 0;
|
|
||||||
break;
|
|
||||||
case 8: // 3/2/0
|
|
||||||
stream.ChannelCount = 5;
|
|
||||||
stream.LFE = 0;
|
|
||||||
break;
|
|
||||||
case 9: // 3/2/1
|
|
||||||
stream.ChannelCount = 5;
|
|
||||||
stream.LFE = 1;
|
|
||||||
break;
|
|
||||||
case 10: // 3/4/0
|
|
||||||
stream.ChannelCount = 7;
|
|
||||||
stream.LFE = 0;
|
|
||||||
break;
|
|
||||||
case 11: // 3/4/1
|
|
||||||
stream.ChannelCount = 7;
|
|
||||||
stream.LFE = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stream.ChannelCount = 0;
|
|
||||||
stream.LFE = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ((flags & 0xC0) >> 6)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
stream.BitDepth = 16;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
stream.BitDepth = 20;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
stream.BitDepth = 24;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stream.BitDepth = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ((flags & 0xF00) >> 8)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
stream.SampleRate = 48000;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
stream.SampleRate = 96000;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
stream.SampleRate = 192000;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stream.SampleRate = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.BitRate = (uint)
|
|
||||||
(stream.SampleRate * stream.BitDepth *
|
|
||||||
(stream.ChannelCount + stream.LFE));
|
|
||||||
|
|
||||||
stream.IsVBR = false;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,208 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
#undef DEBUG
|
|
||||||
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public abstract class TSCodecMPEG2
|
|
||||||
{
|
|
||||||
public static void Scan(
|
|
||||||
TSVideoStream stream,
|
|
||||||
TSStreamBuffer buffer,
|
|
||||||
ref string tag)
|
|
||||||
{
|
|
||||||
int parse = 0;
|
|
||||||
int pictureParse = 0;
|
|
||||||
int sequenceHeaderParse = 0;
|
|
||||||
int extensionParse = 0;
|
|
||||||
int sequenceExtensionParse = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < buffer.Length; i++)
|
|
||||||
{
|
|
||||||
parse = (parse << 8) + buffer.ReadByte();
|
|
||||||
|
|
||||||
if (parse == 0x00000100)
|
|
||||||
{
|
|
||||||
pictureParse = 2;
|
|
||||||
}
|
|
||||||
else if (parse == 0x000001B3)
|
|
||||||
{
|
|
||||||
sequenceHeaderParse = 7;
|
|
||||||
}
|
|
||||||
else if (sequenceHeaderParse > 0)
|
|
||||||
{
|
|
||||||
--sequenceHeaderParse;
|
|
||||||
switch (sequenceHeaderParse)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
case 6:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
stream.Width =
|
|
||||||
(int)((parse & 0xFFF000) >> 12);
|
|
||||||
stream.Height =
|
|
||||||
(int)(parse & 0xFFF);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
stream.AspectRatio =
|
|
||||||
(TSAspectRatio)((parse & 0xF0) >> 4);
|
|
||||||
|
|
||||||
switch ((parse & 0xF0) >> 4)
|
|
||||||
{
|
|
||||||
case 0: // Forbidden
|
|
||||||
break;
|
|
||||||
case 1: // Square
|
|
||||||
break;
|
|
||||||
case 2: // 4:3
|
|
||||||
break;
|
|
||||||
case 3: // 16:9
|
|
||||||
break;
|
|
||||||
case 4: // 2.21:1
|
|
||||||
break;
|
|
||||||
default: // Reserved
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (parse & 0xF)
|
|
||||||
{
|
|
||||||
case 0: // Forbidden
|
|
||||||
break;
|
|
||||||
case 1: // 23.976
|
|
||||||
stream.FrameRateEnumerator = 24000;
|
|
||||||
stream.FrameRateDenominator = 1001;
|
|
||||||
break;
|
|
||||||
case 2: // 24
|
|
||||||
stream.FrameRateEnumerator = 24000;
|
|
||||||
stream.FrameRateDenominator = 1000;
|
|
||||||
break;
|
|
||||||
case 3: // 25
|
|
||||||
stream.FrameRateEnumerator = 25000;
|
|
||||||
stream.FrameRateDenominator = 1000;
|
|
||||||
break;
|
|
||||||
case 4: // 29.97
|
|
||||||
stream.FrameRateEnumerator = 30000;
|
|
||||||
stream.FrameRateDenominator = 1001;
|
|
||||||
break;
|
|
||||||
case 5: // 30
|
|
||||||
stream.FrameRateEnumerator = 30000;
|
|
||||||
stream.FrameRateDenominator = 1000;
|
|
||||||
break;
|
|
||||||
case 6: // 50
|
|
||||||
stream.FrameRateEnumerator = 50000;
|
|
||||||
stream.FrameRateDenominator = 1000;
|
|
||||||
break;
|
|
||||||
case 7: // 59.94
|
|
||||||
stream.FrameRateEnumerator = 60000;
|
|
||||||
stream.FrameRateDenominator = 1001;
|
|
||||||
break;
|
|
||||||
case 8: // 60
|
|
||||||
stream.FrameRateEnumerator = 60000;
|
|
||||||
stream.FrameRateDenominator = 1000;
|
|
||||||
break;
|
|
||||||
default: // Reserved
|
|
||||||
stream.FrameRateEnumerator = 0;
|
|
||||||
stream.FrameRateDenominator = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
#if DEBUG
|
|
||||||
stream.BitRate =
|
|
||||||
(((parse & 0xFFFFC0) >> 6) * 200);
|
|
||||||
#endif
|
|
||||||
stream.IsVBR = true;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pictureParse > 0)
|
|
||||||
{
|
|
||||||
--pictureParse;
|
|
||||||
if (pictureParse == 0)
|
|
||||||
{
|
|
||||||
switch ((parse & 0x38) >> 3)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
tag = "I";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
tag = "P";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
tag = "B";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (stream.IsInitialized) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (parse == 0x000001B5)
|
|
||||||
{
|
|
||||||
extensionParse = 1;
|
|
||||||
}
|
|
||||||
else if (extensionParse > 0)
|
|
||||||
{
|
|
||||||
--extensionParse;
|
|
||||||
if (extensionParse == 0)
|
|
||||||
{
|
|
||||||
if ((parse & 0xF0) == 0x10)
|
|
||||||
{
|
|
||||||
sequenceExtensionParse = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (sequenceExtensionParse > 0)
|
|
||||||
{
|
|
||||||
--sequenceExtensionParse;
|
|
||||||
#if DEBUG
|
|
||||||
if (sequenceExtensionParse == 0)
|
|
||||||
{
|
|
||||||
uint sequenceExtension =
|
|
||||||
((parse & 0x8) >> 3);
|
|
||||||
if (sequenceExtension == 0)
|
|
||||||
{
|
|
||||||
stream.IsInterlaced = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream.IsInterlaced = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
// TODO: Do something more interesting here...
|
|
||||||
|
|
||||||
public abstract class TSCodecMVC
|
|
||||||
{
|
|
||||||
public static void Scan(
|
|
||||||
TSVideoStream stream,
|
|
||||||
TSStreamBuffer buffer,
|
|
||||||
ref string tag)
|
|
||||||
{
|
|
||||||
stream.IsVBR = true;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,186 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public abstract class TSCodecTrueHD
|
|
||||||
{
|
|
||||||
public static void Scan(
|
|
||||||
TSAudioStream stream,
|
|
||||||
TSStreamBuffer buffer,
|
|
||||||
ref string tag)
|
|
||||||
{
|
|
||||||
if (stream.IsInitialized &&
|
|
||||||
stream.CoreStream != null &&
|
|
||||||
stream.CoreStream.IsInitialized) return;
|
|
||||||
|
|
||||||
bool syncFound = false;
|
|
||||||
uint sync = 0;
|
|
||||||
for (int i = 0; i < buffer.Length; i++)
|
|
||||||
{
|
|
||||||
sync = (sync << 8) + buffer.ReadByte();
|
|
||||||
if (sync == 0xF8726FBA)
|
|
||||||
{
|
|
||||||
syncFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!syncFound)
|
|
||||||
{
|
|
||||||
tag = "CORE";
|
|
||||||
if (stream.CoreStream == null)
|
|
||||||
{
|
|
||||||
stream.CoreStream = new TSAudioStream();
|
|
||||||
stream.CoreStream.StreamType = TSStreamType.AC3_AUDIO;
|
|
||||||
}
|
|
||||||
if (!stream.CoreStream.IsInitialized)
|
|
||||||
{
|
|
||||||
buffer.BeginRead();
|
|
||||||
TSCodecAC3.Scan(stream.CoreStream, buffer, ref tag);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tag = "HD";
|
|
||||||
int ratebits = buffer.ReadBits(4);
|
|
||||||
if (ratebits != 0xF)
|
|
||||||
{
|
|
||||||
stream.SampleRate =
|
|
||||||
(((ratebits & 8) > 0 ? 44100 : 48000) << (ratebits & 7));
|
|
||||||
}
|
|
||||||
int temp1 = buffer.ReadBits(8);
|
|
||||||
int channels_thd_stream1 = buffer.ReadBits(5);
|
|
||||||
int temp2 = buffer.ReadBits(2);
|
|
||||||
|
|
||||||
stream.ChannelCount = 0;
|
|
||||||
stream.LFE = 0;
|
|
||||||
int c_LFE2 = buffer.ReadBits(1);
|
|
||||||
if (c_LFE2 == 1)
|
|
||||||
{
|
|
||||||
stream.LFE += 1;
|
|
||||||
}
|
|
||||||
int c_Cvh = buffer.ReadBits(1);
|
|
||||||
if (c_Cvh == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 1;
|
|
||||||
}
|
|
||||||
int c_LRw = buffer.ReadBits(1);
|
|
||||||
if (c_LRw == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 2;
|
|
||||||
}
|
|
||||||
int c_LRsd = buffer.ReadBits(1);
|
|
||||||
if (c_LRsd == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 2;
|
|
||||||
}
|
|
||||||
int c_Ts = buffer.ReadBits(1);
|
|
||||||
if (c_Ts == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 1;
|
|
||||||
}
|
|
||||||
int c_Cs = buffer.ReadBits(1);
|
|
||||||
if (c_Cs == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 1;
|
|
||||||
}
|
|
||||||
int c_LRrs = buffer.ReadBits(1);
|
|
||||||
if (c_LRrs == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 2;
|
|
||||||
}
|
|
||||||
int c_LRc = buffer.ReadBits(1);
|
|
||||||
if (c_LRc == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 2;
|
|
||||||
}
|
|
||||||
int c_LRvh = buffer.ReadBits(1);
|
|
||||||
if (c_LRvh == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 2;
|
|
||||||
}
|
|
||||||
int c_LRs = buffer.ReadBits(1);
|
|
||||||
if (c_LRs == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 2;
|
|
||||||
}
|
|
||||||
int c_LFE = buffer.ReadBits(1);
|
|
||||||
if (c_LFE == 1)
|
|
||||||
{
|
|
||||||
stream.LFE += 1;
|
|
||||||
}
|
|
||||||
int c_C = buffer.ReadBits(1);
|
|
||||||
if (c_C == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 1;
|
|
||||||
}
|
|
||||||
int c_LR = buffer.ReadBits(1);
|
|
||||||
if (c_LR == 1)
|
|
||||||
{
|
|
||||||
stream.ChannelCount += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int access_unit_size = 40 << (ratebits & 7);
|
|
||||||
int access_unit_size_pow2 = 64 << (ratebits & 7);
|
|
||||||
|
|
||||||
int a1 = buffer.ReadBits(16);
|
|
||||||
int a2 = buffer.ReadBits(16);
|
|
||||||
int a3 = buffer.ReadBits(16);
|
|
||||||
|
|
||||||
int is_vbr = buffer.ReadBits(1);
|
|
||||||
int peak_bitrate = buffer.ReadBits(15);
|
|
||||||
peak_bitrate = (peak_bitrate * stream.SampleRate) >> 4;
|
|
||||||
|
|
||||||
double peak_bitdepth =
|
|
||||||
(double)peak_bitrate /
|
|
||||||
(stream.ChannelCount + stream.LFE) /
|
|
||||||
stream.SampleRate;
|
|
||||||
if (peak_bitdepth > 14)
|
|
||||||
{
|
|
||||||
stream.BitDepth = 24;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream.BitDepth = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
System.Diagnostics.Debug.WriteLine(string.Format(
|
|
||||||
"{0}\t{1}\t{2:F2}",
|
|
||||||
stream.PID, peak_bitrate, peak_bitdepth));
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
// TODO: Get THD dialnorm from metadata
|
|
||||||
if (stream.CoreStream != null)
|
|
||||||
{
|
|
||||||
TSAudioStream coreStream = (TSAudioStream)stream.CoreStream;
|
|
||||||
if (coreStream.DialNorm != 0)
|
|
||||||
{
|
|
||||||
stream.DialNorm = coreStream.DialNorm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
stream.IsVBR = true;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public abstract class TSCodecVC1
|
|
||||||
{
|
|
||||||
public static void Scan(
|
|
||||||
TSVideoStream stream,
|
|
||||||
TSStreamBuffer buffer,
|
|
||||||
ref string tag)
|
|
||||||
{
|
|
||||||
int parse = 0;
|
|
||||||
byte frameHeaderParse = 0;
|
|
||||||
byte sequenceHeaderParse = 0;
|
|
||||||
bool isInterlaced = false;
|
|
||||||
|
|
||||||
for (int i = 0; i < buffer.Length; i++)
|
|
||||||
{
|
|
||||||
parse = (parse << 8) + buffer.ReadByte();
|
|
||||||
|
|
||||||
if (parse == 0x0000010D)
|
|
||||||
{
|
|
||||||
frameHeaderParse = 4;
|
|
||||||
}
|
|
||||||
else if (frameHeaderParse > 0)
|
|
||||||
{
|
|
||||||
--frameHeaderParse;
|
|
||||||
if (frameHeaderParse == 0)
|
|
||||||
{
|
|
||||||
uint pictureType = 0;
|
|
||||||
if (isInterlaced)
|
|
||||||
{
|
|
||||||
if ((parse & 0x80000000) == 0)
|
|
||||||
{
|
|
||||||
pictureType =
|
|
||||||
(uint)((parse & 0x78000000) >> 13);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pictureType =
|
|
||||||
(uint)((parse & 0x3c000000) >> 12);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pictureType =
|
|
||||||
(uint)((parse & 0xf0000000) >> 14);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pictureType & 0x20000) == 0)
|
|
||||||
{
|
|
||||||
tag = "P";
|
|
||||||
}
|
|
||||||
else if ((pictureType & 0x10000) == 0)
|
|
||||||
{
|
|
||||||
tag = "B";
|
|
||||||
}
|
|
||||||
else if ((pictureType & 0x8000) == 0)
|
|
||||||
{
|
|
||||||
tag = "I";
|
|
||||||
}
|
|
||||||
else if ((pictureType & 0x4000) == 0)
|
|
||||||
{
|
|
||||||
tag = "BI";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tag = null;
|
|
||||||
}
|
|
||||||
if (stream.IsInitialized) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (parse == 0x0000010F)
|
|
||||||
{
|
|
||||||
sequenceHeaderParse = 6;
|
|
||||||
}
|
|
||||||
else if (sequenceHeaderParse > 0)
|
|
||||||
{
|
|
||||||
--sequenceHeaderParse;
|
|
||||||
switch (sequenceHeaderParse)
|
|
||||||
{
|
|
||||||
case 5:
|
|
||||||
int profileLevel = ((parse & 0x38) >> 3);
|
|
||||||
if (((parse & 0xC0) >> 6) == 3)
|
|
||||||
{
|
|
||||||
stream.EncodingProfile = string.Format(
|
|
||||||
"Advanced Profile {0}", profileLevel);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream.EncodingProfile = string.Format(
|
|
||||||
"Main Profile {0}", profileLevel);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
if (((parse & 0x40) >> 6) > 0)
|
|
||||||
{
|
|
||||||
isInterlaced = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isInterlaced = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
stream.IsVBR = true;
|
|
||||||
stream.IsInitialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
|
|
||||||
// TODO: Do more interesting things here...
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public class TSInterleavedFile
|
|
||||||
{
|
|
||||||
public FileSystemMetadata FileInfo = null;
|
|
||||||
public string Name = null;
|
|
||||||
|
|
||||||
public TSInterleavedFile(FileSystemMetadata fileInfo)
|
|
||||||
{
|
|
||||||
FileInfo = fileInfo;
|
|
||||||
Name = fileInfo.Name.ToUpper();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,780 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public enum TSStreamType : byte
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
MPEG1_VIDEO = 0x01,
|
|
||||||
MPEG2_VIDEO = 0x02,
|
|
||||||
AVC_VIDEO = 0x1b,
|
|
||||||
MVC_VIDEO = 0x20,
|
|
||||||
VC1_VIDEO = 0xea,
|
|
||||||
MPEG1_AUDIO = 0x03,
|
|
||||||
MPEG2_AUDIO = 0x04,
|
|
||||||
LPCM_AUDIO = 0x80,
|
|
||||||
AC3_AUDIO = 0x81,
|
|
||||||
AC3_PLUS_AUDIO = 0x84,
|
|
||||||
AC3_PLUS_SECONDARY_AUDIO = 0xA1,
|
|
||||||
AC3_TRUE_HD_AUDIO = 0x83,
|
|
||||||
DTS_AUDIO = 0x82,
|
|
||||||
DTS_HD_AUDIO = 0x85,
|
|
||||||
DTS_HD_SECONDARY_AUDIO = 0xA2,
|
|
||||||
DTS_HD_MASTER_AUDIO = 0x86,
|
|
||||||
PRESENTATION_GRAPHICS = 0x90,
|
|
||||||
INTERACTIVE_GRAPHICS = 0x91,
|
|
||||||
SUBTITLE = 0x92
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TSVideoFormat : byte
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
VIDEOFORMAT_480i = 1,
|
|
||||||
VIDEOFORMAT_576i = 2,
|
|
||||||
VIDEOFORMAT_480p = 3,
|
|
||||||
VIDEOFORMAT_1080i = 4,
|
|
||||||
VIDEOFORMAT_720p = 5,
|
|
||||||
VIDEOFORMAT_1080p = 6,
|
|
||||||
VIDEOFORMAT_576p = 7,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TSFrameRate : byte
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
FRAMERATE_23_976 = 1,
|
|
||||||
FRAMERATE_24 = 2,
|
|
||||||
FRAMERATE_25 = 3,
|
|
||||||
FRAMERATE_29_97 = 4,
|
|
||||||
FRAMERATE_50 = 6,
|
|
||||||
FRAMERATE_59_94 = 7
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TSChannelLayout : byte
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
CHANNELLAYOUT_MONO = 1,
|
|
||||||
CHANNELLAYOUT_STEREO = 3,
|
|
||||||
CHANNELLAYOUT_MULTI = 6,
|
|
||||||
CHANNELLAYOUT_COMBO = 12
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TSSampleRate : byte
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
SAMPLERATE_48 = 1,
|
|
||||||
SAMPLERATE_96 = 4,
|
|
||||||
SAMPLERATE_192 = 5,
|
|
||||||
SAMPLERATE_48_192 = 12,
|
|
||||||
SAMPLERATE_48_96 = 14
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TSAspectRatio
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
ASPECT_4_3 = 2,
|
|
||||||
ASPECT_16_9 = 3,
|
|
||||||
ASPECT_2_21 = 4
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TSDescriptor
|
|
||||||
{
|
|
||||||
public byte Name;
|
|
||||||
public byte[] Value;
|
|
||||||
|
|
||||||
public TSDescriptor(byte name, byte length)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
Value = new byte[length];
|
|
||||||
}
|
|
||||||
|
|
||||||
public TSDescriptor Clone()
|
|
||||||
{
|
|
||||||
var descriptor =
|
|
||||||
new TSDescriptor(Name, (byte)Value.Length);
|
|
||||||
Value.CopyTo(descriptor.Value, 0);
|
|
||||||
return descriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class TSStream
|
|
||||||
{
|
|
||||||
public TSStream()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return string.Format("{0} ({1})", CodecShortName, PID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ushort PID;
|
|
||||||
public TSStreamType StreamType;
|
|
||||||
public List<TSDescriptor> Descriptors = null;
|
|
||||||
public long BitRate = 0;
|
|
||||||
public long ActiveBitRate = 0;
|
|
||||||
public bool IsVBR = false;
|
|
||||||
public bool IsInitialized = false;
|
|
||||||
public string LanguageName;
|
|
||||||
public bool IsHidden = false;
|
|
||||||
|
|
||||||
public ulong PayloadBytes = 0;
|
|
||||||
public ulong PacketCount = 0;
|
|
||||||
public double PacketSeconds = 0;
|
|
||||||
public int AngleIndex = 0;
|
|
||||||
|
|
||||||
public ulong PacketSize => PacketCount * 192;
|
|
||||||
|
|
||||||
private string _LanguageCode;
|
|
||||||
public string LanguageCode
|
|
||||||
{
|
|
||||||
get => _LanguageCode;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_LanguageCode = value;
|
|
||||||
LanguageName = LanguageCodes.GetName(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsVideoStream
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (StreamType)
|
|
||||||
{
|
|
||||||
case TSStreamType.MPEG1_VIDEO:
|
|
||||||
case TSStreamType.MPEG2_VIDEO:
|
|
||||||
case TSStreamType.AVC_VIDEO:
|
|
||||||
case TSStreamType.MVC_VIDEO:
|
|
||||||
case TSStreamType.VC1_VIDEO:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsAudioStream
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (StreamType)
|
|
||||||
{
|
|
||||||
case TSStreamType.MPEG1_AUDIO:
|
|
||||||
case TSStreamType.MPEG2_AUDIO:
|
|
||||||
case TSStreamType.LPCM_AUDIO:
|
|
||||||
case TSStreamType.AC3_AUDIO:
|
|
||||||
case TSStreamType.AC3_PLUS_AUDIO:
|
|
||||||
case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
|
|
||||||
case TSStreamType.AC3_TRUE_HD_AUDIO:
|
|
||||||
case TSStreamType.DTS_AUDIO:
|
|
||||||
case TSStreamType.DTS_HD_AUDIO:
|
|
||||||
case TSStreamType.DTS_HD_SECONDARY_AUDIO:
|
|
||||||
case TSStreamType.DTS_HD_MASTER_AUDIO:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsGraphicsStream
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (StreamType)
|
|
||||||
{
|
|
||||||
case TSStreamType.PRESENTATION_GRAPHICS:
|
|
||||||
case TSStreamType.INTERACTIVE_GRAPHICS:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsTextStream
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (StreamType)
|
|
||||||
{
|
|
||||||
case TSStreamType.SUBTITLE:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string CodecName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (StreamType)
|
|
||||||
{
|
|
||||||
case TSStreamType.MPEG1_VIDEO:
|
|
||||||
return "MPEG-1 Video";
|
|
||||||
case TSStreamType.MPEG2_VIDEO:
|
|
||||||
return "MPEG-2 Video";
|
|
||||||
case TSStreamType.AVC_VIDEO:
|
|
||||||
return "MPEG-4 AVC Video";
|
|
||||||
case TSStreamType.MVC_VIDEO:
|
|
||||||
return "MPEG-4 MVC Video";
|
|
||||||
case TSStreamType.VC1_VIDEO:
|
|
||||||
return "VC-1 Video";
|
|
||||||
case TSStreamType.MPEG1_AUDIO:
|
|
||||||
return "MP1 Audio";
|
|
||||||
case TSStreamType.MPEG2_AUDIO:
|
|
||||||
return "MP2 Audio";
|
|
||||||
case TSStreamType.LPCM_AUDIO:
|
|
||||||
return "LPCM Audio";
|
|
||||||
case TSStreamType.AC3_AUDIO:
|
|
||||||
if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended)
|
|
||||||
return "Dolby Digital EX Audio";
|
|
||||||
else
|
|
||||||
return "Dolby Digital Audio";
|
|
||||||
case TSStreamType.AC3_PLUS_AUDIO:
|
|
||||||
case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
|
|
||||||
return "Dolby Digital Plus Audio";
|
|
||||||
case TSStreamType.AC3_TRUE_HD_AUDIO:
|
|
||||||
return "Dolby TrueHD Audio";
|
|
||||||
case TSStreamType.DTS_AUDIO:
|
|
||||||
if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended)
|
|
||||||
return "DTS-ES Audio";
|
|
||||||
else
|
|
||||||
return "DTS Audio";
|
|
||||||
case TSStreamType.DTS_HD_AUDIO:
|
|
||||||
return "DTS-HD High-Res Audio";
|
|
||||||
case TSStreamType.DTS_HD_SECONDARY_AUDIO:
|
|
||||||
return "DTS Express";
|
|
||||||
case TSStreamType.DTS_HD_MASTER_AUDIO:
|
|
||||||
return "DTS-HD Master Audio";
|
|
||||||
case TSStreamType.PRESENTATION_GRAPHICS:
|
|
||||||
return "Presentation Graphics";
|
|
||||||
case TSStreamType.INTERACTIVE_GRAPHICS:
|
|
||||||
return "Interactive Graphics";
|
|
||||||
case TSStreamType.SUBTITLE:
|
|
||||||
return "Subtitle";
|
|
||||||
default:
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string CodecAltName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (StreamType)
|
|
||||||
{
|
|
||||||
case TSStreamType.MPEG1_VIDEO:
|
|
||||||
return "MPEG-1";
|
|
||||||
case TSStreamType.MPEG2_VIDEO:
|
|
||||||
return "MPEG-2";
|
|
||||||
case TSStreamType.AVC_VIDEO:
|
|
||||||
return "AVC";
|
|
||||||
case TSStreamType.MVC_VIDEO:
|
|
||||||
return "MVC";
|
|
||||||
case TSStreamType.VC1_VIDEO:
|
|
||||||
return "VC-1";
|
|
||||||
case TSStreamType.MPEG1_AUDIO:
|
|
||||||
return "MP1";
|
|
||||||
case TSStreamType.MPEG2_AUDIO:
|
|
||||||
return "MP2";
|
|
||||||
case TSStreamType.LPCM_AUDIO:
|
|
||||||
return "LPCM";
|
|
||||||
case TSStreamType.AC3_AUDIO:
|
|
||||||
return "DD AC3";
|
|
||||||
case TSStreamType.AC3_PLUS_AUDIO:
|
|
||||||
case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
|
|
||||||
return "DD AC3+";
|
|
||||||
case TSStreamType.AC3_TRUE_HD_AUDIO:
|
|
||||||
return "Dolby TrueHD";
|
|
||||||
case TSStreamType.DTS_AUDIO:
|
|
||||||
return "DTS";
|
|
||||||
case TSStreamType.DTS_HD_AUDIO:
|
|
||||||
return "DTS-HD Hi-Res";
|
|
||||||
case TSStreamType.DTS_HD_SECONDARY_AUDIO:
|
|
||||||
return "DTS Express";
|
|
||||||
case TSStreamType.DTS_HD_MASTER_AUDIO:
|
|
||||||
return "DTS-HD Master";
|
|
||||||
case TSStreamType.PRESENTATION_GRAPHICS:
|
|
||||||
return "PGS";
|
|
||||||
case TSStreamType.INTERACTIVE_GRAPHICS:
|
|
||||||
return "IGS";
|
|
||||||
case TSStreamType.SUBTITLE:
|
|
||||||
return "SUB";
|
|
||||||
default:
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string CodecShortName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (StreamType)
|
|
||||||
{
|
|
||||||
case TSStreamType.MPEG1_VIDEO:
|
|
||||||
return "MPEG-1";
|
|
||||||
case TSStreamType.MPEG2_VIDEO:
|
|
||||||
return "MPEG-2";
|
|
||||||
case TSStreamType.AVC_VIDEO:
|
|
||||||
return "AVC";
|
|
||||||
case TSStreamType.MVC_VIDEO:
|
|
||||||
return "MVC";
|
|
||||||
case TSStreamType.VC1_VIDEO:
|
|
||||||
return "VC-1";
|
|
||||||
case TSStreamType.MPEG1_AUDIO:
|
|
||||||
return "MP1";
|
|
||||||
case TSStreamType.MPEG2_AUDIO:
|
|
||||||
return "MP2";
|
|
||||||
case TSStreamType.LPCM_AUDIO:
|
|
||||||
return "LPCM";
|
|
||||||
case TSStreamType.AC3_AUDIO:
|
|
||||||
if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended)
|
|
||||||
return "AC3-EX";
|
|
||||||
else
|
|
||||||
return "AC3";
|
|
||||||
case TSStreamType.AC3_PLUS_AUDIO:
|
|
||||||
case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
|
|
||||||
return "AC3+";
|
|
||||||
case TSStreamType.AC3_TRUE_HD_AUDIO:
|
|
||||||
return "TrueHD";
|
|
||||||
case TSStreamType.DTS_AUDIO:
|
|
||||||
if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended)
|
|
||||||
return "DTS-ES";
|
|
||||||
else
|
|
||||||
return "DTS";
|
|
||||||
case TSStreamType.DTS_HD_AUDIO:
|
|
||||||
return "DTS-HD HR";
|
|
||||||
case TSStreamType.DTS_HD_SECONDARY_AUDIO:
|
|
||||||
return "DTS Express";
|
|
||||||
case TSStreamType.DTS_HD_MASTER_AUDIO:
|
|
||||||
return "DTS-HD MA";
|
|
||||||
case TSStreamType.PRESENTATION_GRAPHICS:
|
|
||||||
return "PGS";
|
|
||||||
case TSStreamType.INTERACTIVE_GRAPHICS:
|
|
||||||
return "IGS";
|
|
||||||
case TSStreamType.SUBTITLE:
|
|
||||||
return "SUB";
|
|
||||||
default:
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual string Description => "";
|
|
||||||
|
|
||||||
public abstract TSStream Clone();
|
|
||||||
|
|
||||||
protected void CopyTo(TSStream stream)
|
|
||||||
{
|
|
||||||
stream.PID = PID;
|
|
||||||
stream.StreamType = StreamType;
|
|
||||||
stream.IsVBR = IsVBR;
|
|
||||||
stream.BitRate = BitRate;
|
|
||||||
stream.IsInitialized = IsInitialized;
|
|
||||||
stream.LanguageCode = _LanguageCode;
|
|
||||||
if (Descriptors != null)
|
|
||||||
{
|
|
||||||
stream.Descriptors = new List<TSDescriptor>();
|
|
||||||
foreach (var descriptor in Descriptors)
|
|
||||||
{
|
|
||||||
stream.Descriptors.Add(descriptor.Clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TSVideoStream : TSStream
|
|
||||||
{
|
|
||||||
public TSVideoStream()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Width;
|
|
||||||
public int Height;
|
|
||||||
public bool IsInterlaced;
|
|
||||||
public int FrameRateEnumerator;
|
|
||||||
public int FrameRateDenominator;
|
|
||||||
public TSAspectRatio AspectRatio;
|
|
||||||
public string EncodingProfile;
|
|
||||||
|
|
||||||
private TSVideoFormat _VideoFormat;
|
|
||||||
public TSVideoFormat VideoFormat
|
|
||||||
{
|
|
||||||
get => _VideoFormat;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_VideoFormat = value;
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case TSVideoFormat.VIDEOFORMAT_480i:
|
|
||||||
Height = 480;
|
|
||||||
IsInterlaced = true;
|
|
||||||
break;
|
|
||||||
case TSVideoFormat.VIDEOFORMAT_480p:
|
|
||||||
Height = 480;
|
|
||||||
IsInterlaced = false;
|
|
||||||
break;
|
|
||||||
case TSVideoFormat.VIDEOFORMAT_576i:
|
|
||||||
Height = 576;
|
|
||||||
IsInterlaced = true;
|
|
||||||
break;
|
|
||||||
case TSVideoFormat.VIDEOFORMAT_576p:
|
|
||||||
Height = 576;
|
|
||||||
IsInterlaced = false;
|
|
||||||
break;
|
|
||||||
case TSVideoFormat.VIDEOFORMAT_720p:
|
|
||||||
Height = 720;
|
|
||||||
IsInterlaced = false;
|
|
||||||
break;
|
|
||||||
case TSVideoFormat.VIDEOFORMAT_1080i:
|
|
||||||
Height = 1080;
|
|
||||||
IsInterlaced = true;
|
|
||||||
break;
|
|
||||||
case TSVideoFormat.VIDEOFORMAT_1080p:
|
|
||||||
Height = 1080;
|
|
||||||
IsInterlaced = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TSFrameRate _FrameRate;
|
|
||||||
public TSFrameRate FrameRate
|
|
||||||
{
|
|
||||||
get => _FrameRate;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_FrameRate = value;
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case TSFrameRate.FRAMERATE_23_976:
|
|
||||||
FrameRateEnumerator = 24000;
|
|
||||||
FrameRateDenominator = 1001;
|
|
||||||
break;
|
|
||||||
case TSFrameRate.FRAMERATE_24:
|
|
||||||
FrameRateEnumerator = 24000;
|
|
||||||
FrameRateDenominator = 1000;
|
|
||||||
break;
|
|
||||||
case TSFrameRate.FRAMERATE_25:
|
|
||||||
FrameRateEnumerator = 25000;
|
|
||||||
FrameRateDenominator = 1000;
|
|
||||||
break;
|
|
||||||
case TSFrameRate.FRAMERATE_29_97:
|
|
||||||
FrameRateEnumerator = 30000;
|
|
||||||
FrameRateDenominator = 1001;
|
|
||||||
break;
|
|
||||||
case TSFrameRate.FRAMERATE_50:
|
|
||||||
FrameRateEnumerator = 50000;
|
|
||||||
FrameRateDenominator = 1000;
|
|
||||||
break;
|
|
||||||
case TSFrameRate.FRAMERATE_59_94:
|
|
||||||
FrameRateEnumerator = 60000;
|
|
||||||
FrameRateDenominator = 1001;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Description
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
string description = "";
|
|
||||||
|
|
||||||
if (Height > 0)
|
|
||||||
{
|
|
||||||
description += string.Format("{0:D}{1} / ",
|
|
||||||
Height,
|
|
||||||
IsInterlaced ? "i" : "p");
|
|
||||||
}
|
|
||||||
if (FrameRateEnumerator > 0 &&
|
|
||||||
FrameRateDenominator > 0)
|
|
||||||
{
|
|
||||||
if (FrameRateEnumerator % FrameRateDenominator == 0)
|
|
||||||
{
|
|
||||||
description += string.Format("{0:D} fps / ",
|
|
||||||
FrameRateEnumerator / FrameRateDenominator);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
description += string.Format("{0:F3} fps / ",
|
|
||||||
(double)FrameRateEnumerator / FrameRateDenominator);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (AspectRatio == TSAspectRatio.ASPECT_4_3)
|
|
||||||
{
|
|
||||||
description += "4:3 / ";
|
|
||||||
}
|
|
||||||
else if (AspectRatio == TSAspectRatio.ASPECT_16_9)
|
|
||||||
{
|
|
||||||
description += "16:9 / ";
|
|
||||||
}
|
|
||||||
if (EncodingProfile != null)
|
|
||||||
{
|
|
||||||
description += EncodingProfile + " / ";
|
|
||||||
}
|
|
||||||
if (description.EndsWith(" / "))
|
|
||||||
{
|
|
||||||
description = description.Substring(0, description.Length - 3);
|
|
||||||
}
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override TSStream Clone()
|
|
||||||
{
|
|
||||||
var stream = new TSVideoStream();
|
|
||||||
CopyTo(stream);
|
|
||||||
|
|
||||||
stream.VideoFormat = _VideoFormat;
|
|
||||||
stream.FrameRate = _FrameRate;
|
|
||||||
stream.Width = Width;
|
|
||||||
stream.Height = Height;
|
|
||||||
stream.IsInterlaced = IsInterlaced;
|
|
||||||
stream.FrameRateEnumerator = FrameRateEnumerator;
|
|
||||||
stream.FrameRateDenominator = FrameRateDenominator;
|
|
||||||
stream.AspectRatio = AspectRatio;
|
|
||||||
stream.EncodingProfile = EncodingProfile;
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TSAudioMode
|
|
||||||
{
|
|
||||||
Unknown,
|
|
||||||
DualMono,
|
|
||||||
Stereo,
|
|
||||||
Surround,
|
|
||||||
Extended
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TSAudioStream : TSStream
|
|
||||||
{
|
|
||||||
public TSAudioStream()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public int SampleRate;
|
|
||||||
public int ChannelCount;
|
|
||||||
public int BitDepth;
|
|
||||||
public int LFE;
|
|
||||||
public int DialNorm;
|
|
||||||
public TSAudioMode AudioMode;
|
|
||||||
public TSAudioStream CoreStream;
|
|
||||||
public TSChannelLayout ChannelLayout;
|
|
||||||
|
|
||||||
public static int ConvertSampleRate(
|
|
||||||
TSSampleRate sampleRate)
|
|
||||||
{
|
|
||||||
switch (sampleRate)
|
|
||||||
{
|
|
||||||
case TSSampleRate.SAMPLERATE_48:
|
|
||||||
return 48000;
|
|
||||||
|
|
||||||
case TSSampleRate.SAMPLERATE_96:
|
|
||||||
case TSSampleRate.SAMPLERATE_48_96:
|
|
||||||
return 96000;
|
|
||||||
|
|
||||||
case TSSampleRate.SAMPLERATE_192:
|
|
||||||
case TSSampleRate.SAMPLERATE_48_192:
|
|
||||||
return 192000;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ChannelDescription
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (ChannelLayout == TSChannelLayout.CHANNELLAYOUT_MONO &&
|
|
||||||
ChannelCount == 2)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
string description = "";
|
|
||||||
if (ChannelCount > 0)
|
|
||||||
{
|
|
||||||
description += string.Format(
|
|
||||||
"{0:D}.{1:D}",
|
|
||||||
ChannelCount, LFE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (ChannelLayout)
|
|
||||||
{
|
|
||||||
case TSChannelLayout.CHANNELLAYOUT_MONO:
|
|
||||||
description += "1.0";
|
|
||||||
break;
|
|
||||||
case TSChannelLayout.CHANNELLAYOUT_STEREO:
|
|
||||||
description += "2.0";
|
|
||||||
break;
|
|
||||||
case TSChannelLayout.CHANNELLAYOUT_MULTI:
|
|
||||||
description += "5.1";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (AudioMode == TSAudioMode.Extended)
|
|
||||||
{
|
|
||||||
if (StreamType == TSStreamType.AC3_AUDIO)
|
|
||||||
{
|
|
||||||
description += "-EX";
|
|
||||||
}
|
|
||||||
if (StreamType == TSStreamType.DTS_AUDIO ||
|
|
||||||
StreamType == TSStreamType.DTS_HD_AUDIO ||
|
|
||||||
StreamType == TSStreamType.DTS_HD_MASTER_AUDIO)
|
|
||||||
{
|
|
||||||
description += "-ES";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Description
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
string description = ChannelDescription;
|
|
||||||
|
|
||||||
if (SampleRate > 0)
|
|
||||||
{
|
|
||||||
description += string.Format(
|
|
||||||
" / {0:D} kHz", SampleRate / 1000);
|
|
||||||
}
|
|
||||||
if (BitRate > 0)
|
|
||||||
{
|
|
||||||
description += string.Format(
|
|
||||||
" / {0:D} kbps", (uint)Math.Round((double)BitRate / 1000));
|
|
||||||
}
|
|
||||||
if (BitDepth > 0)
|
|
||||||
{
|
|
||||||
description += string.Format(
|
|
||||||
" / {0:D}-bit", BitDepth);
|
|
||||||
}
|
|
||||||
if (DialNorm != 0)
|
|
||||||
{
|
|
||||||
description += string.Format(
|
|
||||||
" / DN {0}dB", DialNorm);
|
|
||||||
}
|
|
||||||
if (ChannelCount == 2)
|
|
||||||
{
|
|
||||||
switch (AudioMode)
|
|
||||||
{
|
|
||||||
case TSAudioMode.DualMono:
|
|
||||||
description += " / Dual Mono";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSAudioMode.Surround:
|
|
||||||
description += " / Dolby Surround";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (description.EndsWith(" / "))
|
|
||||||
{
|
|
||||||
description = description.Substring(0, description.Length - 3);
|
|
||||||
}
|
|
||||||
if (CoreStream != null)
|
|
||||||
{
|
|
||||||
string codec = "";
|
|
||||||
switch (CoreStream.StreamType)
|
|
||||||
{
|
|
||||||
case TSStreamType.AC3_AUDIO:
|
|
||||||
codec = "AC3 Embedded";
|
|
||||||
break;
|
|
||||||
case TSStreamType.DTS_AUDIO:
|
|
||||||
codec = "DTS Core";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
description += string.Format(
|
|
||||||
" ({0}: {1})",
|
|
||||||
codec,
|
|
||||||
CoreStream.Description);
|
|
||||||
}
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override TSStream Clone()
|
|
||||||
{
|
|
||||||
var stream = new TSAudioStream();
|
|
||||||
CopyTo(stream);
|
|
||||||
|
|
||||||
stream.SampleRate = SampleRate;
|
|
||||||
stream.ChannelLayout = ChannelLayout;
|
|
||||||
stream.ChannelCount = ChannelCount;
|
|
||||||
stream.BitDepth = BitDepth;
|
|
||||||
stream.LFE = LFE;
|
|
||||||
stream.DialNorm = DialNorm;
|
|
||||||
stream.AudioMode = AudioMode;
|
|
||||||
if (CoreStream != null)
|
|
||||||
{
|
|
||||||
stream.CoreStream = (TSAudioStream)CoreStream.Clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TSGraphicsStream : TSStream
|
|
||||||
{
|
|
||||||
public TSGraphicsStream()
|
|
||||||
{
|
|
||||||
IsVBR = true;
|
|
||||||
IsInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override TSStream Clone()
|
|
||||||
{
|
|
||||||
var stream = new TSGraphicsStream();
|
|
||||||
CopyTo(stream);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TSTextStream : TSStream
|
|
||||||
{
|
|
||||||
public TSTextStream()
|
|
||||||
{
|
|
||||||
IsVBR = true;
|
|
||||||
IsInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override TSStream Clone()
|
|
||||||
{
|
|
||||||
var stream = new TSTextStream();
|
|
||||||
CopyTo(stream);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,130 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public class TSStreamBuffer
|
|
||||||
{
|
|
||||||
private MemoryStream Stream = new MemoryStream();
|
|
||||||
private int SkipBits = 0;
|
|
||||||
private byte[] Buffer;
|
|
||||||
private int BufferLength = 0;
|
|
||||||
public int TransferLength = 0;
|
|
||||||
|
|
||||||
public TSStreamBuffer()
|
|
||||||
{
|
|
||||||
Buffer = new byte[4096];
|
|
||||||
Stream = new MemoryStream(Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long Length => (long)BufferLength;
|
|
||||||
|
|
||||||
public long Position => Stream.Position;
|
|
||||||
|
|
||||||
public void Add(
|
|
||||||
byte[] buffer,
|
|
||||||
int offset,
|
|
||||||
int length)
|
|
||||||
{
|
|
||||||
TransferLength += length;
|
|
||||||
|
|
||||||
if (BufferLength + length >= Buffer.Length)
|
|
||||||
{
|
|
||||||
length = Buffer.Length - BufferLength;
|
|
||||||
}
|
|
||||||
if (length > 0)
|
|
||||||
{
|
|
||||||
Array.Copy(buffer, offset, Buffer, BufferLength, length);
|
|
||||||
BufferLength += length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Seek(
|
|
||||||
long offset,
|
|
||||||
SeekOrigin loc)
|
|
||||||
{
|
|
||||||
Stream.Seek(offset, loc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
BufferLength = 0;
|
|
||||||
TransferLength = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void BeginRead()
|
|
||||||
{
|
|
||||||
SkipBits = 0;
|
|
||||||
Stream.Seek(0, SeekOrigin.Begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EndRead()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] ReadBytes(int bytes)
|
|
||||||
{
|
|
||||||
if (Stream.Position + bytes >= BufferLength)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] value = new byte[bytes];
|
|
||||||
Stream.Read(value, 0, bytes);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte ReadByte()
|
|
||||||
{
|
|
||||||
return (byte)Stream.ReadByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadBits(int bits)
|
|
||||||
{
|
|
||||||
long pos = Stream.Position;
|
|
||||||
|
|
||||||
int shift = 24;
|
|
||||||
int data = 0;
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
if (pos + i >= BufferLength) break;
|
|
||||||
data += (Stream.ReadByte() << shift);
|
|
||||||
shift -= 8;
|
|
||||||
}
|
|
||||||
var vector = new BitVector32(data);
|
|
||||||
|
|
||||||
int value = 0;
|
|
||||||
for (int i = SkipBits; i < SkipBits + bits; i++)
|
|
||||||
{
|
|
||||||
value <<= 1;
|
|
||||||
value += (vector[1 << (32 - i - 1)] ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SkipBits += bits;
|
|
||||||
Stream.Seek(pos + (SkipBits >> 3), SeekOrigin.Begin);
|
|
||||||
SkipBits = SkipBits % 8;
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public class TSStreamClip
|
|
||||||
{
|
|
||||||
public int AngleIndex = 0;
|
|
||||||
public string Name;
|
|
||||||
public double TimeIn;
|
|
||||||
public double TimeOut;
|
|
||||||
public double RelativeTimeIn;
|
|
||||||
public double RelativeTimeOut;
|
|
||||||
public double Length;
|
|
||||||
|
|
||||||
public ulong FileSize = 0;
|
|
||||||
public ulong InterleavedFileSize = 0;
|
|
||||||
public ulong PayloadBytes = 0;
|
|
||||||
public ulong PacketCount = 0;
|
|
||||||
public double PacketSeconds = 0;
|
|
||||||
|
|
||||||
public List<double> Chapters = new List<double>();
|
|
||||||
|
|
||||||
public TSStreamFile StreamFile = null;
|
|
||||||
public TSStreamClipFile StreamClipFile = null;
|
|
||||||
|
|
||||||
public TSStreamClip(
|
|
||||||
TSStreamFile streamFile,
|
|
||||||
TSStreamClipFile streamClipFile)
|
|
||||||
{
|
|
||||||
if (streamFile != null)
|
|
||||||
{
|
|
||||||
Name = streamFile.Name;
|
|
||||||
StreamFile = streamFile;
|
|
||||||
FileSize = (ulong)StreamFile.FileInfo.Length;
|
|
||||||
if (StreamFile.InterleavedFile != null)
|
|
||||||
{
|
|
||||||
InterleavedFileSize = (ulong)StreamFile.InterleavedFile.FileInfo.Length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StreamClipFile = streamClipFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string DisplayName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (StreamFile != null &&
|
|
||||||
StreamFile.InterleavedFile != null &&
|
|
||||||
BDInfoSettings.EnableSSIF)
|
|
||||||
{
|
|
||||||
return StreamFile.InterleavedFile.Name;
|
|
||||||
}
|
|
||||||
return Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ulong PacketSize => PacketCount * 192;
|
|
||||||
|
|
||||||
public ulong PacketBitRate
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (PacketSeconds > 0)
|
|
||||||
{
|
|
||||||
return (ulong)Math.Round(((PacketSize * 8.0) / PacketSeconds));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsCompatible(TSStreamClip clip)
|
|
||||||
{
|
|
||||||
foreach (var stream1 in StreamFile.Streams.Values)
|
|
||||||
{
|
|
||||||
if (clip.StreamFile.Streams.ContainsKey(stream1.PID))
|
|
||||||
{
|
|
||||||
var stream2 = clip.StreamFile.Streams[stream1.PID];
|
|
||||||
if (stream1.StreamType != stream2.StreamType)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,244 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
// BDInfo - Blu-ray Video and Audio Analysis Tool
|
|
||||||
// Copyright © 2010 Cinema Squid
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
#undef DEBUG
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
|
|
||||||
namespace BDInfo
|
|
||||||
{
|
|
||||||
public class TSStreamClipFile
|
|
||||||
{
|
|
||||||
public FileSystemMetadata FileInfo = null;
|
|
||||||
public string FileType = null;
|
|
||||||
public bool IsValid = false;
|
|
||||||
public string Name = null;
|
|
||||||
|
|
||||||
public Dictionary<ushort, TSStream> Streams =
|
|
||||||
new Dictionary<ushort, TSStream>();
|
|
||||||
|
|
||||||
public TSStreamClipFile(FileSystemMetadata fileInfo)
|
|
||||||
{
|
|
||||||
FileInfo = fileInfo;
|
|
||||||
Name = fileInfo.Name.ToUpper();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Scan()
|
|
||||||
{
|
|
||||||
Stream fileStream = null;
|
|
||||||
BinaryReader fileReader = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
Debug.WriteLine(string.Format(
|
|
||||||
"Scanning {0}...", Name));
|
|
||||||
#endif
|
|
||||||
Streams.Clear();
|
|
||||||
|
|
||||||
fileStream = File.OpenRead(FileInfo.FullName);
|
|
||||||
fileReader = new BinaryReader(fileStream);
|
|
||||||
|
|
||||||
byte[] data = new byte[fileStream.Length];
|
|
||||||
fileReader.Read(data, 0, data.Length);
|
|
||||||
|
|
||||||
byte[] fileType = new byte[8];
|
|
||||||
Array.Copy(data, 0, fileType, 0, fileType.Length);
|
|
||||||
|
|
||||||
FileType = Encoding.ASCII.GetString(fileType, 0, fileType.Length);
|
|
||||||
if (FileType != "HDMV0100" &&
|
|
||||||
FileType != "HDMV0200")
|
|
||||||
{
|
|
||||||
throw new Exception(string.Format(
|
|
||||||
"Clip info file {0} has an unknown file type {1}.",
|
|
||||||
FileInfo.Name, FileType));
|
|
||||||
}
|
|
||||||
#if DEBUG
|
|
||||||
Debug.WriteLine(string.Format(
|
|
||||||
"\tFileType: {0}", FileType));
|
|
||||||
#endif
|
|
||||||
int clipIndex =
|
|
||||||
((int)data[12] << 24) +
|
|
||||||
((int)data[13] << 16) +
|
|
||||||
((int)data[14] << 8) +
|
|
||||||
((int)data[15]);
|
|
||||||
|
|
||||||
int clipLength =
|
|
||||||
((int)data[clipIndex] << 24) +
|
|
||||||
((int)data[clipIndex + 1] << 16) +
|
|
||||||
((int)data[clipIndex + 2] << 8) +
|
|
||||||
((int)data[clipIndex + 3]);
|
|
||||||
|
|
||||||
byte[] clipData = new byte[clipLength];
|
|
||||||
Array.Copy(data, clipIndex + 4, clipData, 0, clipData.Length);
|
|
||||||
|
|
||||||
int streamCount = clipData[8];
|
|
||||||
#if DEBUG
|
|
||||||
Debug.WriteLine(string.Format(
|
|
||||||
"\tStreamCount: {0}", streamCount));
|
|
||||||
#endif
|
|
||||||
int streamOffset = 10;
|
|
||||||
for (int streamIndex = 0;
|
|
||||||
streamIndex < streamCount;
|
|
||||||
streamIndex++)
|
|
||||||
{
|
|
||||||
TSStream stream = null;
|
|
||||||
|
|
||||||
ushort PID = (ushort)
|
|
||||||
((clipData[streamOffset] << 8) +
|
|
||||||
clipData[streamOffset + 1]);
|
|
||||||
|
|
||||||
streamOffset += 2;
|
|
||||||
|
|
||||||
var streamType = (TSStreamType)
|
|
||||||
clipData[streamOffset + 1];
|
|
||||||
switch (streamType)
|
|
||||||
{
|
|
||||||
case TSStreamType.MVC_VIDEO:
|
|
||||||
// TODO
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSStreamType.AVC_VIDEO:
|
|
||||||
case TSStreamType.MPEG1_VIDEO:
|
|
||||||
case TSStreamType.MPEG2_VIDEO:
|
|
||||||
case TSStreamType.VC1_VIDEO:
|
|
||||||
{
|
|
||||||
var videoFormat = (TSVideoFormat)
|
|
||||||
(clipData[streamOffset + 2] >> 4);
|
|
||||||
var frameRate = (TSFrameRate)
|
|
||||||
(clipData[streamOffset + 2] & 0xF);
|
|
||||||
var aspectRatio = (TSAspectRatio)
|
|
||||||
(clipData[streamOffset + 3] >> 4);
|
|
||||||
|
|
||||||
stream = new TSVideoStream();
|
|
||||||
((TSVideoStream)stream).VideoFormat = videoFormat;
|
|
||||||
((TSVideoStream)stream).AspectRatio = aspectRatio;
|
|
||||||
((TSVideoStream)stream).FrameRate = frameRate;
|
|
||||||
#if DEBUG
|
|
||||||
Debug.WriteLine(string.Format(
|
|
||||||
"\t{0} {1} {2} {3} {4}",
|
|
||||||
PID,
|
|
||||||
streamType,
|
|
||||||
videoFormat,
|
|
||||||
frameRate,
|
|
||||||
aspectRatio));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSStreamType.AC3_AUDIO:
|
|
||||||
case TSStreamType.AC3_PLUS_AUDIO:
|
|
||||||
case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
|
|
||||||
case TSStreamType.AC3_TRUE_HD_AUDIO:
|
|
||||||
case TSStreamType.DTS_AUDIO:
|
|
||||||
case TSStreamType.DTS_HD_AUDIO:
|
|
||||||
case TSStreamType.DTS_HD_MASTER_AUDIO:
|
|
||||||
case TSStreamType.DTS_HD_SECONDARY_AUDIO:
|
|
||||||
case TSStreamType.LPCM_AUDIO:
|
|
||||||
case TSStreamType.MPEG1_AUDIO:
|
|
||||||
case TSStreamType.MPEG2_AUDIO:
|
|
||||||
{
|
|
||||||
byte[] languageBytes = new byte[3];
|
|
||||||
Array.Copy(clipData, streamOffset + 3,
|
|
||||||
languageBytes, 0, languageBytes.Length);
|
|
||||||
string languageCode = Encoding.ASCII.GetString(languageBytes, 0, languageBytes.Length);
|
|
||||||
|
|
||||||
var channelLayout = (TSChannelLayout)
|
|
||||||
(clipData[streamOffset + 2] >> 4);
|
|
||||||
var sampleRate = (TSSampleRate)
|
|
||||||
(clipData[streamOffset + 2] & 0xF);
|
|
||||||
|
|
||||||
stream = new TSAudioStream();
|
|
||||||
((TSAudioStream)stream).LanguageCode = languageCode;
|
|
||||||
((TSAudioStream)stream).ChannelLayout = channelLayout;
|
|
||||||
((TSAudioStream)stream).SampleRate = TSAudioStream.ConvertSampleRate(sampleRate);
|
|
||||||
((TSAudioStream)stream).LanguageCode = languageCode;
|
|
||||||
#if DEBUG
|
|
||||||
Debug.WriteLine(string.Format(
|
|
||||||
"\t{0} {1} {2} {3} {4}",
|
|
||||||
PID,
|
|
||||||
streamType,
|
|
||||||
languageCode,
|
|
||||||
channelLayout,
|
|
||||||
sampleRate));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSStreamType.INTERACTIVE_GRAPHICS:
|
|
||||||
case TSStreamType.PRESENTATION_GRAPHICS:
|
|
||||||
{
|
|
||||||
byte[] languageBytes = new byte[3];
|
|
||||||
Array.Copy(clipData, streamOffset + 2,
|
|
||||||
languageBytes, 0, languageBytes.Length);
|
|
||||||
string languageCode = Encoding.ASCII.GetString(languageBytes, 0, languageBytes.Length);
|
|
||||||
|
|
||||||
stream = new TSGraphicsStream();
|
|
||||||
stream.LanguageCode = languageCode;
|
|
||||||
#if DEBUG
|
|
||||||
Debug.WriteLine(string.Format(
|
|
||||||
"\t{0} {1} {2}",
|
|
||||||
PID,
|
|
||||||
streamType,
|
|
||||||
languageCode));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSStreamType.SUBTITLE:
|
|
||||||
{
|
|
||||||
byte[] languageBytes = new byte[3];
|
|
||||||
Array.Copy(clipData, streamOffset + 3,
|
|
||||||
languageBytes, 0, languageBytes.Length);
|
|
||||||
string languageCode = Encoding.ASCII.GetString(languageBytes, 0, languageBytes.Length);
|
|
||||||
#if DEBUG
|
|
||||||
Debug.WriteLine(string.Format(
|
|
||||||
"\t{0} {1} {2}",
|
|
||||||
PID,
|
|
||||||
streamType,
|
|
||||||
languageCode));
|
|
||||||
#endif
|
|
||||||
stream = new TSTextStream();
|
|
||||||
stream.LanguageCode = languageCode;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stream != null)
|
|
||||||
{
|
|
||||||
stream.PID = PID;
|
|
||||||
stream.StreamType = streamType;
|
|
||||||
Streams.Add(PID, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
streamOffset += clipData[streamOffset] + 1;
|
|
||||||
}
|
|
||||||
IsValid = true;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (fileReader != null) fileReader.Dispose();
|
|
||||||
if (fileStream != null) fileStream.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -31,6 +31,7 @@
|
||||||
- [fhriley](https://github.com/fhriley)
|
- [fhriley](https://github.com/fhriley)
|
||||||
- [nevado](https://github.com/nevado)
|
- [nevado](https://github.com/nevado)
|
||||||
- [mark-monteiro](https://github.com/mark-monteiro)
|
- [mark-monteiro](https://github.com/mark-monteiro)
|
||||||
|
- [ullmie02](https://github.com/ullmie02)
|
||||||
|
|
||||||
# Emby Contributors
|
# Emby Contributors
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
ARG DOTNET_VERSION=3.0
|
ARG DOTNET_VERSION=3.1
|
||||||
ARG FFMPEG_VERSION=latest
|
ARG FFMPEG_VERSION=latest
|
||||||
|
|
||||||
FROM node:alpine as web-builder
|
FROM node:alpine as web-builder
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Requires binfm_misc registration
|
# Requires binfm_misc registration
|
||||||
# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
|
# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
|
||||||
ARG DOTNET_VERSION=3.0
|
ARG DOTNET_VERSION=3.1
|
||||||
|
|
||||||
|
|
||||||
FROM node:alpine as web-builder
|
FROM node:alpine as web-builder
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Requires binfm_misc registration
|
# Requires binfm_misc registration
|
||||||
# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
|
# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
|
||||||
ARG DOTNET_VERSION=3.0
|
ARG DOTNET_VERSION=3.1
|
||||||
|
|
||||||
|
|
||||||
FROM node:alpine as web-builder
|
FROM node:alpine as web-builder
|
||||||
|
|
|
@ -29,25 +29,15 @@ namespace Emby.Dlna.Eventing
|
||||||
{
|
{
|
||||||
var subscription = GetSubscription(subscriptionId, false);
|
var subscription = GetSubscription(subscriptionId, false);
|
||||||
|
|
||||||
int timeoutSeconds;
|
subscription.TimeoutSeconds = ParseTimeout(requestedTimeoutString) ?? 300;
|
||||||
|
int timeoutSeconds = subscription.TimeoutSeconds;
|
||||||
|
subscription.SubscriptionTime = DateTime.UtcNow;
|
||||||
|
|
||||||
// Remove logging for now because some devices are sending this very frequently
|
_logger.LogDebug(
|
||||||
// TODO re-enable with dlna debug logging setting
|
"Renewing event subscription for {0} with timeout of {1} to {2}",
|
||||||
//_logger.LogDebug("Renewing event subscription for {0} with timeout of {1} to {2}",
|
subscription.NotificationType,
|
||||||
// subscription.NotificationType,
|
timeoutSeconds,
|
||||||
// timeout,
|
subscription.CallbackUrl);
|
||||||
// subscription.CallbackUrl);
|
|
||||||
|
|
||||||
if (subscription != null)
|
|
||||||
{
|
|
||||||
subscription.TimeoutSeconds = ParseTimeout(requestedTimeoutString) ?? 300;
|
|
||||||
timeoutSeconds = subscription.TimeoutSeconds;
|
|
||||||
subscription.SubscriptionTime = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
timeoutSeconds = 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetEventSubscriptionResponse(subscriptionId, requestedTimeoutString, timeoutSeconds);
|
return GetEventSubscriptionResponse(subscriptionId, requestedTimeoutString, timeoutSeconds);
|
||||||
}
|
}
|
||||||
|
@ -57,12 +47,10 @@ namespace Emby.Dlna.Eventing
|
||||||
var timeout = ParseTimeout(requestedTimeoutString) ?? 300;
|
var timeout = ParseTimeout(requestedTimeoutString) ?? 300;
|
||||||
var id = "uuid:" + Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
|
var id = "uuid:" + Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
// Remove logging for now because some devices are sending this very frequently
|
_logger.LogDebug("Creating event subscription for {0} with timeout of {1} to {2}",
|
||||||
// TODO re-enable with dlna debug logging setting
|
notificationType,
|
||||||
//_logger.LogDebug("Creating event subscription for {0} with timeout of {1} to {2}",
|
timeout,
|
||||||
// notificationType,
|
callbackUrl);
|
||||||
// timeout,
|
|
||||||
// callbackUrl);
|
|
||||||
|
|
||||||
_subscriptions.TryAdd(id, new EventSubscription
|
_subscriptions.TryAdd(id, new EventSubscription
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.Audio
|
namespace Emby.Naming.Audio
|
||||||
{
|
{
|
||||||
public class MultiPartResult
|
public class MultiPartResult
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.AudioBook
|
namespace Emby.Naming.AudioBook
|
||||||
{
|
{
|
||||||
public class AudioBookFilePathParserResult
|
public class AudioBookFilePathParserResult
|
||||||
|
|
|
@ -7,6 +7,9 @@ namespace Emby.Naming.AudioBook
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AudioBookInfo
|
public class AudioBookInfo
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AudioBookInfo" /> class.
|
||||||
|
/// </summary>
|
||||||
public AudioBookInfo()
|
public AudioBookInfo()
|
||||||
{
|
{
|
||||||
Files = new List<AudioBookFileInfo>();
|
Files = new List<AudioBookFileInfo>();
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Emby.Naming.Common;
|
using Emby.Naming.Common;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.Common
|
namespace Emby.Naming.Common
|
||||||
{
|
{
|
||||||
public enum MediaType
|
public enum MediaType
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\SharedVersion.cs" />
|
<Compile Include="..\SharedVersion.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -21,7 +25,7 @@
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Code analysers-->
|
<!-- Code Analyzers-->
|
||||||
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" PrivateAssets="All" />
|
||||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.Subtitles
|
namespace Emby.Naming.Subtitles
|
||||||
{
|
{
|
||||||
public class SubtitleInfo
|
public class SubtitleInfo
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.TV
|
namespace Emby.Naming.TV
|
||||||
{
|
{
|
||||||
public class EpisodeInfo
|
public class EpisodeInfo
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.TV
|
namespace Emby.Naming.TV
|
||||||
{
|
{
|
||||||
public class EpisodePathParserResult
|
public class EpisodePathParserResult
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.TV
|
namespace Emby.Naming.TV
|
||||||
{
|
{
|
||||||
public class SeasonPathParserResult
|
public class SeasonPathParserResult
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
{
|
{
|
||||||
public class CleanDateTimeResult
|
public class CleanDateTimeResult
|
||||||
|
@ -7,11 +10,13 @@ namespace Emby.Naming.Video
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name.</value>
|
/// <value>The name.</value>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the year.
|
/// Gets or sets the year.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The year.</value>
|
/// <value>The year.</value>
|
||||||
public int? Year { get; set; }
|
public int? Year { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance has changed.
|
/// Gets or sets a value indicating whether this instance has changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
{
|
{
|
||||||
public class CleanStringResult
|
public class CleanStringResult
|
||||||
|
@ -7,6 +10,7 @@ namespace Emby.Naming.Video
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name.</value>
|
/// <value>The name.</value>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance has changed.
|
/// Gets or sets a value indicating whether this instance has changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
{
|
{
|
||||||
public class ExtraResult
|
public class ExtraResult
|
||||||
|
@ -7,6 +10,7 @@ namespace Emby.Naming.Video
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The type of the extra.</value>
|
/// <value>The type of the extra.</value>
|
||||||
public string ExtraType { get; set; }
|
public string ExtraType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the rule.
|
/// Gets or sets the rule.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using Emby.Naming.Common;
|
using Emby.Naming.Common;
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
|
@ -9,16 +12,19 @@ namespace Emby.Naming.Video
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The token.</value>
|
/// <value>The token.</value>
|
||||||
public string Token { get; set; }
|
public string Token { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the type of the extra.
|
/// Gets or sets the type of the extra.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The type of the extra.</value>
|
/// <value>The type of the extra.</value>
|
||||||
public string ExtraType { get; set; }
|
public string ExtraType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the type of the rule.
|
/// Gets or sets the type of the rule.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The type of the rule.</value>
|
/// <value>The type of the rule.</value>
|
||||||
public ExtraRuleType RuleType { get; set; }
|
public ExtraRuleType RuleType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the type of the media.
|
/// Gets or sets the type of the media.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
{
|
{
|
||||||
public enum ExtraRuleType
|
public enum ExtraRuleType
|
||||||
|
@ -6,10 +9,12 @@ namespace Emby.Naming.Video
|
||||||
/// The suffix
|
/// The suffix
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Suffix = 0,
|
Suffix = 0,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The filename
|
/// The filename
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Filename = 1,
|
Filename = 1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The regex
|
/// The regex
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -6,15 +9,17 @@ namespace Emby.Naming.Video
|
||||||
{
|
{
|
||||||
public class FileStack
|
public class FileStack
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
|
||||||
public List<string> Files { get; set; }
|
|
||||||
public bool IsDirectoryStack { get; set; }
|
|
||||||
|
|
||||||
public FileStack()
|
public FileStack()
|
||||||
{
|
{
|
||||||
Files = new List<string>();
|
Files = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public List<string> Files { get; set; }
|
||||||
|
|
||||||
|
public bool IsDirectoryStack { get; set; }
|
||||||
|
|
||||||
public bool ContainsFile(string file, bool isDirectory)
|
public bool ContainsFile(string file, bool isDirectory)
|
||||||
{
|
{
|
||||||
if (IsDirectoryStack == isDirectory)
|
if (IsDirectoryStack == isDirectory)
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Emby.Naming.Common;
|
using Emby.Naming.Common;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Emby.Naming.Common;
|
using Emby.Naming.Common;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
{
|
{
|
||||||
public class Format3DRule
|
public class Format3DRule
|
||||||
|
@ -7,6 +10,7 @@ namespace Emby.Naming.Video
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The token.</value>
|
/// <value>The token.</value>
|
||||||
public string Token { get; set; }
|
public string Token { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the preceeding token.
|
/// Gets or sets the preceeding token.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
{
|
{
|
||||||
public struct StubResult
|
public struct StubResult
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
namespace Emby.Naming.Video
|
namespace Emby.Naming.Video
|
||||||
{
|
{
|
||||||
public class StubTypeRule
|
public class StubTypeRule
|
||||||
|
|
|
@ -77,6 +77,7 @@ namespace Emby.Naming.Video
|
||||||
/// <value>The file name without extension.</value>
|
/// <value>The file name without extension.</value>
|
||||||
public string FileNameWithoutExtension => !IsDirectory ? System.IO.Path.GetFileNameWithoutExtension(Path) : System.IO.Path.GetFileName(Path);
|
public string FileNameWithoutExtension => !IsDirectory ? System.IO.Path.GetFileNameWithoutExtension(Path) : System.IO.Path.GetFileName(Path);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
// Makes debugging easier
|
// Makes debugging easier
|
||||||
|
|
|
@ -7,6 +7,16 @@ namespace Emby.Naming.Video
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class VideoInfo
|
public class VideoInfo
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="VideoInfo" /> class.
|
||||||
|
/// </summary>
|
||||||
|
public VideoInfo()
|
||||||
|
{
|
||||||
|
Files = new List<VideoFileInfo>();
|
||||||
|
Extras = new List<VideoFileInfo>();
|
||||||
|
AlternateVersions = new List<VideoFileInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the name.
|
/// Gets or sets the name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -36,12 +46,5 @@ namespace Emby.Naming.Video
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The alternate versions.</value>
|
/// <value>The alternate versions.</value>
|
||||||
public List<VideoFileInfo> AlternateVersions { get; set; }
|
public List<VideoFileInfo> AlternateVersions { get; set; }
|
||||||
|
|
||||||
public VideoInfo()
|
|
||||||
{
|
|
||||||
Files = new List<VideoFileInfo>();
|
|
||||||
Extras = new List<VideoFileInfo>();
|
|
||||||
AlternateVersions = new List<VideoFileInfo>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
|
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
|
||||||
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
|
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
|
||||||
|
@ -20,7 +24,7 @@
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Code analysers-->
|
<!-- Code Analyzers-->
|
||||||
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" />
|
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" />
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
|
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
|
||||||
|
|
|
@ -764,9 +764,8 @@ namespace Emby.Server.Implementations
|
||||||
LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager);
|
LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager);
|
||||||
serviceCollection.AddSingleton(LibraryManager);
|
serviceCollection.AddSingleton(LibraryManager);
|
||||||
|
|
||||||
// TODO wtaylor: investigate use of second music manager
|
|
||||||
var musicManager = new MusicManager(LibraryManager);
|
var musicManager = new MusicManager(LibraryManager);
|
||||||
serviceCollection.AddSingleton<IMusicManager>(new MusicManager(LibraryManager));
|
serviceCollection.AddSingleton<IMusicManager>(musicManager);
|
||||||
|
|
||||||
LibraryMonitor = new LibraryMonitor(LoggerFactory, LibraryManager, ServerConfigurationManager, FileSystemManager);
|
LibraryMonitor = new LibraryMonitor(LoggerFactory, LibraryManager, ServerConfigurationManager, FileSystemManager);
|
||||||
serviceCollection.AddSingleton(LibraryMonitor);
|
serviceCollection.AddSingleton(LibraryMonitor);
|
||||||
|
|
|
@ -31,11 +31,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IProviderManager _providerManager;
|
private readonly IProviderManager _providerManager;
|
||||||
private readonly ILocalizationManager _localizationManager;
|
private readonly ILocalizationManager _localizationManager;
|
||||||
private IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
|
|
||||||
public event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
|
|
||||||
public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
|
|
||||||
public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
|
|
||||||
|
|
||||||
public CollectionManager(
|
public CollectionManager(
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
|
@ -55,6 +51,10 @@ namespace Emby.Server.Implementations.Collections
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
|
||||||
|
public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
|
||||||
|
public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
|
||||||
|
|
||||||
private IEnumerable<Folder> FindFolders(string path)
|
private IEnumerable<Folder> FindFolders(string path)
|
||||||
{
|
{
|
||||||
return _libraryManager
|
return _libraryManager
|
||||||
|
@ -341,11 +341,11 @@ namespace Emby.Server.Implementations.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CollectionManagerEntryPoint : IServerEntryPoint
|
public sealed class CollectionManagerEntryPoint : IServerEntryPoint
|
||||||
{
|
{
|
||||||
private readonly CollectionManager _collectionManager;
|
private readonly CollectionManager _collectionManager;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, ILogger logger)
|
public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, ILogger logger)
|
||||||
{
|
{
|
||||||
|
@ -354,6 +354,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public async Task RunAsync()
|
public async Task RunAsync()
|
||||||
{
|
{
|
||||||
if (!_config.Configuration.CollectionsUpgraded && _config.Configuration.IsStartupWizardCompleted)
|
if (!_config.Configuration.CollectionsUpgraded && _config.Configuration.IsStartupWizardCompleted)
|
||||||
|
@ -377,39 +378,10 @@ namespace Emby.Server.Implementations.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IDisposable Support
|
/// <inheritdoc />
|
||||||
private bool disposedValue = false; // To detect redundant calls
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (!disposedValue)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
// TODO: dispose managed state (managed objects).
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
|
|
||||||
// TODO: set large fields to null.
|
|
||||||
|
|
||||||
disposedValue = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
|
|
||||||
// ~CollectionManagerEntryPoint() {
|
|
||||||
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
|
||||||
// Dispose(false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// This code added to correctly implement the disposable pattern.
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
// Nothing to dispose
|
||||||
Dispose(true);
|
|
||||||
// TODO: uncomment the following line if the finalizer is overridden above.
|
|
||||||
// GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4593,10 +4593,20 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
if (query.ExcludeInheritedTags.Length > 0)
|
if (query.ExcludeInheritedTags.Length > 0)
|
||||||
{
|
{
|
||||||
var tagValues = query.ExcludeInheritedTags.Select(i => "'" + GetCleanValue(i) + "'");
|
var paramName = "@ExcludeInheritedTags";
|
||||||
var tagValuesList = string.Join(",", tagValues);
|
if (statement == null)
|
||||||
|
{
|
||||||
whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + tagValuesList + ")) is null)");
|
int index = 0;
|
||||||
|
string excludedTags = string.Join(",", query.ExcludeInheritedTags.Select(t => paramName + index++));
|
||||||
|
whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + excludedTags + ")) is null)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int index = 0; index < query.ExcludeInheritedTags.Length; index++)
|
||||||
|
{
|
||||||
|
statement.TryBind(paramName + index, GetCleanValue(query.ExcludeInheritedTags[index]));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.SeriesStatuses.Length > 0)
|
if (query.SeriesStatuses.Length > 0)
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Code analysers-->
|
<!-- Code Analyzers-->
|
||||||
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" />
|
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" />
|
||||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
|
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
|
||||||
|
|
|
@ -392,9 +392,9 @@ namespace Emby.Server.Implementations.Library
|
||||||
// Add this flag to GetDeletePaths if required in the future
|
// Add this flag to GetDeletePaths if required in the future
|
||||||
var isRequiredForDelete = true;
|
var isRequiredForDelete = true;
|
||||||
|
|
||||||
foreach (var fileSystemInfo in item.GetDeletePaths().ToList())
|
foreach (var fileSystemInfo in item.GetDeletePaths())
|
||||||
{
|
{
|
||||||
if (File.Exists(fileSystemInfo.FullName))
|
if (Directory.Exists(fileSystemInfo.FullName) || File.Exists(fileSystemInfo.FullName))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,13 +42,13 @@ namespace Emby.Server.Implementations.Library
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UserManager : IUserManager
|
public class UserManager : IUserManager
|
||||||
{
|
{
|
||||||
|
private readonly object _policySyncLock = new object();
|
||||||
|
private readonly object _configSyncLock = new object();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger.
|
/// The logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
private readonly object _policySyncLock = new object();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the active user repository.
|
/// Gets the active user repository.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -255,7 +255,12 @@ namespace Emby.Server.Implementations.Library
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<User> AuthenticateUser(string username, string password, string hashedPassword, string remoteEndPoint, bool isUserSession)
|
public async Task<User> AuthenticateUser(
|
||||||
|
string username,
|
||||||
|
string password,
|
||||||
|
string hashedPassword,
|
||||||
|
string remoteEndPoint,
|
||||||
|
bool isUserSession)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(username))
|
if (string.IsNullOrWhiteSpace(username))
|
||||||
{
|
{
|
||||||
|
@ -392,7 +397,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
if (providers.Length == 0)
|
if (providers.Length == 0)
|
||||||
{
|
{
|
||||||
// Assign the user to the InvalidAuthProvider since no configured auth provider was valid/found
|
// Assign the user to the InvalidAuthProvider since no configured auth provider was valid/found
|
||||||
_logger.LogWarning("User {UserName} was found with invalid/missing Authentication Provider {AuthenticationProviderId}. Assigning user to InvalidAuthProvider until this is corrected", user.Name, user.Policy.AuthenticationProviderId);
|
_logger.LogWarning("User {UserName} was found with invalid/missing Authentication Provider {AuthenticationProviderId}. Assigning user to InvalidAuthProvider until this is corrected", user?.Name, user?.Policy.AuthenticationProviderId);
|
||||||
providers = new IAuthenticationProvider[] { _invalidAuthProvider };
|
providers = new IAuthenticationProvider[] { _invalidAuthProvider };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,7 +477,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
if (!success
|
if (!success
|
||||||
&& _networkManager.IsInLocalNetwork(remoteEndPoint)
|
&& _networkManager.IsInLocalNetwork(remoteEndPoint)
|
||||||
&& user.Configuration.EnableLocalPassword
|
&& user?.Configuration.EnableLocalPassword == true
|
||||||
&& !string.IsNullOrEmpty(user.EasyPassword))
|
&& !string.IsNullOrEmpty(user.EasyPassword))
|
||||||
{
|
{
|
||||||
// Check easy password
|
// Check easy password
|
||||||
|
@ -754,13 +759,10 @@ namespace Emby.Server.Implementations.Library
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Deletes the user.
|
/// <exception cref="ArgumentNullException">The <c>user</c> is <c>null</c>.</exception>
|
||||||
/// </summary>
|
/// <exception cref="ArgumentException">The <c>user</c> doesn't exist, or is the last administrator.</exception>
|
||||||
/// <param name="user">The user.</param>
|
/// <exception cref="InvalidOperationException">The <c>user</c> can't be deleted; there are no other users.</exception>
|
||||||
/// <returns>Task.</returns>
|
|
||||||
/// <exception cref="ArgumentNullException">user</exception>
|
|
||||||
/// <exception cref="ArgumentException"></exception>
|
|
||||||
public void DeleteUser(User user)
|
public void DeleteUser(User user)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
|
@ -779,7 +781,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
if (_users.Count == 1)
|
if (_users.Count == 1)
|
||||||
{
|
{
|
||||||
throw new ArgumentException(string.Format(
|
throw new InvalidOperationException(string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"The user '{0}' cannot be deleted because there must be at least one user in the system.",
|
"The user '{0}' cannot be deleted because there must be at least one user in the system.",
|
||||||
user.Name));
|
user.Name));
|
||||||
|
@ -800,16 +802,19 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
_userRepository.DeleteUser(user);
|
_userRepository.DeleteUser(user);
|
||||||
|
|
||||||
try
|
// Delete user config dir
|
||||||
|
lock (_configSyncLock)
|
||||||
|
lock (_policySyncLock)
|
||||||
{
|
{
|
||||||
_fileSystem.DeleteFile(configPath);
|
try
|
||||||
|
{
|
||||||
|
Directory.Delete(user.ConfigurationDirectoryPath, true);
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error deleting user config dir: {Path}", user.ConfigurationDirectoryPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Error deleting file {path}", configPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteUserPolicy(user);
|
|
||||||
|
|
||||||
_users.TryRemove(user.Id, out _);
|
_users.TryRemove(user.Id, out _);
|
||||||
|
|
||||||
|
@ -918,10 +923,9 @@ namespace Emby.Server.Implementations.Library
|
||||||
public UserPolicy GetUserPolicy(User user)
|
public UserPolicy GetUserPolicy(User user)
|
||||||
{
|
{
|
||||||
var path = GetPolicyFilePath(user);
|
var path = GetPolicyFilePath(user);
|
||||||
|
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
{
|
{
|
||||||
return GetDefaultPolicy(user);
|
return GetDefaultPolicy();
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -931,19 +935,15 @@ namespace Emby.Server.Implementations.Library
|
||||||
return (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), path);
|
return (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException)
|
|
||||||
{
|
|
||||||
return GetDefaultPolicy(user);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error reading policy file: {path}", path);
|
_logger.LogError(ex, "Error reading policy file: {Path}", path);
|
||||||
|
|
||||||
return GetDefaultPolicy(user);
|
return GetDefaultPolicy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UserPolicy GetDefaultPolicy(User user)
|
private static UserPolicy GetDefaultPolicy()
|
||||||
{
|
{
|
||||||
return new UserPolicy
|
return new UserPolicy
|
||||||
{
|
{
|
||||||
|
@ -983,27 +983,6 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteUserPolicy(User user)
|
|
||||||
{
|
|
||||||
var path = GetPolicyFilePath(user);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
lock (_policySyncLock)
|
|
||||||
{
|
|
||||||
_fileSystem.DeleteFile(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Error deleting policy file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetPolicyFilePath(User user)
|
private static string GetPolicyFilePath(User user)
|
||||||
{
|
{
|
||||||
return Path.Combine(user.ConfigurationDirectoryPath, "policy.xml");
|
return Path.Combine(user.ConfigurationDirectoryPath, "policy.xml");
|
||||||
|
@ -1030,19 +1009,14 @@ namespace Emby.Server.Implementations.Library
|
||||||
return (UserConfiguration)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), path);
|
return (UserConfiguration)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException)
|
|
||||||
{
|
|
||||||
return new UserConfiguration();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error reading policy file: {path}", path);
|
_logger.LogError(ex, "Error reading policy file: {Path}", path);
|
||||||
|
|
||||||
return new UserConfiguration();
|
return new UserConfiguration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly object _configSyncLock = new object();
|
|
||||||
public void UpdateConfiguration(Guid userId, UserConfiguration config)
|
public void UpdateConfiguration(Guid userId, UserConfiguration config)
|
||||||
{
|
{
|
||||||
var user = GetUserById(userId);
|
var user = GetUserById(userId);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
|
@ -74,7 +75,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
DecompressionMethod = CompressionMethod.None
|
DecompressionMethod = CompressionMethod.None
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var response = await _httpClient.SendAsync(httpRequestOptions, "GET").ConfigureAwait(false))
|
using (var response = await _httpClient.SendAsync(httpRequestOptions, HttpMethod.Get).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Opened recording stream from tuner provider");
|
_logger.LogInformation("Opened recording stream from tuner provider");
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
|
@ -12,7 +13,6 @@ using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Extensions;
|
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
|
@ -663,7 +663,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
|
return await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
|
@ -738,7 +738,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
|
|
||||||
httpOptions.RequestHeaders["token"] = token;
|
httpOptions.RequestHeaders["token"] = token;
|
||||||
|
|
||||||
using (await _httpClient.SendAsync(httpOptions, "PUT").ConfigureAwait(false))
|
using (await _httpClient.SendAsync(httpOptions, HttpMethod.Put).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
@ -64,7 +65,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
httpRequestOptions.RequestHeaders[header.Key] = header.Value;
|
httpRequestOptions.RequestHeaders[header.Key] = header.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = await _httpClient.SendAsync(httpRequestOptions, "GET").ConfigureAwait(false);
|
var response = await _httpClient.SendAsync(httpRequestOptions, HttpMethod.Get).ConfigureAwait(false);
|
||||||
|
|
||||||
var extension = "ts";
|
var extension = "ts";
|
||||||
var requiresRemux = false;
|
var requiresRemux = false;
|
||||||
|
|
32
Emby.Server.Implementations/Localization/Core/id.json
Normal file
32
Emby.Server.Implementations/Localization/Core/id.json
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"Albums": "Album",
|
||||||
|
"AuthenticationSucceededWithUserName": "{0} berhasil diautentikasi",
|
||||||
|
"AppDeviceValues": "Aplikasi: {0}, Alat: {1}",
|
||||||
|
"LabelRunningTimeValue": "Waktu berjalan: {0}",
|
||||||
|
"MessageApplicationUpdatedTo": "Jellyfin Server sudah diperbarui ke {0}",
|
||||||
|
"MessageApplicationUpdated": "Jellyfin Server sudah diperbarui",
|
||||||
|
"Latest": "Terbaru",
|
||||||
|
"LabelIpAddressValue": "IP address: {0}",
|
||||||
|
"ItemRemovedWithName": "{0} sudah dikeluarkan dari perpustakaan",
|
||||||
|
"ItemAddedWithName": "{0} sudah dimasukkan ke dalam perpustakaan",
|
||||||
|
"Inherit": "Warisan",
|
||||||
|
"HomeVideos": "Video Rumah",
|
||||||
|
"HeaderRecordingGroups": "Grup Rekaman",
|
||||||
|
"HeaderNextUp": "Selanjutnya",
|
||||||
|
"HeaderLiveTV": "TV Live",
|
||||||
|
"HeaderFavoriteSongs": "Lagu Favorit",
|
||||||
|
"HeaderFavoriteShows": "Tayangan Favorit",
|
||||||
|
"HeaderFavoriteEpisodes": "Episode Favorit",
|
||||||
|
"HeaderFavoriteArtists": "Artis Favorit",
|
||||||
|
"HeaderFavoriteAlbums": "Album Favorit",
|
||||||
|
"HeaderContinueWatching": "Masih Melihat",
|
||||||
|
"HeaderCameraUploads": "Uplod Kamera",
|
||||||
|
"HeaderAlbumArtists": "Album Artis",
|
||||||
|
"Genres": "Genre",
|
||||||
|
"Folders": "Folder",
|
||||||
|
"Favorites": "Favorit",
|
||||||
|
"Collections": "Koleksi",
|
||||||
|
"Books": "Buku",
|
||||||
|
"Artists": "Artis",
|
||||||
|
"Application": "Aplikasi"
|
||||||
|
}
|
|
@ -1,97 +1,97 @@
|
||||||
{
|
{
|
||||||
"Albums": "Albumai",
|
"Albums": "Albumai",
|
||||||
"AppDeviceValues": "App: {0}, Device: {1}",
|
"AppDeviceValues": "Programa: {0}, Įrenginys: {1}",
|
||||||
"Application": "Application",
|
"Application": "Programa",
|
||||||
"Artists": "Atlikėjai",
|
"Artists": "Atlikėjai",
|
||||||
"AuthenticationSucceededWithUserName": "{0} successfully authenticated",
|
"AuthenticationSucceededWithUserName": "{0} sėkmingai autentifikuota",
|
||||||
"Books": "Knygos",
|
"Books": "Knygos",
|
||||||
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
|
"CameraImageUploadedFrom": "Nauja nuotrauka įkelta iš kameros {0}",
|
||||||
"Channels": "Kanalai",
|
"Channels": "Kanalai",
|
||||||
"ChapterNameValue": "Chapter {0}",
|
"ChapterNameValue": "Scena{0}",
|
||||||
"Collections": "Kolekcijos",
|
"Collections": "Kolekcijos",
|
||||||
"DeviceOfflineWithName": "{0} has disconnected",
|
"DeviceOfflineWithName": "{0} buvo atjungtas",
|
||||||
"DeviceOnlineWithName": "{0} is connected",
|
"DeviceOnlineWithName": "{0} prisijungęs",
|
||||||
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
|
"FailedLoginAttemptWithUserName": "{0} - nesėkmingas bandymas prisijungti",
|
||||||
"Favorites": "Mėgstami",
|
"Favorites": "Mėgstami",
|
||||||
"Folders": "Katalogai",
|
"Folders": "Katalogai",
|
||||||
"Genres": "Žanrai",
|
"Genres": "Žanrai",
|
||||||
"HeaderAlbumArtists": "Albumo atlikėjai",
|
"HeaderAlbumArtists": "Albumo atlikėjai",
|
||||||
"HeaderCameraUploads": "Camera Uploads",
|
"HeaderCameraUploads": "Kameros",
|
||||||
"HeaderContinueWatching": "Žiūrėti toliau",
|
"HeaderContinueWatching": "Žiūrėti toliau",
|
||||||
"HeaderFavoriteAlbums": "Favorite Albums",
|
"HeaderFavoriteAlbums": "Mėgstami Albumai",
|
||||||
"HeaderFavoriteArtists": "Favorite Artists",
|
"HeaderFavoriteArtists": "Mėgstami Atlikėjai",
|
||||||
"HeaderFavoriteEpisodes": "Favorite Episodes",
|
"HeaderFavoriteEpisodes": "Mėgstamiausios serijos",
|
||||||
"HeaderFavoriteShows": "Favorite Shows",
|
"HeaderFavoriteShows": "Mėgstamiausi serialai",
|
||||||
"HeaderFavoriteSongs": "Favorite Songs",
|
"HeaderFavoriteSongs": "Mėgstamos dainos",
|
||||||
"HeaderLiveTV": "Live TV",
|
"HeaderLiveTV": "TV gyvai",
|
||||||
"HeaderNextUp": "Next Up",
|
"HeaderNextUp": "Toliau eilėje",
|
||||||
"HeaderRecordingGroups": "Recording Groups",
|
"HeaderRecordingGroups": "Įrašų grupės",
|
||||||
"HomeVideos": "Home videos",
|
"HomeVideos": "Namų vaizdo įrašai",
|
||||||
"Inherit": "Inherit",
|
"Inherit": "Paveldėti",
|
||||||
"ItemAddedWithName": "{0} was added to the library",
|
"ItemAddedWithName": "{0} - buvo įkeltas į mediateką",
|
||||||
"ItemRemovedWithName": "{0} was removed from the library",
|
"ItemRemovedWithName": "{0} - buvo pašalinta iš mediatekos",
|
||||||
"LabelIpAddressValue": "Ip address: {0}",
|
"LabelIpAddressValue": "IP adresas: {0}",
|
||||||
"LabelRunningTimeValue": "Running time: {0}",
|
"LabelRunningTimeValue": "Trukmė: {0}",
|
||||||
"Latest": "Latest",
|
"Latest": "Naujausi",
|
||||||
"MessageApplicationUpdated": "Jellyfin Server has been updated",
|
"MessageApplicationUpdated": "\"Jellyfin Server\" atnaujintas",
|
||||||
"MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}",
|
"MessageApplicationUpdatedTo": "\"Jellyfin Server\" buvo atnaujinta iki {0}",
|
||||||
"MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
|
"MessageNamedServerConfigurationUpdatedWithValue": "Serverio nustatymai (skyrius {0}) buvo atnaujinti",
|
||||||
"MessageServerConfigurationUpdated": "Server configuration has been updated",
|
"MessageServerConfigurationUpdated": "Serverio nustatymai buvo atnaujinti",
|
||||||
"MixedContent": "Mixed content",
|
"MixedContent": "Mixed content",
|
||||||
"Movies": "Filmai",
|
"Movies": "Filmai",
|
||||||
"Music": "Music",
|
"Music": "Muzika",
|
||||||
"MusicVideos": "Music videos",
|
"MusicVideos": "Muzikiniai klipai",
|
||||||
"NameInstallFailed": "{0} installation failed",
|
"NameInstallFailed": "{0} diegimo klaida",
|
||||||
"NameSeasonNumber": "Season {0}",
|
"NameSeasonNumber": "Sezonas {0}",
|
||||||
"NameSeasonUnknown": "Season Unknown",
|
"NameSeasonUnknown": "Sezonas neatpažintas",
|
||||||
"NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.",
|
"NewVersionIsAvailable": "Nauja \"Jellyfin Server\" versija yra prieinama atsisiuntimui.",
|
||||||
"NotificationOptionApplicationUpdateAvailable": "Application update available",
|
"NotificationOptionApplicationUpdateAvailable": "Galimi programos atnaujinimai",
|
||||||
"NotificationOptionApplicationUpdateInstalled": "Application update installed",
|
"NotificationOptionApplicationUpdateInstalled": "Programos atnaujinimai įdiegti",
|
||||||
"NotificationOptionAudioPlayback": "Audio playback started",
|
"NotificationOptionAudioPlayback": "Garso atkūrimas pradėtas",
|
||||||
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
|
"NotificationOptionAudioPlaybackStopped": "Garso atkūrimas sustabdytas",
|
||||||
"NotificationOptionCameraImageUploaded": "Camera image uploaded",
|
"NotificationOptionCameraImageUploaded": "Kameros vaizdai įkelti",
|
||||||
"NotificationOptionInstallationFailed": "Installation failure",
|
"NotificationOptionInstallationFailed": "Diegimo klaida",
|
||||||
"NotificationOptionNewLibraryContent": "New content added",
|
"NotificationOptionNewLibraryContent": "Naujas turinys įkeltas",
|
||||||
"NotificationOptionPluginError": "Plugin failure",
|
"NotificationOptionPluginError": "Įskiepio klaida",
|
||||||
"NotificationOptionPluginInstalled": "Plugin installed",
|
"NotificationOptionPluginInstalled": "Įskiepis įdiegtas",
|
||||||
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
|
"NotificationOptionPluginUninstalled": "Įskiepis pašalintas",
|
||||||
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
|
"NotificationOptionPluginUpdateInstalled": "Įskiepio atnaujinimas įdiegtas",
|
||||||
"NotificationOptionServerRestartRequired": "Server restart required",
|
"NotificationOptionServerRestartRequired": "Reikalingas serverio perleidimas",
|
||||||
"NotificationOptionTaskFailed": "Scheduled task failure",
|
"NotificationOptionTaskFailed": "Suplanuotos užduoties klaida",
|
||||||
"NotificationOptionUserLockedOut": "User locked out",
|
"NotificationOptionUserLockedOut": "Vartotojas užblokuotas",
|
||||||
"NotificationOptionVideoPlayback": "Video playback started",
|
"NotificationOptionVideoPlayback": "Vaizdo įrašo atkūrimas pradėtas",
|
||||||
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
|
"NotificationOptionVideoPlaybackStopped": "Vaizdo įrašo atkūrimas sustabdytas",
|
||||||
"Photos": "Photos",
|
"Photos": "Nuotraukos",
|
||||||
"Playlists": "Playlists",
|
"Playlists": "Grojaraštis",
|
||||||
"Plugin": "Plugin",
|
"Plugin": "Plugin",
|
||||||
"PluginInstalledWithName": "{0} was installed",
|
"PluginInstalledWithName": "{0} buvo įdiegtas",
|
||||||
"PluginUninstalledWithName": "{0} was uninstalled",
|
"PluginUninstalledWithName": "{0} buvo pašalintas",
|
||||||
"PluginUpdatedWithName": "{0} was updated",
|
"PluginUpdatedWithName": "{0} buvo atnaujintas",
|
||||||
"ProviderValue": "Provider: {0}",
|
"ProviderValue": "Provider: {0}",
|
||||||
"ScheduledTaskFailedWithName": "{0} failed",
|
"ScheduledTaskFailedWithName": "{0} klaida",
|
||||||
"ScheduledTaskStartedWithName": "{0} started",
|
"ScheduledTaskStartedWithName": "{0} paleista",
|
||||||
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted",
|
"ServerNameNeedsToBeRestarted": "{0} reikia iš naujo paleisti",
|
||||||
"Shows": "Shows",
|
"Shows": "Laidos",
|
||||||
"Songs": "Songs",
|
"Songs": "Kūriniai",
|
||||||
"StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.",
|
"StartupEmbyServerIsLoading": "Jellyfin Server kraunasi. Netrukus pabandykite dar kartą.",
|
||||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||||
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
|
"SubtitleDownloadFailureFromForItem": "{1} subtitrai buvo nesėkmingai parsiųsti iš {0}",
|
||||||
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
|
"SubtitlesDownloadedForItem": "{0} subtitrai parsiųsti",
|
||||||
"Sync": "Sinchronizuoti",
|
"Sync": "Sinchronizuoti",
|
||||||
"System": "System",
|
"System": "System",
|
||||||
"TvShows": "TV Shows",
|
"TvShows": "TV Serialai",
|
||||||
"User": "User",
|
"User": "User",
|
||||||
"UserCreatedWithName": "User {0} has been created",
|
"UserCreatedWithName": "Vartotojas {0} buvo sukurtas",
|
||||||
"UserDeletedWithName": "User {0} has been deleted",
|
"UserDeletedWithName": "Vartotojas {0} ištrintas",
|
||||||
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
"UserDownloadingItemWithValues": "{0} siunčiasi {1}",
|
||||||
"UserLockedOutWithName": "User {0} has been locked out",
|
"UserLockedOutWithName": "Vartotojas {0} užblokuotas",
|
||||||
"UserOfflineFromDevice": "{0} has disconnected from {1}",
|
"UserOfflineFromDevice": "{0} buvo atjungtas nuo {1}",
|
||||||
"UserOnlineFromDevice": "{0} is online from {1}",
|
"UserOnlineFromDevice": "{0} prisijungęs iš {1}",
|
||||||
"UserPasswordChangedWithName": "Password has been changed for user {0}",
|
"UserPasswordChangedWithName": "Slaptažodis pakeistas vartotojui {0}",
|
||||||
"UserPolicyUpdatedWithName": "User policy has been updated for {0}",
|
"UserPolicyUpdatedWithName": "Vartotojo {0} teisės buvo pakeistos",
|
||||||
"UserStartedPlayingItemWithValues": "{0} is playing {1} on {2}",
|
"UserStartedPlayingItemWithValues": "{0} leidžia {1} į {2}",
|
||||||
"UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}",
|
"UserStoppedPlayingItemWithValues": "{0} baigė leisti {1} į {2}",
|
||||||
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
|
"ValueHasBeenAddedToLibrary": "{0} pridėtas į mediateką",
|
||||||
"ValueSpecialEpisodeName": "Ypatinga - {0}",
|
"ValueSpecialEpisodeName": "Ypatinga - {0}",
|
||||||
"VersionNumber": "Version {0}"
|
"VersionNumber": "Version {0}"
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
"Genres": "Sjangre",
|
"Genres": "Sjangre",
|
||||||
"HeaderAlbumArtists": "Albumartister",
|
"HeaderAlbumArtists": "Albumartister",
|
||||||
"HeaderCameraUploads": "Kameraopplastinger",
|
"HeaderCameraUploads": "Kameraopplastinger",
|
||||||
"HeaderContinueWatching": "Forsett å se på",
|
"HeaderContinueWatching": "Fortsett å se",
|
||||||
"HeaderFavoriteAlbums": "Favorittalbum",
|
"HeaderFavoriteAlbums": "Favorittalbum",
|
||||||
"HeaderFavoriteArtists": "Favorittartister",
|
"HeaderFavoriteArtists": "Favorittartister",
|
||||||
"HeaderFavoriteEpisodes": "Favorittepisoder",
|
"HeaderFavoriteEpisodes": "Favorittepisoder",
|
||||||
|
@ -25,18 +25,18 @@
|
||||||
"HeaderFavoriteSongs": "Favorittsanger",
|
"HeaderFavoriteSongs": "Favorittsanger",
|
||||||
"HeaderLiveTV": "Direkte-TV",
|
"HeaderLiveTV": "Direkte-TV",
|
||||||
"HeaderNextUp": "Neste",
|
"HeaderNextUp": "Neste",
|
||||||
"HeaderRecordingGroups": "Opptak Grupper",
|
"HeaderRecordingGroups": "Opptaksgrupper",
|
||||||
"HomeVideos": "Hjemmelaget filmer",
|
"HomeVideos": "Hjemmelagde filmer",
|
||||||
"Inherit": "Arve",
|
"Inherit": "Arve",
|
||||||
"ItemAddedWithName": "{0} ble lagt til i biblioteket",
|
"ItemAddedWithName": "{0} ble lagt til i biblioteket",
|
||||||
"ItemRemovedWithName": "{0} ble fjernet fra biblioteket",
|
"ItemRemovedWithName": "{0} ble fjernet fra biblioteket",
|
||||||
"LabelIpAddressValue": "IP adresse: {0}",
|
"LabelIpAddressValue": "IP-adresse: {0}",
|
||||||
"LabelRunningTimeValue": "Løpetid {0}",
|
"LabelRunningTimeValue": "Kjøretid {0}",
|
||||||
"Latest": "Siste",
|
"Latest": "Siste",
|
||||||
"MessageApplicationUpdated": "Jellyfin server har blitt oppdatert",
|
"MessageApplicationUpdated": "Jellyfin Server har blitt oppdatert",
|
||||||
"MessageApplicationUpdatedTo": "Jellyfin-serveren ble oppdatert til {0}",
|
"MessageApplicationUpdatedTo": "Jellyfin Server ble oppdatert til {0}",
|
||||||
"MessageNamedServerConfigurationUpdatedWithValue": "Server konfigurasjon seksjon {0} har blitt oppdatert",
|
"MessageNamedServerConfigurationUpdatedWithValue": "Serverkonfigurasjon seksjon {0} har blitt oppdatert",
|
||||||
"MessageServerConfigurationUpdated": "Server konfigurasjon er oppdatert",
|
"MessageServerConfigurationUpdated": "Serverkonfigurasjon er oppdatert",
|
||||||
"MixedContent": "Blandet innhold",
|
"MixedContent": "Blandet innhold",
|
||||||
"Movies": "Filmer",
|
"Movies": "Filmer",
|
||||||
"Music": "Musikk",
|
"Music": "Musikk",
|
||||||
|
@ -44,38 +44,38 @@
|
||||||
"NameInstallFailed": "{0}-installasjonen mislyktes",
|
"NameInstallFailed": "{0}-installasjonen mislyktes",
|
||||||
"NameSeasonNumber": "Sesong {0}",
|
"NameSeasonNumber": "Sesong {0}",
|
||||||
"NameSeasonUnknown": "Sesong ukjent",
|
"NameSeasonUnknown": "Sesong ukjent",
|
||||||
"NewVersionIsAvailable": "En ny versjon av Jellyfin-serveren er tilgjengelig for nedlastning.",
|
"NewVersionIsAvailable": "En ny versjon av Jellyfin Server er tilgjengelig for nedlasting.",
|
||||||
"NotificationOptionApplicationUpdateAvailable": "Applikasjon oppdatering tilgjengelig",
|
"NotificationOptionApplicationUpdateAvailable": "Programvareoppdatering er tilgjengelig",
|
||||||
"NotificationOptionApplicationUpdateInstalled": "Applikasjonsoppdatering installert",
|
"NotificationOptionApplicationUpdateInstalled": "Applikasjonsoppdatering installert",
|
||||||
"NotificationOptionAudioPlayback": "Lyd tilbakespilling startet",
|
"NotificationOptionAudioPlayback": "Lydavspilling startet",
|
||||||
"NotificationOptionAudioPlaybackStopped": "Lyd avspilling stoppet",
|
"NotificationOptionAudioPlaybackStopped": "Lydavspilling stoppet",
|
||||||
"NotificationOptionCameraImageUploaded": "Kamera bilde lastet opp",
|
"NotificationOptionCameraImageUploaded": "Kamerabilde lastet opp",
|
||||||
"NotificationOptionInstallationFailed": "Installasjonsfeil",
|
"NotificationOptionInstallationFailed": "Installasjonsfeil",
|
||||||
"NotificationOptionNewLibraryContent": "Ny innhold er lagt til",
|
"NotificationOptionNewLibraryContent": "Nytt innhold lagt til",
|
||||||
"NotificationOptionPluginError": "Plugin feil",
|
"NotificationOptionPluginError": "Pluginfeil",
|
||||||
"NotificationOptionPluginInstalled": "Plugin installert",
|
"NotificationOptionPluginInstalled": "Plugin installert",
|
||||||
"NotificationOptionPluginUninstalled": "Plugin avinstallert",
|
"NotificationOptionPluginUninstalled": "Plugin avinstallert",
|
||||||
"NotificationOptionPluginUpdateInstalled": "Plugin oppdatering installert",
|
"NotificationOptionPluginUpdateInstalled": "Pluginoppdatering installert",
|
||||||
"NotificationOptionServerRestartRequired": "Server omstart er nødvendig",
|
"NotificationOptionServerRestartRequired": "Serveromstart er nødvendig",
|
||||||
"NotificationOptionTaskFailed": "Feil under utføring av planlagt oppgaver",
|
"NotificationOptionTaskFailed": "Feil under utføring av planlagt oppgave",
|
||||||
"NotificationOptionUserLockedOut": "Bruker er utestengt",
|
"NotificationOptionUserLockedOut": "Bruker er utestengt",
|
||||||
"NotificationOptionVideoPlayback": "Video tilbakespilling startet",
|
"NotificationOptionVideoPlayback": "Videoavspilling startet",
|
||||||
"NotificationOptionVideoPlaybackStopped": "Video avspilling stoppet",
|
"NotificationOptionVideoPlaybackStopped": "Videoavspilling stoppet",
|
||||||
"Photos": "Bilder",
|
"Photos": "Bilder",
|
||||||
"Playlists": "Spillelister",
|
"Playlists": "Spliielister",
|
||||||
"Plugin": "Plugin",
|
"Plugin": "Plugin",
|
||||||
"PluginInstalledWithName": "{0} ble installert",
|
"PluginInstalledWithName": "{0} ble installert",
|
||||||
"PluginUninstalledWithName": "{0} ble avinstallert",
|
"PluginUninstalledWithName": "{0} ble avinstallert",
|
||||||
"PluginUpdatedWithName": "{0} ble oppdatert",
|
"PluginUpdatedWithName": "{0} ble oppdatert",
|
||||||
"ProviderValue": "Leverandører: {0}",
|
"ProviderValue": "Leverandør: {0}",
|
||||||
"ScheduledTaskFailedWithName": "{0} Mislykkes",
|
"ScheduledTaskFailedWithName": "{0} mislykkes",
|
||||||
"ScheduledTaskStartedWithName": "{0} Startet",
|
"ScheduledTaskStartedWithName": "{0} startet",
|
||||||
"ServerNameNeedsToBeRestarted": "{0} må startes på nytt",
|
"ServerNameNeedsToBeRestarted": "{0} må startes på nytt",
|
||||||
"Shows": "Programmer",
|
"Shows": "Programmer",
|
||||||
"Songs": "Sanger",
|
"Songs": "Sanger",
|
||||||
"StartupEmbyServerIsLoading": "Jellyfin server laster. Prøv igjen snart.",
|
"StartupEmbyServerIsLoading": "Jellyfin Server laster. Prøv igjen snart.",
|
||||||
"SubtitleDownloadFailureForItem": "En feil oppstå under nedlasting av undertekster for {0}",
|
"SubtitleDownloadFailureForItem": "En feil oppstå under nedlasting av undertekster for {0}",
|
||||||
"SubtitleDownloadFailureFromForItem": "Kunne ikke laste ned teksting fra {0} for {1}",
|
"SubtitleDownloadFailureFromForItem": "Kunne ikke laste ned undertekster fra {0} for {1}",
|
||||||
"SubtitlesDownloadedForItem": "Undertekster lastet ned for {0}",
|
"SubtitlesDownloadedForItem": "Undertekster lastet ned for {0}",
|
||||||
"Sync": "Synkroniser",
|
"Sync": "Synkroniser",
|
||||||
"System": "System",
|
"System": "System",
|
||||||
|
|
1
Emby.Server.Implementations/Localization/Core/pt.json
Normal file
1
Emby.Server.Implementations/Localization/Core/pt.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
96
Emby.Server.Implementations/Localization/Core/ro.json
Normal file
96
Emby.Server.Implementations/Localization/Core/ro.json
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
{
|
||||||
|
"HeaderNextUp": "Urmează",
|
||||||
|
"VersionNumber": "Versiunea {0}",
|
||||||
|
"ValueSpecialEpisodeName": "Special - {0}",
|
||||||
|
"ValueHasBeenAddedToLibrary": "{0} a fost adăugat la biblioteca multimedia",
|
||||||
|
"UserStoppedPlayingItemWithValues": "{0} a terminat rularea {1} pe {2}",
|
||||||
|
"UserStartedPlayingItemWithValues": "{0} ruleaza {1} pe {2}",
|
||||||
|
"UserPolicyUpdatedWithName": "Politica utilizatorului {0} a fost actualizată",
|
||||||
|
"UserPasswordChangedWithName": "Parola utilizatorului {0} a fost schimbată",
|
||||||
|
"UserOnlineFromDevice": "{0} este conectat de la {1}",
|
||||||
|
"UserOfflineFromDevice": "{0} s-a deconectat de la {1}",
|
||||||
|
"UserLockedOutWithName": "Utilizatorul {0} a fost blocat",
|
||||||
|
"UserDownloadingItemWithValues": "{0} descarcă {1}",
|
||||||
|
"UserDeletedWithName": "Utilizatorul {0} a fost eliminat",
|
||||||
|
"UserCreatedWithName": "Utilizatorul {0} a fost creat",
|
||||||
|
"User": "Utilizator",
|
||||||
|
"TvShows": "Spectacole TV",
|
||||||
|
"System": "Sistem",
|
||||||
|
"Sync": "Sincronizare",
|
||||||
|
"SubtitlesDownloadedForItem": "Subtitrari descarcate pentru {0}",
|
||||||
|
"SubtitleDownloadFailureFromForItem": "Subtitrările nu au putut fi descărcate de la {0} pentru {1}",
|
||||||
|
"StartupEmbyServerIsLoading": "Se încarcă serverul Jellyfin. Încercați din nou în scurt timp.",
|
||||||
|
"Songs": "Melodii",
|
||||||
|
"Shows": "Spectacole",
|
||||||
|
"ServerNameNeedsToBeRestarted": "{0} trebuie repornit",
|
||||||
|
"ScheduledTaskStartedWithName": "{0} pornit/ă",
|
||||||
|
"ScheduledTaskFailedWithName": "{0} eșuat/ă",
|
||||||
|
"ProviderValue": "Furnizor: {0}",
|
||||||
|
"PluginUpdatedWithName": "{0} a fost actualizat/ă",
|
||||||
|
"PluginUninstalledWithName": "{0} a fost dezinstalat",
|
||||||
|
"PluginInstalledWithName": "{0} a fost instalat",
|
||||||
|
"Plugin": "Complement",
|
||||||
|
"Playlists": "Liste redare",
|
||||||
|
"Photos": "Fotografii",
|
||||||
|
"NotificationOptionVideoPlaybackStopped": "Redarea video oprită",
|
||||||
|
"NotificationOptionVideoPlayback": "Începută redarea video",
|
||||||
|
"NotificationOptionUserLockedOut": "Utilizatorul a fost blocat",
|
||||||
|
"NotificationOptionTaskFailed": "Activitate programata eșuată",
|
||||||
|
"NotificationOptionServerRestartRequired": "Este necesară repornirea Serverului",
|
||||||
|
"NotificationOptionPluginUpdateInstalled": "Actualizare plugin instalată",
|
||||||
|
"NotificationOptionPluginUninstalled": "Plugin dezinstalat",
|
||||||
|
"NotificationOptionPluginInstalled": "Plugin instalat",
|
||||||
|
"NotificationOptionPluginError": "Plugin-ul a eșuat",
|
||||||
|
"NotificationOptionNewLibraryContent": "Adăugat conținut nou",
|
||||||
|
"NotificationOptionInstallationFailed": "Eșec la instalare",
|
||||||
|
"NotificationOptionCameraImageUploaded": "Încarcată imagine cameră",
|
||||||
|
"NotificationOptionAudioPlaybackStopped": "Redare audio oprită",
|
||||||
|
"NotificationOptionAudioPlayback": "A inceput redarea audio",
|
||||||
|
"NotificationOptionApplicationUpdateInstalled": "Actualizarea aplicației a fost instalată",
|
||||||
|
"NotificationOptionApplicationUpdateAvailable": "Disponibilă o actualizare a aplicației",
|
||||||
|
"NewVersionIsAvailable": "O nouă versiune a Jellyfin Server este disponibilă pentru descărcare.",
|
||||||
|
"NameSeasonUnknown": "Sezon Necunoscut",
|
||||||
|
"NameSeasonNumber": "Sezonul {0}",
|
||||||
|
"NameInstallFailed": "{0} instalare eșuată",
|
||||||
|
"MusicVideos": "Videoclipuri muzicale",
|
||||||
|
"Music": "Muzică",
|
||||||
|
"Movies": "Filme",
|
||||||
|
"MixedContent": "Conținut mixt",
|
||||||
|
"MessageServerConfigurationUpdated": "Configurația serverului a fost actualizată",
|
||||||
|
"MessageNamedServerConfigurationUpdatedWithValue": "Secțiunea de configurare a serverului {0} a fost acualizata",
|
||||||
|
"MessageApplicationUpdatedTo": "Jellyfin Server a fost actualizat la {0}",
|
||||||
|
"MessageApplicationUpdated": "Jellyfin Server a fost actualizat",
|
||||||
|
"Latest": "Cele mai recente",
|
||||||
|
"LabelRunningTimeValue": "Durată: {0}",
|
||||||
|
"LabelIpAddressValue": "Adresa IP: {0}",
|
||||||
|
"ItemRemovedWithName": "{0} a fost eliminat din bibliotecă",
|
||||||
|
"ItemAddedWithName": "{0} a fost adăugat în bibliotecă",
|
||||||
|
"Inherit": "moștenit",
|
||||||
|
"HomeVideos": "Videoclipuri personale",
|
||||||
|
"HeaderRecordingGroups": "Grupuri de înregistrare",
|
||||||
|
"HeaderLiveTV": "TV în Direct",
|
||||||
|
"HeaderFavoriteSongs": "Melodii Favorite",
|
||||||
|
"HeaderFavoriteShows": "Spectacole Favorite",
|
||||||
|
"HeaderFavoriteEpisodes": "Episoade Favorite",
|
||||||
|
"HeaderFavoriteArtists": "Artiști Favoriți",
|
||||||
|
"HeaderFavoriteAlbums": "Albume Favorite",
|
||||||
|
"HeaderContinueWatching": "Vizionează în continuare",
|
||||||
|
"HeaderCameraUploads": "Incărcări Cameră Foto",
|
||||||
|
"HeaderAlbumArtists": "Album Artiști",
|
||||||
|
"Genres": "Genuri",
|
||||||
|
"Folders": "Dosare",
|
||||||
|
"Favorites": "Favorite",
|
||||||
|
"FailedLoginAttemptWithUserName": "Încercare de conectare nereușită de la {0}",
|
||||||
|
"DeviceOnlineWithName": "{0} este conectat",
|
||||||
|
"DeviceOfflineWithName": "{0} s-a deconectat",
|
||||||
|
"Collections": "Colecții",
|
||||||
|
"ChapterNameValue": "Capitol {0}",
|
||||||
|
"Channels": "Canale",
|
||||||
|
"CameraImageUploadedFrom": "O nouă fotografie a fost încărcată din {0}",
|
||||||
|
"Books": "Cărți",
|
||||||
|
"AuthenticationSucceededWithUserName": "{0} autentificare reușită",
|
||||||
|
"Artists": "Artiști",
|
||||||
|
"Application": "Aplicație",
|
||||||
|
"AppDeviceValues": "Aplicație: {0}, Dispozitiv: {1}",
|
||||||
|
"Albums": "Albume"
|
||||||
|
}
|
|
@ -24,7 +24,7 @@
|
||||||
"HeaderFavoriteShows": "最爱的节目",
|
"HeaderFavoriteShows": "最爱的节目",
|
||||||
"HeaderFavoriteSongs": "最爱的歌曲",
|
"HeaderFavoriteSongs": "最爱的歌曲",
|
||||||
"HeaderLiveTV": "电视直播",
|
"HeaderLiveTV": "电视直播",
|
||||||
"HeaderNextUp": "接下来",
|
"HeaderNextUp": "下一步",
|
||||||
"HeaderRecordingGroups": "录制组",
|
"HeaderRecordingGroups": "录制组",
|
||||||
"HomeVideos": "家庭视频",
|
"HomeVideos": "家庭视频",
|
||||||
"Inherit": "继承",
|
"Inherit": "继承",
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
"LabelRunningTimeValue": "运行时间:{0}",
|
"LabelRunningTimeValue": "运行时间:{0}",
|
||||||
"Latest": "最新",
|
"Latest": "最新",
|
||||||
"MessageApplicationUpdated": "Jellyfin 服务器已更新",
|
"MessageApplicationUpdated": "Jellyfin 服务器已更新",
|
||||||
"MessageApplicationUpdatedTo": "Jellyfin Server 的版本已更新为 {0}",
|
"MessageApplicationUpdatedTo": "Jellyfin Server 版本已更新为 {0}",
|
||||||
"MessageNamedServerConfigurationUpdatedWithValue": "服务器配置 {0} 部分已更新",
|
"MessageNamedServerConfigurationUpdatedWithValue": "服务器配置 {0} 部分已更新",
|
||||||
"MessageServerConfigurationUpdated": "服务器配置已更新",
|
"MessageServerConfigurationUpdated": "服务器配置已更新",
|
||||||
"MixedContent": "混合内容",
|
"MixedContent": "混合内容",
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
"Music": "音乐",
|
"Music": "音乐",
|
||||||
"MusicVideos": "音乐视频",
|
"MusicVideos": "音乐视频",
|
||||||
"NameInstallFailed": "{0} 安装失败",
|
"NameInstallFailed": "{0} 安装失败",
|
||||||
"NameSeasonNumber": "季 {0}",
|
"NameSeasonNumber": "第 {0} 季",
|
||||||
"NameSeasonUnknown": "未知季",
|
"NameSeasonUnknown": "未知季",
|
||||||
"NewVersionIsAvailable": "Jellyfin Server 有新版本可以下载。",
|
"NewVersionIsAvailable": "Jellyfin Server 有新版本可以下载。",
|
||||||
"NotificationOptionApplicationUpdateAvailable": "有可用的应用程序更新",
|
"NotificationOptionApplicationUpdateAvailable": "有可用的应用程序更新",
|
||||||
|
|
|
@ -56,10 +56,8 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
{
|
{
|
||||||
var name = options.Name;
|
var name = options.Name;
|
||||||
|
|
||||||
var folderName = _fileSystem.GetValidFilename(name) + " [playlist]";
|
var folderName = _fileSystem.GetValidFilename(name);
|
||||||
|
|
||||||
var parentFolder = GetPlaylistsFolder(Guid.Empty);
|
var parentFolder = GetPlaylistsFolder(Guid.Empty);
|
||||||
|
|
||||||
if (parentFolder == null)
|
if (parentFolder == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentException();
|
throw new ArgumentException();
|
||||||
|
@ -253,11 +251,13 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
SavePlaylistFile(playlist);
|
SavePlaylistFile(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
_providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
_providerManager.QueueRefresh(
|
||||||
{
|
playlist.Id,
|
||||||
ForceSave = true
|
new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
||||||
|
{
|
||||||
}, RefreshPriority.High);
|
ForceSave = true
|
||||||
|
},
|
||||||
|
RefreshPriority.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MoveItem(string playlistId, string entryId, int newIndex)
|
public void MoveItem(string playlistId, string entryId, int newIndex)
|
||||||
|
@ -303,7 +303,8 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
|
|
||||||
private void SavePlaylistFile(Playlist item)
|
private void SavePlaylistFile(Playlist item)
|
||||||
{
|
{
|
||||||
// This is probably best done as a metatata provider, but saving a file over itself will first require some core work to prevent this from happening when not needed
|
// this is probably best done as a metadata provider
|
||||||
|
// saving a file over itself will require some work to prevent this from happening when not needed
|
||||||
var playlistPath = item.Path;
|
var playlistPath = item.Path;
|
||||||
var extension = Path.GetExtension(playlistPath);
|
var extension = Path.GetExtension(playlistPath);
|
||||||
|
|
||||||
|
@ -335,12 +336,14 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
{
|
{
|
||||||
entry.Duration = TimeSpan.FromTicks(child.RunTimeTicks.Value);
|
entry.Duration = TimeSpan.FromTicks(child.RunTimeTicks.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist.PlaylistEntries.Add(entry);
|
playlist.PlaylistEntries.Add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
string text = new WplContent().ToText(playlist);
|
string text = new WplContent().ToText(playlist);
|
||||||
File.WriteAllText(playlistPath, text);
|
File.WriteAllText(playlistPath, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(".zpl", extension, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(".zpl", extension, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var playlist = new ZplPlaylist();
|
var playlist = new ZplPlaylist();
|
||||||
|
@ -375,6 +378,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
string text = new ZplContent().ToText(playlist);
|
string text = new ZplContent().ToText(playlist);
|
||||||
File.WriteAllText(playlistPath, text);
|
File.WriteAllText(playlistPath, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(".m3u", extension, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(".m3u", extension, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var playlist = new M3uPlaylist();
|
var playlist = new M3uPlaylist();
|
||||||
|
@ -398,12 +402,14 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
{
|
{
|
||||||
entry.Duration = TimeSpan.FromTicks(child.RunTimeTicks.Value);
|
entry.Duration = TimeSpan.FromTicks(child.RunTimeTicks.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist.PlaylistEntries.Add(entry);
|
playlist.PlaylistEntries.Add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
string text = new M3uContent().ToText(playlist);
|
string text = new M3uContent().ToText(playlist);
|
||||||
File.WriteAllText(playlistPath, text);
|
File.WriteAllText(playlistPath, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(".m3u8", extension, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(".m3u8", extension, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var playlist = new M3uPlaylist();
|
var playlist = new M3uPlaylist();
|
||||||
|
@ -427,12 +433,14 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
{
|
{
|
||||||
entry.Duration = TimeSpan.FromTicks(child.RunTimeTicks.Value);
|
entry.Duration = TimeSpan.FromTicks(child.RunTimeTicks.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist.PlaylistEntries.Add(entry);
|
playlist.PlaylistEntries.Add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
string text = new M3u8Content().ToText(playlist);
|
string text = new M3u8Content().ToText(playlist);
|
||||||
File.WriteAllText(playlistPath, text);
|
File.WriteAllText(playlistPath, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(".pls", extension, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(".pls", extension, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var playlist = new PlsPlaylist();
|
var playlist = new PlsPlaylist();
|
||||||
|
@ -448,6 +456,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
{
|
{
|
||||||
entry.Length = TimeSpan.FromTicks(child.RunTimeTicks.Value);
|
entry.Length = TimeSpan.FromTicks(child.RunTimeTicks.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist.PlaylistEntries.Add(entry);
|
playlist.PlaylistEntries.Add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,7 +482,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
throw new ArgumentException("File absolute path was null or empty.", nameof(fileAbsolutePath));
|
throw new ArgumentException("File absolute path was null or empty.", nameof(fileAbsolutePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!folderPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
|
if (!folderPath.EndsWith(Path.DirectorySeparatorChar))
|
||||||
{
|
{
|
||||||
folderPath = folderPath + Path.DirectorySeparatorChar;
|
folderPath = folderPath + Path.DirectorySeparatorChar;
|
||||||
}
|
}
|
||||||
|
@ -481,7 +490,11 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
var folderUri = new Uri(folderPath);
|
var folderUri = new Uri(folderPath);
|
||||||
var fileAbsoluteUri = new Uri(fileAbsolutePath);
|
var fileAbsoluteUri = new Uri(fileAbsolutePath);
|
||||||
|
|
||||||
if (folderUri.Scheme != fileAbsoluteUri.Scheme) { return fileAbsolutePath; } // path can't be made relative.
|
// path can't be made relative
|
||||||
|
if (folderUri.Scheme != fileAbsoluteUri.Scheme)
|
||||||
|
{
|
||||||
|
return fileAbsolutePath;
|
||||||
|
}
|
||||||
|
|
||||||
var relativeUri = folderUri.MakeRelativeUri(fileAbsoluteUri);
|
var relativeUri = folderUri.MakeRelativeUri(fileAbsoluteUri);
|
||||||
string relativePath = Uri.UnescapeDataString(relativeUri.ToString());
|
string relativePath = Uri.UnescapeDataString(relativeUri.ToString());
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -189,7 +189,7 @@ namespace Emby.Server.Implementations.Updates
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async IAsyncEnumerable<PackageVersionInfo> GetAvailablePluginUpdates(CancellationToken cancellationToken = default)
|
public async IAsyncEnumerable<PackageVersionInfo> GetAvailablePluginUpdates([EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false);
|
var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
|
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Code analysers-->
|
<!-- Code Analyzers-->
|
||||||
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" PrivateAssets="All" />
|
||||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AssemblyName>jellyfin</AssemblyName>
|
<AssemblyName>jellyfin</AssemblyName>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -24,8 +24,8 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Code analyzers-->
|
<!-- Code Analyzers-->
|
||||||
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" />
|
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" />
|
||||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
|
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
|
||||||
|
|
|
@ -1006,8 +1006,8 @@ namespace MediaBrowser.Api.Library
|
||||||
public void Delete(DeleteItems request)
|
public void Delete(DeleteItems request)
|
||||||
{
|
{
|
||||||
var ids = string.IsNullOrWhiteSpace(request.Ids)
|
var ids = string.IsNullOrWhiteSpace(request.Ids)
|
||||||
? Array.Empty<string>()
|
? Array.Empty<string>()
|
||||||
: request.Ids.Split(',');
|
: request.Ids.Split(',');
|
||||||
|
|
||||||
foreach (var i in ids)
|
foreach (var i in ids)
|
||||||
{
|
{
|
||||||
|
@ -1028,7 +1028,6 @@ namespace MediaBrowser.Api.Library
|
||||||
_libraryManager.DeleteItem(item, new DeleteOptions
|
_libraryManager.DeleteItem(item, new DeleteOptions
|
||||||
{
|
{
|
||||||
DeleteFileLocation = true
|
DeleteFileLocation = true
|
||||||
|
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,8 +102,6 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
/// <exception cref="ArgumentNullException">user</exception>
|
|
||||||
/// <exception cref="ArgumentException"></exception>
|
|
||||||
void DeleteUser(User user);
|
void DeleteUser(User user);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
74
MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs
Normal file
74
MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using BDInfo.IO;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
|
namespace MediaBrowser.MediaEncoding.BdInfo
|
||||||
|
{
|
||||||
|
class BdInfoDirectoryInfo : BDInfo.IO.IDirectoryInfo
|
||||||
|
{
|
||||||
|
IFileSystem _fileSystem = null;
|
||||||
|
|
||||||
|
FileSystemMetadata _impl = null;
|
||||||
|
|
||||||
|
public string Name => _impl.Name;
|
||||||
|
|
||||||
|
public string FullName => _impl.FullName;
|
||||||
|
|
||||||
|
public IDirectoryInfo Parent
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var parentFolder = System.IO.Path.GetDirectoryName(_impl.FullName);
|
||||||
|
if (parentFolder != null)
|
||||||
|
{
|
||||||
|
return new BdInfoDirectoryInfo(_fileSystem, parentFolder);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BdInfoDirectoryInfo(IFileSystem fileSystem, string path)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
_impl = _fileSystem.GetDirectoryInfo(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BdInfoDirectoryInfo(IFileSystem fileSystem, FileSystemMetadata impl)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
_impl = impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDirectoryInfo[] GetDirectories()
|
||||||
|
{
|
||||||
|
return Array.ConvertAll(_fileSystem.GetDirectories(_impl.FullName).ToArray(),
|
||||||
|
x => new BdInfoDirectoryInfo(_fileSystem, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFileInfo[] GetFiles()
|
||||||
|
{
|
||||||
|
return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName).ToArray(),
|
||||||
|
x => new BdInfoFileInfo(_fileSystem, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFileInfo[] GetFiles(string searchPattern)
|
||||||
|
{
|
||||||
|
return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, false).ToArray(),
|
||||||
|
x => new BdInfoFileInfo(_fileSystem, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFileInfo[] GetFiles(string searchPattern, System.IO.SearchOption searchOption)
|
||||||
|
{
|
||||||
|
return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false,
|
||||||
|
searchOption.HasFlag(System.IO.SearchOption.AllDirectories)).ToArray(),
|
||||||
|
x => new BdInfoFileInfo(_fileSystem, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IDirectoryInfo FromFileSystemPath(Model.IO.IFileSystem fs, string path)
|
||||||
|
{
|
||||||
|
return new BdInfoDirectoryInfo(fs, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using BDInfo;
|
using BDInfo;
|
||||||
|
@ -32,7 +32,7 @@ namespace MediaBrowser.MediaEncoding.BdInfo
|
||||||
throw new ArgumentNullException(nameof(path));
|
throw new ArgumentNullException(nameof(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
var bdrom = new BDROM(path, _fileSystem);
|
var bdrom = new BDROM(BdInfoDirectoryInfo.FromFileSystemPath(_fileSystem, path));
|
||||||
|
|
||||||
bdrom.Scan();
|
bdrom.Scan();
|
||||||
|
|
||||||
|
|
40
MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs
Normal file
40
MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
|
namespace MediaBrowser.MediaEncoding.BdInfo
|
||||||
|
{
|
||||||
|
class BdInfoFileInfo : BDInfo.IO.IFileInfo
|
||||||
|
{
|
||||||
|
IFileSystem _fileSystem = null;
|
||||||
|
|
||||||
|
FileSystemMetadata _impl = null;
|
||||||
|
|
||||||
|
public string Name => _impl.Name;
|
||||||
|
|
||||||
|
public string FullName => _impl.FullName;
|
||||||
|
|
||||||
|
public string Extension => _impl.Extension;
|
||||||
|
|
||||||
|
public long Length => _impl.Length;
|
||||||
|
|
||||||
|
public bool IsDir => _impl.IsDirectory;
|
||||||
|
|
||||||
|
public BdInfoFileInfo(IFileSystem fileSystem, FileSystemMetadata impl)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
_impl = impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public System.IO.Stream OpenRead()
|
||||||
|
{
|
||||||
|
return _fileSystem.GetFileStream(FullName,
|
||||||
|
FileOpenMode.Open,
|
||||||
|
FileAccessMode.Read,
|
||||||
|
FileShareMode.Read);
|
||||||
|
}
|
||||||
|
|
||||||
|
public System.IO.StreamReader OpenText()
|
||||||
|
{
|
||||||
|
return new System.IO.StreamReader(OpenRead());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,13 +11,13 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\BDInfo\BDInfo.csproj" />
|
|
||||||
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
|
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
|
||||||
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
|
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
|
||||||
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
|
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BDInfo" Version="0.7.6.1" />
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.6.0" />
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.6.0" />
|
||||||
<PackageReference Include="UTF.Unknown" Version="2.2.0" />
|
<PackageReference Include="UTF.Unknown" Version="2.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
146
MediaBrowser.Providers/Tmdb/TV/TmdbSeasonImageProvider.cs
Normal file
146
MediaBrowser.Providers/Tmdb/TV/TmdbSeasonImageProvider.cs
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
|
using MediaBrowser.Controller.Providers;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
|
using MediaBrowser.Model.Providers;
|
||||||
|
using MediaBrowser.Model.Serialization;
|
||||||
|
using MediaBrowser.Providers.Tmdb.Models.General;
|
||||||
|
using MediaBrowser.Providers.Tmdb.Movies;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Providers.Tmdb.TV
|
||||||
|
{
|
||||||
|
public class TmdbSeasonImageProvider : IRemoteImageProvider, IHasOrder
|
||||||
|
{
|
||||||
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
|
private readonly IHttpClient _httpClient;
|
||||||
|
|
||||||
|
public TmdbSeasonImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient)
|
||||||
|
{
|
||||||
|
_jsonSerializer = jsonSerializer;
|
||||||
|
_httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Order => 1;
|
||||||
|
|
||||||
|
public string Name => ProviderName;
|
||||||
|
|
||||||
|
public static string ProviderName => TmdbUtils.ProviderName;
|
||||||
|
|
||||||
|
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
|
{
|
||||||
|
CancellationToken = cancellationToken,
|
||||||
|
Url = url
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var season = (Season)item;
|
||||||
|
var series = season.Series;
|
||||||
|
|
||||||
|
var seriesId = series?.GetProviderId(MetadataProviders.Tmdb);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(seriesId))
|
||||||
|
{
|
||||||
|
return Enumerable.Empty<RemoteImageInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var seasonNumber = season.IndexNumber;
|
||||||
|
|
||||||
|
if (!seasonNumber.HasValue)
|
||||||
|
{
|
||||||
|
return Enumerable.Empty<RemoteImageInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var language = item.GetPreferredMetadataLanguage();
|
||||||
|
|
||||||
|
var results = await FetchImages(season, seriesId, language, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
|
||||||
|
|
||||||
|
var list = results.Select(i => new RemoteImageInfo
|
||||||
|
{
|
||||||
|
Url = tmdbImageUrl + i.File_Path,
|
||||||
|
CommunityRating = i.Vote_Average,
|
||||||
|
VoteCount = i.Vote_Count,
|
||||||
|
Width = i.Width,
|
||||||
|
Height = i.Height,
|
||||||
|
Language = TmdbMovieProvider.AdjustImageLanguage(i.Iso_639_1, language),
|
||||||
|
ProviderName = Name,
|
||||||
|
Type = ImageType.Primary,
|
||||||
|
RatingType = RatingType.Score
|
||||||
|
});
|
||||||
|
|
||||||
|
var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
return list.OrderByDescending(i =>
|
||||||
|
{
|
||||||
|
if (string.Equals(language, i.Language, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLanguageEn)
|
||||||
|
{
|
||||||
|
if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(i.Language))
|
||||||
|
{
|
||||||
|
return isLanguageEn ? 3 : 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
.ThenByDescending(i => i.CommunityRating ?? 0)
|
||||||
|
.ThenByDescending(i => i.VoteCount ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<Poster>> FetchImages(Season item, string tmdbId, string language, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await TmdbSeasonProvider.Current.EnsureSeasonInfo(tmdbId, item.IndexNumber.GetValueOrDefault(), language, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var path = TmdbSeriesProvider.Current.GetDataFilePath(tmdbId, language);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
return _jsonSerializer.DeserializeFromFile<Models.TV.SeasonResult>(path).Images.Posters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
|
||||||
|
{
|
||||||
|
return new List<ImageType>
|
||||||
|
{
|
||||||
|
ImageType.Primary
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Supports(BaseItem item)
|
||||||
|
{
|
||||||
|
return item is Season;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,8 @@ namespace MediaBrowser.Providers.Tmdb.TV
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
internal static TmdbSeasonProvider Current { get; private set; }
|
||||||
|
|
||||||
public TmdbSeasonProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory)
|
public TmdbSeasonProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
|
@ -40,6 +42,7 @@ namespace MediaBrowser.Providers.Tmdb.TV
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
_logger = loggerFactory.CreateLogger(GetType().Name);
|
_logger = loggerFactory.CreateLogger(GetType().Name);
|
||||||
|
Current = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<MetadataResult<Season>> GetMetadata(SeasonInfo info, CancellationToken cancellationToken)
|
public async Task<MetadataResult<Season>> GetMetadata(SeasonInfo info, CancellationToken cancellationToken)
|
||||||
|
|
|
@ -24,8 +24,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Photos", "Emby.Photos\
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DvdLib", "DvdLib\DvdLib.csproj", "{713F42B5-878E-499D-A878-E4C652B1D5E8}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DvdLib", "DvdLib\DvdLib.csproj", "{713F42B5-878E-499D-A878-E4C652B1D5E8}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BDInfo", "BDInfo\BDInfo.csproj", "{88AE38DF-19D7-406F-A6A9-09527719A21E}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Server.Implementations", "Emby.Server.Implementations\Emby.Server.Implementations.csproj", "{E383961B-9356-4D5D-8233-9A1079D03055}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Server.Implementations", "Emby.Server.Implementations\Emby.Server.Implementations.csproj", "{E383961B-9356-4D5D-8233-9A1079D03055}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RSSDP", "RSSDP\RSSDP.csproj", "{21002819-C39A-4D3E-BE83-2A276A77FB1F}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RSSDP", "RSSDP\RSSDP.csproj", "{21002819-C39A-4D3E-BE83-2A276A77FB1F}"
|
||||||
|
|
|
@ -3,7 +3,7 @@ FROM centos:7
|
||||||
ARG SOURCE_DIR=/jellyfin
|
ARG SOURCE_DIR=/jellyfin
|
||||||
ARG PLATFORM_DIR=/jellyfin/deployment/centos-package-x64
|
ARG PLATFORM_DIR=/jellyfin/deployment/centos-package-x64
|
||||||
ARG ARTIFACT_DIR=/dist
|
ARG ARTIFACT_DIR=/dist
|
||||||
ARG SDK_VERSION=3.0
|
ARG SDK_VERSION=3.1
|
||||||
# Docker run environment
|
# Docker run environment
|
||||||
ENV SOURCE_DIR=/jellyfin
|
ENV SOURCE_DIR=/jellyfin
|
||||||
ENV ARTIFACT_DIR=/dist
|
ENV ARTIFACT_DIR=/dist
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue