From 8fd3bf42173e02f3b05c0373072c97e19fb76b9a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 3 Nov 2016 15:07:48 -0400 Subject: change pcl's to .netstandard --- Emby.Server.Implementations/project.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Emby.Server.Implementations/project.json (limited to 'Emby.Server.Implementations/project.json') diff --git a/Emby.Server.Implementations/project.json b/Emby.Server.Implementations/project.json new file mode 100644 index 000000000..1e12b0074 --- /dev/null +++ b/Emby.Server.Implementations/project.json @@ -0,0 +1,12 @@ +{ + "supports": {}, + "dependencies": { + "MediaBrowser.Naming": "1.0.0.58", + "Microsoft.NETCore.Portable.Compatibility": "1.0.1", + "NETStandard.Library": "1.6.0", + "Patterns.Logging": "1.0.0.5" + }, + "frameworks": { + "netstandard1.3": {} + } +} \ No newline at end of file -- cgit v1.2.3 From 13dcb5abb1682940a45e83e5a9f7b71289231986 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 3 Nov 2016 17:04:55 -0400 Subject: fix projects --- .../Emby.Server.Implementations.csproj | 7 +- Emby.Server.Implementations/project.json | 10 +-- MediaBrowser.Common/MediaBrowser.Common.csproj | 7 +- .../MediaBrowser.Common.nuget.targets | 6 ++ MediaBrowser.Common/project.json | 25 +++--- .../MediaBrowser.Controller.csproj | 7 +- .../MediaBrowser.Controller.nuget.targets | 6 ++ MediaBrowser.Controller/project.json | 25 +++--- MediaBrowser.Model/MediaBrowser.Model.csproj | 7 +- .../MediaBrowser.Model.nuget.targets | 6 ++ MediaBrowser.Model/project.json | 25 +++--- .../MediaBrowser.Server.Implementations.csproj | 18 ++--- .../packages.config | 6 +- .../MediaBrowser.Server.Mono.csproj | 4 +- MediaBrowser.Server.Mono/packages.config | 2 +- .../MediaBrowser.Server.Startup.Common.csproj | 4 +- MediaBrowser.Server.Startup.Common/packages.config | 2 +- .../MediaBrowser.ServerApplication.csproj | 4 +- MediaBrowser.ServerApplication/packages.config | 2 +- MediaBrowser.sln | 62 +++++++-------- Mono.Nat/Mono.Nat.csproj | 89 ---------------------- Mono.Nat/Mono.Nat.xproj | 23 ++++++ Mono.Nat/Properties/AssemblyInfo.cs | 26 ++----- Mono.Nat/project.json | 44 +++++++++-- 24 files changed, 200 insertions(+), 217 deletions(-) create mode 100644 MediaBrowser.Common/MediaBrowser.Common.nuget.targets create mode 100644 MediaBrowser.Controller/MediaBrowser.Controller.nuget.targets create mode 100644 MediaBrowser.Model/MediaBrowser.Model.nuget.targets delete mode 100644 Mono.Nat/Mono.Nat.csproj create mode 100644 Mono.Nat/Mono.Nat.xproj (limited to 'Emby.Server.Implementations/project.json') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 5c7136eab..4a32d00a2 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -2,7 +2,7 @@ - 14.0 + 11.0 Debug AnyCPU {E383961B-9356-4D5D-8233-9A1079D03055} @@ -13,9 +13,8 @@ en-US 512 {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - v5.0 + Profile7 + v4.5 true diff --git a/Emby.Server.Implementations/project.json b/Emby.Server.Implementations/project.json index 1e12b0074..b1373cd45 100644 --- a/Emby.Server.Implementations/project.json +++ b/Emby.Server.Implementations/project.json @@ -1,12 +1,10 @@ -{ +{ "supports": {}, "dependencies": { - "MediaBrowser.Naming": "1.0.0.58", - "Microsoft.NETCore.Portable.Compatibility": "1.0.1", - "NETStandard.Library": "1.6.0", - "Patterns.Logging": "1.0.0.5" + "MediaBrowser.Naming": "1.0.0.59", + "Patterns.Logging": "1.0.0.6" }, "frameworks": { - "netstandard1.3": {} + ".NETPortable,Version=v4.5,Profile=Profile7": {} } } \ No newline at end of file diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 0164a7829..9e212219d 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -14,10 +14,9 @@ 10.0.0 2.0 {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - v5.0 - 14.0 + Profile7 + v4.5 + 11.0 true diff --git a/MediaBrowser.Common/MediaBrowser.Common.nuget.targets b/MediaBrowser.Common/MediaBrowser.Common.nuget.targets new file mode 100644 index 000000000..e69ce0e64 --- /dev/null +++ b/MediaBrowser.Common/MediaBrowser.Common.nuget.targets @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/MediaBrowser.Common/project.json b/MediaBrowser.Common/project.json index 19f6c6a99..fbbe9eaf3 100644 --- a/MediaBrowser.Common/project.json +++ b/MediaBrowser.Common/project.json @@ -1,10 +1,17 @@ -{ - "supports": {}, - "dependencies": { - "Microsoft.NETCore.Portable.Compatibility": "1.0.1", - "NETStandard.Library": "1.6.0" - }, - "frameworks": { - "netstandard1.0": {} - } +{ + "frameworks":{ + "netstandard1.6":{ + "dependencies":{ + "NETStandard.Library":"1.6.0", + } + }, + ".NETPortable,Version=v4.5,Profile=Profile7":{ + "buildOptions": { + "define": [ ] + }, + "frameworkAssemblies":{ + + } + } + } } \ No newline at end of file diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 5c48adfe7..6801a4639 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -12,10 +12,9 @@ 512 ..\ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - v5.0 - 14.0 + Profile7 + v4.5 + 11.0 true diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.nuget.targets b/MediaBrowser.Controller/MediaBrowser.Controller.nuget.targets new file mode 100644 index 000000000..e69ce0e64 --- /dev/null +++ b/MediaBrowser.Controller/MediaBrowser.Controller.nuget.targets @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/MediaBrowser.Controller/project.json b/MediaBrowser.Controller/project.json index 7af946da1..fbbe9eaf3 100644 --- a/MediaBrowser.Controller/project.json +++ b/MediaBrowser.Controller/project.json @@ -1,10 +1,17 @@ -{ - "supports": {}, - "dependencies": { - "Microsoft.NETCore.Portable.Compatibility": "1.0.1", - "NETStandard.Library": "1.6.0" - }, - "frameworks": { - "netstandard1.1": {} - } +{ + "frameworks":{ + "netstandard1.6":{ + "dependencies":{ + "NETStandard.Library":"1.6.0", + } + }, + ".NETPortable,Version=v4.5,Profile=Profile7":{ + "buildOptions": { + "define": [ ] + }, + "frameworkAssemblies":{ + + } + } + } } \ No newline at end of file diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 1dc2b52b0..5999f02db 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -2,7 +2,7 @@ - 14.0 + 11.0 Debug AnyCPU {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B} @@ -13,9 +13,8 @@ en-US 512 {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - v5.0 + Profile7 + v4.5 true diff --git a/MediaBrowser.Model/MediaBrowser.Model.nuget.targets b/MediaBrowser.Model/MediaBrowser.Model.nuget.targets new file mode 100644 index 000000000..e69ce0e64 --- /dev/null +++ b/MediaBrowser.Model/MediaBrowser.Model.nuget.targets @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/MediaBrowser.Model/project.json b/MediaBrowser.Model/project.json index 19f6c6a99..fbbe9eaf3 100644 --- a/MediaBrowser.Model/project.json +++ b/MediaBrowser.Model/project.json @@ -1,10 +1,17 @@ -{ - "supports": {}, - "dependencies": { - "Microsoft.NETCore.Portable.Compatibility": "1.0.1", - "NETStandard.Library": "1.6.0" - }, - "frameworks": { - "netstandard1.0": {} - } +{ + "frameworks":{ + "netstandard1.6":{ + "dependencies":{ + "NETStandard.Library":"1.6.0", + } + }, + ".NETPortable,Version=v4.5,Profile=Profile7":{ + "buildOptions": { + "define": [ ] + }, + "frameworkAssemblies":{ + + } + } + } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index dba48c78b..88e9478df 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -46,23 +46,27 @@ ..\ThirdParty\emby\Emby.Common.Implementations.dll - ..\packages\Emby.XmlTv.1.0.0.59\lib\netstandard1.0\Emby.XmlTv.dll + ..\packages\Emby.XmlTv.1.0.0.62\lib\portable-net45+win8\Emby.XmlTv.dll True ..\packages\ini-parser.2.3.0\lib\net20\INIFileParser.dll True - - ..\packages\MediaBrowser.Naming.1.0.0.58\lib\netstandard1.0\MediaBrowser.Naming.dll + + ..\packages\MediaBrowser.Naming.1.0.0.59\lib\portable-net45+win8\MediaBrowser.Naming.dll True ..\packages\Microsoft.IO.RecyclableMemoryStream.1.1.0.0\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll True - - ..\packages\Patterns.Logging.1.0.0.5\lib\netstandard1.0\Patterns.Logging.dll + + False + ..\ThirdParty\emby\Mono.Nat.dll + + + ..\packages\Patterns.Logging.1.0.0.6\lib\portable-net45+win8\Patterns.Logging.dll True @@ -281,10 +285,6 @@ {442b5058-dcaf-4263-bb6a-f21e31120a1b} MediaBrowser.Providers - - {e9db21d4-05e8-4883-b161-c55071166579} - Mono.Nat - diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index e1c681a25..cdfb48abe 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,10 +1,10 @@  - + - + - + \ No newline at end of file diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index 8b7efe22b..fcaeb035d 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -69,8 +69,8 @@ ..\packages\NLog.4.4.0-betaV15\lib\net45\NLog.dll True - - ..\packages\Patterns.Logging.1.0.0.5\lib\netstandard1.0\Patterns.Logging.dll + + ..\packages\Patterns.Logging.1.0.0.6\lib\portable-net45+win8\Patterns.Logging.dll True diff --git a/MediaBrowser.Server.Mono/packages.config b/MediaBrowser.Server.Mono/packages.config index 93f827a84..8d1ebc141 100644 --- a/MediaBrowser.Server.Mono/packages.config +++ b/MediaBrowser.Server.Mono/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index 909d944fd..c64f065d7 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -42,8 +42,8 @@ False ..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll - - ..\packages\Patterns.Logging.1.0.0.5\lib\netstandard1.0\Patterns.Logging.dll + + ..\packages\Patterns.Logging.1.0.0.6\lib\portable-net45+win8\Patterns.Logging.dll True diff --git a/MediaBrowser.Server.Startup.Common/packages.config b/MediaBrowser.Server.Startup.Common/packages.config index 503b0b826..aa11730c7 100644 --- a/MediaBrowser.Server.Startup.Common/packages.config +++ b/MediaBrowser.Server.Startup.Common/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 1d0c2302f..a306274e1 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -75,8 +75,8 @@ ..\packages\NLog.4.4.0-betaV15\lib\net45\NLog.dll True - - ..\packages\Patterns.Logging.1.0.0.5\lib\netstandard1.0\Patterns.Logging.dll + + ..\packages\Patterns.Logging.1.0.0.6\lib\portable-net45+win8\Patterns.Logging.dll True diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index b971a2d9a..8dbcaa2b9 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -2,6 +2,6 @@ - + \ No newline at end of file diff --git a/MediaBrowser.sln b/MediaBrowser.sln index daa5d417c..34c50de38 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -70,7 +70,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Server.Implementations EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Emby.Dlna", "Emby.Dlna\Emby.Dlna.xproj", "{F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Nat", "Mono.Nat\Mono.Nat.csproj", "{E9DB21D4-05E8-4883-B161-C55071166579}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Mono.Nat", "Mono.Nat\Mono.Nat.xproj", "{4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -656,36 +656,36 @@ Global {F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}.Release|x64.Build.0 = Release|Any CPU {F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}.Release|x86.ActiveCfg = Release|Any CPU {F40E364D-01D9-4BBF-B82C-5D6C55E0A1F5}.Release|x86.Build.0 = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Debug|Win32.ActiveCfg = Debug|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Debug|Win32.Build.0 = Debug|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Debug|x64.ActiveCfg = Debug|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Debug|x64.Build.0 = Debug|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Debug|x86.ActiveCfg = Debug|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Debug|x86.Build.0 = Debug|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release Mono|Any CPU.Build.0 = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release Mono|Mixed Platforms.ActiveCfg = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release Mono|Mixed Platforms.Build.0 = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release Mono|Win32.ActiveCfg = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release Mono|Win32.Build.0 = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release Mono|x64.ActiveCfg = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release Mono|x64.Build.0 = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release Mono|x86.ActiveCfg = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release Mono|x86.Build.0 = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release|Any CPU.Build.0 = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release|Win32.ActiveCfg = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release|Win32.Build.0 = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release|x64.ActiveCfg = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release|x64.Build.0 = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release|x86.ActiveCfg = Release|Any CPU - {E9DB21D4-05E8-4883-B161-C55071166579}.Release|x86.Build.0 = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Debug|Win32.ActiveCfg = Debug|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Debug|Win32.Build.0 = Debug|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Debug|x64.ActiveCfg = Debug|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Debug|x64.Build.0 = Debug|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Debug|x86.ActiveCfg = Debug|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Debug|x86.Build.0 = Debug|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release Mono|Mixed Platforms.ActiveCfg = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release Mono|Mixed Platforms.Build.0 = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release Mono|Win32.ActiveCfg = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release Mono|Win32.Build.0 = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release Mono|x64.ActiveCfg = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release Mono|x64.Build.0 = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release Mono|x86.ActiveCfg = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release Mono|x86.Build.0 = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release|Any CPU.Build.0 = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release|Win32.ActiveCfg = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release|Win32.Build.0 = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release|x64.ActiveCfg = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release|x64.Build.0 = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release|x86.ActiveCfg = Release|Any CPU + {4ACAB6A2-AC9A-4B50-BAEC-1FE4A1F3B8BC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Mono.Nat/Mono.Nat.csproj b/Mono.Nat/Mono.Nat.csproj deleted file mode 100644 index 09e3baffa..000000000 --- a/Mono.Nat/Mono.Nat.csproj +++ /dev/null @@ -1,89 +0,0 @@ - - - - - 14.0 - Debug - AnyCPU - {E9DB21D4-05E8-4883-B161-C55071166579} - Library - Properties - Mono.Nat - Mono.Nat - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - v5.0 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {9142eefa-7570-41e1-bfcc-468bb571af2f} - MediaBrowser.Common - - - {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} - MediaBrowser.Model - - - - - \ No newline at end of file diff --git a/Mono.Nat/Mono.Nat.xproj b/Mono.Nat/Mono.Nat.xproj new file mode 100644 index 000000000..3479a2a67 --- /dev/null +++ b/Mono.Nat/Mono.Nat.xproj @@ -0,0 +1,23 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 4acab6a2-ac9a-4b50-baec-1fe4a1f3b8bc + Mono.Nat + .\obj + .\bin\ + v4.5.2 + + + 2.0 + + + + + + + \ No newline at end of file diff --git a/Mono.Nat/Properties/AssemblyInfo.cs b/Mono.Nat/Properties/AssemblyInfo.cs index 2ad8adf6f..2a4e75c21 100644 --- a/Mono.Nat/Properties/AssemblyInfo.cs +++ b/Mono.Nat/Properties/AssemblyInfo.cs @@ -1,30 +1,16 @@ -using System.Resources; -using System.Reflection; +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// 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("Mono.Nat")] -[assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Mono.Nat")] -[assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en")] -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +// 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)] diff --git a/Mono.Nat/project.json b/Mono.Nat/project.json index 7d5dc4874..9f1c3247f 100644 --- a/Mono.Nat/project.json +++ b/Mono.Nat/project.json @@ -1,11 +1,41 @@ -{ - "supports": {}, +{ + "version": "1.0.0-*", + "dependencies": { - "Microsoft.NETCore.Portable.Compatibility": "1.0.1", - "NETStandard.Library": "1.6.0", - "System.Net.NetworkInformation": "4.1.0" + }, + "frameworks": { - "netstandard1.3": {} + "net46": { + "frameworkAssemblies": { + "System.Collections": "4.0.0.0", + "System.Net": "4.0.0.0", + "System.Runtime": "4.0.0.0", + "System.Threading": "4.0.0.0", + "System.Threading.Tasks": "4.0.0.0", + "System.Xml": "4.0.0.0" + }, + "dependencies": { + "MediaBrowser.Common": { + "target": "project" + }, + "MediaBrowser.Model": { + "target": "project" + } + } + }, + "netstandard1.6": { + "imports": "dnxcore50", + "dependencies": { + "NETStandard.Library": "1.6.0", + "MediaBrowser.Common": { + "target": "project" + }, + "MediaBrowser.Model": { + "target": "project" + }, + "System.Net.NetworkInformation": "4.1.0" + } + } } -} \ No newline at end of file +} -- cgit v1.2.3 From 1d62a88fd8147e9c1bf01cac2852b929b1737c17 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 3 Nov 2016 18:06:00 -0400 Subject: move classes to portable server project --- .../Emby.Server.Implementations.csproj | 11 + .../EntryPoints/AutomaticRestartEntryPoint.cs | 124 ++++++++ .../EntryPoints/LibraryChangedNotifier.cs | 343 +++++++++++++++++++++ .../EntryPoints/LoadRegistrations.cs | 73 +++++ .../EntryPoints/RecordingNotifier.cs | 77 +++++ .../EntryPoints/RefreshUsersMetadata.cs | 41 +++ .../EntryPoints/ServerEventNotifier.cs | 203 ++++++++++++ .../EntryPoints/UsageEntryPoint.cs | 133 ++++++++ .../EntryPoints/UsageReporter.cs | 138 +++++++++ .../EntryPoints/UserDataChangeNotifier.cs | 165 ++++++++++ .../MediaEncoder/EncodingManager.cs | 236 ++++++++++++++ Emby.Server.Implementations/News/NewsEntryPoint.cs | 260 ++++++++++++++++ Emby.Server.Implementations/project.json | 5 +- .../EntryPoints/AutomaticRestartEntryPoint.cs | 121 -------- .../EntryPoints/LibraryChangedNotifier.cs | 340 -------------------- .../EntryPoints/LoadRegistrations.cs | 71 ----- .../EntryPoints/RecordingNotifier.cs | 77 ----- .../EntryPoints/RefreshUsersMetadata.cs | 41 --- .../EntryPoints/ServerEventNotifier.cs | 203 ------------ .../EntryPoints/UsageEntryPoint.cs | 133 -------- .../EntryPoints/UsageReporter.cs | 138 --------- .../EntryPoints/UserDataChangeNotifier.cs | 162 ---------- .../MediaBrowser.Server.Implementations.csproj | 137 ++++---- .../MediaEncoder/EncodingManager.cs | 236 -------------- .../News/NewsEntryPoint.cs | 170 ---------- .../packages.config | 3 +- .../ApplicationHost.cs | 2 +- .../MediaBrowser.Server.Startup.Common.csproj | 4 + MediaBrowser.Server.Startup.Common/packages.config | 1 + .../MediaBrowser.XbmcMetadata.csproj | 5 - MediaBrowser.XbmcMetadata/packages.config | 1 - 31 files changed, 1872 insertions(+), 1782 deletions(-) create mode 100644 Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs create mode 100644 Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs create mode 100644 Emby.Server.Implementations/EntryPoints/LoadRegistrations.cs create mode 100644 Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs create mode 100644 Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs create mode 100644 Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs create mode 100644 Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs create mode 100644 Emby.Server.Implementations/EntryPoints/UsageReporter.cs create mode 100644 Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs create mode 100644 Emby.Server.Implementations/MediaEncoder/EncodingManager.cs create mode 100644 Emby.Server.Implementations/News/NewsEntryPoint.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/RecordingNotifier.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs delete mode 100644 MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs delete mode 100644 MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs (limited to 'Emby.Server.Implementations/project.json') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 4a32d00a2..e3d404644 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -51,6 +51,15 @@ + + + + + + + + + @@ -100,6 +109,8 @@ + + diff --git a/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs new file mode 100644 index 000000000..38708648f --- /dev/null +++ b/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs @@ -0,0 +1,124 @@ +using MediaBrowser.Controller; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Tasks; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Threading; + +namespace Emby.Server.Implementations.EntryPoints +{ + public class AutomaticRestartEntryPoint : IServerEntryPoint + { + private readonly IServerApplicationHost _appHost; + private readonly ILogger _logger; + private readonly ITaskManager _iTaskManager; + private readonly ISessionManager _sessionManager; + private readonly IServerConfigurationManager _config; + private readonly ILiveTvManager _liveTvManager; + private readonly ITimerFactory _timerFactory; + + private ITimer _timer; + + public AutomaticRestartEntryPoint(IServerApplicationHost appHost, ILogger logger, ITaskManager iTaskManager, ISessionManager sessionManager, IServerConfigurationManager config, ILiveTvManager liveTvManager, ITimerFactory timerFactory) + { + _appHost = appHost; + _logger = logger; + _iTaskManager = iTaskManager; + _sessionManager = sessionManager; + _config = config; + _liveTvManager = liveTvManager; + _timerFactory = timerFactory; + } + + public void Run() + { + if (_appHost.CanSelfRestart) + { + _appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged; + } + } + + void _appHost_HasPendingRestartChanged(object sender, EventArgs e) + { + DisposeTimer(); + + if (_appHost.HasPendingRestart) + { + _timer = _timerFactory.Create(TimerCallback, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); + } + } + + private async void TimerCallback(object state) + { + if (_config.Configuration.EnableAutomaticRestart) + { + var isIdle = await IsIdle().ConfigureAwait(false); + + if (isIdle) + { + DisposeTimer(); + + try + { + _appHost.Restart(); + } + catch (Exception ex) + { + _logger.ErrorException("Error restarting server", ex); + } + } + } + } + + private async Task IsIdle() + { + if (_iTaskManager.ScheduledTasks.Any(i => i.State != TaskState.Idle)) + { + return false; + } + + if (_liveTvManager.Services.Count == 1) + { + try + { + var timers = await _liveTvManager.GetTimers(new TimerQuery(), CancellationToken.None).ConfigureAwait(false); + if (timers.Items.Any(i => i.Status == RecordingStatus.InProgress)) + { + return false; + } + } + catch (Exception ex) + { + _logger.ErrorException("Error getting timers", ex); + } + } + + var now = DateTime.UtcNow; + + return !_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 30); + } + + public void Dispose() + { + _appHost.HasPendingRestartChanged -= _appHost_HasPendingRestartChanged; + + DisposeTimer(); + } + + private void DisposeTimer() + { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } + } + } +} diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs new file mode 100644 index 000000000..91142f928 --- /dev/null +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -0,0 +1,343 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Threading; + +namespace Emby.Server.Implementations.EntryPoints +{ + public class LibraryChangedNotifier : IServerEntryPoint + { + /// + /// The _library manager + /// + private readonly ILibraryManager _libraryManager; + + private readonly ISessionManager _sessionManager; + private readonly IUserManager _userManager; + private readonly ILogger _logger; + private readonly ITimerFactory _timerFactory; + + /// + /// The _library changed sync lock + /// + private readonly object _libraryChangedSyncLock = new object(); + + private readonly List _foldersAddedTo = new List(); + private readonly List _foldersRemovedFrom = new List(); + + private readonly List _itemsAdded = new List(); + private readonly List _itemsRemoved = new List(); + private readonly List _itemsUpdated = new List(); + + /// + /// Gets or sets the library update timer. + /// + /// The library update timer. + private ITimer LibraryUpdateTimer { get; set; } + + /// + /// The library update duration + /// + private const int LibraryUpdateDuration = 5000; + + public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger, ITimerFactory timerFactory) + { + _libraryManager = libraryManager; + _sessionManager = sessionManager; + _userManager = userManager; + _logger = logger; + _timerFactory = timerFactory; + } + + public void Run() + { + _libraryManager.ItemAdded += libraryManager_ItemAdded; + _libraryManager.ItemUpdated += libraryManager_ItemUpdated; + _libraryManager.ItemRemoved += libraryManager_ItemRemoved; + + } + + /// + /// Handles the ItemAdded event of the libraryManager control. + /// + /// The source of the event. + /// The instance containing the event data. + void libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) + { + if (!FilterItem(e.Item)) + { + return; + } + + lock (_libraryChangedSyncLock) + { + if (LibraryUpdateTimer == null) + { + LibraryUpdateTimer = _timerFactory.Create(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, + Timeout.Infinite); + } + else + { + LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); + } + + if (e.Item.Parent != null) + { + _foldersAddedTo.Add(e.Item.Parent); + } + + _itemsAdded.Add(e.Item); + } + } + + /// + /// Handles the ItemUpdated event of the libraryManager control. + /// + /// The source of the event. + /// The instance containing the event data. + void libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e) + { + if (!FilterItem(e.Item)) + { + return; + } + + lock (_libraryChangedSyncLock) + { + if (LibraryUpdateTimer == null) + { + LibraryUpdateTimer = _timerFactory.Create(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, + Timeout.Infinite); + } + else + { + LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); + } + + _itemsUpdated.Add(e.Item); + } + } + + /// + /// Handles the ItemRemoved event of the libraryManager control. + /// + /// The source of the event. + /// The instance containing the event data. + void libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e) + { + if (!FilterItem(e.Item)) + { + return; + } + + lock (_libraryChangedSyncLock) + { + if (LibraryUpdateTimer == null) + { + LibraryUpdateTimer = _timerFactory.Create(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, + Timeout.Infinite); + } + else + { + LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); + } + + if (e.Item.Parent != null) + { + _foldersRemovedFrom.Add(e.Item.Parent); + } + + _itemsRemoved.Add(e.Item); + } + } + + /// + /// Libraries the update timer callback. + /// + /// The state. + private void LibraryUpdateTimerCallback(object state) + { + lock (_libraryChangedSyncLock) + { + // Remove dupes in case some were saved multiple times + var foldersAddedTo = _foldersAddedTo.DistinctBy(i => i.Id).ToList(); + + var foldersRemovedFrom = _foldersRemovedFrom.DistinctBy(i => i.Id).ToList(); + + var itemsUpdated = _itemsUpdated + .Where(i => !_itemsAdded.Contains(i)) + .DistinctBy(i => i.Id) + .ToList(); + + SendChangeNotifications(_itemsAdded.ToList(), itemsUpdated, _itemsRemoved.ToList(), foldersAddedTo, foldersRemovedFrom, CancellationToken.None); + + if (LibraryUpdateTimer != null) + { + LibraryUpdateTimer.Dispose(); + LibraryUpdateTimer = null; + } + + _itemsAdded.Clear(); + _itemsRemoved.Clear(); + _itemsUpdated.Clear(); + _foldersAddedTo.Clear(); + _foldersRemovedFrom.Clear(); + } + } + + /// + /// Sends the change notifications. + /// + /// The items added. + /// The items updated. + /// The items removed. + /// The folders added to. + /// The folders removed from. + /// The cancellation token. + private async void SendChangeNotifications(List itemsAdded, List itemsUpdated, List itemsRemoved, List foldersAddedTo, List foldersRemovedFrom, CancellationToken cancellationToken) + { + foreach (var user in _userManager.Users.ToList()) + { + var id = user.Id; + var userSessions = _sessionManager.Sessions + .Where(u => u.UserId.HasValue && u.UserId.Value == id && u.SessionController != null && u.IsActive) + .ToList(); + + if (userSessions.Count > 0) + { + LibraryUpdateInfo info; + + try + { + info = GetLibraryUpdateInfo(itemsAdded, itemsUpdated, itemsRemoved, foldersAddedTo, + foldersRemovedFrom, id); + } + catch (Exception ex) + { + _logger.ErrorException("Error in GetLibraryUpdateInfo", ex); + return; + } + + foreach (var userSession in userSessions) + { + try + { + await userSession.SessionController.SendLibraryUpdateInfo(info, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending LibraryChanged message", ex); + } + } + } + + } + } + + /// + /// Gets the library update info. + /// + /// The items added. + /// The items updated. + /// The items removed. + /// The folders added to. + /// The folders removed from. + /// The user id. + /// LibraryUpdateInfo. + private LibraryUpdateInfo GetLibraryUpdateInfo(IEnumerable itemsAdded, IEnumerable itemsUpdated, IEnumerable itemsRemoved, IEnumerable foldersAddedTo, IEnumerable foldersRemovedFrom, Guid userId) + { + var user = _userManager.GetUserById(userId); + + return new LibraryUpdateInfo + { + ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(), + + ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(), + + ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, true)).Select(i => i.Id.ToString("N")).Distinct().ToList(), + + FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(), + + FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList() + }; + } + + private bool FilterItem(BaseItem item) + { + if (!item.IsFolder && item.LocationType == LocationType.Virtual) + { + return false; + } + + if (item is IItemByName && !(item is MusicArtist)) + { + return false; + } + + return item.SourceType == SourceType.Library; + } + + /// + /// Translates the physical item to user library. + /// + /// + /// The item. + /// The user. + /// if set to true [include if not found]. + /// IEnumerable{``0}. + private IEnumerable TranslatePhysicalItemToUserLibrary(T item, User user, bool includeIfNotFound = false) + where T : BaseItem + { + // If the physical root changed, return the user root + if (item is AggregateFolder) + { + return new[] { user.RootFolder as T }; + } + + // Return it only if it's in the user's library + if (includeIfNotFound || item.IsVisibleStandalone(user)) + { + return new[] { item }; + } + + return new T[] { }; + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + if (LibraryUpdateTimer != null) + { + LibraryUpdateTimer.Dispose(); + LibraryUpdateTimer = null; + } + + _libraryManager.ItemAdded -= libraryManager_ItemAdded; + _libraryManager.ItemUpdated -= libraryManager_ItemUpdated; + _libraryManager.ItemRemoved -= libraryManager_ItemRemoved; + } + } + } +} diff --git a/Emby.Server.Implementations/EntryPoints/LoadRegistrations.cs b/Emby.Server.Implementations/EntryPoints/LoadRegistrations.cs new file mode 100644 index 000000000..0203b5192 --- /dev/null +++ b/Emby.Server.Implementations/EntryPoints/LoadRegistrations.cs @@ -0,0 +1,73 @@ +using MediaBrowser.Common.Security; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Model.Logging; +using System; +using System.Threading.Tasks; +using MediaBrowser.Model.Threading; + +namespace Emby.Server.Implementations.EntryPoints +{ + /// + /// Class LoadRegistrations + /// + public class LoadRegistrations : IServerEntryPoint + { + /// + /// The _security manager + /// + private readonly ISecurityManager _securityManager; + + /// + /// The _logger + /// + private readonly ILogger _logger; + + private ITimer _timer; + private readonly ITimerFactory _timerFactory; + + /// + /// Initializes a new instance of the class. + /// + /// The security manager. + /// The log manager. + public LoadRegistrations(ISecurityManager securityManager, ILogManager logManager, ITimerFactory timerFactory) + { + _securityManager = securityManager; + _timerFactory = timerFactory; + + _logger = logManager.GetLogger("Registration Loader"); + } + + /// + /// Runs this instance. + /// + public void Run() + { + _timer = _timerFactory.Create(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(12)); + } + + private async Task LoadAllRegistrations() + { + try + { + await _securityManager.LoadAllRegistrationInfo().ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error loading registration info", ex); + } + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } + } + } +} diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs new file mode 100644 index 000000000..b674fc39b --- /dev/null +++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs @@ -0,0 +1,77 @@ +using System; +using System.Linq; +using System.Threading; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Logging; + +namespace Emby.Server.Implementations.EntryPoints +{ + public class RecordingNotifier : IServerEntryPoint + { + private readonly ILiveTvManager _liveTvManager; + private readonly ISessionManager _sessionManager; + private readonly IUserManager _userManager; + private readonly ILogger _logger; + + public RecordingNotifier(ISessionManager sessionManager, IUserManager userManager, ILogger logger, ILiveTvManager liveTvManager) + { + _sessionManager = sessionManager; + _userManager = userManager; + _logger = logger; + _liveTvManager = liveTvManager; + } + + public void Run() + { + _liveTvManager.TimerCancelled += _liveTvManager_TimerCancelled; + _liveTvManager.SeriesTimerCancelled += _liveTvManager_SeriesTimerCancelled; + _liveTvManager.TimerCreated += _liveTvManager_TimerCreated; + _liveTvManager.SeriesTimerCreated += _liveTvManager_SeriesTimerCreated; + } + + private void _liveTvManager_SeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + { + SendMessage("SeriesTimerCreated", e.Argument); + } + + private void _liveTvManager_TimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + { + SendMessage("TimerCreated", e.Argument); + } + + private void _liveTvManager_SeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + { + SendMessage("SeriesTimerCancelled", e.Argument); + } + + private void _liveTvManager_TimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + { + SendMessage("TimerCancelled", e.Argument); + } + + private async void SendMessage(string name, TimerEventInfo info) + { + var users = _userManager.Users.Where(i => i.Policy.EnableLiveTvAccess).Select(i => i.Id.ToString("N")).ToList(); + + try + { + await _sessionManager.SendMessageToUserSessions(users, name, info, CancellationToken.None); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending message", ex); + } + } + + public void Dispose() + { + _liveTvManager.TimerCancelled -= _liveTvManager_TimerCancelled; + _liveTvManager.SeriesTimerCancelled -= _liveTvManager_SeriesTimerCancelled; + _liveTvManager.TimerCreated -= _liveTvManager_TimerCreated; + _liveTvManager.SeriesTimerCreated -= _liveTvManager_SeriesTimerCreated; + } + } +} diff --git a/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs b/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs new file mode 100644 index 000000000..77de849a1 --- /dev/null +++ b/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs @@ -0,0 +1,41 @@ +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Plugins; +using System.Threading; + +namespace Emby.Server.Implementations.EntryPoints +{ + /// + /// Class RefreshUsersMetadata + /// + public class RefreshUsersMetadata : IServerEntryPoint + { + /// + /// The _user manager + /// + private readonly IUserManager _userManager; + + /// + /// Initializes a new instance of the class. + /// + /// The user manager. + public RefreshUsersMetadata(IUserManager userManager) + { + _userManager = userManager; + } + + /// + /// Runs this instance. + /// + public async void Run() + { + await _userManager.RefreshUsersMetadata(CancellationToken.None).ConfigureAwait(false); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + } + } +} diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs new file mode 100644 index 000000000..4d640bc95 --- /dev/null +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -0,0 +1,203 @@ +using MediaBrowser.Common.Plugins; +using MediaBrowser.Common.Updates; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; +using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Events; +using MediaBrowser.Model.Sync; +using System; +using System.Collections.Generic; +using System.Threading; +using MediaBrowser.Model.Tasks; + +namespace Emby.Server.Implementations.EntryPoints +{ + /// + /// Class WebSocketEvents + /// + public class ServerEventNotifier : IServerEntryPoint + { + /// + /// The _server manager + /// + private readonly IServerManager _serverManager; + + /// + /// The _user manager + /// + private readonly IUserManager _userManager; + + /// + /// The _installation manager + /// + private readonly IInstallationManager _installationManager; + + /// + /// The _kernel + /// + private readonly IServerApplicationHost _appHost; + + /// + /// The _task manager + /// + private readonly ITaskManager _taskManager; + + private readonly ISessionManager _sessionManager; + private readonly ISyncManager _syncManager; + + public ServerEventNotifier(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, ISessionManager sessionManager, ISyncManager syncManager) + { + _serverManager = serverManager; + _userManager = userManager; + _installationManager = installationManager; + _appHost = appHost; + _taskManager = taskManager; + _sessionManager = sessionManager; + _syncManager = syncManager; + } + + public void Run() + { + _userManager.UserDeleted += userManager_UserDeleted; + _userManager.UserUpdated += userManager_UserUpdated; + _userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated; + + _appHost.HasPendingRestartChanged += kernel_HasPendingRestartChanged; + + _installationManager.PluginUninstalled += InstallationManager_PluginUninstalled; + _installationManager.PackageInstalling += _installationManager_PackageInstalling; + _installationManager.PackageInstallationCancelled += _installationManager_PackageInstallationCancelled; + _installationManager.PackageInstallationCompleted += _installationManager_PackageInstallationCompleted; + _installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed; + + _taskManager.TaskCompleted += _taskManager_TaskCompleted; + _syncManager.SyncJobCreated += _syncManager_SyncJobCreated; + _syncManager.SyncJobCancelled += _syncManager_SyncJobCancelled; + } + + void _syncManager_SyncJobCancelled(object sender, GenericEventArgs e) + { + _sessionManager.SendMessageToUserDeviceSessions(e.Argument.TargetId, "SyncJobCancelled", e.Argument, CancellationToken.None); + } + + void _syncManager_SyncJobCreated(object sender, GenericEventArgs e) + { + _sessionManager.SendMessageToUserDeviceSessions(e.Argument.Job.TargetId, "SyncJobCreated", e.Argument, CancellationToken.None); + } + + void _installationManager_PackageInstalling(object sender, InstallationEventArgs e) + { + _serverManager.SendWebSocketMessage("PackageInstalling", e.InstallationInfo); + } + + void _installationManager_PackageInstallationCancelled(object sender, InstallationEventArgs e) + { + _serverManager.SendWebSocketMessage("PackageInstallationCancelled", e.InstallationInfo); + } + + void _installationManager_PackageInstallationCompleted(object sender, InstallationEventArgs e) + { + _serverManager.SendWebSocketMessage("PackageInstallationCompleted", e.InstallationInfo); + } + + void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) + { + _serverManager.SendWebSocketMessage("PackageInstallationFailed", e.InstallationInfo); + } + + void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) + { + _serverManager.SendWebSocketMessage("ScheduledTaskEnded", e.Result); + } + + /// + /// Installations the manager_ plugin uninstalled. + /// + /// The sender. + /// The e. + void InstallationManager_PluginUninstalled(object sender, GenericEventArgs e) + { + _serverManager.SendWebSocketMessage("PluginUninstalled", e.Argument.GetPluginInfo()); + } + + /// + /// Handles the HasPendingRestartChanged event of the kernel control. + /// + /// The source of the event. + /// The instance containing the event data. + void kernel_HasPendingRestartChanged(object sender, EventArgs e) + { + _sessionManager.SendRestartRequiredNotification(CancellationToken.None); + } + + /// + /// Users the manager_ user updated. + /// + /// The sender. + /// The e. + void userManager_UserUpdated(object sender, GenericEventArgs e) + { + var dto = _userManager.GetUserDto(e.Argument); + + SendMessageToUserSession(e.Argument, "UserUpdated", dto); + } + + /// + /// Users the manager_ user deleted. + /// + /// The sender. + /// The e. + void userManager_UserDeleted(object sender, GenericEventArgs e) + { + SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N")); + } + + void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs e) + { + var dto = _userManager.GetUserDto(e.Argument); + + SendMessageToUserSession(e.Argument, "UserConfigurationUpdated", dto); + } + + private async void SendMessageToUserSession(User user, string name, T data) + { + await _sessionManager.SendMessageToUserSessions(new List { user.Id.ToString("N") }, name, data, CancellationToken.None); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + _userManager.UserDeleted -= userManager_UserDeleted; + _userManager.UserUpdated -= userManager_UserUpdated; + _userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated; + + _installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled; + _installationManager.PackageInstalling -= _installationManager_PackageInstalling; + _installationManager.PackageInstallationCancelled -= _installationManager_PackageInstallationCancelled; + _installationManager.PackageInstallationCompleted -= _installationManager_PackageInstallationCompleted; + _installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed; + + _appHost.HasPendingRestartChanged -= kernel_HasPendingRestartChanged; + _syncManager.SyncJobCreated -= _syncManager_SyncJobCreated; + _syncManager.SyncJobCancelled -= _syncManager_SyncJobCancelled; + } + } + } +} diff --git a/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs new file mode 100644 index 000000000..1b897ca29 --- /dev/null +++ b/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs @@ -0,0 +1,133 @@ +using MediaBrowser.Common; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Configuration; + +namespace Emby.Server.Implementations.EntryPoints +{ + /// + /// Class UsageEntryPoint + /// + public class UsageEntryPoint : IServerEntryPoint + { + private readonly IApplicationHost _applicationHost; + private readonly IHttpClient _httpClient; + private readonly ILogger _logger; + private readonly ISessionManager _sessionManager; + private readonly IUserManager _userManager; + private readonly IServerConfigurationManager _config; + + private readonly ConcurrentDictionary _apps = new ConcurrentDictionary(); + + public UsageEntryPoint(ILogger logger, IApplicationHost applicationHost, IHttpClient httpClient, ISessionManager sessionManager, IUserManager userManager, IServerConfigurationManager config) + { + _logger = logger; + _applicationHost = applicationHost; + _httpClient = httpClient; + _sessionManager = sessionManager; + _userManager = userManager; + _config = config; + + _sessionManager.SessionStarted += _sessionManager_SessionStarted; + } + + void _sessionManager_SessionStarted(object sender, SessionEventArgs e) + { + var session = e.SessionInfo; + + if (!string.IsNullOrEmpty(session.Client) && + !string.IsNullOrEmpty(session.DeviceName) && + !string.IsNullOrEmpty(session.DeviceId) && + !string.IsNullOrEmpty(session.ApplicationVersion)) + { + var keys = new List + { + session.Client, + session.DeviceName, + session.DeviceId, + session.ApplicationVersion + }; + + var key = string.Join("_", keys.ToArray()).GetMD5(); + + _apps.GetOrAdd(key, guid => GetNewClientInfo(session)); + } + } + + private async void ReportNewSession(ClientInfo client) + { + if (!_config.Configuration.EnableAnonymousUsageReporting) + { + return; + } + + try + { + await new UsageReporter(_applicationHost, _httpClient, _userManager, _logger) + .ReportAppUsage(client, CancellationToken.None) + .ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending anonymous usage statistics.", ex); + } + } + + private ClientInfo GetNewClientInfo(SessionInfo session) + { + var info = new ClientInfo + { + AppName = session.Client, + AppVersion = session.ApplicationVersion, + DeviceName = session.DeviceName, + DeviceId = session.DeviceId + }; + + ReportNewSession(info); + + return info; + } + + public async void Run() + { + await Task.Delay(5000).ConfigureAwait(false); + OnTimerFired(); + } + + /// + /// Called when [timer fired]. + /// + private async void OnTimerFired() + { + if (!_config.Configuration.EnableAnonymousUsageReporting) + { + return; + } + + try + { + await new UsageReporter(_applicationHost, _httpClient, _userManager, _logger) + .ReportServerUsage(CancellationToken.None) + .ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending anonymous usage statistics.", ex); + } + } + + public void Dispose() + { + _sessionManager.SessionStarted -= _sessionManager_SessionStarted; + } + } +} diff --git a/Emby.Server.Implementations/EntryPoints/UsageReporter.cs b/Emby.Server.Implementations/EntryPoints/UsageReporter.cs new file mode 100644 index 000000000..be848acb7 --- /dev/null +++ b/Emby.Server.Implementations/EntryPoints/UsageReporter.cs @@ -0,0 +1,138 @@ +using MediaBrowser.Common; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Connect; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; + +namespace Emby.Server.Implementations.EntryPoints +{ + public class UsageReporter + { + private readonly IApplicationHost _applicationHost; + private readonly IHttpClient _httpClient; + private readonly IUserManager _userManager; + private readonly ILogger _logger; + private const string MbAdminUrl = "https://www.mb3admin.com/admin/"; + + public UsageReporter(IApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager, ILogger logger) + { + _applicationHost = applicationHost; + _httpClient = httpClient; + _userManager = userManager; + _logger = logger; + } + + public async Task ReportServerUsage(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var data = new Dictionary + { + { "feature", _applicationHost.Name }, + { "mac", _applicationHost.SystemId }, + { "serverid", _applicationHost.SystemId }, + { "deviceid", _applicationHost.SystemId }, + { "ver", _applicationHost.ApplicationVersion.ToString() }, + { "platform", _applicationHost.OperatingSystemDisplayName }, + { "isservice", _applicationHost.IsRunningAsService.ToString().ToLower()} + }; + + var users = _userManager.Users.ToList(); + + data["localusers"] = users.Count(i => !i.ConnectLinkType.HasValue).ToString(CultureInfo.InvariantCulture); + data["guests"] = users.Count(i => i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.Guest).ToString(CultureInfo.InvariantCulture); + data["linkedusers"] = users.Count(i => i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.LinkedUser).ToString(CultureInfo.InvariantCulture); + + data["plugins"] = string.Join(",", _applicationHost.Plugins.Select(i => i.Id).ToArray()); + + var logErrors = false; +#if DEBUG + logErrors = true; +#endif + var options = new HttpRequestOptions + { + Url = MbAdminUrl + "service/registration/ping", + CancellationToken = cancellationToken, + + // Seeing block length errors + EnableHttpCompression = false, + + LogRequest = false, + LogErrors = logErrors, + BufferContent = false + }; + + options.SetPostData(data); + + using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)) + { + + } + } + + public async Task ReportAppUsage(ClientInfo app, CancellationToken cancellationToken) + { + if (string.IsNullOrWhiteSpace(app.DeviceId)) + { + throw new ArgumentException("Client info must have a device Id"); + } + + _logger.Info("App Activity: app: {0}, version: {1}, deviceId: {2}, deviceName: {3}", + app.AppName ?? "Unknown App", + app.AppVersion ?? "Unknown", + app.DeviceId, + app.DeviceName ?? "Unknown"); + + cancellationToken.ThrowIfCancellationRequested(); + + var data = new Dictionary + { + { "feature", app.AppName ?? "Unknown App" }, + { "serverid", _applicationHost.SystemId }, + { "deviceid", app.DeviceId }, + { "mac", app.DeviceId }, + { "ver", app.AppVersion ?? "Unknown" }, + { "platform", app.DeviceName }, + }; + + var logErrors = false; + +#if DEBUG + logErrors = true; +#endif + var options = new HttpRequestOptions + { + Url = MbAdminUrl + "service/registration/ping", + CancellationToken = cancellationToken, + + // Seeing block length errors + EnableHttpCompression = false, + + LogRequest = false, + LogErrors = logErrors, + BufferContent = false + }; + + options.SetPostData(data); + + using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)) + { + + } + } + } + + public class ClientInfo + { + public string AppName { get; set; } + public string AppVersion { get; set; } + public string DeviceName { get; set; } + public string DeviceId { get; set; } + } +} diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs new file mode 100644 index 000000000..b93410180 --- /dev/null +++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -0,0 +1,165 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Session; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Threading; + +namespace Emby.Server.Implementations.EntryPoints +{ + class UserDataChangeNotifier : IServerEntryPoint + { + private readonly ISessionManager _sessionManager; + private readonly ILogger _logger; + private readonly IUserDataManager _userDataManager; + private readonly IUserManager _userManager; + + private readonly object _syncLock = new object(); + private ITimer UpdateTimer { get; set; } + private readonly ITimerFactory _timerFactory; + private const int UpdateDuration = 500; + + private readonly Dictionary> _changedItems = new Dictionary>(); + + public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager, ITimerFactory timerFactory) + { + _userDataManager = userDataManager; + _sessionManager = sessionManager; + _logger = logger; + _userManager = userManager; + _timerFactory = timerFactory; + } + + public void Run() + { + _userDataManager.UserDataSaved += _userDataManager_UserDataSaved; + } + + void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e) + { + if (e.SaveReason == UserDataSaveReason.PlaybackProgress) + { + return; + } + + lock (_syncLock) + { + if (UpdateTimer == null) + { + UpdateTimer = _timerFactory.Create(UpdateTimerCallback, null, UpdateDuration, + Timeout.Infinite); + } + else + { + UpdateTimer.Change(UpdateDuration, Timeout.Infinite); + } + + List keys; + + if (!_changedItems.TryGetValue(e.UserId, out keys)) + { + keys = new List(); + _changedItems[e.UserId] = keys; + } + + keys.Add(e.Item); + + var baseItem = e.Item as BaseItem; + + // Go up one level for indicators + if (baseItem != null) + { + var parent = baseItem.GetParent(); + + if (parent != null) + { + keys.Add(parent); + } + } + } + } + + private void UpdateTimerCallback(object state) + { + lock (_syncLock) + { + // Remove dupes in case some were saved multiple times + var changes = _changedItems.ToList(); + _changedItems.Clear(); + + var task = SendNotifications(changes, CancellationToken.None); + + if (UpdateTimer != null) + { + UpdateTimer.Dispose(); + UpdateTimer = null; + } + } + } + + private async Task SendNotifications(IEnumerable>> changes, CancellationToken cancellationToken) + { + foreach (var pair in changes) + { + var userId = pair.Key; + var userSessions = _sessionManager.Sessions + .Where(u => u.ContainsUser(userId) && u.SessionController != null && u.IsActive) + .ToList(); + + if (userSessions.Count > 0) + { + var user = _userManager.GetUserById(userId); + + var dtoList = pair.Value + .DistinctBy(i => i.Id) + .Select(i => + { + var dto = _userDataManager.GetUserDataDto(i, user).Result; + dto.ItemId = i.Id.ToString("N"); + return dto; + }) + .ToList(); + + var info = new UserDataChangeInfo + { + UserId = userId.ToString("N"), + + UserDataList = dtoList + }; + + foreach (var userSession in userSessions) + { + try + { + await userSession.SessionController.SendUserDataChangeInfo(info, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending UserDataChanged message", ex); + } + } + } + + } + } + + public void Dispose() + { + if (UpdateTimer != null) + { + UpdateTimer.Dispose(); + UpdateTimer = null; + } + + _userDataManager.UserDataSaved -= _userDataManager_UserDataSaved; + } + } +} diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs new file mode 100644 index 000000000..204e04061 --- /dev/null +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -0,0 +1,236 @@ +using MediaBrowser.Controller.Chapters; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.MediaInfo; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; +using MediaBrowser.Controller.Library; + +namespace Emby.Server.Implementations.MediaEncoder +{ + public class EncodingManager : IEncodingManager + { + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private readonly IFileSystem _fileSystem; + private readonly ILogger _logger; + private readonly IMediaEncoder _encoder; + private readonly IChapterManager _chapterManager; + private readonly ILibraryManager _libraryManager; + + public EncodingManager(IFileSystem fileSystem, + ILogger logger, + IMediaEncoder encoder, + IChapterManager chapterManager, ILibraryManager libraryManager) + { + _fileSystem = fileSystem; + _logger = logger; + _encoder = encoder; + _chapterManager = chapterManager; + _libraryManager = libraryManager; + } + + /// + /// Gets the chapter images data path. + /// + /// The chapter images data path. + private string GetChapterImagesPath(IHasImages item) + { + return Path.Combine(item.GetInternalMetadataPath(), "chapters"); + } + + /// + /// Determines whether [is eligible for chapter image extraction] [the specified video]. + /// + /// The video. + /// true if [is eligible for chapter image extraction] [the specified video]; otherwise, false. + private bool IsEligibleForChapterImageExtraction(Video video) + { + if (video.IsPlaceHolder) + { + return false; + } + + var libraryOptions = _libraryManager.GetLibraryOptions(video); + if (libraryOptions != null) + { + if (!libraryOptions.EnableChapterImageExtraction) + { + return false; + } + } + else + { + return false; + } + + // Can't extract images if there are no video streams + return video.DefaultVideoStreamIndex.HasValue; + } + + /// + /// The first chapter ticks + /// + private static readonly long FirstChapterTicks = TimeSpan.FromSeconds(15).Ticks; + + public async Task RefreshChapterImages(ChapterImageRefreshOptions options, CancellationToken cancellationToken) + { + var extractImages = options.ExtractImages; + var video = options.Video; + var chapters = options.Chapters; + var saveChapters = options.SaveChapters; + + if (!IsEligibleForChapterImageExtraction(video)) + { + extractImages = false; + } + + var success = true; + var changesMade = false; + + var runtimeTicks = video.RunTimeTicks ?? 0; + + var currentImages = GetSavedChapterImages(video); + + foreach (var chapter in chapters) + { + if (chapter.StartPositionTicks >= runtimeTicks) + { + _logger.Info("Stopping chapter extraction for {0} because a chapter was found with a position greater than the runtime.", video.Name); + break; + } + + var path = GetChapterImagePath(video, chapter.StartPositionTicks); + + if (!currentImages.Contains(path, StringComparer.OrdinalIgnoreCase)) + { + if (extractImages) + { + if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso) + { + continue; + } + if (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd) + { + if (video.PlayableStreamFileNames.Count != 1) + { + continue; + } + } + + try + { + // Add some time for the first chapter to make sure we don't end up with a black image + var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); + + var protocol = MediaProtocol.File; + + var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames); + + _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + + var container = video.Container; + + var tempFile = await _encoder.ExtractVideoImage(inputPath, container, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false); + _fileSystem.CopyFile(tempFile, path, true); + + try + { + _fileSystem.DeleteFile(tempFile); + } + catch + { + + } + + chapter.ImagePath = path; + chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path); + changesMade = true; + } + catch (Exception ex) + { + _logger.ErrorException("Error extracting chapter images for {0}", ex, string.Join(",", video.Path)); + success = false; + break; + } + } + else if (!string.IsNullOrEmpty(chapter.ImagePath)) + { + chapter.ImagePath = null; + changesMade = true; + } + } + else if (!string.Equals(path, chapter.ImagePath, StringComparison.OrdinalIgnoreCase)) + { + chapter.ImagePath = path; + chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path); + changesMade = true; + } + } + + if (saveChapters && changesMade) + { + await _chapterManager.SaveChapters(video.Id.ToString(), chapters, cancellationToken).ConfigureAwait(false); + } + + DeleteDeadImages(currentImages, chapters); + + return success; + } + + private string GetChapterImagePath(Video video, long chapterPositionTicks) + { + var filename = video.DateModified.Ticks.ToString(_usCulture) + "_" + chapterPositionTicks.ToString(_usCulture) + ".jpg"; + + return Path.Combine(GetChapterImagesPath(video), filename); + } + + private List GetSavedChapterImages(Video video) + { + var path = GetChapterImagesPath(video); + + try + { + return _fileSystem.GetFilePaths(path) + .ToList(); + } + catch (IOException) + { + return new List(); + } + } + + private void DeleteDeadImages(IEnumerable images, IEnumerable chapters) + { + var deadImages = images + .Except(chapters.Select(i => i.ImagePath).Where(i => !string.IsNullOrEmpty(i)), StringComparer.OrdinalIgnoreCase) + .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i), StringComparer.OrdinalIgnoreCase)) + .ToList(); + + foreach (var image in deadImages) + { + _logger.Debug("Deleting dead chapter image {0}", image); + + try + { + _fileSystem.DeleteFile(image); + } + catch (IOException ex) + { + _logger.ErrorException("Error deleting {0}.", ex, image); + } + } + } + } +} diff --git a/Emby.Server.Implementations/News/NewsEntryPoint.cs b/Emby.Server.Implementations/News/NewsEntryPoint.cs new file mode 100644 index 000000000..1497d066f --- /dev/null +++ b/Emby.Server.Implementations/News/NewsEntryPoint.cs @@ -0,0 +1,260 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Notifications; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.News; +using MediaBrowser.Model.Notifications; +using MediaBrowser.Model.Serialization; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Threading; + +namespace Emby.Server.Implementations.News +{ + public class NewsEntryPoint : IServerEntryPoint + { + private ITimer _timer; + private readonly IHttpClient _httpClient; + private readonly IApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; + private readonly ILogger _logger; + private readonly IJsonSerializer _json; + + private readonly INotificationManager _notifications; + private readonly IUserManager _userManager; + + private readonly TimeSpan _frequency = TimeSpan.FromHours(24); + private readonly ITimerFactory _timerFactory; + + public NewsEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IJsonSerializer json, INotificationManager notifications, IUserManager userManager, ITimerFactory timerFactory) + { + _httpClient = httpClient; + _appPaths = appPaths; + _fileSystem = fileSystem; + _logger = logger; + _json = json; + _notifications = notifications; + _userManager = userManager; + _timerFactory = timerFactory; + } + + public void Run() + { + _timer = _timerFactory.Create(OnTimerFired, null, TimeSpan.FromMilliseconds(500), _frequency); + } + + /// + /// Called when [timer fired]. + /// + /// The state. + private async void OnTimerFired(object state) + { + var path = Path.Combine(_appPaths.CachePath, "news.json"); + + try + { + await DownloadNews(path).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error downloading news", ex); + } + } + + private async Task DownloadNews(string path) + { + DateTime? lastUpdate = null; + + if (_fileSystem.FileExists(path)) + { + lastUpdate = _fileSystem.GetLastWriteTimeUtc(path); + } + + var requestOptions = new HttpRequestOptions + { + Url = "http://emby.media/community/index.php?/blog/rss/1-media-browser-developers-blog", + Progress = new Progress(), + UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.42 Safari/537.36", + BufferContent = false + }; + + using (var stream = await _httpClient.Get(requestOptions).ConfigureAwait(false)) + { + using (var reader = XmlReader.Create(stream)) + { + var news = ParseRssItems(reader).ToList(); + + _json.SerializeToFile(news, path); + + await CreateNotifications(news, lastUpdate, CancellationToken.None).ConfigureAwait(false); + } + } + } + + private Task CreateNotifications(List items, DateTime? lastUpdate, CancellationToken cancellationToken) + { + if (lastUpdate.HasValue) + { + items = items.Where(i => i.Date.ToUniversalTime() >= lastUpdate.Value) + .ToList(); + } + + var tasks = items.Select(i => _notifications.SendNotification(new NotificationRequest + { + Date = i.Date, + Name = i.Title, + Description = i.Description, + Url = i.Link, + UserIds = _userManager.Users.Select(u => u.Id.ToString("N")).ToList() + + }, cancellationToken)); + + return Task.WhenAll(tasks); + } + + private IEnumerable ParseRssItems(XmlReader reader) + { + reader.MoveToContent(); + reader.Read(); + + while (!reader.EOF) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "channel": + { + using (var subReader = reader.ReadSubtree()) + { + return ParseFromChannelNode(subReader); + } + } + default: + { + reader.Skip(); + break; + } + } + } + else + { + reader.Read(); + } + } + + return new List(); + } + + private IEnumerable ParseFromChannelNode(XmlReader reader) + { + var list = new List(); + + reader.MoveToContent(); + reader.Read(); + + while (!reader.EOF) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "item": + { + using (var subReader = reader.ReadSubtree()) + { + list.Add(ParseItem(subReader)); + } + break; + } + default: + { + reader.Skip(); + break; + } + } + } + else + { + reader.Read(); + } + } + + return list; + } + + private NewsItem ParseItem(XmlReader reader) + { + var item = new NewsItem(); + + reader.MoveToContent(); + reader.Read(); + + while (!reader.EOF) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "title": + { + item.Title = reader.ReadElementContentAsString(); + break; + } + case "link": + { + item.Link = reader.ReadElementContentAsString(); + break; + } + case "description": + { + item.DescriptionHtml = reader.ReadElementContentAsString(); + item.Description = item.DescriptionHtml.StripHtml(); + break; + } + case "pubDate": + { + var date = reader.ReadElementContentAsString(); + DateTime parsedDate; + + if (DateTime.TryParse(date, out parsedDate)) + { + item.Date = parsedDate; + } + break; + } + default: + { + reader.Skip(); + break; + } + } + } + else + { + reader.Read(); + } + } + + return item; + } + + public void Dispose() + { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } + } + } +} diff --git a/Emby.Server.Implementations/project.json b/Emby.Server.Implementations/project.json index b1373cd45..81f816753 100644 --- a/Emby.Server.Implementations/project.json +++ b/Emby.Server.Implementations/project.json @@ -1,8 +1,7 @@ -{ +{ "supports": {}, "dependencies": { - "MediaBrowser.Naming": "1.0.0.59", - "Patterns.Logging": "1.0.0.6" + "MediaBrowser.Naming": "1.0.0.59" }, "frameworks": { ".NETPortable,Version=v4.5,Profile=Profile7": {} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs deleted file mode 100644 index 1067e052d..000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs +++ /dev/null @@ -1,121 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Tasks; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.LiveTv; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - public class AutomaticRestartEntryPoint : IServerEntryPoint - { - private readonly IServerApplicationHost _appHost; - private readonly ILogger _logger; - private readonly ITaskManager _iTaskManager; - private readonly ISessionManager _sessionManager; - private readonly IServerConfigurationManager _config; - private readonly ILiveTvManager _liveTvManager; - - private Timer _timer; - - public AutomaticRestartEntryPoint(IServerApplicationHost appHost, ILogger logger, ITaskManager iTaskManager, ISessionManager sessionManager, IServerConfigurationManager config, ILiveTvManager liveTvManager) - { - _appHost = appHost; - _logger = logger; - _iTaskManager = iTaskManager; - _sessionManager = sessionManager; - _config = config; - _liveTvManager = liveTvManager; - } - - public void Run() - { - if (_appHost.CanSelfRestart) - { - _appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged; - } - } - - void _appHost_HasPendingRestartChanged(object sender, EventArgs e) - { - DisposeTimer(); - - if (_appHost.HasPendingRestart) - { - _timer = new Timer(TimerCallback, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); - } - } - - private async void TimerCallback(object state) - { - if (_config.Configuration.EnableAutomaticRestart) - { - var isIdle = await IsIdle().ConfigureAwait(false); - - if (isIdle) - { - DisposeTimer(); - - try - { - _appHost.Restart(); - } - catch (Exception ex) - { - _logger.ErrorException("Error restarting server", ex); - } - } - } - } - - private async Task IsIdle() - { - if (_iTaskManager.ScheduledTasks.Any(i => i.State != TaskState.Idle)) - { - return false; - } - - if (_liveTvManager.Services.Count == 1) - { - try - { - var timers = await _liveTvManager.GetTimers(new TimerQuery(), CancellationToken.None).ConfigureAwait(false); - if (timers.Items.Any(i => i.Status == RecordingStatus.InProgress)) - { - return false; - } - } - catch (Exception ex) - { - _logger.ErrorException("Error getting timers", ex); - } - } - - var now = DateTime.UtcNow; - - return !_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 30); - } - - public void Dispose() - { - _appHost.HasPendingRestartChanged -= _appHost_HasPendingRestartChanged; - - DisposeTimer(); - } - - private void DisposeTimer() - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs deleted file mode 100644 index 9f06a9860..000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ /dev/null @@ -1,340 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - public class LibraryChangedNotifier : IServerEntryPoint - { - /// - /// The _library manager - /// - private readonly ILibraryManager _libraryManager; - - private readonly ISessionManager _sessionManager; - private readonly IUserManager _userManager; - private readonly ILogger _logger; - - /// - /// The _library changed sync lock - /// - private readonly object _libraryChangedSyncLock = new object(); - - private readonly List _foldersAddedTo = new List(); - private readonly List _foldersRemovedFrom = new List(); - - private readonly List _itemsAdded = new List(); - private readonly List _itemsRemoved = new List(); - private readonly List _itemsUpdated = new List(); - - /// - /// Gets or sets the library update timer. - /// - /// The library update timer. - private Timer LibraryUpdateTimer { get; set; } - - /// - /// The library update duration - /// - private const int LibraryUpdateDuration = 5000; - - public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger) - { - _libraryManager = libraryManager; - _sessionManager = sessionManager; - _userManager = userManager; - _logger = logger; - } - - public void Run() - { - _libraryManager.ItemAdded += libraryManager_ItemAdded; - _libraryManager.ItemUpdated += libraryManager_ItemUpdated; - _libraryManager.ItemRemoved += libraryManager_ItemRemoved; - - } - - /// - /// Handles the ItemAdded event of the libraryManager control. - /// - /// The source of the event. - /// The instance containing the event data. - void libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) - { - if (!FilterItem(e.Item)) - { - return; - } - - lock (_libraryChangedSyncLock) - { - if (LibraryUpdateTimer == null) - { - LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, - Timeout.Infinite); - } - else - { - LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); - } - - if (e.Item.Parent != null) - { - _foldersAddedTo.Add(e.Item.Parent); - } - - _itemsAdded.Add(e.Item); - } - } - - /// - /// Handles the ItemUpdated event of the libraryManager control. - /// - /// The source of the event. - /// The instance containing the event data. - void libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e) - { - if (!FilterItem(e.Item)) - { - return; - } - - lock (_libraryChangedSyncLock) - { - if (LibraryUpdateTimer == null) - { - LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, - Timeout.Infinite); - } - else - { - LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); - } - - _itemsUpdated.Add(e.Item); - } - } - - /// - /// Handles the ItemRemoved event of the libraryManager control. - /// - /// The source of the event. - /// The instance containing the event data. - void libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e) - { - if (!FilterItem(e.Item)) - { - return; - } - - lock (_libraryChangedSyncLock) - { - if (LibraryUpdateTimer == null) - { - LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, - Timeout.Infinite); - } - else - { - LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); - } - - if (e.Item.Parent != null) - { - _foldersRemovedFrom.Add(e.Item.Parent); - } - - _itemsRemoved.Add(e.Item); - } - } - - /// - /// Libraries the update timer callback. - /// - /// The state. - private void LibraryUpdateTimerCallback(object state) - { - lock (_libraryChangedSyncLock) - { - // Remove dupes in case some were saved multiple times - var foldersAddedTo = _foldersAddedTo.DistinctBy(i => i.Id).ToList(); - - var foldersRemovedFrom = _foldersRemovedFrom.DistinctBy(i => i.Id).ToList(); - - var itemsUpdated = _itemsUpdated - .Where(i => !_itemsAdded.Contains(i)) - .DistinctBy(i => i.Id) - .ToList(); - - SendChangeNotifications(_itemsAdded.ToList(), itemsUpdated, _itemsRemoved.ToList(), foldersAddedTo, foldersRemovedFrom, CancellationToken.None); - - if (LibraryUpdateTimer != null) - { - LibraryUpdateTimer.Dispose(); - LibraryUpdateTimer = null; - } - - _itemsAdded.Clear(); - _itemsRemoved.Clear(); - _itemsUpdated.Clear(); - _foldersAddedTo.Clear(); - _foldersRemovedFrom.Clear(); - } - } - - /// - /// Sends the change notifications. - /// - /// The items added. - /// The items updated. - /// The items removed. - /// The folders added to. - /// The folders removed from. - /// The cancellation token. - private async void SendChangeNotifications(List itemsAdded, List itemsUpdated, List itemsRemoved, List foldersAddedTo, List foldersRemovedFrom, CancellationToken cancellationToken) - { - foreach (var user in _userManager.Users.ToList()) - { - var id = user.Id; - var userSessions = _sessionManager.Sessions - .Where(u => u.UserId.HasValue && u.UserId.Value == id && u.SessionController != null && u.IsActive) - .ToList(); - - if (userSessions.Count > 0) - { - LibraryUpdateInfo info; - - try - { - info = GetLibraryUpdateInfo(itemsAdded, itemsUpdated, itemsRemoved, foldersAddedTo, - foldersRemovedFrom, id); - } - catch (Exception ex) - { - _logger.ErrorException("Error in GetLibraryUpdateInfo", ex); - return; - } - - foreach (var userSession in userSessions) - { - try - { - await userSession.SessionController.SendLibraryUpdateInfo(info, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending LibraryChanged message", ex); - } - } - } - - } - } - - /// - /// Gets the library update info. - /// - /// The items added. - /// The items updated. - /// The items removed. - /// The folders added to. - /// The folders removed from. - /// The user id. - /// LibraryUpdateInfo. - private LibraryUpdateInfo GetLibraryUpdateInfo(IEnumerable itemsAdded, IEnumerable itemsUpdated, IEnumerable itemsRemoved, IEnumerable foldersAddedTo, IEnumerable foldersRemovedFrom, Guid userId) - { - var user = _userManager.GetUserById(userId); - - return new LibraryUpdateInfo - { - ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(), - - ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(), - - ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, true)).Select(i => i.Id.ToString("N")).Distinct().ToList(), - - FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(), - - FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList() - }; - } - - private bool FilterItem(BaseItem item) - { - if (!item.IsFolder && item.LocationType == LocationType.Virtual) - { - return false; - } - - if (item is IItemByName && !(item is MusicArtist)) - { - return false; - } - - return item.SourceType == SourceType.Library; - } - - /// - /// Translates the physical item to user library. - /// - /// - /// The item. - /// The user. - /// if set to true [include if not found]. - /// IEnumerable{``0}. - private IEnumerable TranslatePhysicalItemToUserLibrary(T item, User user, bool includeIfNotFound = false) - where T : BaseItem - { - // If the physical root changed, return the user root - if (item is AggregateFolder) - { - return new[] { user.RootFolder as T }; - } - - // Return it only if it's in the user's library - if (includeIfNotFound || item.IsVisibleStandalone(user)) - { - return new[] { item }; - } - - return new T[] { }; - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - if (LibraryUpdateTimer != null) - { - LibraryUpdateTimer.Dispose(); - LibraryUpdateTimer = null; - } - - _libraryManager.ItemAdded -= libraryManager_ItemAdded; - _libraryManager.ItemUpdated -= libraryManager_ItemUpdated; - _libraryManager.ItemRemoved -= libraryManager_ItemRemoved; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs deleted file mode 100644 index 47f22cae6..000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs +++ /dev/null @@ -1,71 +0,0 @@ -using MediaBrowser.Common.Security; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Logging; -using System; -using System.Threading.Tasks; -using MediaBrowser.Server.Implementations.Threading; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - /// - /// Class LoadRegistrations - /// - public class LoadRegistrations : IServerEntryPoint - { - /// - /// The _security manager - /// - private readonly ISecurityManager _securityManager; - - /// - /// The _logger - /// - private readonly ILogger _logger; - - private PeriodicTimer _timer; - - /// - /// Initializes a new instance of the class. - /// - /// The security manager. - /// The log manager. - public LoadRegistrations(ISecurityManager securityManager, ILogManager logManager) - { - _securityManager = securityManager; - - _logger = logManager.GetLogger("Registration Loader"); - } - - /// - /// Runs this instance. - /// - public void Run() - { - _timer = new PeriodicTimer(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(12)); - } - - private async Task LoadAllRegistrations() - { - try - { - await _securityManager.LoadAllRegistrationInfo().ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error loading registration info", ex); - } - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/RecordingNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/RecordingNotifier.cs deleted file mode 100644 index 414fda400..000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/RecordingNotifier.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - public class RecordingNotifier : IServerEntryPoint - { - private readonly ILiveTvManager _liveTvManager; - private readonly ISessionManager _sessionManager; - private readonly IUserManager _userManager; - private readonly ILogger _logger; - - public RecordingNotifier(ISessionManager sessionManager, IUserManager userManager, ILogger logger, ILiveTvManager liveTvManager) - { - _sessionManager = sessionManager; - _userManager = userManager; - _logger = logger; - _liveTvManager = liveTvManager; - } - - public void Run() - { - _liveTvManager.TimerCancelled += _liveTvManager_TimerCancelled; - _liveTvManager.SeriesTimerCancelled += _liveTvManager_SeriesTimerCancelled; - _liveTvManager.TimerCreated += _liveTvManager_TimerCreated; - _liveTvManager.SeriesTimerCreated += _liveTvManager_SeriesTimerCreated; - } - - private void _liveTvManager_SeriesTimerCreated(object sender, Model.Events.GenericEventArgs e) - { - SendMessage("SeriesTimerCreated", e.Argument); - } - - private void _liveTvManager_TimerCreated(object sender, Model.Events.GenericEventArgs e) - { - SendMessage("TimerCreated", e.Argument); - } - - private void _liveTvManager_SeriesTimerCancelled(object sender, Model.Events.GenericEventArgs e) - { - SendMessage("SeriesTimerCancelled", e.Argument); - } - - private void _liveTvManager_TimerCancelled(object sender, Model.Events.GenericEventArgs e) - { - SendMessage("TimerCancelled", e.Argument); - } - - private async void SendMessage(string name, TimerEventInfo info) - { - var users = _userManager.Users.Where(i => i.Policy.EnableLiveTvAccess).Select(i => i.Id.ToString("N")).ToList(); - - try - { - await _sessionManager.SendMessageToUserSessions(users, name, info, CancellationToken.None); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending message", ex); - } - } - - public void Dispose() - { - _liveTvManager.TimerCancelled -= _liveTvManager_TimerCancelled; - _liveTvManager.SeriesTimerCancelled -= _liveTvManager_SeriesTimerCancelled; - _liveTvManager.TimerCreated -= _liveTvManager_TimerCreated; - _liveTvManager.SeriesTimerCreated -= _liveTvManager_SeriesTimerCreated; - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs b/MediaBrowser.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs deleted file mode 100644 index a0b7ff515..000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; -using System.Threading; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - /// - /// Class RefreshUsersMetadata - /// - public class RefreshUsersMetadata : IServerEntryPoint - { - /// - /// The _user manager - /// - private readonly IUserManager _userManager; - - /// - /// Initializes a new instance of the class. - /// - /// The user manager. - public RefreshUsersMetadata(IUserManager userManager) - { - _userManager = userManager; - } - - /// - /// Runs this instance. - /// - public async void Run() - { - await _userManager.RefreshUsersMetadata(CancellationToken.None).ConfigureAwait(false); - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs deleted file mode 100644 index 0da48a2d8..000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ /dev/null @@ -1,203 +0,0 @@ -using MediaBrowser.Common.Plugins; -using MediaBrowser.Common.Updates; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Sync; -using System; -using System.Collections.Generic; -using System.Threading; -using MediaBrowser.Model.Tasks; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - /// - /// Class WebSocketEvents - /// - public class ServerEventNotifier : IServerEntryPoint - { - /// - /// The _server manager - /// - private readonly IServerManager _serverManager; - - /// - /// The _user manager - /// - private readonly IUserManager _userManager; - - /// - /// The _installation manager - /// - private readonly IInstallationManager _installationManager; - - /// - /// The _kernel - /// - private readonly IServerApplicationHost _appHost; - - /// - /// The _task manager - /// - private readonly ITaskManager _taskManager; - - private readonly ISessionManager _sessionManager; - private readonly ISyncManager _syncManager; - - public ServerEventNotifier(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, ISessionManager sessionManager, ISyncManager syncManager) - { - _serverManager = serverManager; - _userManager = userManager; - _installationManager = installationManager; - _appHost = appHost; - _taskManager = taskManager; - _sessionManager = sessionManager; - _syncManager = syncManager; - } - - public void Run() - { - _userManager.UserDeleted += userManager_UserDeleted; - _userManager.UserUpdated += userManager_UserUpdated; - _userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated; - - _appHost.HasPendingRestartChanged += kernel_HasPendingRestartChanged; - - _installationManager.PluginUninstalled += InstallationManager_PluginUninstalled; - _installationManager.PackageInstalling += _installationManager_PackageInstalling; - _installationManager.PackageInstallationCancelled += _installationManager_PackageInstallationCancelled; - _installationManager.PackageInstallationCompleted += _installationManager_PackageInstallationCompleted; - _installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed; - - _taskManager.TaskCompleted += _taskManager_TaskCompleted; - _syncManager.SyncJobCreated += _syncManager_SyncJobCreated; - _syncManager.SyncJobCancelled += _syncManager_SyncJobCancelled; - } - - void _syncManager_SyncJobCancelled(object sender, GenericEventArgs e) - { - _sessionManager.SendMessageToUserDeviceSessions(e.Argument.TargetId, "SyncJobCancelled", e.Argument, CancellationToken.None); - } - - void _syncManager_SyncJobCreated(object sender, GenericEventArgs e) - { - _sessionManager.SendMessageToUserDeviceSessions(e.Argument.Job.TargetId, "SyncJobCreated", e.Argument, CancellationToken.None); - } - - void _installationManager_PackageInstalling(object sender, InstallationEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstalling", e.InstallationInfo); - } - - void _installationManager_PackageInstallationCancelled(object sender, InstallationEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstallationCancelled", e.InstallationInfo); - } - - void _installationManager_PackageInstallationCompleted(object sender, InstallationEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstallationCompleted", e.InstallationInfo); - } - - void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstallationFailed", e.InstallationInfo); - } - - void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) - { - _serverManager.SendWebSocketMessage("ScheduledTaskEnded", e.Result); - } - - /// - /// Installations the manager_ plugin uninstalled. - /// - /// The sender. - /// The e. - void InstallationManager_PluginUninstalled(object sender, GenericEventArgs e) - { - _serverManager.SendWebSocketMessage("PluginUninstalled", e.Argument.GetPluginInfo()); - } - - /// - /// Handles the HasPendingRestartChanged event of the kernel control. - /// - /// The source of the event. - /// The instance containing the event data. - void kernel_HasPendingRestartChanged(object sender, EventArgs e) - { - _sessionManager.SendRestartRequiredNotification(CancellationToken.None); - } - - /// - /// Users the manager_ user updated. - /// - /// The sender. - /// The e. - void userManager_UserUpdated(object sender, GenericEventArgs e) - { - var dto = _userManager.GetUserDto(e.Argument); - - SendMessageToUserSession(e.Argument, "UserUpdated", dto); - } - - /// - /// Users the manager_ user deleted. - /// - /// The sender. - /// The e. - void userManager_UserDeleted(object sender, GenericEventArgs e) - { - SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N")); - } - - void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs e) - { - var dto = _userManager.GetUserDto(e.Argument); - - SendMessageToUserSession(e.Argument, "UserConfigurationUpdated", dto); - } - - private async void SendMessageToUserSession(User user, string name, T data) - { - await _sessionManager.SendMessageToUserSessions(new List { user.Id.ToString("N") }, name, data, CancellationToken.None); - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - _userManager.UserDeleted -= userManager_UserDeleted; - _userManager.UserUpdated -= userManager_UserUpdated; - _userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated; - - _installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled; - _installationManager.PackageInstalling -= _installationManager_PackageInstalling; - _installationManager.PackageInstallationCancelled -= _installationManager_PackageInstallationCancelled; - _installationManager.PackageInstallationCompleted -= _installationManager_PackageInstallationCompleted; - _installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed; - - _appHost.HasPendingRestartChanged -= kernel_HasPendingRestartChanged; - _syncManager.SyncJobCreated -= _syncManager_SyncJobCreated; - _syncManager.SyncJobCancelled -= _syncManager_SyncJobCancelled; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs deleted file mode 100644 index d14bd4368..000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs +++ /dev/null @@ -1,133 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Configuration; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - /// - /// Class UsageEntryPoint - /// - public class UsageEntryPoint : IServerEntryPoint - { - private readonly IApplicationHost _applicationHost; - private readonly IHttpClient _httpClient; - private readonly ILogger _logger; - private readonly ISessionManager _sessionManager; - private readonly IUserManager _userManager; - private readonly IServerConfigurationManager _config; - - private readonly ConcurrentDictionary _apps = new ConcurrentDictionary(); - - public UsageEntryPoint(ILogger logger, IApplicationHost applicationHost, IHttpClient httpClient, ISessionManager sessionManager, IUserManager userManager, IServerConfigurationManager config) - { - _logger = logger; - _applicationHost = applicationHost; - _httpClient = httpClient; - _sessionManager = sessionManager; - _userManager = userManager; - _config = config; - - _sessionManager.SessionStarted += _sessionManager_SessionStarted; - } - - void _sessionManager_SessionStarted(object sender, SessionEventArgs e) - { - var session = e.SessionInfo; - - if (!string.IsNullOrEmpty(session.Client) && - !string.IsNullOrEmpty(session.DeviceName) && - !string.IsNullOrEmpty(session.DeviceId) && - !string.IsNullOrEmpty(session.ApplicationVersion)) - { - var keys = new List - { - session.Client, - session.DeviceName, - session.DeviceId, - session.ApplicationVersion - }; - - var key = string.Join("_", keys.ToArray()).GetMD5(); - - _apps.GetOrAdd(key, guid => GetNewClientInfo(session)); - } - } - - private async void ReportNewSession(ClientInfo client) - { - if (!_config.Configuration.EnableAnonymousUsageReporting) - { - return; - } - - try - { - await new UsageReporter(_applicationHost, _httpClient, _userManager, _logger) - .ReportAppUsage(client, CancellationToken.None) - .ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending anonymous usage statistics.", ex); - } - } - - private ClientInfo GetNewClientInfo(SessionInfo session) - { - var info = new ClientInfo - { - AppName = session.Client, - AppVersion = session.ApplicationVersion, - DeviceName = session.DeviceName, - DeviceId = session.DeviceId - }; - - ReportNewSession(info); - - return info; - } - - public async void Run() - { - await Task.Delay(5000).ConfigureAwait(false); - OnTimerFired(); - } - - /// - /// Called when [timer fired]. - /// - private async void OnTimerFired() - { - if (!_config.Configuration.EnableAnonymousUsageReporting) - { - return; - } - - try - { - await new UsageReporter(_applicationHost, _httpClient, _userManager, _logger) - .ReportServerUsage(CancellationToken.None) - .ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending anonymous usage statistics.", ex); - } - } - - public void Dispose() - { - _sessionManager.SessionStarted -= _sessionManager_SessionStarted; - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs deleted file mode 100644 index e445300e4..000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs +++ /dev/null @@ -1,138 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Connect; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - public class UsageReporter - { - private readonly IApplicationHost _applicationHost; - private readonly IHttpClient _httpClient; - private readonly IUserManager _userManager; - private readonly ILogger _logger; - private const string MbAdminUrl = "https://www.mb3admin.com/admin/"; - - public UsageReporter(IApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager, ILogger logger) - { - _applicationHost = applicationHost; - _httpClient = httpClient; - _userManager = userManager; - _logger = logger; - } - - public async Task ReportServerUsage(CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var data = new Dictionary - { - { "feature", _applicationHost.Name }, - { "mac", _applicationHost.SystemId }, - { "serverid", _applicationHost.SystemId }, - { "deviceid", _applicationHost.SystemId }, - { "ver", _applicationHost.ApplicationVersion.ToString() }, - { "platform", _applicationHost.OperatingSystemDisplayName }, - { "isservice", _applicationHost.IsRunningAsService.ToString().ToLower()} - }; - - var users = _userManager.Users.ToList(); - - data["localusers"] = users.Count(i => !i.ConnectLinkType.HasValue).ToString(CultureInfo.InvariantCulture); - data["guests"] = users.Count(i => i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.Guest).ToString(CultureInfo.InvariantCulture); - data["linkedusers"] = users.Count(i => i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.LinkedUser).ToString(CultureInfo.InvariantCulture); - - data["plugins"] = string.Join(",", _applicationHost.Plugins.Select(i => i.Id).ToArray()); - - var logErrors = false; -#if DEBUG - logErrors = true; -#endif - var options = new HttpRequestOptions - { - Url = MbAdminUrl + "service/registration/ping", - CancellationToken = cancellationToken, - - // Seeing block length errors - EnableHttpCompression = false, - - LogRequest = false, - LogErrors = logErrors, - BufferContent = false - }; - - options.SetPostData(data); - - using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)) - { - - } - } - - public async Task ReportAppUsage(ClientInfo app, CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(app.DeviceId)) - { - throw new ArgumentException("Client info must have a device Id"); - } - - _logger.Info("App Activity: app: {0}, version: {1}, deviceId: {2}, deviceName: {3}", - app.AppName ?? "Unknown App", - app.AppVersion ?? "Unknown", - app.DeviceId, - app.DeviceName ?? "Unknown"); - - cancellationToken.ThrowIfCancellationRequested(); - - var data = new Dictionary - { - { "feature", app.AppName ?? "Unknown App" }, - { "serverid", _applicationHost.SystemId }, - { "deviceid", app.DeviceId }, - { "mac", app.DeviceId }, - { "ver", app.AppVersion ?? "Unknown" }, - { "platform", app.DeviceName }, - }; - - var logErrors = false; - -#if DEBUG - logErrors = true; -#endif - var options = new HttpRequestOptions - { - Url = MbAdminUrl + "service/registration/ping", - CancellationToken = cancellationToken, - - // Seeing block length errors - EnableHttpCompression = false, - - LogRequest = false, - LogErrors = logErrors, - BufferContent = false - }; - - options.SetPostData(data); - - using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)) - { - - } - } - } - - public class ClientInfo - { - public string AppName { get; set; } - public string AppVersion { get; set; } - public string DeviceName { get; set; } - public string DeviceId { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs deleted file mode 100644 index 8262048b1..000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ /dev/null @@ -1,162 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Session; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - class UserDataChangeNotifier : IServerEntryPoint - { - private readonly ISessionManager _sessionManager; - private readonly ILogger _logger; - private readonly IUserDataManager _userDataManager; - private readonly IUserManager _userManager; - - private readonly object _syncLock = new object(); - private Timer UpdateTimer { get; set; } - private const int UpdateDuration = 500; - - private readonly Dictionary> _changedItems = new Dictionary>(); - - public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager) - { - _userDataManager = userDataManager; - _sessionManager = sessionManager; - _logger = logger; - _userManager = userManager; - } - - public void Run() - { - _userDataManager.UserDataSaved += _userDataManager_UserDataSaved; - } - - void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e) - { - if (e.SaveReason == UserDataSaveReason.PlaybackProgress) - { - return; - } - - lock (_syncLock) - { - if (UpdateTimer == null) - { - UpdateTimer = new Timer(UpdateTimerCallback, null, UpdateDuration, - Timeout.Infinite); - } - else - { - UpdateTimer.Change(UpdateDuration, Timeout.Infinite); - } - - List keys; - - if (!_changedItems.TryGetValue(e.UserId, out keys)) - { - keys = new List(); - _changedItems[e.UserId] = keys; - } - - keys.Add(e.Item); - - var baseItem = e.Item as BaseItem; - - // Go up one level for indicators - if (baseItem != null) - { - var parent = baseItem.GetParent(); - - if (parent != null) - { - keys.Add(parent); - } - } - } - } - - private void UpdateTimerCallback(object state) - { - lock (_syncLock) - { - // Remove dupes in case some were saved multiple times - var changes = _changedItems.ToList(); - _changedItems.Clear(); - - var task = SendNotifications(changes, CancellationToken.None); - - if (UpdateTimer != null) - { - UpdateTimer.Dispose(); - UpdateTimer = null; - } - } - } - - private async Task SendNotifications(IEnumerable>> changes, CancellationToken cancellationToken) - { - foreach (var pair in changes) - { - var userId = pair.Key; - var userSessions = _sessionManager.Sessions - .Where(u => u.ContainsUser(userId) && u.SessionController != null && u.IsActive) - .ToList(); - - if (userSessions.Count > 0) - { - var user = _userManager.GetUserById(userId); - - var dtoList = pair.Value - .DistinctBy(i => i.Id) - .Select(i => - { - var dto = _userDataManager.GetUserDataDto(i, user).Result; - dto.ItemId = i.Id.ToString("N"); - return dto; - }) - .ToList(); - - var info = new UserDataChangeInfo - { - UserId = userId.ToString("N"), - - UserDataList = dtoList - }; - - foreach (var userSession in userSessions) - { - try - { - await userSession.SessionController.SendUserDataChangeInfo(info, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending UserDataChanged message", ex); - } - } - } - - } - } - - public void Dispose() - { - if (UpdateTimer != null) - { - UpdateTimer.Dispose(); - UpdateTimer = null; - } - - _userDataManager.UserDataSaved -= _userDataManager_UserDataSaved; - } - } -} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 88e9478df..b31c8286c 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -46,17 +46,13 @@ ..\ThirdParty\emby\Emby.Common.Implementations.dll - ..\packages\Emby.XmlTv.1.0.0.62\lib\portable-net45+win8\Emby.XmlTv.dll + ..\packages\Emby.XmlTv.1.0.0.63\lib\portable-net45+win8\Emby.XmlTv.dll True ..\packages\ini-parser.2.3.0\lib\net20\INIFileParser.dll True - - ..\packages\MediaBrowser.Naming.1.0.0.59\lib\portable-net45+win8\MediaBrowser.Naming.dll - True - ..\packages\Microsoft.IO.RecyclableMemoryStream.1.1.0.0\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll True @@ -120,17 +116,8 @@ - - - - - - - - - @@ -211,8 +198,6 @@ - - @@ -286,23 +271,6 @@ MediaBrowser.Providers - - - - - - - - - - - - - - - - - swagger-ui\lib\backbone-min.js @@ -368,7 +336,6 @@ swagger-ui\swagger-ui.min.js PreserveNewest - swagger-ui\fonts\droid-sans-v6-latin-700.eot PreserveNewest @@ -401,46 +368,25 @@ swagger-ui\fonts\droid-sans-v6-latin-regular.woff2 PreserveNewest + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -610,12 +556,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - swagger-ui\css\reset.css @@ -665,8 +648,6 @@ swagger-ui\lib\shred\content.js PreserveNewest - - diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs deleted file mode 100644 index 9f1744cc9..000000000 --- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs +++ /dev/null @@ -1,236 +0,0 @@ -using MediaBrowser.Controller.Chapters; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; -using MediaBrowser.Controller.Library; - -namespace MediaBrowser.Server.Implementations.MediaEncoder -{ - public class EncodingManager : IEncodingManager - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; - private readonly IMediaEncoder _encoder; - private readonly IChapterManager _chapterManager; - private readonly ILibraryManager _libraryManager; - - public EncodingManager(IFileSystem fileSystem, - ILogger logger, - IMediaEncoder encoder, - IChapterManager chapterManager, ILibraryManager libraryManager) - { - _fileSystem = fileSystem; - _logger = logger; - _encoder = encoder; - _chapterManager = chapterManager; - _libraryManager = libraryManager; - } - - /// - /// Gets the chapter images data path. - /// - /// The chapter images data path. - private string GetChapterImagesPath(IHasImages item) - { - return Path.Combine(item.GetInternalMetadataPath(), "chapters"); - } - - /// - /// Determines whether [is eligible for chapter image extraction] [the specified video]. - /// - /// The video. - /// true if [is eligible for chapter image extraction] [the specified video]; otherwise, false. - private bool IsEligibleForChapterImageExtraction(Video video) - { - if (video.IsPlaceHolder) - { - return false; - } - - var libraryOptions = _libraryManager.GetLibraryOptions(video); - if (libraryOptions != null) - { - if (!libraryOptions.EnableChapterImageExtraction) - { - return false; - } - } - else - { - return false; - } - - // Can't extract images if there are no video streams - return video.DefaultVideoStreamIndex.HasValue; - } - - /// - /// The first chapter ticks - /// - private static readonly long FirstChapterTicks = TimeSpan.FromSeconds(15).Ticks; - - public async Task RefreshChapterImages(ChapterImageRefreshOptions options, CancellationToken cancellationToken) - { - var extractImages = options.ExtractImages; - var video = options.Video; - var chapters = options.Chapters; - var saveChapters = options.SaveChapters; - - if (!IsEligibleForChapterImageExtraction(video)) - { - extractImages = false; - } - - var success = true; - var changesMade = false; - - var runtimeTicks = video.RunTimeTicks ?? 0; - - var currentImages = GetSavedChapterImages(video); - - foreach (var chapter in chapters) - { - if (chapter.StartPositionTicks >= runtimeTicks) - { - _logger.Info("Stopping chapter extraction for {0} because a chapter was found with a position greater than the runtime.", video.Name); - break; - } - - var path = GetChapterImagePath(video, chapter.StartPositionTicks); - - if (!currentImages.Contains(path, StringComparer.OrdinalIgnoreCase)) - { - if (extractImages) - { - if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso) - { - continue; - } - if (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd) - { - if (video.PlayableStreamFileNames.Count != 1) - { - continue; - } - } - - try - { - // Add some time for the first chapter to make sure we don't end up with a black image - var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); - - var protocol = MediaProtocol.File; - - var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames); - - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - - var container = video.Container; - - var tempFile = await _encoder.ExtractVideoImage(inputPath, container, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false); - File.Copy(tempFile, path, true); - - try - { - File.Delete(tempFile); - } - catch - { - - } - - chapter.ImagePath = path; - chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path); - changesMade = true; - } - catch (Exception ex) - { - _logger.ErrorException("Error extracting chapter images for {0}", ex, string.Join(",", video.Path)); - success = false; - break; - } - } - else if (!string.IsNullOrEmpty(chapter.ImagePath)) - { - chapter.ImagePath = null; - changesMade = true; - } - } - else if (!string.Equals(path, chapter.ImagePath, StringComparison.OrdinalIgnoreCase)) - { - chapter.ImagePath = path; - chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path); - changesMade = true; - } - } - - if (saveChapters && changesMade) - { - await _chapterManager.SaveChapters(video.Id.ToString(), chapters, cancellationToken).ConfigureAwait(false); - } - - DeleteDeadImages(currentImages, chapters); - - return success; - } - - private string GetChapterImagePath(Video video, long chapterPositionTicks) - { - var filename = video.DateModified.Ticks.ToString(_usCulture) + "_" + chapterPositionTicks.ToString(_usCulture) + ".jpg"; - - return Path.Combine(GetChapterImagesPath(video), filename); - } - - private List GetSavedChapterImages(Video video) - { - var path = GetChapterImagesPath(video); - - try - { - return _fileSystem.GetFilePaths(path) - .ToList(); - } - catch (DirectoryNotFoundException) - { - return new List(); - } - } - - private void DeleteDeadImages(IEnumerable images, IEnumerable chapters) - { - var deadImages = images - .Except(chapters.Select(i => i.ImagePath).Where(i => !string.IsNullOrEmpty(i)), StringComparer.OrdinalIgnoreCase) - .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i), StringComparer.OrdinalIgnoreCase)) - .ToList(); - - foreach (var image in deadImages) - { - _logger.Debug("Deleting dead chapter image {0}", image); - - try - { - _fileSystem.DeleteFile(image); - } - catch (IOException ex) - { - _logger.ErrorException("Error deleting {0}.", ex, image); - } - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs b/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs deleted file mode 100644 index 22cb4e86a..000000000 --- a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs +++ /dev/null @@ -1,170 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Notifications; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.News; -using MediaBrowser.Model.Notifications; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Xml; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; -using MediaBrowser.Server.Implementations.Threading; - -namespace MediaBrowser.Server.Implementations.News -{ - public class NewsEntryPoint : IServerEntryPoint - { - private PeriodicTimer _timer; - private readonly IHttpClient _httpClient; - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; - private readonly IJsonSerializer _json; - - private readonly INotificationManager _notifications; - private readonly IUserManager _userManager; - - private readonly TimeSpan _frequency = TimeSpan.FromHours(24); - - public NewsEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IJsonSerializer json, INotificationManager notifications, IUserManager userManager) - { - _httpClient = httpClient; - _appPaths = appPaths; - _fileSystem = fileSystem; - _logger = logger; - _json = json; - _notifications = notifications; - _userManager = userManager; - } - - public void Run() - { - _timer = new PeriodicTimer(OnTimerFired, null, TimeSpan.FromMilliseconds(500), _frequency); - } - - /// - /// Called when [timer fired]. - /// - /// The state. - private async void OnTimerFired(object state) - { - var path = Path.Combine(_appPaths.CachePath, "news.json"); - - try - { - await DownloadNews(path).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error downloading news", ex); - } - } - - private async Task DownloadNews(string path) - { - DateTime? lastUpdate = null; - - if (_fileSystem.FileExists(path)) - { - lastUpdate = _fileSystem.GetLastWriteTimeUtc(path); - } - - var requestOptions = new HttpRequestOptions - { - Url = "http://emby.media/community/index.php?/blog/rss/1-media-browser-developers-blog", - Progress = new Progress(), - UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.42 Safari/537.36", - BufferContent = false - }; - - using (var stream = await _httpClient.Get(requestOptions).ConfigureAwait(false)) - { - var doc = new XmlDocument(); - doc.Load(stream); - - var news = ParseRssItems(doc).ToList(); - - _json.SerializeToFile(news, path); - - await CreateNotifications(news, lastUpdate, CancellationToken.None).ConfigureAwait(false); - } - } - - private Task CreateNotifications(List items, DateTime? lastUpdate, CancellationToken cancellationToken) - { - if (lastUpdate.HasValue) - { - items = items.Where(i => i.Date.ToUniversalTime() >= lastUpdate.Value) - .ToList(); - } - - var tasks = items.Select(i => _notifications.SendNotification(new NotificationRequest - { - Date = i.Date, - Name = i.Title, - Description = i.Description, - Url = i.Link, - UserIds = _userManager.Users.Select(u => u.Id.ToString("N")).ToList() - - }, cancellationToken)); - - return Task.WhenAll(tasks); - } - - private IEnumerable ParseRssItems(XmlDocument xmlDoc) - { - var nodes = xmlDoc.SelectNodes("rss/channel/item"); - - if (nodes != null) - { - foreach (XmlNode node in nodes) - { - var newsItem = new NewsItem(); - - newsItem.Title = ParseDocElements(node, "title"); - - newsItem.DescriptionHtml = ParseDocElements(node, "description"); - newsItem.Description = newsItem.DescriptionHtml.StripHtml(); - - newsItem.Link = ParseDocElements(node, "link"); - - var date = ParseDocElements(node, "pubDate"); - DateTime parsedDate; - - if (DateTime.TryParse(date, out parsedDate)) - { - newsItem.Date = parsedDate; - } - - yield return newsItem; - } - } - } - - private string ParseDocElements(XmlNode parent, string xPath) - { - var node = parent.SelectSingleNode(xPath); - - return node != null ? node.InnerText : string.Empty; - } - - public void Dispose() - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index cdfb48abe..5a43abe0f 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,8 +1,7 @@  - + - diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 294e780cc..861d59908 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -59,7 +59,6 @@ using MediaBrowser.Server.Implementations.HttpServer.Security; using MediaBrowser.Server.Implementations.IO; using MediaBrowser.Server.Implementations.LiveTv; using MediaBrowser.Server.Implementations.Localization; -using MediaBrowser.Server.Implementations.MediaEncoder; using MediaBrowser.Server.Implementations.Notifications; using MediaBrowser.Server.Implementations.Persistence; using MediaBrowser.Server.Implementations.Security; @@ -107,6 +106,7 @@ using Emby.Server.Implementations.Devices; using Emby.Server.Implementations.Dto; using Emby.Server.Implementations.FileOrganization; using Emby.Server.Implementations.Library; +using Emby.Server.Implementations.MediaEncoder; using Emby.Server.Implementations.Notifications; using Emby.Server.Implementations.Persistence; using Emby.Server.Implementations.Playlists; diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index c64f065d7..6a84ee0c5 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -38,6 +38,10 @@ ..\ThirdParty\emby\Emby.Dlna.dll + + ..\packages\MediaBrowser.Naming.1.0.0.59\lib\portable-net45+win8\MediaBrowser.Naming.dll + True + False ..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll diff --git a/MediaBrowser.Server.Startup.Common/packages.config b/MediaBrowser.Server.Startup.Common/packages.config index aa11730c7..ea3d0e7f8 100644 --- a/MediaBrowser.Server.Startup.Common/packages.config +++ b/MediaBrowser.Server.Startup.Common/packages.config @@ -1,5 +1,6 @@  + diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 0a86e96a5..e84fa8e65 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -32,11 +32,6 @@ prompt 4 - - - ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll - - Properties\SharedVersion.cs diff --git a/MediaBrowser.XbmcMetadata/packages.config b/MediaBrowser.XbmcMetadata/packages.config index 79ff26ec6..6b8deb9c9 100644 --- a/MediaBrowser.XbmcMetadata/packages.config +++ b/MediaBrowser.XbmcMetadata/packages.config @@ -1,4 +1,3 @@  - \ No newline at end of file -- cgit v1.2.3 From 8ef442c2e8f39307f72bc98d6c79a9b5f09e6d72 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 3 Nov 2016 18:53:02 -0400 Subject: move classes --- Emby.Dlna/DlnaManager.cs | 6 +- .../Emby.Server.Implementations.csproj | 7 + .../ServerManager/ServerManager.cs | 353 +++++++++++++++++++++ .../ServerManager/WebSocketConnection.cs | 295 +++++++++++++++++ .../TV/SeriesPostScanTask.cs | 241 ++++++++++++++ Emby.Server.Implementations/project.json | 3 +- .../Connect/ConnectEntryPoint.cs | 10 +- .../EntryPoints/ExternalPortForwarding.cs | 10 +- .../MediaBrowser.Server.Implementations.csproj | 4 - .../ServerManager/ServerManager.cs | 353 --------------------- .../ServerManager/WebSocketConnection.cs | 292 ----------------- .../TV/SeriesPostScanTask.cs | 238 -------------- .../Threading/PeriodicTimer.cs | 72 ----- .../ApplicationHost.cs | 4 +- .../EntryPoints/KeepServerAwake.cs | 2 +- .../MediaBrowser.Server.Startup.Common.csproj | 1 + .../Threading/PeriodicTimer.cs | 72 +++++ 17 files changed, 990 insertions(+), 973 deletions(-) create mode 100644 Emby.Server.Implementations/ServerManager/ServerManager.cs create mode 100644 Emby.Server.Implementations/ServerManager/WebSocketConnection.cs create mode 100644 Emby.Server.Implementations/TV/SeriesPostScanTask.cs delete mode 100644 MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs delete mode 100644 MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs delete mode 100644 MediaBrowser.Server.Implementations/TV/SeriesPostScanTask.cs delete mode 100644 MediaBrowser.Server.Implementations/Threading/PeriodicTimer.cs create mode 100644 MediaBrowser.Server.Startup.Common/Threading/PeriodicTimer.cs (limited to 'Emby.Server.Implementations/project.json') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index c5798a5d1..c348e658c 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -560,17 +560,19 @@ namespace Emby.Dlna ? ImageFormat.Png : ImageFormat.Jpg; + var resource = GetType().Namespace + ".Images." + filename.ToLower(); + #if NET46 return new ImageStream { Format = format, - Stream = GetType().Assembly.GetManifestResourceStream("MediaBrowser.Dlna.Images." + filename.ToLower()) + Stream = GetType().Assembly.GetManifestResourceStream(resource) }; #elif NETSTANDARD1_6 return new ImageStream { Format = format, - Stream = GetType().GetTypeInfo().Assembly.GetManifestResourceStream("MediaBrowser.Dlna.Images." + filename.ToLower()) + Stream = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(resource) }; #endif throw new NotImplementedException(); diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 152a165e2..7829193c5 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -131,6 +131,8 @@ + + @@ -178,6 +180,7 @@ + @@ -197,6 +200,10 @@ {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} MediaBrowser.Model + + {442b5058-dcaf-4263-bb6a-f21e31120a1b} + MediaBrowser.Providers +