aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Dockerfile5
-rw-r--r--Dockerfile.arm2
-rw-r--r--Dockerfile.arm642
-rw-r--r--Emby.Dlna/ContentDirectory/ControlHandler.cs11
-rw-r--r--Emby.Dlna/Didl/DidlBuilder.cs9
-rw-r--r--Emby.IsoMounting/.gitignore108
-rw-r--r--Emby.IsoMounting/IsoMounter.sln25
-rw-r--r--Emby.IsoMounting/IsoMounter/Configuration/PluginConfiguration.cs11
-rw-r--r--Emby.IsoMounting/IsoMounter/IsoMounter.csproj30
-rw-r--r--Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs298
-rw-r--r--Emby.IsoMounting/IsoMounter/LinuxMount.cs58
-rw-r--r--Emby.IsoMounting/IsoMounter/Plugin.cs33
-rw-r--r--Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs21
-rw-r--r--Emby.IsoMounting/LICENSE339
-rw-r--r--Emby.IsoMounting/README.md14
-rw-r--r--Emby.Notifications/Notifications.cs37
-rw-r--r--Emby.Photos/PhotoProvider.cs4
-rw-r--r--Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs149
-rw-r--r--Emby.Server.Implementations/Activity/ActivityRepository.cs2
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs18
-rw-r--r--Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs8
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs16
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs113
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs17
-rw-r--r--Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs3
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs5
-rw-r--r--Emby.Server.Implementations/Library/UserViewManager.cs30
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs75
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs18
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs15
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs48
-rw-r--r--Emby.Server.Implementations/Localization/Core/el.json10
-rw-r--r--Emby.Server.Implementations/Localization/Core/es.json4
-rw-r--r--Emby.Server.Implementations/Localization/Core/fr.json4
-rw-r--r--Emby.Server.Implementations/Localization/Core/nb.json4
-rw-r--r--Emby.Server.Implementations/MediaEncoder/EncodingManager.cs2
-rw-r--r--Emby.Server.Implementations/Net/SocketFactory.cs3
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs (renamed from Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodingTempTask.cs)9
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs13
-rw-r--r--Emby.Server.Implementations/Services/ResponseHelper.cs2
-rw-r--r--Emby.Server.Implementations/Services/ServiceExec.cs39
-rw-r--r--Emby.Server.Implementations/Services/UrlExtensions.cs14
-rw-r--r--Emby.Server.Implementations/Sorting/ArtistComparer.cs24
-rw-r--r--Jellyfin.Server/Jellyfin.Server.csproj1
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs2
-rw-r--r--MediaBrowser.Api/Movies/MoviesService.cs2
-rw-r--r--MediaBrowser.Api/Music/AlbumsService.cs11
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs2
-rw-r--r--MediaBrowser.Api/PlaylistService.cs6
-rw-r--r--MediaBrowser.Api/SuggestionsService.cs5
-rw-r--r--MediaBrowser.Api/TvShowsService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemsService.cs5
-rw-r--r--MediaBrowser.Api/UserLibrary/UserLibraryService.cs15
-rw-r--r--MediaBrowser.Api/UserService.cs12
-rw-r--r--MediaBrowser.Common/Extensions/CollectionExtensions.cs17
-rw-r--r--MediaBrowser.Common/Net/CustomHeaderNames.cs2
-rw-r--r--MediaBrowser.Controller/Dto/IDtoService.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Audio/Audio.cs37
-rw-r--r--MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs27
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs38
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs16
-rw-r--r--MediaBrowser.Controller/Entities/Extensions.cs9
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs18
-rw-r--r--MediaBrowser.Controller/Entities/IHasTrailers.cs70
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs10
-rw-r--r--MediaBrowser.Controller/Entities/Movies/Movie.cs7
-rw-r--r--MediaBrowser.Controller/Entities/MusicVideo.cs7
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs7
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs7
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs4
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs792
-rw-r--r--MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs17
-rw-r--r--MediaBrowser.Controller/Providers/AlbumInfo.cs2
-rw-r--r--MediaBrowser.Controller/Providers/MusicVideoInfo.cs4
-rw-r--r--MediaBrowser.Controller/Providers/SongInfo.cs7
-rw-r--r--MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs2
-rw-r--r--MediaBrowser.Model/Cryptography/PasswordHash.cs16
-rw-r--r--MediaBrowser.Model/Dto/BaseItemDto.cs4
-rw-r--r--MediaBrowser.Model/Dto/RecommendationDto.cs3
-rw-r--r--MediaBrowser.Model/Net/MimeTypes.cs1
-rw-r--r--MediaBrowser.Model/Querying/QueryResult.cs7
-rw-r--r--MediaBrowser.Model/Search/SearchHint.cs4
-rw-r--r--MediaBrowser.Providers/Books/AudioBookMetadataService.cs25
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs3
-rw-r--r--MediaBrowser.Providers/Manager/ProviderUtils.cs46
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj5
-rw-r--r--MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/Movies/MovieExternalIds.cs79
-rw-r--r--MediaBrowser.Providers/Music/AlbumMetadataService.cs42
-rw-r--r--MediaBrowser.Providers/Music/AudioMetadataService.cs18
-rw-r--r--MediaBrowser.Providers/Music/MusicVideoMetadataService.cs25
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs10
-rw-r--r--MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetExternalId.cs25
-rw-r--r--MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs (renamed from MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs)55
-rw-r--r--MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetProvider.cs (renamed from MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs)120
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Collections/CollectionImages.cs11
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Collections/CollectionResult.cs15
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Collections/Part.cs11
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Backdrop.cs13
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Crew.cs12
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/ExternalIds.cs11
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Genre.cs8
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Images.cs10
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Keyword.cs8
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Keywords.cs9
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Poster.cs13
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Profile.cs11
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Still.cs14
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/StillImages.cs9
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Video.cs14
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/General/Videos.cs9
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/BelongsToCollection.cs10
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/Cast.cs12
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/Casts.cs11
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/Country.cs11
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/MovieResult.cs49
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/ProductionCompany.cs8
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/ProductionCountry.cs8
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/Releases.cs9
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/SpokenLanguage.cs8
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/Trailers.cs9
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Movies/Youtube.cs9
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/People/PersonImages.cs10
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/People/PersonResult.cs23
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Search/ExternalIdLookupResult.cs10
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Search/MovieResult.cs65
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Search/PersonSearchResult.cs29
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Search/TmdbSearchResult.cs31
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/Search/TvResult.cs15
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/Cast.cs12
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/ContentRating.cs8
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/ContentRatings.cs9
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/CreatedBy.cs9
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/Credits.cs11
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/Episode.cs14
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/EpisodeCredits.cs12
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/EpisodeResult.cs23
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/GuestStar.cs12
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/Network.cs8
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/Season.cs11
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/SeasonImages.cs10
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/SeasonResult.cs21
-rw-r--r--MediaBrowser.Providers/Tmdb/Models/TV/SeriesResult.cs40
-rw-r--r--MediaBrowser.Providers/Tmdb/Movies/GenericTmdbMovieInfo.cs (renamed from MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs)136
-rw-r--r--MediaBrowser.Providers/Tmdb/Movies/TmdbImageProvider.cs (renamed from MediaBrowser.Providers/Movies/MovieDbImageProvider.cs)61
-rw-r--r--MediaBrowser.Providers/Tmdb/Movies/TmdbMovieExternalId.cs32
-rw-r--r--MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs (renamed from MediaBrowser.Providers/Movies/MovieDbProvider.cs)262
-rw-r--r--MediaBrowser.Providers/Tmdb/Movies/TmdbSearch.cs (renamed from MediaBrowser.Providers/Movies/MovieDbSearch.cs)198
-rw-r--r--MediaBrowser.Providers/Tmdb/Movies/TmdbSettings.cs (renamed from MediaBrowser.Providers/Movies/TmdbSettings.cs)2
-rw-r--r--MediaBrowser.Providers/Tmdb/Music/TmdbMusicVideoProvider.cs (renamed from MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs)9
-rw-r--r--MediaBrowser.Providers/Tmdb/People/TmdbPersonExternalId.cs24
-rw-r--r--MediaBrowser.Providers/Tmdb/People/TmdbPersonImageProvider.cs (renamed from MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs)37
-rw-r--r--MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs (renamed from MediaBrowser.Providers/People/MovieDbPersonProvider.cs)188
-rw-r--r--MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs (renamed from MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs)33
-rw-r--r--MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProvider.cs (renamed from MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs)71
-rw-r--r--MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs (renamed from MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs)127
-rw-r--r--MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs (renamed from MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs)131
-rw-r--r--MediaBrowser.Providers/Tmdb/TV/TmdbSeriesExternalId.cs24
-rw-r--r--MediaBrowser.Providers/Tmdb/TV/TmdbSeriesImageProvider.cs (renamed from MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs)56
-rw-r--r--MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs (renamed from MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs)334
-rw-r--r--MediaBrowser.Providers/Tmdb/TmdbUtils.cs31
-rw-r--r--MediaBrowser.Providers/Tmdb/Trailers/TmdbTrailerProvider.cs (renamed from MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs)14
m---------MediaBrowser.WebDashboard/jellyfin-web0
-rw-r--r--MediaBrowser.XbmcMetadata/EntryPoint.cs16
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs39
-rw-r--r--MediaBrowser.sln8
-rw-r--r--SharedVersion.cs4
-rw-r--r--build.yaml2
-rwxr-xr-xbump_version8
-rw-r--r--deployment/debian-package-x64/pkg-src/changelog6
-rw-r--r--deployment/fedora-package-x64/pkg-src/jellyfin.spec8
172 files changed, 2605 insertions, 3274 deletions
diff --git a/Dockerfile b/Dockerfile
index f8e6fec31..ec64398b2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,5 @@
ARG DOTNET_VERSION=2.2
+ARG FFMPEG_VERSION=latest
FROM mcr.microsoft.com/dotnet/core/sdk:${DOTNET_VERSION} as builder
WORKDIR /repo
@@ -7,7 +8,7 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
RUN bash -c "source deployment/common.build.sh && \
build_jellyfin Jellyfin.Server Release linux-x64 /jellyfin"
-FROM jellyfin/ffmpeg as ffmpeg
+FROM jellyfin/ffmpeg:${FFMPEG_VERSION} as ffmpeg
FROM mcr.microsoft.com/dotnet/core/runtime:${DOTNET_VERSION}
# libfontconfig1 is required for Skia
RUN apt-get update \
@@ -21,7 +22,7 @@ RUN apt-get update \
COPY --from=ffmpeg / /
COPY --from=builder /jellyfin /jellyfin
-ARG JELLYFIN_WEB_VERSION=v10.3.7
+ARG JELLYFIN_WEB_VERSION=v10.4.0
RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
&& rm -rf /jellyfin/jellyfin-web \
&& mv jellyfin-web-* /jellyfin/jellyfin-web
diff --git a/Dockerfile.arm b/Dockerfile.arm
index 651bdeff4..2b1c6bb62 100644
--- a/Dockerfile.arm
+++ b/Dockerfile.arm
@@ -26,7 +26,7 @@ RUN apt-get update \
&& chmod 777 /cache /config /media
COPY --from=builder /jellyfin /jellyfin
-ARG JELLYFIN_WEB_VERSION=v10.3.7
+ARG JELLYFIN_WEB_VERSION=v10.4.0
RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
&& rm -rf /jellyfin/jellyfin-web \
&& mv jellyfin-web-* /jellyfin/jellyfin-web
diff --git a/Dockerfile.arm64 b/Dockerfile.arm64
index f6bd81e4c..5ebc82ebc 100644
--- a/Dockerfile.arm64
+++ b/Dockerfile.arm64
@@ -26,7 +26,7 @@ RUN apt-get update \
&& chmod 777 /cache /config /media
COPY --from=builder /jellyfin /jellyfin
-ARG JELLYFIN_WEB_VERSION=v10.3.7
+ARG JELLYFIN_WEB_VERSION=v10.4.0
RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
&& rm -rf /jellyfin/jellyfin-web \
&& mv jellyfin-web-* /jellyfin/jellyfin-web
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs
index 4f8c89e48..d22fc2177 100644
--- a/Emby.Dlna/ContentDirectory/ControlHandler.cs
+++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs
@@ -289,7 +289,7 @@ namespace Emby.Dlna.ContentDirectory
var childrenResult = GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount);
totalCount = childrenResult.TotalRecordCount;
- provided = childrenResult.Items.Length;
+ provided = childrenResult.Items.Count;
foreach (var i in childrenResult.Items)
{
@@ -309,6 +309,7 @@ namespace Emby.Dlna.ContentDirectory
}
}
}
+
writer.WriteFullEndElement();
//writer.WriteEndDocument();
}
@@ -386,7 +387,7 @@ namespace Emby.Dlna.ContentDirectory
totalCount = childrenResult.TotalRecordCount;
- provided = childrenResult.Items.Length;
+ provided = childrenResult.Items.Count;
var dlnaOptions = _config.GetDlnaConfiguration();
@@ -677,7 +678,7 @@ namespace Emby.Dlna.ContentDirectory
return new QueryResult<ServerItem>
{
- Items = list.ToArray(),
+ Items = list,
TotalRecordCount = list.Count
};
}
@@ -755,7 +756,7 @@ namespace Emby.Dlna.ContentDirectory
return new QueryResult<ServerItem>
{
- Items = list.ToArray(),
+ Items = list,
TotalRecordCount = list.Count
};
}
@@ -860,7 +861,7 @@ namespace Emby.Dlna.ContentDirectory
return new QueryResult<ServerItem>
{
- Items = list.ToArray(),
+ Items = list,
TotalRecordCount = list.Count
};
}
diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs
index 26adfde83..85ef9d482 100644
--- a/Emby.Dlna/Didl/DidlBuilder.cs
+++ b/Emby.Dlna/Didl/DidlBuilder.cs
@@ -158,7 +158,7 @@ namespace Emby.Dlna.Didl
AddGeneralProperties(item, null, context, writer, filter);
- AddSamsungBookmarkInfo(item, user, writer);
+ AddSamsungBookmarkInfo(item, user, writer, streamInfo);
// refID?
// storeAttribute(itemNode, object, ClassProperties.REF_ID, false);
@@ -581,7 +581,7 @@ namespace Emby.Dlna.Didl
writer.WriteFullEndElement();
}
- private void AddSamsungBookmarkInfo(BaseItem item, User user, XmlWriter writer)
+ private void AddSamsungBookmarkInfo(BaseItem item, User user, XmlWriter writer, StreamInfo streamInfo)
{
if (!item.SupportsPositionTicksResume || item is Folder)
{
@@ -605,10 +605,11 @@ namespace Emby.Dlna.Didl
}
var userdata = _userDataManager.GetUserData(user, item);
+ var playbackPositionTicks = (streamInfo != null && streamInfo.StartPositionTicks > 0) ? streamInfo.StartPositionTicks : userdata.PlaybackPositionTicks;
- if (userdata.PlaybackPositionTicks > 0)
+ if (playbackPositionTicks > 0)
{
- var elementValue = string.Format("BM={0}", Convert.ToInt32(TimeSpan.FromTicks(userdata.PlaybackPositionTicks).TotalSeconds).ToString(_usCulture));
+ var elementValue = string.Format("BM={0}", Convert.ToInt32(TimeSpan.FromTicks(playbackPositionTicks).TotalSeconds).ToString(_usCulture));
AddValue(writer, "sec", "dcmInfo", elementValue, secAttribute.Value);
}
}
diff --git a/Emby.IsoMounting/.gitignore b/Emby.IsoMounting/.gitignore
deleted file mode 100644
index bdc3535f7..000000000
--- a/Emby.IsoMounting/.gitignore
+++ /dev/null
@@ -1,108 +0,0 @@
-# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
-[Bb]in/
-[Oo]bj/
-
-# mstest test results
-TestResults
-
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# User-specific files
-*.suo
-*.user
-*.sln.docstates
-
-# Build results
-[Dd]ebug/
-[Rr]elease/
-x64/
-*_i.c
-*_p.c
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.log
-*.vspscc
-*.vssscc
-.builds
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opensdf
-*.sdf
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*
-
-# NCrunch
-*.ncrunch*
-.*crunch*.local.xml
-
-# Installshield output folder
-[Ee]xpress
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish
-
-# Publish Web Output
-*.Publish.xml
-
-# NuGet Packages Directory
-packages
-
-# Windows Azure Build Output
-csx
-*.build.csdef
-
-# Windows Store app package directory
-AppPackages/
-
-# Others
-[Bb]in
-[Oo]bj
-sql
-TestResults
-[Tt]est[Rr]esult*
-*.Cache
-ClientBin
-[Ss]tyle[Cc]op.*
-~$*
-*.dbmdl
-Generated_Code #added for RIA/Silverlight projects
-
-# Backup & report files from converting an old project file to a newer
-# Visual Studio version. Backup files are not needed, because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
diff --git a/Emby.IsoMounting/IsoMounter.sln b/Emby.IsoMounting/IsoMounter.sln
deleted file mode 100644
index 55db1b1ae..000000000
--- a/Emby.IsoMounting/IsoMounter.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27004.2009
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IsoMounter", "IsoMounter\IsoMounter.csproj", "{B94C929C-6552-4620-9BE5-422DD9A151BA}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {B94C929C-6552-4620-9BE5-422DD9A151BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B94C929C-6552-4620-9BE5-422DD9A151BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B94C929C-6552-4620-9BE5-422DD9A151BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B94C929C-6552-4620-9BE5-422DD9A151BA}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {C0E8EAD1-E4D7-44CD-B801-03BD12F30B1B}
- EndGlobalSection
-EndGlobal
diff --git a/Emby.IsoMounting/IsoMounter/Configuration/PluginConfiguration.cs b/Emby.IsoMounting/IsoMounter/Configuration/PluginConfiguration.cs
deleted file mode 100644
index ca6f40cc4..000000000
--- a/Emby.IsoMounting/IsoMounter/Configuration/PluginConfiguration.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using MediaBrowser.Model.Plugins;
-
-namespace IsoMounter.Configuration
-{
- /// <summary>
- /// Class PluginConfiguration.
- /// </summary>
- public class PluginConfiguration : BasePluginConfiguration
- {
- }
-}
diff --git a/Emby.IsoMounting/IsoMounter/IsoMounter.csproj b/Emby.IsoMounting/IsoMounter/IsoMounter.csproj
deleted file mode 100644
index 4fa07fbf1..000000000
--- a/Emby.IsoMounting/IsoMounter/IsoMounter.csproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
- <ItemGroup>
- <Compile Include="..\..\SharedVersion.cs" />
- </ItemGroup>
-
- <ItemGroup>
- <ProjectReference Include="..\..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
- <ProjectReference Include="..\..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
- </ItemGroup>
-
- <PropertyGroup>
- <TargetFramework>netstandard2.0</TargetFramework>
- <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
- <GenerateDocumentationFile>true</GenerateDocumentationFile>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- </PropertyGroup>
-
- <!-- Code analysers-->
- <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
- <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.4" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
- <PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
- </ItemGroup>
-
- <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
- <CodeAnalysisRuleSet>../../jellyfin.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
-
-</Project>
diff --git a/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs b/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs
deleted file mode 100644
index 48cb2e1d5..000000000
--- a/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs
+++ /dev/null
@@ -1,298 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.System;
-using Microsoft.Extensions.Logging;
-using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
-
-namespace IsoMounter
-{
- /// <summary>
- /// The ISO manager implementation for Linux.
- /// </summary>
- public class LinuxIsoManager : IIsoMounter
- {
- private const string MountCommand = "mount";
- private const string UnmountCommand = "umount";
- private const string SudoCommand = "sudo";
-
- private readonly ILogger _logger;
- private readonly string _mountPointRoot;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="LinuxIsoManager" /> class.
- /// </summary>
- /// <param name="logger">The logger.</param>
- public LinuxIsoManager(ILogger logger)
- {
- _logger = logger;
-
- _mountPointRoot = Path.DirectorySeparatorChar + "tmp" + Path.DirectorySeparatorChar + "Emby";
-
- _logger.LogDebug(
- "[{0}] System PATH is currently set to [{1}].",
- Name,
- Environment.GetEnvironmentVariable("PATH") ?? string.Empty);
-
- _logger.LogDebug(
- "[{0}] System path separator is [{1}].",
- Name,
- Path.PathSeparator);
-
- _logger.LogDebug(
- "[{0}] Mount point root is [{1}].",
- Name,
- _mountPointRoot);
- }
-
- /// <inheritdoc />
- public string Name => "LinuxMount";
-
-#pragma warning disable SA1300
-#pragma warning disable SA1400
- [DllImport("libc", SetLastError = true)]
- static extern uint getuid();
-
-#pragma warning restore SA1300
-#pragma warning restore SA1400
-
- /// <inheritdoc />
- public bool CanMount(string path)
- {
- if (OperatingSystem.Id != OperatingSystemId.Linux)
- {
- return false;
- }
-
- _logger.LogInformation(
- "[{0}] Checking we can attempt to mount [{1}], Extension = [{2}], Operating System = [{3}].",
- Name,
- path,
- Path.GetExtension(path),
- OperatingSystem.Name);
-
- return string.Equals(Path.GetExtension(path), ".iso", StringComparison.OrdinalIgnoreCase);
- }
-
- /// <inheritdoc />
- public Task<IIsoMount> Mount(string isoPath, CancellationToken cancellationToken)
- {
- string cmdArguments;
- string cmdFilename;
- string mountPoint = Path.Combine(_mountPointRoot, Guid.NewGuid().ToString());
-
- if (string.IsNullOrEmpty(isoPath))
- {
- throw new ArgumentNullException(nameof(isoPath));
- }
-
- _logger.LogInformation(
- "[{Name}] Attempting to mount [{Path}].",
- Name,
- isoPath);
-
- _logger.LogDebug(
- "[{Name}] ISO will be mounted at [{Path}].",
- Name,
- mountPoint);
-
- try
- {
- Directory.CreateDirectory(mountPoint);
- }
- catch (UnauthorizedAccessException ex)
- {
- throw new IOException("Unable to create mount point(Permission denied) for " + isoPath, ex);
- }
- catch (Exception ex)
- {
- throw new IOException("Unable to create mount point for " + isoPath, ex);
- }
-
- if (GetUID() == 0)
- {
- cmdFilename = MountCommand;
- cmdArguments = string.Format(
- CultureInfo.InvariantCulture,
- "\"{0}\" \"{1}\"",
- isoPath,
- mountPoint);
- }
- else
- {
- cmdFilename = SudoCommand;
- cmdArguments = string.Format(
- CultureInfo.InvariantCulture,
- "\"{0}\" \"{1}\" \"{2}\"",
- MountCommand,
- isoPath,
- mountPoint);
- }
-
- _logger.LogDebug(
- "[{0}] Mount command [{1}], mount arguments [{2}].",
- Name,
- cmdFilename,
- cmdArguments);
-
- int exitcode = ExecuteCommand(cmdFilename, cmdArguments);
- if (exitcode == 0)
- {
- _logger.LogInformation(
- "[{0}] ISO mount completed successfully.",
- Name);
-
- return Task.FromResult<IIsoMount>(new LinuxMount(this, isoPath, mountPoint));
- }
-
- _logger.LogInformation(
- "[{0}] ISO mount completed with errors.",
- Name);
-
- try
- {
- Directory.Delete(mountPoint, false);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "[{Name}] Unhandled exception removing mount point.", Name);
- throw;
- }
-
- throw new ExternalException("Mount command failed", exitcode);
- }
-
- private uint GetUID()
- {
- var uid = getuid();
-
- _logger.LogDebug(
- "[{0}] GetUserId() returned [{2}].",
- Name,
- uid);
-
- return uid;
- }
-
- private int ExecuteCommand(string cmdFilename, string cmdArguments)
- {
- var startInfo = new ProcessStartInfo
- {
- FileName = cmdFilename,
- Arguments = cmdArguments,
- UseShellExecute = false,
- CreateNoWindow = true,
- ErrorDialog = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true
- };
-
- var process = new Process()
- {
- StartInfo = startInfo
- };
-
- try
- {
- process.Start();
-
- _logger.LogDebug(
- "[{Name}] Standard output from process is [{Error}].",
- Name,
- process.StandardOutput.ReadToEnd());
-
- _logger.LogDebug(
- "[{Name}] Standard error from process is [{Error}].",
- Name,
- process.StandardError.ReadToEnd());
-
- return process.ExitCode;
- }
- catch (Exception ex)
- {
- _logger.LogDebug(ex, "[{Name}] Unhandled exception executing command.", Name);
- throw;
- }
- finally
- {
- process?.Dispose();
- }
- }
-
- /// <summary>
- /// Unmounts the specified mount.
- /// </summary>
- /// <param name="mount">The mount.</param>
- internal void OnUnmount(LinuxMount mount)
- {
- if (mount == null)
- {
- throw new ArgumentNullException(nameof(mount));
- }
-
- _logger.LogInformation(
- "[{0}] Attempting to unmount ISO [{1}] mounted on [{2}].",
- Name,
- mount.IsoPath,
- mount.MountedPath);
-
- string cmdArguments;
- string cmdFilename;
-
- if (GetUID() == 0)
- {
- cmdFilename = UnmountCommand;
- cmdArguments = string.Format(
- CultureInfo.InvariantCulture,
- "\"{0}\"",
- mount.MountedPath);
- }
- else
- {
- cmdFilename = SudoCommand;
- cmdArguments = string.Format(
- CultureInfo.InvariantCulture,
- "\"{0}\" \"{1}\"",
- UnmountCommand,
- mount.MountedPath);
- }
-
- _logger.LogDebug(
- "[{0}] Umount command [{1}], umount arguments [{2}].",
- Name,
- cmdFilename,
- cmdArguments);
-
- int exitcode = ExecuteCommand(cmdFilename, cmdArguments);
- if (exitcode == 0)
- {
- _logger.LogInformation(
- "[{0}] ISO unmount completed successfully.",
- Name);
- }
- else
- {
- _logger.LogInformation(
- "[{0}] ISO unmount completed with errors.",
- Name);
- }
-
- try
- {
- Directory.Delete(mount.MountedPath, false);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "[{Name}] Unhandled exception removing mount point.", Name);
- throw;
- }
-
- throw new ExternalException("Mount command failed", exitcode);
- }
- }
-}
diff --git a/Emby.IsoMounting/IsoMounter/LinuxMount.cs b/Emby.IsoMounting/IsoMounter/LinuxMount.cs
deleted file mode 100644
index ccad8ce20..000000000
--- a/Emby.IsoMounting/IsoMounter/LinuxMount.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using System;
-using MediaBrowser.Model.IO;
-
-namespace IsoMounter
-{
- /// <summary>
- /// Class LinuxMount.
- /// </summary>
- internal class LinuxMount : IIsoMount
- {
- private readonly LinuxIsoManager _linuxIsoManager;
-
- private bool _disposed = false;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="LinuxMount" /> class.
- /// </summary>
- /// <param name="isoManager">The ISO manager that mounted this ISO file.</param>
- /// <param name="isoPath">The path to the ISO file.</param>
- /// <param name="mountFolder">The folder the ISO is mounted in.</param>
- internal LinuxMount(LinuxIsoManager isoManager, string isoPath, string mountFolder)
- {
- _linuxIsoManager = isoManager;
-
- IsoPath = isoPath;
- MountedPath = mountFolder;
- }
-
- /// <inheritdoc />
- public string IsoPath { get; }
-
- /// <inheritdoc />
- public string MountedPath { get; }
-
- /// <inheritdoc />
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Releases the unmanaged resources and disposes of the managed resources used.
- /// </summary>
- /// <param name="disposing">Whether or not the managed resources should be disposed.</param>
- protected virtual void Dispose(bool disposing)
- {
- if (_disposed)
- {
- return;
- }
-
- _linuxIsoManager.OnUnmount(this);
-
- _disposed = true;
- }
- }
-}
diff --git a/Emby.IsoMounting/IsoMounter/Plugin.cs b/Emby.IsoMounting/IsoMounter/Plugin.cs
deleted file mode 100644
index 433294d74..000000000
--- a/Emby.IsoMounting/IsoMounter/Plugin.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using IsoMounter.Configuration;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Plugins;
-using MediaBrowser.Model.Serialization;
-
-namespace IsoMounter
-{
- /// <summary>
- /// The LinuxMount plugin class.
- /// </summary>
- public class Plugin : BasePlugin<PluginConfiguration>
- {
- /// <summary>
- /// Initializes a new instance of the <see cref="Plugin" /> class.
- /// </summary>
- /// <param name="applicationPaths">The application paths.</param>
- /// <param name="xmlSerializer">The XML serializer.</param>
- public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
- : base(applicationPaths, xmlSerializer)
- {
- }
-
- /// <inheritdoc />
- public override Guid Id { get; } = new Guid("4682DD4C-A675-4F1B-8E7C-79ADF137A8F8");
-
- /// <inheritdoc />
- public override string Name => "Iso Mounter";
-
- /// <inheritdoc />
- public override string Description => "Mount and stream ISO contents";
- }
-}
diff --git a/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs b/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs
deleted file mode 100644
index 5956fc3b3..000000000
--- a/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Reflection;
-using System.Resources;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("IsoMounter")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Jellyfin Project")]
-[assembly: AssemblyProduct("Jellyfin Server")]
-[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: NeutralResourcesLanguage("en")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
diff --git a/Emby.IsoMounting/LICENSE b/Emby.IsoMounting/LICENSE
deleted file mode 100644
index d7f105139..000000000
--- a/Emby.IsoMounting/LICENSE
+++ /dev/null
@@ -1,339 +0,0 @@
-GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- {description}
- Copyright (C) {year} {fullname}
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- {signature of Ty Coon}, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/Emby.IsoMounting/README.md b/Emby.IsoMounting/README.md
deleted file mode 100644
index 78bab9936..000000000
--- a/Emby.IsoMounting/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# MediaBrowser.IsoMounting.Linux
-This implements two core interfaces, IIsoManager, and IIsoMount.
-### IIsoManager
-The manager class can be used to create a mount, and also determine if the mounter is capable of mounting a given file.
-### IIsoMount
-IIsoMount then represents a mount instance, which will be unmounted on disposal.
-***
-This Linux version use sudo, mount and umount.
-
-You need to add this to your sudo file via visudo(change the username):
-
- Defaults:jsmith !requiretty
- jsmith ALL=(root) NOPASSWD: /bin/mount
- jsmith ALL=(root) NOPASSWD: /bin/umount
diff --git a/Emby.Notifications/Notifications.cs b/Emby.Notifications/Notifications.cs
index ec08fd193..7aa1e7ae8 100644
--- a/Emby.Notifications/Notifications.cs
+++ b/Emby.Notifications/Notifications.cs
@@ -209,47 +209,48 @@ namespace Emby.Notifications
public static string GetItemName(BaseItem item)
{
var name = item.Name;
- var episode = item as Episode;
- if (episode != null)
+ if (item is Episode episode)
{
if (episode.IndexNumber.HasValue)
{
- name = string.Format("Ep{0} - {1}", episode.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), name);
+ name = string.Format(
+ CultureInfo.InvariantCulture,
+ "Ep{0} - {1}",
+ episode.IndexNumber.Value,
+ name);
}
if (episode.ParentIndexNumber.HasValue)
{
- name = string.Format("S{0}, {1}", episode.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture), name);
+ name = string.Format(
+ CultureInfo.InvariantCulture,
+ "S{0}, {1}",
+ episode.ParentIndexNumber.Value,
+ name);
}
}
- var hasSeries = item as IHasSeries;
- if (hasSeries != null)
+ if (item is IHasSeries hasSeries)
{
name = hasSeries.SeriesName + " - " + name;
}
- var hasAlbumArtist = item as IHasAlbumArtist;
- if (hasAlbumArtist != null)
+ if (item is IHasAlbumArtist hasAlbumArtist)
{
var artists = hasAlbumArtist.AlbumArtists;
- if (artists.Length > 0)
+ if (artists.Count > 0)
{
name = artists[0] + " - " + name;
}
}
- else
+ else if (item is IHasArtist hasArtist)
{
- var hasArtist = item as IHasArtist;
- if (hasArtist != null)
- {
- var artists = hasArtist.Artists;
+ var artists = hasArtist.Artists;
- if (artists.Length > 0)
- {
- name = artists[0] + " - " + name;
- }
+ if (artists.Count > 0)
+ {
+ name = artists[0] + " - " + name;
}
}
diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs
index 99a635e60..1591609ab 100644
--- a/Emby.Photos/PhotoProvider.cs
+++ b/Emby.Photos/PhotoProvider.cs
@@ -170,8 +170,8 @@ namespace Emby.Photos
}
}
- const ItemUpdateType result = ItemUpdateType.ImageUpdate | ItemUpdateType.MetadataImport;
- return Task.FromResult(result);
+ const ItemUpdateType Result = ItemUpdateType.ImageUpdate | ItemUpdateType.MetadataImport;
+ return Task.FromResult(Result);
}
}
}
diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
index fb4ffd74b..1514402d6 100644
--- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
+++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
@@ -96,7 +96,10 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("CameraImageUploadedFrom"), e.Argument.Device.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("CameraImageUploadedFrom"),
+ e.Argument.Device.Name),
Type = NotificationType.CameraImageUploaded.ToString()
});
}
@@ -105,7 +108,10 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("UserLockedOutWithName"), e.Argument.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("UserLockedOutWithName"),
+ e.Argument.Name),
Type = NotificationType.UserLockedOut.ToString(),
UserId = e.Argument.Id
});
@@ -115,7 +121,11 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"), e.Provider, Notifications.Notifications.GetItemName(e.Item)),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"),
+ e.Provider,
+ Notifications.Notifications.GetItemName(e.Item)),
Type = "SubtitleDownloadFailure",
ItemId = e.Item.Id.ToString("N", CultureInfo.InvariantCulture),
ShortOverview = e.Exception.Message
@@ -178,7 +188,12 @@ namespace Emby.Server.Implementations.Activity
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), user.Name, GetItemName(item), e.DeviceName),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("UserStartedPlayingItemWithValues"),
+ user.Name,
+ GetItemName(item),
+ e.DeviceName),
Type = GetPlaybackNotificationType(item.MediaType),
UserId = user.Id
});
@@ -193,7 +208,7 @@ namespace Emby.Server.Implementations.Activity
name = item.SeriesName + " - " + name;
}
- if (item.Artists != null && item.Artists.Length > 0)
+ if (item.Artists != null && item.Artists.Count > 0)
{
name = item.Artists[0] + " - " + name;
}
@@ -238,21 +253,31 @@ namespace Emby.Server.Implementations.Activity
if (string.IsNullOrEmpty(session.UserName))
{
- name = string.Format(_localization.GetLocalizedString("DeviceOfflineWithName"), session.DeviceName);
+ name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("DeviceOfflineWithName"),
+ session.DeviceName);
// Causing too much spam for now
return;
}
else
{
- name = string.Format(_localization.GetLocalizedString("UserOfflineFromDevice"), session.UserName, session.DeviceName);
+ name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("UserOfflineFromDevice"),
+ session.UserName,
+ session.DeviceName);
}
CreateLogEntry(new ActivityLogEntry
{
Name = name,
Type = "SessionEnded",
- ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint),
+ ShortOverview = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("LabelIpAddressValue"),
+ session.RemoteEndPoint),
UserId = session.UserId
});
}
@@ -263,9 +288,15 @@ namespace Emby.Server.Implementations.Activity
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("AuthenticationSucceededWithUserName"), user.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("AuthenticationSucceededWithUserName"),
+ user.Name),
Type = "AuthenticationSucceeded",
- ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), e.Argument.SessionInfo.RemoteEndPoint),
+ ShortOverview = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("LabelIpAddressValue"),
+ e.Argument.SessionInfo.RemoteEndPoint),
UserId = user.Id
});
}
@@ -274,9 +305,15 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("FailedLoginAttemptWithUserName"), e.Argument.Username),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("FailedLoginAttemptWithUserName"),
+ e.Argument.Username),
Type = "AuthenticationFailed",
- ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), e.Argument.RemoteEndPoint),
+ ShortOverview = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("LabelIpAddressValue"),
+ e.Argument.RemoteEndPoint),
Severity = LogLevel.Error
});
}
@@ -285,7 +322,10 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("UserPolicyUpdatedWithName"), e.Argument.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("UserPolicyUpdatedWithName"),
+ e.Argument.Name),
Type = "UserPolicyUpdated",
UserId = e.Argument.Id
});
@@ -295,7 +335,10 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("UserDeletedWithName"), e.Argument.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("UserDeletedWithName"),
+ e.Argument.Name),
Type = "UserDeleted"
});
}
@@ -304,7 +347,10 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("UserPasswordChangedWithName"), e.Argument.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("UserPasswordChangedWithName"),
+ e.Argument.Name),
Type = "UserPasswordChanged",
UserId = e.Argument.Id
});
@@ -314,7 +360,10 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("UserCreatedWithName"), e.Argument.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("UserCreatedWithName"),
+ e.Argument.Name),
Type = "UserCreated",
UserId = e.Argument.Id
});
@@ -327,21 +376,31 @@ namespace Emby.Server.Implementations.Activity
if (string.IsNullOrEmpty(session.UserName))
{
- name = string.Format(_localization.GetLocalizedString("DeviceOnlineWithName"), session.DeviceName);
+ name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("DeviceOnlineWithName"),
+ session.DeviceName);
// Causing too much spam for now
return;
}
else
{
- name = string.Format(_localization.GetLocalizedString("UserOnlineFromDevice"), session.UserName, session.DeviceName);
+ name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("UserOnlineFromDevice"),
+ session.UserName,
+ session.DeviceName);
}
CreateLogEntry(new ActivityLogEntry
{
Name = name,
Type = "SessionStarted",
- ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint),
+ ShortOverview = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("LabelIpAddressValue"),
+ session.RemoteEndPoint),
UserId = session.UserId
});
}
@@ -350,9 +409,15 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("PluginUpdatedWithName"), e.Argument.Item1.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("PluginUpdatedWithName"),
+ e.Argument.Item1.Name),
Type = NotificationType.PluginUpdateInstalled.ToString(),
- ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.Item2.versionStr),
+ ShortOverview = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("VersionNumber"),
+ e.Argument.Item2.versionStr),
Overview = e.Argument.Item2.description
});
}
@@ -361,7 +426,10 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("PluginUninstalledWithName"), e.Argument.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("PluginUninstalledWithName"),
+ e.Argument.Name),
Type = NotificationType.PluginUninstalled.ToString()
});
}
@@ -370,9 +438,15 @@ namespace Emby.Server.Implementations.Activity
{
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("PluginInstalledWithName"), e.Argument.name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("PluginInstalledWithName"),
+ e.Argument.name),
Type = NotificationType.PluginInstalled.ToString(),
- ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.versionStr)
+ ShortOverview = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("VersionNumber"),
+ e.Argument.versionStr)
});
}
@@ -382,9 +456,15 @@ namespace Emby.Server.Implementations.Activity
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("NameInstallFailed"), installationInfo.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("NameInstallFailed"),
+ installationInfo.Name),
Type = NotificationType.InstallationFailed.ToString(),
- ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), installationInfo.Version),
+ ShortOverview = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("VersionNumber"),
+ installationInfo.Version),
Overview = e.Exception.Message
});
}
@@ -401,7 +481,10 @@ namespace Emby.Server.Implementations.Activity
}
var time = result.EndTimeUtc - result.StartTimeUtc;
- var runningTime = string.Format(_localization.GetLocalizedString("LabelRunningTimeValue"), ToUserFriendlyString(time));
+ var runningTime = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("LabelRunningTimeValue"),
+ ToUserFriendlyString(time));
if (result.Status == TaskCompletionStatus.Failed)
{
@@ -419,7 +502,10 @@ namespace Emby.Server.Implementations.Activity
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("ScheduledTaskFailedWithName"),
+ task.Name),
Type = NotificationType.TaskFailed.ToString(),
Overview = string.Join(Environment.NewLine, vals),
ShortOverview = runningTime,
@@ -534,8 +620,11 @@ namespace Emby.Server.Implementations.Activity
/// <param name="description">The name of this item (singular form)</param>
private static string CreateValueString(int value, string description)
{
- return string.Format("{0:#,##0} {1}",
- value, value == 1 ? description : string.Format("{0}s", description));
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0:#,##0} {1}",
+ value,
+ value == 1 ? description : string.Format(CultureInfo.InvariantCulture, "{0}s", description));
}
}
}
diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs
index 541b23afd..ffaeaa541 100644
--- a/Emby.Server.Implementations/Activity/ActivityRepository.cs
+++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs
@@ -247,7 +247,7 @@ namespace Emby.Server.Implementations.Activity
ReadTransactionMode);
}
- result.Items = list.ToArray();
+ result.Items = list;
return result;
}
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 6ab3d1bb1..24f59478c 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -202,10 +202,10 @@ namespace Emby.Server.Implementations
/// Gets or sets all concrete types.
/// </summary>
/// <value>All concrete types.</value>
- public Type[] AllConcreteTypes { get; protected set; }
+ private Type[] _allConcreteTypes;
/// <summary>
- /// The disposable parts
+ /// The disposable parts.
/// </summary>
private readonly List<IDisposable> _disposableParts = new List<IDisposable>();
@@ -499,7 +499,7 @@ namespace Emby.Server.Implementations
{
var currentType = typeof(T);
- return AllConcreteTypes.Where(i => currentType.IsAssignableFrom(i));
+ return _allConcreteTypes.Where(i => currentType.IsAssignableFrom(i));
}
/// <inheritdoc />
@@ -1010,9 +1010,11 @@ namespace Emby.Server.Implementations
.Select(x => Assembly.LoadFrom(x))
.SelectMany(x => x.ExportedTypes)
.Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface && !x.IsGenericType)
- .ToList();
+ .ToArray();
- types.AddRange(types);
+ int oldLen = _allConcreteTypes.Length;
+ Array.Resize(ref _allConcreteTypes, oldLen + types.Length);
+ types.CopyTo(_allConcreteTypes, oldLen);
var plugins = types.Where(x => x.IsAssignableFrom(typeof(IPlugin)))
.Select(CreateInstanceSafe)
@@ -1022,8 +1024,8 @@ namespace Emby.Server.Implementations
.Where(x => x != null)
.ToArray();
- int oldLen = _plugins.Length;
- Array.Resize<IPlugin>(ref _plugins, _plugins.Length + plugins.Length);
+ oldLen = _plugins.Length;
+ Array.Resize(ref _plugins, oldLen + plugins.Length);
plugins.CopyTo(_plugins, oldLen);
var entries = types.Where(x => x.IsAssignableFrom(typeof(IServerEntryPoint)))
@@ -1140,7 +1142,7 @@ namespace Emby.Server.Implementations
{
Logger.LogInformation("Loading assemblies");
- AllConcreteTypes = GetTypes(GetComposablePartAssemblies()).ToArray();
+ _allConcreteTypes = GetTypes(GetComposablePartAssemblies()).ToArray();
}
private IEnumerable<Type> GetTypes(IEnumerable<Assembly> assemblies)
diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs
index c4fa68cac..c7f92b80b 100644
--- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs
+++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs
@@ -66,7 +66,7 @@ namespace Emby.Server.Implementations.Configuration
{
base.AddParts(factories);
- UpdateTranscodingTempPath();
+ UpdateTranscodePath();
}
/// <summary>
@@ -87,13 +87,13 @@ namespace Emby.Server.Implementations.Configuration
/// <summary>
/// Updates the transcoding temporary path.
/// </summary>
- private void UpdateTranscodingTempPath()
+ private void UpdateTranscodePath()
{
var encodingConfig = this.GetConfiguration<EncodingOptions>("encoding");
((ServerApplicationPaths)ApplicationPaths).TranscodingTempPath = string.IsNullOrEmpty(encodingConfig.TranscodingTempPath) ?
null :
- Path.Combine(encodingConfig.TranscodingTempPath, "transcoding-temp");
+ Path.Combine(encodingConfig.TranscodingTempPath, "transcodes");
}
protected override void OnNamedConfigurationUpdated(string key, object configuration)
@@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Configuration
if (string.Equals(key, "encoding", StringComparison.OrdinalIgnoreCase))
{
- UpdateTranscodingTempPath();
+ UpdateTranscodePath();
}
}
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index 9d983307f..2f083dda4 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -979,7 +979,7 @@ namespace Emby.Server.Implementations.Data
}
string artists = null;
- if (item is IHasArtist hasArtists && hasArtists.Artists.Length > 0)
+ if (item is IHasArtist hasArtists && hasArtists.Artists.Count > 0)
{
artists = string.Join("|", hasArtists.Artists);
}
@@ -987,7 +987,7 @@ namespace Emby.Server.Implementations.Data
string albumArtists = null;
if (item is IHasAlbumArtist hasAlbumArtists
- && hasAlbumArtists.AlbumArtists.Length > 0)
+ && hasAlbumArtists.AlbumArtists.Count > 0)
{
albumArtists = string.Join("|", hasAlbumArtists.AlbumArtists);
}
@@ -2746,7 +2746,7 @@ namespace Emby.Server.Implementations.Data
var returnList = GetItemList(query);
return new QueryResult<BaseItem>
{
- Items = returnList.ToArray(),
+ Items = returnList,
TotalRecordCount = returnList.Count
};
}
@@ -2883,7 +2883,7 @@ namespace Emby.Server.Implementations.Data
}
LogQueryTime("GetItems", commandText, now);
- result.Items = list.ToArray();
+ result.Items = list;
return result;
}
@@ -3161,7 +3161,7 @@ namespace Emby.Server.Implementations.Data
var returnList = GetItemIdsList(query);
return new QueryResult<Guid>
{
- Items = returnList.ToArray(),
+ Items = returnList,
TotalRecordCount = returnList.Count
};
}
@@ -3281,7 +3281,7 @@ namespace Emby.Server.Implementations.Data
LogQueryTime("GetItemIds", commandText, now);
- result.Items = list.ToArray();
+ result.Items = list;
return result;
}
@@ -5520,7 +5520,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
result.TotalRecordCount = list.Count;
}
- result.Items = list.ToArray();
+ result.Items = list;
return result;
}
@@ -5731,7 +5731,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
{
if (isSubsequentRow)
{
- insertText.Append(",");
+ insertText.Append(',');
}
insertText.AppendFormat("(@ItemId, @Name{0}, @Role{0}, @PersonType{0}, @SortOrder{0}, @ListOrder{0})", i.ToString(CultureInfo.InvariantCulture));
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index 1a7f10634..75192a8f1 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -80,27 +80,25 @@ namespace Emby.Server.Implementations.Dto
return GetBaseItemDto(item, options, user, owner);
}
- public BaseItemDto[] GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
- => GetBaseItemDtos(items, items.Count, options, user, owner);
-
- public BaseItemDto[] GetBaseItemDtos(IEnumerable<BaseItem> items, int itemCount, DtoOptions options, User user = null, BaseItem owner = null)
+ /// <inheritdoc />
+ public IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
{
- var returnItems = new BaseItemDto[itemCount];
- var programTuples = new List<Tuple<BaseItem, BaseItemDto>>();
- var channelTuples = new List<Tuple<BaseItemDto, LiveTvChannel>>();
+ var returnItems = new BaseItemDto[items.Count];
+ var programTuples = new List<(BaseItem, BaseItemDto)>();
+ var channelTuples = new List<(BaseItemDto, LiveTvChannel)>();
- var index = 0;
- foreach (var item in items)
+ for (int index = 0; index < items.Count; index++)
{
+ var item = items[index];
var dto = GetBaseItemDtoInternal(item, options, user, owner);
if (item is LiveTvChannel tvChannel)
{
- channelTuples.Add(new Tuple<BaseItemDto, LiveTvChannel>(dto, tvChannel));
+ channelTuples.Add((dto, tvChannel));
}
else if (item is LiveTvProgram)
{
- programTuples.Add(new Tuple<BaseItem, BaseItemDto>(item, dto));
+ programTuples.Add((item, dto));
}
if (item is IItemByName byName)
@@ -121,7 +119,6 @@ namespace Emby.Server.Implementations.Dto
}
returnItems[index] = dto;
- index++;
}
if (programTuples.Count > 0)
@@ -140,33 +137,32 @@ namespace Emby.Server.Implementations.Dto
public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
{
var dto = GetBaseItemDtoInternal(item, options, user, owner);
- var tvChannel = item as LiveTvChannel;
- if (tvChannel != null)
+ if (item is LiveTvChannel tvChannel)
{
- var list = new List<Tuple<BaseItemDto, LiveTvChannel>> { new Tuple<BaseItemDto, LiveTvChannel>(dto, tvChannel) };
+ var list = new List<(BaseItemDto, LiveTvChannel)>(1) { (dto, tvChannel) };
_livetvManager().AddChannelInfo(list, options, user);
}
else if (item is LiveTvProgram)
{
- var list = new List<Tuple<BaseItem, BaseItemDto>> { new Tuple<BaseItem, BaseItemDto>(item, dto) };
+ var list = new List<(BaseItem, BaseItemDto)>(1) { (item, dto) };
var task = _livetvManager().AddInfoToProgramDto(list, options.Fields, user);
Task.WaitAll(task);
}
- var byName = item as IItemByName;
-
- if (byName != null)
+ if (item is IItemByName itemByName
+ && options.ContainsField(ItemFields.ItemCounts))
{
- if (options.ContainsField(ItemFields.ItemCounts))
- {
- SetItemByNameInfo(item, dto, GetTaggedItems(byName, user, new DtoOptions(false)
- {
- EnableImages = false
-
- }), user);
- }
-
- return dto;
+ SetItemByNameInfo(
+ item,
+ dto,
+ GetTaggedItems(
+ itemByName,
+ user,
+ new DtoOptions(false)
+ {
+ EnableImages = false
+ }),
+ user);
}
return dto;
@@ -174,12 +170,12 @@ namespace Emby.Server.Implementations.Dto
private static IList<BaseItem> GetTaggedItems(IItemByName byName, User user, DtoOptions options)
{
- return byName.GetTaggedItems(new InternalItemsQuery(user)
- {
- Recursive = true,
- DtoOptions = options
-
- });
+ return byName.GetTaggedItems(
+ new InternalItemsQuery(user)
+ {
+ Recursive = true,
+ DtoOptions = options
+ });
}
private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
@@ -222,8 +218,7 @@ namespace Emby.Server.Implementations.Dto
AttachUserSpecificInfo(dto, item, user, options);
}
- var hasMediaSources = item as IHasMediaSources;
- if (hasMediaSources != null)
+ if (item is IHasMediaSources hasMediaSources)
{
if (options.ContainsField(ItemFields.MediaSources))
{
@@ -769,14 +764,12 @@ namespace Emby.Server.Implementations.Dto
dto.CriticRating = item.CriticRating;
- var hasDisplayOrder = item as IHasDisplayOrder;
- if (hasDisplayOrder != null)
+ if (item is IHasDisplayOrder hasDisplayOrder)
{
dto.DisplayOrder = hasDisplayOrder.DisplayOrder;
}
- var hasCollectionType = item as IHasCollectionType;
- if (hasCollectionType != null)
+ if (item is IHasCollectionType hasCollectionType)
{
dto.CollectionType = hasCollectionType.CollectionType;
}
@@ -886,8 +879,7 @@ namespace Emby.Server.Implementations.Dto
//}
}
- var hasArtist = item as IHasArtist;
- if (hasArtist != null)
+ if (item is IHasArtist hasArtist)
{
dto.Artists = hasArtist.Artists;
@@ -1074,17 +1066,24 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.LocalTrailerCount))
{
+ int trailerCount = 0;
if (allExtras == null)
{
allExtras = item.GetExtras().ToArray();
}
- dto.LocalTrailerCount = allExtras.Count(i => i.ExtraType.HasValue && i.ExtraType.Value == ExtraType.Trailer);
+ trailerCount += allExtras.Count(i => i.ExtraType.HasValue && i.ExtraType.Value == ExtraType.Trailer);
+
+ if (item is IHasTrailers hasTrailers)
+ {
+ trailerCount += hasTrailers.GetTrailerCount();
+ }
+
+ dto.LocalTrailerCount = trailerCount;
}
// Add EpisodeInfo
- var episode = item as Episode;
- if (episode != null)
+ if (item is Episode episode)
{
dto.IndexNumberEnd = episode.IndexNumberEnd;
dto.SeriesName = episode.SeriesName;
@@ -1102,7 +1101,7 @@ namespace Emby.Server.Implementations.Dto
Series episodeSeries = null;
- //if (options.ContainsField(ItemFields.SeriesPrimaryImage))
+ if (options.ContainsField(ItemFields.SeriesPrimaryImage))
{
episodeSeries = episodeSeries ?? episode.Series;
if (episodeSeries != null)
@@ -1122,8 +1121,7 @@ namespace Emby.Server.Implementations.Dto
}
// Add SeriesInfo
- var series = item as Series;
- if (series != null)
+ if (item is Series series)
{
dto.AirDays = series.AirDays;
dto.AirTime = series.AirTime;
@@ -1131,8 +1129,7 @@ namespace Emby.Server.Implementations.Dto
}
// Add SeasonInfo
- var season = item as Season;
- if (season != null)
+ if (item is Season season)
{
dto.SeriesName = season.SeriesName;
dto.SeriesId = season.SeriesId;
@@ -1148,7 +1145,7 @@ namespace Emby.Server.Implementations.Dto
}
}
- //if (options.ContainsField(ItemFields.SeriesPrimaryImage))
+ if (options.ContainsField(ItemFields.SeriesPrimaryImage))
{
series = series ?? season.Series;
if (series != null)
@@ -1158,14 +1155,12 @@ namespace Emby.Server.Implementations.Dto
}
}
- var musicVideo = item as MusicVideo;
- if (musicVideo != null)
+ if (item is MusicVideo musicVideo)
{
SetMusicVideoProperties(dto, musicVideo);
}
- var book = item as Book;
- if (book != null)
+ if (item is Book book)
{
SetBookProperties(dto, book);
}
@@ -1205,8 +1200,7 @@ namespace Emby.Server.Implementations.Dto
}
}
- var photo = item as Photo;
- if (photo != null)
+ if (item is Photo photo)
{
SetPhotoProperties(dto, photo);
}
@@ -1225,8 +1219,7 @@ namespace Emby.Server.Implementations.Dto
private BaseItem GetImageDisplayParent(BaseItem currentItem, BaseItem originalItem)
{
- var musicAlbum = currentItem as MusicAlbum;
- if (musicAlbum != null)
+ if (currentItem is MusicAlbum musicAlbum)
{
var artist = musicAlbum.GetMusicArtist(new DtoOptions(false));
if (artist != null)
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
index 276312a30..457448604 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Net;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security;
@@ -89,7 +90,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
AccessToken = token
});
- var tokenInfo = result.Items.Length > 0 ? result.Items[0] : null;
+ var tokenInfo = result.Items.Count > 0 ? result.Items[0] : null;
if (tokenInfo != null)
{
@@ -190,17 +191,23 @@ namespace Emby.Server.Implementations.HttpServer.Security
/// <returns>Dictionary{System.StringSystem.String}.</returns>
private Dictionary<string, string> GetAuthorization(string authorizationHeader)
{
- if (authorizationHeader == null) return null;
+ if (authorizationHeader == null)
+ {
+ return null;
+ }
var parts = authorizationHeader.Split(new[] { ' ' }, 2);
// There should be at least to parts
- if (parts.Length != 2) return null;
+ if (parts.Length != 2)
+ {
+ return null;
+ }
var acceptedNames = new[] { "MediaBrowser", "Emby" };
// It has to be a digest request
- if (!acceptedNames.Contains(parts[0] ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ if (!acceptedNames.Contains(parts[0], StringComparer.OrdinalIgnoreCase))
{
return null;
}
@@ -232,7 +239,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
return value;
}
- return System.Net.WebUtility.HtmlEncode(value);
+ return WebUtility.HtmlEncode(value);
}
}
}
diff --git a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
index b07244fda..2282b8efb 100644
--- a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
+++ b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
@@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentNullException(nameof(resolvedUser));
}
- // As long as jellyfin supports passwordless users, we need this little block here to accomodate
+ // As long as jellyfin supports passwordless users, we need this little block here to accommodate
if (!HasPassword(resolvedUser) && string.IsNullOrEmpty(password))
{
return Task.FromResult(new ProviderAuthenticationResult
@@ -105,6 +105,7 @@ namespace Emby.Server.Implementations.Library
public Task ChangePassword(User user, string newPassword)
{
ConvertPasswordFormat(user);
+
// This is needed to support changing a no password user to a password user
if (string.IsNullOrEmpty(user.Password))
{
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 30ff855cc..36934f65f 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1441,7 +1441,7 @@ namespace Emby.Server.Implementations.Library
return new QueryResult<BaseItem>
{
- Items = list.ToArray()
+ Items = list
};
}
@@ -1977,8 +1977,7 @@ namespace Emby.Server.Implementations.Library
public LibraryOptions GetLibraryOptions(BaseItem item)
{
- var collectionFolder = item as CollectionFolder;
- if (collectionFolder == null)
+ if (!(item is CollectionFolder collectionFolder))
{
collectionFolder = GetCollectionFolders(item)
.OfType<CollectionFolder>()
diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs
index 71f16ac3e..4d79cae13 100644
--- a/Emby.Server.Implementations/Library/UserViewManager.cs
+++ b/Emby.Server.Implementations/Library/UserViewManager.cs
@@ -224,7 +224,7 @@ namespace Emby.Server.Implementations.Library
return list;
}
- private List<BaseItem> GetItemsForLatestItems(User user, LatestItemsQuery request, DtoOptions options)
+ private IReadOnlyList<BaseItem> GetItemsForLatestItems(User user, LatestItemsQuery request, DtoOptions options)
{
var parentId = request.ParentId;
@@ -236,24 +236,22 @@ namespace Emby.Server.Implementations.Library
if (!parentId.Equals(Guid.Empty))
{
var parentItem = _libraryManager.GetItemById(parentId);
- var parentItemChannel = parentItem as Channel;
- if (parentItemChannel != null)
+ if (parentItem is Channel parentItemChannel)
{
- return _channelManager.GetLatestChannelItemsInternal(new InternalItemsQuery(user)
- {
- ChannelIds = new[] { parentId },
- IsPlayed = request.IsPlayed,
- StartIndex = request.StartIndex,
- Limit = request.Limit,
- IncludeItemTypes = request.IncludeItemTypes,
- EnableTotalRecordCount = false
-
-
- }, CancellationToken.None).Result.Items.ToList();
+ return _channelManager.GetLatestChannelItemsInternal(
+ new InternalItemsQuery(user)
+ {
+ ChannelIds = new[] { parentId },
+ IsPlayed = request.IsPlayed,
+ StartIndex = request.StartIndex,
+ Limit = request.Limit,
+ IncludeItemTypes = request.IncludeItemTypes,
+ EnableTotalRecordCount = false
+ },
+ CancellationToken.None).Result.Items;
}
- var parent = parentItem as Folder;
- if (parent != null)
+ if (parentItem is Folder parent)
{
parents.Add(parent);
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index 9a9bae215..3cc0541e7 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -87,8 +87,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
CreateNoWindow = true,
UseShellExecute = false,
- // Must consume both stdout and stderr or deadlocks may occur
- //RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
@@ -120,9 +118,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
cancellationToken.Register(Stop);
- // MUST read both stdout and stderr asynchronously or a deadlock may occurr
- //process.BeginOutputReadLine();
-
onStarted();
// Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
@@ -138,11 +133,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
string videoArgs;
if (EncodeVideo(mediaSource))
{
- var maxBitrate = 25000000;
+ const int MaxBitrate = 25000000;
videoArgs = string.Format(
- "-codec:v:0 libx264 -force_key_frames \"expr:gte(t,n_forced*5)\" {0} -pix_fmt yuv420p -preset superfast -crf 23 -b:v {1} -maxrate {1} -bufsize ({1}*2) -vsync -1 -profile:v high -level 41",
- GetOutputSizeParam(),
- maxBitrate.ToString(CultureInfo.InvariantCulture));
+ CultureInfo.InvariantCulture,
+ "-codec:v:0 libx264 -force_key_frames \"expr:gte(t,n_forced*5)\" {0} -pix_fmt yuv420p -preset superfast -crf 23 -b:v {1} -maxrate {1} -bufsize ({1}*2) -vsync -1 -profile:v high -level 41",
+ GetOutputSizeParam(),
+ MaxBitrate);
}
else
{
@@ -151,18 +147,17 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
videoArgs += " -fflags +genpts";
- var durationParam = " -t " + _mediaEncoder.GetTimeParameter(duration.Ticks);
- durationParam = string.Empty;
-
var flags = new List<string>();
if (mediaSource.IgnoreDts)
{
flags.Add("+igndts");
}
+
if (mediaSource.IgnoreIndex)
{
flags.Add("+ignidx");
}
+
if (mediaSource.GenPtsInput)
{
flags.Add("+genpts");
@@ -172,11 +167,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (flags.Count > 0)
{
- inputModifier += " -fflags " + string.Join("", flags.ToArray());
+ inputModifier += " -fflags " + string.Join(string.Empty, flags);
}
- var videoStream = mediaSource.VideoStream;
-
if (mediaSource.ReadAtNativeFramerate)
{
inputModifier += " -re";
@@ -200,13 +193,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var outputParam = string.Empty;
- var commandLineArgs = string.Format("-i \"{0}\"{5} {2} -map_metadata -1 -threads 0 {3}{4}{6} -y \"{1}\"",
+ var commandLineArgs = string.Format(
+ CultureInfo.InvariantCulture,
+ "-i \"{0}\" {2} -map_metadata -1 -threads 0 {3}{4}{5} -y \"{1}\"",
inputTempFile,
targetFile,
videoArgs,
GetAudioArgs(mediaSource),
subtitleArgs,
- durationParam,
outputParam);
return inputModifier + " " + commandLineArgs;
@@ -257,7 +251,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
_logger.LogInformation("Stopping ffmpeg recording process for {path}", _targetPath);
- //process.Kill();
_process.StandardInput.WriteLine("q");
}
catch (Exception ex)
@@ -309,44 +302,26 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
_hasExited = true;
- DisposeLogStream();
+ _logFileStream?.Dispose();
+ _logFileStream = null;
- try
- {
- var exitCode = process.ExitCode;
+ var exitCode = process.ExitCode;
- _logger.LogInformation("FFMpeg recording exited with code {ExitCode} for {path}", exitCode, _targetPath);
+ _logger.LogInformation("FFMpeg recording exited with code {ExitCode} for {Path}", exitCode, _targetPath);
- if (exitCode == 0)
- {
- _taskCompletionSource.TrySetResult(true);
- }
- else
- {
- _taskCompletionSource.TrySetException(new Exception(string.Format("Recording for {path} failed. Exit code {ExitCode}", _targetPath, exitCode)));
- }
- }
- catch
+ if (exitCode == 0)
{
- _logger.LogError("FFMpeg recording exited with an error for {path}.", _targetPath);
- _taskCompletionSource.TrySetException(new Exception(string.Format("Recording for {path} failed", _targetPath)));
+ _taskCompletionSource.TrySetResult(true);
}
- }
-
- private void DisposeLogStream()
- {
- if (_logFileStream != null)
+ else
{
- try
- {
- _logFileStream.Dispose();
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error disposing recording log stream");
- }
-
- _logFileStream = null;
+ _taskCompletionSource.TrySetException(
+ new Exception(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "Recording for {0} failed. Exit code {1}",
+ _targetPath,
+ exitCode)));
}
}
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index 1e5198dd6..ee975e19a 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -881,7 +881,7 @@ namespace Emby.Server.Implementations.LiveTv
}
var programList = _libraryManager.QueryItems(internalQuery).Items;
- var totalCount = programList.Length;
+ var totalCount = programList.Count;
var orderedPrograms = programList.Cast<LiveTvProgram>().OrderBy(i => i.StartDate.Date);
@@ -969,8 +969,8 @@ namespace Emby.Server.Implementations.LiveTv
var timers = new Dictionary<string, List<TimerInfo>>();
var seriesTimers = new Dictionary<string, List<SeriesTimerInfo>>();
- TimerInfo[] timerList = null;
- SeriesTimerInfo[] seriesTimerList = null;
+ IReadOnlyList<TimerInfo> timerList = null;
+ IReadOnlyList<SeriesTimerInfo> seriesTimerList = null;
foreach (var programTuple in programs)
{
@@ -1296,6 +1296,7 @@ namespace Emby.Server.Implementations.LiveTv
}
private const int MaxGuideDays = 14;
+
private double GetGuideDays()
{
var config = GetConfiguration();
@@ -1340,6 +1341,7 @@ namespace Emby.Server.Implementations.LiveTv
excludeItemTypes.Add(typeof(Movie).Name);
}
}
+
if (query.IsSeries.HasValue)
{
if (query.IsSeries.Value)
@@ -1351,10 +1353,12 @@ namespace Emby.Server.Implementations.LiveTv
excludeItemTypes.Add(typeof(Episode).Name);
}
}
+
if (query.IsSports ?? false)
{
genres.Add("Sports");
}
+
if (query.IsKids ?? false)
{
genres.Add("Kids");
@@ -1400,20 +1404,20 @@ namespace Emby.Server.Implementations.LiveTv
if (query.IsInProgress ?? false)
{
- //TODO Fix The co-variant conversion between Video[] and BaseItem[], this can generate runtime issues.
+ // TODO: Fix The co-variant conversion between Video[] and BaseItem[], this can generate runtime issues.
result.Items = result
.Items
.OfType<Video>()
.Where(i => !i.IsCompleteMedia)
.ToArray();
- result.TotalRecordCount = result.Items.Length;
+ result.TotalRecordCount = result.Items.Count;
}
return result;
}
- public Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> tuples, ItemFields[] fields, User user = null)
+ public Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> tuples, ItemFields[] fields, User user = null)
{
var programTuples = new List<Tuple<BaseItemDto, string, string>>();
var hasChannelImage = fields.Contains(ItemFields.ChannelImage);
@@ -1877,7 +1881,7 @@ namespace Emby.Server.Implementations.LiveTv
return _libraryManager.GetItemById(internalChannelId);
}
- public void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> tuples, DtoOptions options, User user)
+ public void AddChannelInfo(IReadOnlyCollection<(BaseItemDto, LiveTvChannel)> tuples, DtoOptions options, User user)
{
var now = DateTime.UtcNow;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index 85754ca8b..da98f3e58 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -584,9 +584,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
Logger,
Config.ApplicationPaths,
_appHost,
- _socketFactory,
_networkManager,
_streamHelper);
+
}
var enableHttpStream = true;
@@ -601,9 +601,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
httpUrl += "?transcode=" + profile;
}
+
mediaSource.Path = httpUrl;
- return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _streamHelper);
+ return new SharedHttpStream(
+ mediaSource,
+ info,
+ streamId,
+ FileSystem,
+ _httpClient,
+ Logger,
+ Config.ApplicationPaths,
+ _appHost,
+ _streamHelper);
}
return new HdHomerunUdpStream(
@@ -616,7 +626,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
Logger,
Config.ApplicationPaths,
_appHost,
- _socketFactory,
_networkManager,
_streamHelper);
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
index fbbab07f8..eafa86d54 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
@@ -1,5 +1,4 @@
using System;
-using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Net;
@@ -22,8 +21,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private const int RtpHeaderBytes = 12;
private readonly IServerApplicationHost _appHost;
- private readonly MediaBrowser.Model.Net.ISocketFactory _socketFactory;
-
private readonly IHdHomerunChannelCommands _channelCommands;
private readonly int _numTuners;
private readonly INetworkManager _networkManager;
@@ -38,13 +35,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
ILogger logger,
IServerApplicationPaths appPaths,
IServerApplicationHost appHost,
- MediaBrowser.Model.Net.ISocketFactory socketFactory,
INetworkManager networkManager,
IStreamHelper streamHelper)
: base(mediaSource, tunerHostInfo, fileSystem, logger, appPaths, streamHelper)
{
_appHost = appHost;
- _socketFactory = socketFactory;
_networkManager = networkManager;
OriginalStreamId = originalStreamId;
_channelCommands = channelCommands;
@@ -82,7 +77,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
}
}
- var udpClient = _socketFactory.CreateUdpSocket(localPort);
+ var udpClient = new UdpClient(localPort, AddressFamily.InterNetwork);
var hdHomerunManager = new HdHomerunManager();
try
@@ -133,7 +128,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
await taskCompletionSource.Task.ConfigureAwait(false);
}
- private Task StartStreaming(MediaBrowser.Model.Net.ISocket udpClient, HdHomerunManager hdHomerunManager, IPAddress remoteAddress, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
+ private Task StartStreaming(UdpClient udpClient, HdHomerunManager hdHomerunManager, IPAddress remoteAddress, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
{
return Task.Run(async () =>
{
@@ -162,28 +157,37 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
});
}
- private async Task CopyTo(MediaBrowser.Model.Net.ISocket udpClient, string file, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
+ private async Task CopyTo(UdpClient udpClient, string file, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
{
- byte[] buffer = ArrayPool<byte>.Shared.Rent(StreamDefaults.DefaultCopyToBufferSize);
- try
+ var resolved = false;
+
+ using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read))
{
- using (var source = _socketFactory.CreateNetworkStream(udpClient, false))
- using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read))
+ while (true)
{
- var currentCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token).Token;
- int read;
- var resolved = false;
- while ((read = await source.ReadAsync(buffer, 0, buffer.Length, currentCancellationToken).ConfigureAwait(false)) != 0)
+ cancellationToken.ThrowIfCancellationRequested();
+ using (var timeOutSource = new CancellationTokenSource())
+ using (var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(
+ cancellationToken,
+ timeOutSource.Token))
{
- cancellationToken.ThrowIfCancellationRequested();
+ var resTask = udpClient.ReceiveAsync();
+ if (await Task.WhenAny(resTask, Task.Delay(30000, linkedSource.Token)).ConfigureAwait(false) != resTask)
+ {
+ resTask.Dispose();
+ break;
+ }
- currentCancellationToken = cancellationToken;
+ // We don't want all these delay tasks to keep running
+ timeOutSource.Cancel();
+ var res = await resTask.ConfigureAwait(false);
+ var buffer = res.Buffer;
- read -= RtpHeaderBytes;
+ var read = buffer.Length - RtpHeaderBytes;
if (read > 0)
{
- await fileStream.WriteAsync(buffer, RtpHeaderBytes, read).ConfigureAwait(false);
+ fileStream.Write(buffer, RtpHeaderBytes, read);
}
if (!resolved)
@@ -195,10 +199,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
}
}
}
- finally
- {
- ArrayPool<byte>.Shared.Return(buffer);
- }
}
}
}
diff --git a/Emby.Server.Implementations/Localization/Core/el.json b/Emby.Server.Implementations/Localization/Core/el.json
index db7ebb0c0..3589a4893 100644
--- a/Emby.Server.Implementations/Localization/Core/el.json
+++ b/Emby.Server.Implementations/Localization/Core/el.json
@@ -3,7 +3,7 @@
"AppDeviceValues": "Εφαρμογή: {0}, Συσκευή: {1}",
"Application": "Εφαρμογή",
"Artists": "Καλλιτέχνες",
- "AuthenticationSucceededWithUserName": "{0} επιτυχείς σύνδεση",
+ "AuthenticationSucceededWithUserName": "Ο χρήστης {0} επαληθεύτηκε με επιτυχία",
"Books": "Βιβλία",
"CameraImageUploadedFrom": "Μια νέα εικόνα κάμερας έχει αποσταλεί από {0}",
"Channels": "Κανάλια",
@@ -15,9 +15,9 @@
"Favorites": "Αγαπημένα",
"Folders": "Φάκελοι",
"Genres": "Είδη",
- "HeaderAlbumArtists": "Άλμπουμ Καλλιτεχνών",
+ "HeaderAlbumArtists": "Καλλιτέχνες του Άλμπουμ",
"HeaderCameraUploads": "Μεταφορτώσεις Κάμερας",
- "HeaderContinueWatching": "Συνεχίστε να παρακολουθείτε",
+ "HeaderContinueWatching": "Συνεχίστε την παρακολούθηση",
"HeaderFavoriteAlbums": "Αγαπημένα Άλμπουμ",
"HeaderFavoriteArtists": "Αγαπημένοι Καλλιτέχνες",
"HeaderFavoriteEpisodes": "Αγαπημένα Επεισόδια",
@@ -27,7 +27,7 @@
"HeaderNextUp": "Επόμενο",
"HeaderRecordingGroups": "Γκρουπ Εγγραφών",
"HomeVideos": "Προσωπικά βίντεο",
- "Inherit": "Inherit",
+ "Inherit": "Κληρονόμηση",
"ItemAddedWithName": "{0} προστέθηκε στη βιβλιοθήκη",
"ItemRemovedWithName": "{0} διαγράφηκε από τη βιβλιοθήκη",
"LabelIpAddressValue": "Διεύθυνση IP: {0}",
@@ -92,6 +92,6 @@
"UserStartedPlayingItemWithValues": "{0} παίζει {1} σε {2}",
"UserStoppedPlayingItemWithValues": "{0} τελείωσε να παίζει {1} σε {2}",
"ValueHasBeenAddedToLibrary": "{0} προστέθηκαν στη βιβλιοθήκη πολυμέσων σας",
- "ValueSpecialEpisodeName": "Special - {0}",
+ "ValueSpecialEpisodeName": "Σπέσιαλ - {0}",
"VersionNumber": "Έκδοση {0}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/es.json b/Emby.Server.Implementations/Localization/Core/es.json
index f03184d5b..c78794967 100644
--- a/Emby.Server.Implementations/Localization/Core/es.json
+++ b/Emby.Server.Implementations/Localization/Core/es.json
@@ -23,7 +23,7 @@
"HeaderFavoriteEpisodes": "Episodios favoritos",
"HeaderFavoriteShows": "Series favoritas",
"HeaderFavoriteSongs": "Canciones favoritas",
- "HeaderLiveTV": "TV en directo",
+ "HeaderLiveTV": "Televisión en directo",
"HeaderNextUp": "Siguiendo",
"HeaderRecordingGroups": "Grupos de grabación",
"HomeVideos": "Vídeos caseros",
@@ -79,7 +79,7 @@
"SubtitlesDownloadedForItem": "Descargar subtítulos para {0}",
"Sync": "Sincronizar",
"System": "Sistema",
- "TvShows": "Series de TV",
+ "TvShows": "Programas de televisión",
"User": "Usuario",
"UserCreatedWithName": "El usuario {0} ha sido creado",
"UserDeletedWithName": "El usuario {0} ha sido borrado",
diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json
index e434b7605..6bfedb712 100644
--- a/Emby.Server.Implementations/Localization/Core/fr.json
+++ b/Emby.Server.Implementations/Localization/Core/fr.json
@@ -17,14 +17,14 @@
"Genres": "Genres",
"HeaderAlbumArtists": "Artistes de l'album",
"HeaderCameraUploads": "Photos transférées",
- "HeaderContinueWatching": "Continuer à regarder",
+ "HeaderContinueWatching": "Reprendre",
"HeaderFavoriteAlbums": "Albums favoris",
"HeaderFavoriteArtists": "Artistes favoris",
"HeaderFavoriteEpisodes": "Épisodes favoris",
"HeaderFavoriteShows": "Séries favorites",
"HeaderFavoriteSongs": "Chansons favorites",
"HeaderLiveTV": "TV en direct",
- "HeaderNextUp": "En Cours",
+ "HeaderNextUp": "À suivre",
"HeaderRecordingGroups": "Groupes d'enregistrements",
"HomeVideos": "Vidéos personnelles",
"Inherit": "Hériter",
diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json
index dbda794ad..daa3f5880 100644
--- a/Emby.Server.Implementations/Localization/Core/nb.json
+++ b/Emby.Server.Implementations/Localization/Core/nb.json
@@ -1,11 +1,11 @@
{
"Albums": "Album",
- "AppDeviceValues": "App:{0}, Enhet {1}",
+ "AppDeviceValues": "App:{0}, Enhet: {1}",
"Application": "Applikasjon",
"Artists": "Artister",
"AuthenticationSucceededWithUserName": "{0} vellykkede autentisert",
"Books": "Bøker",
- "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
+ "CameraImageUploadedFrom": "Et nytt kamerabilde er lastet opp fra {0}",
"Channels": "Kanaler",
"ChapterNameValue": "Kapittel {0}",
"Collections": "Samlinger",
diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
index 52d07d784..840aca7a6 100644
--- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.MediaEncoder
var protocol = MediaProtocol.File;
- var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, Array.Empty<string>());
+ var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, null, Array.Empty<string>());
Directory.CreateDirectory(Path.GetDirectoryName(path));
diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs
index cb53ce50c..0870db003 100644
--- a/Emby.Server.Implementations/Net/SocketFactory.cs
+++ b/Emby.Server.Implementations/Net/SocketFactory.cs
@@ -19,7 +19,8 @@ namespace Emby.Server.Implementations.Net
throw new ArgumentException("localPort cannot be less than zero.", nameof(localPort));
}
- var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
+ var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+
try
{
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodingTempTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs
index ad9b56535..c343a7d48 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodingTempTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs
@@ -13,23 +13,22 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
/// <summary>
/// Deletes all transcoding temp files
/// </summary>
- public class DeleteTranscodingTempTask : IScheduledTask, IConfigurableScheduledTask
+ public class DeleteTranscodeFileTask : IScheduledTask, IConfigurableScheduledTask
{
/// <summary>
/// Gets or sets the application paths.
/// </summary>
/// <value>The application paths.</value>
- protected ServerApplicationPaths ApplicationPaths { get; set; }
-
+ private ServerApplicationPaths ApplicationPaths { get; set; }
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
/// <summary>
- /// Initializes a new instance of the <see cref="DeleteTranscodingTempTask" /> class.
+ /// Initializes a new instance of the <see cref="DeleteTranscodeFileTask" /> class.
/// </summary>
- public DeleteTranscodingTempTask(ServerApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
+ public DeleteTranscodeFileTask(ServerApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
{
ApplicationPaths = appPaths;
_logger = logger;
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
index 1a3d85ad7..3e6d251c9 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
@@ -10,7 +10,7 @@ using MediaBrowser.Model.Tasks;
namespace Emby.Server.Implementations.ScheduledTasks
{
/// <summary>
- /// Class RefreshMediaLibraryTask
+ /// Class RefreshMediaLibraryTask.
/// </summary>
public class RefreshMediaLibraryTask : IScheduledTask
{
@@ -31,15 +31,14 @@ namespace Emby.Server.Implementations.ScheduledTasks
}
/// <summary>
- /// Creates the triggers that define when the task will run
+ /// Creates the triggers that define when the task will run.
/// </summary>
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
- return new[] {
-
- // Every so often
- new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(12).Ticks}
+ yield return new TaskTriggerInfo
+ {
+ Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(12).Ticks
};
}
@@ -60,7 +59,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
public string Name => "Scan media library";
- public string Description => "Scans your media library and refreshes metatata based on configuration.";
+ public string Description => "Scans your media library for new files and refreshes metadata.";
public string Category => "Library";
diff --git a/Emby.Server.Implementations/Services/ResponseHelper.cs b/Emby.Server.Implementations/Services/ResponseHelper.cs
index ca2b22fe0..a566b18dd 100644
--- a/Emby.Server.Implementations/Services/ResponseHelper.cs
+++ b/Emby.Server.Implementations/Services/ResponseHelper.cs
@@ -6,8 +6,8 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.HttpServer;
-using Microsoft.AspNetCore.Http;
using MediaBrowser.Model.Services;
+using Microsoft.AspNetCore.Http;
namespace Emby.Server.Implementations.Services
{
diff --git a/Emby.Server.Implementations/Services/ServiceExec.cs b/Emby.Server.Implementations/Services/ServiceExec.cs
index 9124b9c14..9f5f97028 100644
--- a/Emby.Server.Implementations/Services/ServiceExec.cs
+++ b/Emby.Server.Implementations/Services/ServiceExec.cs
@@ -87,8 +87,7 @@ namespace Emby.Server.Implementations.Services
var response = actionContext.ServiceAction(instance, requestDto);
- var taskResponse = response as Task;
- if (taskResponse != null)
+ if (response is Task taskResponse)
{
return GetTaskResult(taskResponse);
}
@@ -104,8 +103,7 @@ namespace Emby.Server.Implementations.Services
{
try
{
- var taskObject = task as Task<object>;
- if (taskObject != null)
+ if (task is Task<object> taskObject)
{
return await taskObject.ConfigureAwait(false);
}
@@ -136,7 +134,7 @@ namespace Emby.Server.Implementations.Services
}
catch (TypeAccessException)
{
- return null; //return null for void Task's
+ return null; // return null for void Task's
}
}
@@ -155,29 +153,22 @@ namespace Emby.Server.Implementations.Services
Id = ServiceMethod.Key(serviceType, actionName, requestType.GetMethodName())
};
- try
- {
- actionCtx.ServiceAction = CreateExecFn(serviceType, requestType, mi);
- }
- catch
- {
- //Potential problems with MONO, using reflection for fallback
- actionCtx.ServiceAction = (service, request) =>
- mi.Invoke(service, new[] { request });
- }
+ actionCtx.ServiceAction = CreateExecFn(serviceType, requestType, mi);
var reqFilters = new List<IHasRequestFilter>();
foreach (var attr in mi.GetCustomAttributes(true))
{
- var hasReqFilter = attr as IHasRequestFilter;
-
- if (hasReqFilter != null)
+ if (attr is IHasRequestFilter hasReqFilter)
+ {
reqFilters.Add(hasReqFilter);
+ }
}
if (reqFilters.Count > 0)
+ {
actionCtx.RequestFilters = reqFilters.OrderBy(i => i.Priority).ToArray();
+ }
actions.Add(actionCtx);
}
@@ -198,15 +189,19 @@ namespace Emby.Server.Implementations.Services
if (mi.ReturnType != typeof(void))
{
- var executeFunc = Expression.Lambda<ActionInvokerFn>
- (callExecute, serviceParam, requestDtoParam).Compile();
+ var executeFunc = Expression.Lambda<ActionInvokerFn>(
+ callExecute,
+ serviceParam,
+ requestDtoParam).Compile();
return executeFunc;
}
else
{
- var executeFunc = Expression.Lambda<VoidActionInvokerFn>
- (callExecute, serviceParam, requestDtoParam).Compile();
+ var executeFunc = Expression.Lambda<VoidActionInvokerFn>(
+ callExecute,
+ serviceParam,
+ requestDtoParam).Compile();
return (service, request) =>
{
diff --git a/Emby.Server.Implementations/Services/UrlExtensions.cs b/Emby.Server.Implementations/Services/UrlExtensions.cs
index 8899fbfa3..5d4407f3b 100644
--- a/Emby.Server.Implementations/Services/UrlExtensions.cs
+++ b/Emby.Server.Implementations/Services/UrlExtensions.cs
@@ -12,10 +12,10 @@ namespace Emby.Server.Implementations.Services
{
public static string GetMethodName(this Type type)
{
- var typeName = type.FullName != null //can be null, e.g. generic types
- ? LeftPart(type.FullName, "[[") //Generic Fullname
- .Replace(type.Namespace + ".", "") //Trim Namespaces
- .Replace("+", ".") //Convert nested into normal type
+ var typeName = type.FullName != null // can be null, e.g. generic types
+ ? LeftPart(type.FullName, "[[") // Generic Fullname
+ .Replace(type.Namespace + ".", string.Empty) // Trim Namespaces
+ .Replace("+", ".") // Convert nested into normal type
: type.Name;
return type.IsGenericParameter ? "'" + typeName : typeName;
@@ -23,7 +23,11 @@ namespace Emby.Server.Implementations.Services
private static string LeftPart(string strVal, string needle)
{
- if (strVal == null) return null;
+ if (strVal == null)
+ {
+ return null;
+ }
+
var pos = strVal.IndexOf(needle, StringComparison.OrdinalIgnoreCase);
return pos == -1
? strVal
diff --git a/Emby.Server.Implementations/Sorting/ArtistComparer.cs b/Emby.Server.Implementations/Sorting/ArtistComparer.cs
index 9d5befc9a..756d3c5b6 100644
--- a/Emby.Server.Implementations/Sorting/ArtistComparer.cs
+++ b/Emby.Server.Implementations/Sorting/ArtistComparer.cs
@@ -7,16 +7,14 @@ using MediaBrowser.Model.Querying;
namespace Emby.Server.Implementations.Sorting
{
/// <summary>
- /// Class ArtistComparer
+ /// Class ArtistComparer.
/// </summary>
public class ArtistComparer : IBaseItemComparer
{
- /// <summary>
- /// Compares the specified x.
- /// </summary>
- /// <param name="x">The x.</param>
- /// <param name="y">The y.</param>
- /// <returns>System.Int32.</returns>
+ /// <inheritdoc />
+ public string Name => ItemSortBy.Artist;
+
+ /// <inheritdoc />
public int Compare(BaseItem x, BaseItem y)
{
return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase);
@@ -29,20 +27,12 @@ namespace Emby.Server.Implementations.Sorting
/// <returns>System.String.</returns>
private static string GetValue(BaseItem x)
{
- var audio = x as Audio;
-
- if (audio == null)
+ if (!(x is Audio audio))
{
return string.Empty;
}
- return audio.Artists.Length == 0 ? null : audio.Artists[0];
+ return audio.Artists.Count == 0 ? null : audio.Artists[0];
}
-
- /// <summary>
- /// Gets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name => ItemSortBy.Artist;
}
}
diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj
index e87283477..8c57ee453 100644
--- a/Jellyfin.Server/Jellyfin.Server.csproj
+++ b/Jellyfin.Server/Jellyfin.Server.csproj
@@ -49,7 +49,6 @@
<ItemGroup>
<ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj" />
- <ProjectReference Include="..\Emby.IsoMounting\IsoMounter\IsoMounter.csproj" />
<ProjectReference Include="..\Emby.Server.Implementations\Emby.Server.Implementations.csproj" />
<ProjectReference Include="..\Jellyfin.Drawing.Skia\Jellyfin.Drawing.Skia.csproj" />
</ItemGroup>
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 8a4d6e216..3a15c3776 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -741,7 +741,7 @@ namespace MediaBrowser.Api.LiveTv
var result = new QueryResult<BaseItemDto>
{
Items = returnArray,
- TotalRecordCount = returnArray.Length
+ TotalRecordCount = returnArray.Count
};
return ToOptimizedResult(result);
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index d601fb500..c1c6ffc2e 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -243,7 +243,7 @@ namespace MediaBrowser.Api.Movies
}
}
- return categories.OrderBy(i => i.RecommendationType).ThenBy(i => Guid.NewGuid());
+ return categories.OrderBy(i => i.RecommendationType);
}
private IEnumerable<RecommendationDto> GetWithDirector(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs
index c48bcde5c..2cd3a1003 100644
--- a/MediaBrowser.Api/Music/AlbumsService.cs
+++ b/MediaBrowser.Api/Music/AlbumsService.cs
@@ -104,16 +104,15 @@ namespace MediaBrowser.Api.Music
var album2 = (MusicAlbum)item2;
var artists1 = album1
- .AllArtists
+ .GetAllArtists()
.DistinctNames()
.ToList();
- var artists2 = album2
- .AllArtists
- .DistinctNames()
- .ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
+ var artists2 = new HashSet<string>(
+ album2.GetAllArtists().DistinctNames(),
+ StringComparer.OrdinalIgnoreCase);
- return points + artists1.Where(artists2.ContainsKey).Sum(i => 5);
+ return points + artists1.Where(artists2.Contains).Sum(i => 5);
}
}
}
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 496c2032a..17aa6b23a 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -634,7 +634,7 @@ namespace MediaBrowser.Api.Playback
}
else
{
- value = value.Substring(Npt.Length, index);
+ value = value.Substring(Npt.Length, index - Npt.Length);
}
if (value.IndexOf(':') == -1)
diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs
index 482c1a2a8..483bf98fb 100644
--- a/MediaBrowser.Api/PlaylistService.cs
+++ b/MediaBrowser.Api/PlaylistService.cs
@@ -189,11 +189,9 @@ namespace MediaBrowser.Api
var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user);
- var index = 0;
- foreach (var item in dtos)
+ for (int index = 0; index < dtos.Count; index++)
{
- item.PlaylistItemId = items[index].Item1.Id;
- index++;
+ dtos[index].PlaylistItemId = items[index].Item1.Id;
}
var result = new QueryResult<BaseItemDto>
diff --git a/MediaBrowser.Api/SuggestionsService.cs b/MediaBrowser.Api/SuggestionsService.cs
index 72fdae365..4e857eafc 100644
--- a/MediaBrowser.Api/SuggestionsService.cs
+++ b/MediaBrowser.Api/SuggestionsService.cs
@@ -61,11 +61,6 @@ namespace MediaBrowser.Api
var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user);
- if (dtoList == null)
- {
- throw new InvalidOperationException("GetBaseItemDtos returned null");
- }
-
return new QueryResult<BaseItemDto>
{
TotalRecordCount = result.TotalRecordCount,
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index 2951fa6b4..1340bd8ef 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -382,13 +382,13 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("Series not found");
}
- var seasons = (series.GetItemList(new InternalItemsQuery(user)
+ var seasons = series.GetItemList(new InternalItemsQuery(user)
{
IsMissing = request.IsMissing,
IsSpecialSeason = request.IsSpecialSeason,
AdjacentTo = request.AdjacentTo
- }));
+ });
var dtoOptions = GetDtoOptions(_authContext, request);
@@ -396,7 +396,7 @@ namespace MediaBrowser.Api
return new QueryResult<BaseItemDto>
{
- TotalRecordCount = returnItems.Length,
+ TotalRecordCount = returnItems.Count,
Items = returnItems
};
}
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index a1e976bed..ada540ba6 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -175,11 +175,6 @@ namespace MediaBrowser.Api.UserLibrary
var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user);
- if (dtoList == null)
- {
- throw new InvalidOperationException("GetBaseItemDtos returned null");
- }
-
return new QueryResult<BaseItemDto>
{
TotalRecordCount = result.TotalRecordCount,
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index a9b06095d..45694a678 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -2,6 +2,7 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -366,11 +367,21 @@ namespace MediaBrowser.Api.UserLibrary
var dtoOptions = GetDtoOptions(_authContext, request);
- var dtos = item.GetExtras(new[] { ExtraType.Trailer })
+ var dtosExtras = item.GetExtras(new[] { ExtraType.Trailer })
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
.ToArray();
- return ToOptimizedResult(dtos);
+ if (item is IHasTrailers hasTrailers)
+ {
+ var trailers = hasTrailers.GetTrailers();
+ var dtosTrailers = _dtoService.GetBaseItemDtos(trailers, dtoOptions, user, item);
+ var allTrailers = new BaseItemDto[dtosExtras.Length + dtosTrailers.Count];
+ dtosExtras.CopyTo(allTrailers, 0);
+ dtosTrailers.CopyTo(allTrailers, dtosExtras.Length);
+ return ToOptimizedResult(allTrailers);
+ }
+
+ return ToOptimizedResult(dtosExtras);
}
/// <summary>
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index f08d070ca..2c0a0b443 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -248,9 +248,14 @@ namespace MediaBrowser.Api
private readonly INetworkManager _networkManager;
private readonly IDeviceManager _deviceManager;
private readonly IAuthorizationContext _authContext;
- private readonly ILogger _logger;
- public UserService(IUserManager userManager, ISessionManager sessionMananger, IServerConfigurationManager config, INetworkManager networkManager, IDeviceManager deviceManager, IAuthorizationContext authContext, ILoggerFactory loggerFactory)
+ public UserService(
+ IUserManager userManager,
+ ISessionManager sessionMananger,
+ IServerConfigurationManager config,
+ INetworkManager networkManager,
+ IDeviceManager deviceManager,
+ IAuthorizationContext authContext)
{
_userManager = userManager;
_sessionMananger = sessionMananger;
@@ -258,7 +263,6 @@ namespace MediaBrowser.Api
_networkManager = networkManager;
_deviceManager = deviceManager;
_authContext = authContext;
- _logger = loggerFactory.CreateLogger(nameof(UserService));
}
public object Get(GetPublicUsers request)
@@ -418,7 +422,7 @@ namespace MediaBrowser.Api
return ToOptimizedResult(result);
}
- catch(SecurityException e)
+ catch (SecurityException e)
{
// rethrow adding IP address to message
throw new SecurityException($"[{Request.RemoteIp}] {e.Message}");
diff --git a/MediaBrowser.Common/Extensions/CollectionExtensions.cs b/MediaBrowser.Common/Extensions/CollectionExtensions.cs
index f7c0e3cf0..3bc0295a0 100644
--- a/MediaBrowser.Common/Extensions/CollectionExtensions.cs
+++ b/MediaBrowser.Common/Extensions/CollectionExtensions.cs
@@ -10,5 +10,22 @@ namespace MediaBrowser.Common.Extensions
dictionary.TryGetValue(key, out var ret);
return ret;
}
+
+ // REVIEW: Inline?
+ /// <summary>
+ /// Copies all the elements of the current collection to the specified list
+ /// starting at the specified destination array index. The index is specified as a 32-bit integer.
+ /// </summary>
+ /// <param name="source">The current collection that is the source of the elements.</param>
+ /// <param name="destination">The list that is the destination of the elements copied from the current collection.</param>
+ /// <param name="index">A 32-bit integer that represents the index in <c>destination</c> at which copying begins.</param>
+ /// <typeparam name="T"></typeparam>
+ public static void CopyTo<T>(this IReadOnlyCollection<T> source, IList<T> destination, int index = 0)
+ {
+ foreach (T item in source)
+ {
+ destination[index++] = item;
+ }
+ }
}
}
diff --git a/MediaBrowser.Common/Net/CustomHeaderNames.cs b/MediaBrowser.Common/Net/CustomHeaderNames.cs
index ff148dc80..bda897ed9 100644
--- a/MediaBrowser.Common/Net/CustomHeaderNames.cs
+++ b/MediaBrowser.Common/Net/CustomHeaderNames.cs
@@ -8,4 +8,4 @@ namespace MediaBrowser.Common.Net
public const string XForwardedProto = "X-Forwarded-Proto";
public const string XRealIP = "X-Real-IP";
}
-} \ No newline at end of file
+}
diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs
index 4b6fd58fe..ba693a065 100644
--- a/MediaBrowser.Controller/Dto/IDtoService.cs
+++ b/MediaBrowser.Controller/Dto/IDtoService.cs
@@ -57,7 +57,7 @@ namespace MediaBrowser.Controller.Dto
/// <param name="options">The options.</param>
/// <param name="user">The user.</param>
/// <param name="owner">The owner.</param>
- BaseItemDto[] GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null);
+ IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null);
/// <summary>
/// Gets the item by name dto.
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 13a6fe44a..67b21068a 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
@@ -19,15 +20,13 @@ namespace MediaBrowser.Controller.Entities.Audio
IHasLookupInfo<SongInfo>,
IHasMediaSources
{
- /// <summary>
- /// Gets or sets the artist.
- /// </summary>
- /// <value>The artist.</value>
+ /// <inheritdoc />
[IgnoreDataMember]
- public string[] Artists { get; set; }
+ public IReadOnlyList<string> Artists { get; set; }
+ /// <inheritdoc />
[IgnoreDataMember]
- public string[] AlbumArtists { get; set; }
+ public IReadOnlyList<string> AlbumArtists { get; set; }
public Audio()
{
@@ -64,30 +63,6 @@ namespace MediaBrowser.Controller.Entities.Audio
}
[IgnoreDataMember]
- public string[] AllArtists
- {
- get
- {
- var list = new string[AlbumArtists.Length + Artists.Length];
-
- var index = 0;
- foreach (var artist in AlbumArtists)
- {
- list[index] = artist;
- index++;
- }
- foreach (var artist in Artists)
- {
- list[index] = artist;
- index++;
- }
-
- return list;
-
- }
- }
-
- [IgnoreDataMember]
public MusicAlbum AlbumEntity => FindParent<MusicAlbum>();
/// <summary>
@@ -125,7 +100,7 @@ namespace MediaBrowser.Controller.Entities.Audio
songKey = Album + "-" + songKey;
}
- var albumArtist = AlbumArtists.Length == 0 ? null : AlbumArtists[0];
+ var albumArtist = AlbumArtists.FirstOrDefault();
if (!string.IsNullOrEmpty(albumArtist))
{
songKey = albumArtist + "-" + songKey;
diff --git a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
index a269b3486..056f31f78 100644
--- a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
@@ -1,14 +1,35 @@
+using System.Collections.Generic;
+
namespace MediaBrowser.Controller.Entities.Audio
{
public interface IHasAlbumArtist
{
- string[] AlbumArtists { get; set; }
+ IReadOnlyList<string> AlbumArtists { get; set; }
}
public interface IHasArtist
{
- string[] AllArtists { get; }
+ /// <summary>
+ /// Gets or sets the artists.
+ /// </summary>
+ /// <value>The artists.</value>
+ IReadOnlyList<string> Artists { get; set; }
+ }
+
+ public static class Extentions
+ {
+ public static IEnumerable<string> GetAllArtists<T>(this T item)
+ where T : IHasArtist, IHasAlbumArtist
+ {
+ foreach (var i in item.AlbumArtists)
+ {
+ yield return i;
+ }
- string[] Artists { get; set; }
+ foreach (var i in item.Artists)
+ {
+ yield return i;
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 5b2939b75..edf6ffa21 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -18,8 +18,11 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary>
public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer
{
- public string[] AlbumArtists { get; set; }
- public string[] Artists { get; set; }
+ /// <inheritdoc />
+ public IReadOnlyList<string> AlbumArtists { get; set; }
+
+ /// <inheritdoc />
+ public IReadOnlyList<string> Artists { get; set; }
public MusicAlbum()
{
@@ -41,8 +44,7 @@ namespace MediaBrowser.Controller.Entities.Audio
var parents = GetParents();
foreach (var parent in parents)
{
- var artist = parent as MusicArtist;
- if (artist != null)
+ if (parent is MusicArtist artist)
{
return artist;
}
@@ -63,30 +65,7 @@ namespace MediaBrowser.Controller.Entities.Audio
public override bool SupportsCumulativeRunTimeTicks => true;
[IgnoreDataMember]
- public string[] AllArtists
- {
- get
- {
- var list = new string[AlbumArtists.Length + Artists.Length];
-
- var index = 0;
- foreach (var artist in AlbumArtists)
- {
- list[index] = artist;
- index++;
- }
- foreach (var artist in Artists)
- {
- list[index] = artist;
- index++;
- }
-
- return list;
- }
- }
-
- [IgnoreDataMember]
- public string AlbumArtist => AlbumArtists.Length == 0 ? null : AlbumArtists[0];
+ public string AlbumArtist => AlbumArtists.FirstOrDefault();
[IgnoreDataMember]
public override bool SupportsPeople => false;
@@ -216,8 +195,7 @@ namespace MediaBrowser.Controller.Entities.Audio
private async Task RefreshArtists(MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken)
{
- var all = AllArtists;
- foreach (var i in all)
+ foreach (var i in this.GetAllArtists())
{
// This should not be necessary but we're seeing some cases of it
if (string.IsNullOrEmpty(i))
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 2ae856b02..0e9f7ee44 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -2871,16 +2871,24 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the remote trailers.
/// </summary>
/// <value>The remote trailers.</value>
- public MediaUrl[] RemoteTrailers { get; set; }
+ public IReadOnlyList<MediaUrl> RemoteTrailers { get; set; }
public IEnumerable<BaseItem> GetExtras()
{
return ExtraIds.Select(LibraryManager.GetItemById).Where(i => i != null).OrderBy(i => i.SortName);
}
- public IEnumerable<BaseItem> GetExtras(ExtraType[] extraTypes)
+ public IEnumerable<BaseItem> GetExtras(IReadOnlyCollection<ExtraType> extraTypes)
{
- return ExtraIds.Select(LibraryManager.GetItemById).Where(i => i != null && extraTypes.Contains(i.ExtraType.Value)).OrderBy(i => i.SortName);
+ return ExtraIds.Select(LibraryManager.GetItemById).Where(i => i != null && extraTypes.Contains(i.ExtraType.Value));
+ }
+
+ public IEnumerable<BaseItem> GetTrailers()
+ {
+ if (this is IHasTrailers)
+ return ((IHasTrailers)this).LocalTrailerIds.Select(LibraryManager.GetItemById).Where(i => i != null).OrderBy(i => i.SortName);
+ else
+ return Array.Empty<BaseItem>();
}
public IEnumerable<BaseItem> GetDisplayExtras()
@@ -2900,7 +2908,7 @@ namespace MediaBrowser.Controller.Entities
}
// Possible types of extra videos
- public static ExtraType[] DisplayExtraTypes = new[] { Model.Entities.ExtraType.BehindTheScenes, Model.Entities.ExtraType.Clip, Model.Entities.ExtraType.DeletedScene, Model.Entities.ExtraType.Interview, Model.Entities.ExtraType.Sample, Model.Entities.ExtraType.Scene };
+ public static readonly IReadOnlyCollection<ExtraType> DisplayExtraTypes = new[] { Model.Entities.ExtraType.BehindTheScenes, Model.Entities.ExtraType.Clip, Model.Entities.ExtraType.DeletedScene, Model.Entities.ExtraType.Interview, Model.Entities.ExtraType.Sample, Model.Entities.ExtraType.Scene };
public virtual bool SupportsExternalTransfer => false;
}
diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs
index f3bddd29c..d2ca11740 100644
--- a/MediaBrowser.Controller/Entities/Extensions.cs
+++ b/MediaBrowser.Controller/Entities/Extensions.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities
@@ -28,13 +29,17 @@ namespace MediaBrowser.Controller.Entities
Url = url
};
- if (item.RemoteTrailers.Length == 0)
+ if (item.RemoteTrailers.Count == 0)
{
item.RemoteTrailers = new[] { mediaUrl };
}
else
{
- item.RemoteTrailers = item.RemoteTrailers.Concat(new[] { mediaUrl }).ToArray();
+ var oldIds = item.RemoteTrailers;
+ var newIds = new MediaUrl[oldIds.Count + 1];
+ oldIds.CopyTo(newIds);
+ newIds[oldIds.Count] = mediaUrl;
+ item.RemoteTrailers = newIds;
}
}
}
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index d841b7ef8..d61a07066 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -666,36 +666,36 @@ namespace MediaBrowser.Controller.Entities
query.StartIndex = null;
query.Limit = null;
- var itemsList = LibraryManager.GetItemList(query);
+ IEnumerable<BaseItem> itemsList = LibraryManager.GetItemList(query);
var user = query.User;
if (user != null)
{
// needed for boxsets
- itemsList = itemsList.Where(i => i.IsVisibleStandalone(query.User)).ToList();
+ itemsList = itemsList.Where(i => i.IsVisibleStandalone(query.User));
}
- BaseItem[] returnItems;
+ IEnumerable<BaseItem> returnItems;
int totalCount = 0;
if (query.EnableTotalRecordCount)
{
- var itemsArray = itemsList.ToArray();
- totalCount = itemsArray.Length;
- returnItems = itemsArray;
+ var itemArray = itemsList.ToArray();
+ totalCount = itemArray.Length;
+ returnItems = itemArray;
}
else
{
- returnItems = itemsList.ToArray();
+ returnItems = itemsList;
}
if (limit.HasValue)
{
- returnItems = returnItems.Skip(startIndex ?? 0).Take(limit.Value).ToArray();
+ returnItems = returnItems.Skip(startIndex ?? 0).Take(limit.Value);
}
else if (startIndex.HasValue)
{
- returnItems = returnItems.Skip(startIndex.Value).ToArray();
+ returnItems = returnItems.Skip(startIndex.Value);
}
return new QueryResult<BaseItem>
diff --git a/MediaBrowser.Controller/Entities/IHasTrailers.cs b/MediaBrowser.Controller/Entities/IHasTrailers.cs
index 3bdb9b64a..dd8e3c45f 100644
--- a/MediaBrowser.Controller/Entities/IHasTrailers.cs
+++ b/MediaBrowser.Controller/Entities/IHasTrailers.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities
@@ -11,29 +10,82 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the remote trailers.
/// </summary>
/// <value>The remote trailers.</value>
- MediaUrl[] RemoteTrailers { get; set; }
+ IReadOnlyList<MediaUrl> RemoteTrailers { get; set; }
/// <summary>
/// Gets or sets the local trailer ids.
/// </summary>
/// <value>The local trailer ids.</value>
- Guid[] LocalTrailerIds { get; set; }
- Guid[] RemoteTrailerIds { get; set; }
+ IReadOnlyList<Guid> LocalTrailerIds { get; set; }
+
+ /// <summary>
+ /// Gets or sets the remote trailer ids.
+ /// </summary>
+ /// <value>The remote trailer ids.</value>
+ IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
+
Guid Id { get; set; }
}
+ /// <summary>
+ /// Class providing extension methods for working with <see cref="IHasTrailers" />.
+ /// </summary>
public static class HasTrailerExtensions
{
/// <summary>
+ /// Gets the trailer count.
+ /// </summary>
+ /// <returns><see cref="IReadOnlyList{Guid}" />.</returns>
+ public static int GetTrailerCount(this IHasTrailers item)
+ => item.LocalTrailerIds.Count + item.RemoteTrailerIds.Count;
+
+ /// <summary>
/// Gets the trailer ids.
/// </summary>
- /// <returns>List&lt;Guid&gt;.</returns>
- public static List<Guid> GetTrailerIds(this IHasTrailers item)
+ /// <returns><see cref="IReadOnlyList{Guid}" />.</returns>
+ public static IReadOnlyList<Guid> GetTrailerIds(this IHasTrailers item)
{
- var list = item.LocalTrailerIds.ToList();
- list.AddRange(item.RemoteTrailerIds);
- return list;
+ var localIds = item.LocalTrailerIds;
+ var remoteIds = item.RemoteTrailerIds;
+
+ var all = new Guid[localIds.Count + remoteIds.Count];
+ var index = 0;
+ foreach (var id in localIds)
+ {
+ all[index++] = id;
+ }
+
+ foreach (var id in remoteIds)
+ {
+ all[index++] = id;
+ }
+
+ return all;
}
+ /// <summary>
+ /// Gets the trailers.
+ /// </summary>
+ /// <returns><see cref="IReadOnlyList{BaseItem}" />.</returns>
+ public static IReadOnlyList<BaseItem> GetTrailers(this IHasTrailers item)
+ {
+ var localIds = item.LocalTrailerIds;
+ var remoteIds = item.RemoteTrailerIds;
+ var libraryManager = BaseItem.LibraryManager;
+
+ var all = new BaseItem[localIds.Count + remoteIds.Count];
+ var index = 0;
+ foreach (var id in localIds)
+ {
+ all[index++] = libraryManager.GetItemById(id);
+ }
+
+ foreach (var id in remoteIds)
+ {
+ all[index++] = libraryManager.GetItemById(id);
+ }
+
+ return all;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index a532b5ee9..e7ac2a05c 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -33,8 +33,11 @@ namespace MediaBrowser.Controller.Entities.Movies
[IgnoreDataMember]
public override bool SupportsPeople => true;
- public Guid[] LocalTrailerIds { get; set; }
- public Guid[] RemoteTrailerIds { get; set; }
+ /// <inheritdoc />
+ public IReadOnlyList<Guid> LocalTrailerIds { get; set; }
+
+ /// <inheritdoc />
+ public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary>
/// Gets or sets the display order.
@@ -61,7 +64,8 @@ namespace MediaBrowser.Controller.Entities.Movies
{
return base.GetNonCachedChildren(directoryService);
}
- return new List<BaseItem>();
+
+ return Enumerable.Empty<BaseItem>();
}
protected override List<BaseItem> LoadChildren()
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index 20c5b3521..184528fdc 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -27,8 +27,11 @@ namespace MediaBrowser.Controller.Entities.Movies
RemoteTrailerIds = Array.Empty<Guid>();
}
- public Guid[] LocalTrailerIds { get; set; }
- public Guid[] RemoteTrailerIds { get; set; }
+ /// <inheritdoc />
+ public IReadOnlyList<Guid> LocalTrailerIds { get; set; }
+
+ /// <inheritdoc />
+ public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary>
/// Gets or sets the name of the TMDB collection.
diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs
index 5bf082b7e..94fe11e9d 100644
--- a/MediaBrowser.Controller/Entities/MusicVideo.cs
+++ b/MediaBrowser.Controller/Entities/MusicVideo.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
@@ -8,17 +9,15 @@ namespace MediaBrowser.Controller.Entities
{
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasLookupInfo<MusicVideoInfo>
{
+ /// <inheritdoc />
[IgnoreDataMember]
- public string[] Artists { get; set; }
+ public IReadOnlyList<string> Artists { get; set; }
public MusicVideo()
{
Artists = Array.Empty<string>();
}
- [IgnoreDataMember]
- public string[] AllArtists => Artists;
-
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Music;
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index fb29c07b0..e67c00fed 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -23,8 +23,11 @@ namespace MediaBrowser.Controller.Entities.TV
RemoteTrailerIds = Array.Empty<Guid>();
}
- public Guid[] LocalTrailerIds { get; set; }
- public Guid[] RemoteTrailerIds { get; set; }
+ /// <inheritdoc />
+ public IReadOnlyList<Guid> LocalTrailerIds { get; set; }
+
+ /// <inheritdoc />
+ public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary>
/// Gets the season in which it aired.
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index 1aacc13c9..a50da9b0a 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -46,8 +46,11 @@ namespace MediaBrowser.Controller.Entities.TV
[IgnoreDataMember]
public override bool SupportsPeople => true;
- public Guid[] LocalTrailerIds { get; set; }
- public Guid[] RemoteTrailerIds { get; set; }
+ /// <inheritdoc />
+ public IReadOnlyList<Guid> LocalTrailerIds { get; set; }
+
+ /// <inheritdoc />
+ public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary>
/// airdate, dvd or absolute
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index f99df6c7c..e02c387e4 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -221,7 +221,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="fields">The fields.</param>
/// <param name="user">The user.</param>
/// <returns>Task.</returns>
- Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> programs, ItemFields[] fields, User user = null);
+ Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> programs, ItemFields[] fields, User user = null);
/// <summary>
/// Saves the tuner host.
@@ -258,7 +258,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="items">The items.</param>
/// <param name="options">The options.</param>
/// <param name="user">The user.</param>
- void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> items, DtoOptions options, User user);
+ void AddChannelInfo(IReadOnlyCollection<(BaseItemDto, LiveTvChannel)> items, DtoOptions options, User user);
Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken);
Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken);
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 87874001a..963091673 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Text;
using System.Threading;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
@@ -22,8 +23,17 @@ namespace MediaBrowser.Controller.MediaEncoding
private readonly IMediaEncoder _mediaEncoder;
private readonly IFileSystem _fileSystem;
private readonly ISubtitleEncoder _subtitleEncoder;
- // private readonly IApplicationPaths _appPaths;
- // private readonly IAssemblyInfo _assemblyInfo;
+
+ private static readonly string[] _videoProfiles = new[]
+ {
+ "ConstrainedBaseline",
+ "Baseline",
+ "Extended",
+ "Main",
+ "High",
+ "ProgressiveHigh",
+ "ConstrainedHigh"
+ };
public EncodingHelper(IMediaEncoder mediaEncoder, IFileSystem fileSystem, ISubtitleEncoder subtitleEncoder)
{
@@ -33,14 +43,10 @@ namespace MediaBrowser.Controller.MediaEncoding
}
public string GetH264Encoder(EncodingJobInfo state, EncodingOptions encodingOptions)
- {
- return GetH264OrH265Encoder("libx264", "h264", state, encodingOptions);
- }
+ => GetH264OrH265Encoder("libx264", "h264", state, encodingOptions);
public string GetH265Encoder(EncodingJobInfo state, EncodingOptions encodingOptions)
- {
- return GetH264OrH265Encoder("libx265", "hevc", state, encodingOptions);
- }
+ => GetH264OrH265Encoder("libx265", "hevc", state, encodingOptions);
private string GetH264OrH265Encoder(string defaultEncoder, string hwEncoder, EncodingJobInfo state, EncodingOptions encodingOptions)
{
@@ -64,19 +70,17 @@ namespace MediaBrowser.Controller.MediaEncoding
};
if (!string.IsNullOrEmpty(hwType)
- && encodingOptions.EnableHardwareEncoding && codecMap.ContainsKey(hwType))
+ && encodingOptions.EnableHardwareEncoding
+ && codecMap.ContainsKey(hwType)
+ && CheckVaapi(state, hwType, encodingOptions))
{
- if (CheckVaapi(state, hwType, encodingOptions))
- {
- var preferredEncoder = codecMap[hwType];
+ var preferredEncoder = codecMap[hwType];
- if (_mediaEncoder.SupportsEncoder(preferredEncoder))
- {
- return preferredEncoder;
- }
+ if (_mediaEncoder.SupportsEncoder(preferredEncoder))
+ {
+ return preferredEncoder;
}
}
-
}
// Avoid performing a second attempt when the first one
@@ -106,15 +110,13 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var videoStream = state.VideoStream;
- if (videoStream != null)
+ // vaapi will throw an error with this input
+ // [vaapi @ 0x7faed8000960] No VAAPI support for codec mpeg4 profile -99.
+ if (string.Equals(videoStream?.Codec, "mpeg4", StringComparison.OrdinalIgnoreCase))
{
- // vaapi will throw an error with this input
- // [vaapi @ 0x7faed8000960] No VAAPI support for codec mpeg4 profile -99.
- if (string.Equals(videoStream.Codec, "mpeg4", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
+ return false;
}
+
return true;
}
@@ -127,23 +129,27 @@ namespace MediaBrowser.Controller.MediaEncoding
if (!string.IsNullOrEmpty(codec))
{
- if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
{
return GetH265Encoder(state, encodingOptions);
}
+
if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase))
{
return GetH264Encoder(state, encodingOptions);
}
+
if (string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase))
{
return "libvpx";
}
+
if (string.Equals(codec, "wmv", StringComparison.OrdinalIgnoreCase))
{
return "wmv2";
}
+
if (string.Equals(codec, "theora", StringComparison.OrdinalIgnoreCase))
{
return "libtheora";
@@ -162,9 +168,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <returns>System.String.</returns>
public string GetUserAgentParam(EncodingJobInfo state)
{
- string useragent = null;
-
- state.RemoteHttpHeaders.TryGetValue("User-Agent", out useragent);
+ state.RemoteHttpHeaders.TryGetValue("User-Agent", out string useragent);
if (!string.IsNullOrEmpty(useragent))
{
@@ -193,50 +197,62 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return null;
}
+
if (string.Equals(container, "wmv", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "mts", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "vob", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "mpg", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "mpeg", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "rec", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "dvr-ms", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "ogm", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "divx", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "tp", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "rmvb", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(container, "rtp", StringComparison.OrdinalIgnoreCase))
{
return null;
@@ -264,10 +280,12 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return null;
}
+
if (string.Equals(codec, "aac_latm", StringComparison.OrdinalIgnoreCase))
{
return null;
}
+
if (string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase))
{
return null;
@@ -292,30 +310,37 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return "mp3";
}
+
if (string.Equals(ext, ".aac", StringComparison.OrdinalIgnoreCase))
{
return "aac";
}
+
if (string.Equals(ext, ".wma", StringComparison.OrdinalIgnoreCase))
{
return "wma";
}
+
if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase))
{
return "vorbis";
}
+
if (string.Equals(ext, ".oga", StringComparison.OrdinalIgnoreCase))
{
return "vorbis";
}
+
if (string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase))
{
return "vorbis";
}
+
if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase))
{
return "vorbis";
}
+
if (string.Equals(ext, ".webma", StringComparison.OrdinalIgnoreCase))
{
return "vorbis";
@@ -337,14 +362,17 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return "wmv";
}
+
if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase))
{
return "vpx";
}
+
if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase))
{
return "theora";
}
+
if (string.Equals(ext, ".m3u8", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ts", StringComparison.OrdinalIgnoreCase))
{
return "h264";
@@ -355,19 +383,9 @@ namespace MediaBrowser.Controller.MediaEncoding
public int GetVideoProfileScore(string profile)
{
- var list = new[]
- {
- "ConstrainedBaseline",
- "Baseline",
- "Extended",
- "Main",
- "High",
- "ProgressiveHigh",
- "ConstrainedHigh"
- };
-
// strip spaces because they may be stripped out on the query string
- return Array.FindIndex(list, t => string.Equals(t, profile.Replace(" ", ""), StringComparison.OrdinalIgnoreCase));
+ profile = profile.Replace(" ", "");
+ return Array.FindIndex(_videoProfiles, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase));
}
public string GetInputPathArgument(EncodingJobInfo state)
@@ -375,14 +393,19 @@ namespace MediaBrowser.Controller.MediaEncoding
var protocol = state.InputProtocol;
var mediaPath = state.MediaPath ?? string.Empty;
- var inputPath = new[] { mediaPath };
-
- if (state.IsInputVideo)
+ string[] inputPath;
+ if (state.IsInputVideo
+ && !(state.VideoType == VideoType.Iso && state.IsoMount == null))
{
- if (!(state.VideoType == VideoType.Iso && state.IsoMount == null))
- {
- inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, mediaPath, state.InputProtocol, state.IsoMount, state.PlayableStreamFileNames);
- }
+ inputPath = MediaEncoderHelpers.GetInputArgument(
+ _fileSystem,
+ mediaPath,
+ state.IsoMount,
+ state.PlayableStreamFileNames);
+ }
+ else
+ {
+ inputPath = new[] { mediaPath };
}
return _mediaEncoder.GetInputArgument(inputPath, protocol);
@@ -401,18 +424,22 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return "aac -strict experimental";
}
+
if (string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase))
{
return "libmp3lame";
}
+
if (string.Equals(codec, "vorbis", StringComparison.OrdinalIgnoreCase))
{
return "libvorbis";
}
+
if (string.Equals(codec, "wma", StringComparison.OrdinalIgnoreCase))
{
return "wmav2";
}
+
if (string.Equals(codec, "opus", StringComparison.OrdinalIgnoreCase))
{
return "libopus";
@@ -426,54 +453,59 @@ namespace MediaBrowser.Controller.MediaEncoding
/// </summary>
public string GetInputArgument(EncodingJobInfo state, EncodingOptions encodingOptions)
{
- var request = state.BaseRequest;
-
- var arg = string.Format("-i {0}", GetInputPathArgument(state));
+ var arg = new StringBuilder();
- if (state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
+ if (state.IsVideoRequest
+ && string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
{
- if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)
+ var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hwOutputFormat = "vaapi";
+
+ if (hasGraphicalSubs)
{
- if (state.VideoStream != null && state.VideoStream.Width.HasValue)
- {
- // This is hacky but not sure how to get the exact subtitle resolution
- int height = Convert.ToInt32((double)state.VideoStream.Width.Value / 16.0 * 9.0);
+ hwOutputFormat = "yuv420p";
+ }
- arg += string.Format(" -canvas_size {0}:{1}", state.VideoStream.Width.Value.ToString(CultureInfo.InvariantCulture), height.ToString(CultureInfo.InvariantCulture));
- }
+ arg.Append("-hwaccel vaapi -hwaccel_output_format ")
+ .Append(hwOutputFormat)
+ .Append(" -vaapi_device ")
+ .Append(encodingOptions.VaapiDevice)
+ .Append(' ');
+ }
- var subtitlePath = state.SubtitleStream.Path;
+ arg.Append("-i ")
+ .Append(GetInputPathArgument(state));
- if (string.Equals(Path.GetExtension(subtitlePath), ".sub", StringComparison.OrdinalIgnoreCase))
- {
- var idxFile = Path.ChangeExtension(subtitlePath, ".idx");
- if (File.Exists(idxFile))
- {
- subtitlePath = idxFile;
- }
- }
+ if (state.SubtitleStream != null
+ && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode
+ && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)
+ {
+ if (state.VideoStream != null && state.VideoStream.Width.HasValue)
+ {
+ // This is hacky but not sure how to get the exact subtitle resolution
+ int height = Convert.ToInt32(state.VideoStream.Width.Value / 16.0 * 9.0);
- arg += " -i \"" + subtitlePath + "\"";
+ arg.Append(" -canvas_size ")
+ .Append(state.VideoStream.Width.Value.ToString(CultureInfo.InvariantCulture))
+ .Append(':')
+ .Append(height.ToString(CultureInfo.InvariantCulture));
}
- }
- if (state.IsVideoRequest)
- {
- if (GetVideoEncoder(state, encodingOptions).IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1)
- {
- var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
- var hwOutputFormat = "vaapi";
+ var subtitlePath = state.SubtitleStream.Path;
- if (hasGraphicalSubs)
+ if (string.Equals(Path.GetExtension(subtitlePath), ".sub", StringComparison.OrdinalIgnoreCase))
+ {
+ var idxFile = Path.ChangeExtension(subtitlePath, ".idx");
+ if (File.Exists(idxFile))
{
- hwOutputFormat = "yuv420p";
+ subtitlePath = idxFile;
}
-
- arg = "-hwaccel vaapi -hwaccel_output_format " + hwOutputFormat + " -vaapi_device " + encodingOptions.VaapiDevice + " " + arg;
}
+
+ arg.Append(" -i \"").Append(subtitlePath).Append('\"');
}
- return arg.Trim();
+ return arg.ToString();
}
/// <summary>
@@ -485,16 +517,16 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var codec = stream.Codec ?? string.Empty;
- return codec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 ||
- codec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1;
+ return codec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1
+ || codec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1;
}
public bool IsH265(MediaStream stream)
{
var codec = stream.Codec ?? string.Empty;
- return codec.IndexOf("265", StringComparison.OrdinalIgnoreCase) != -1 ||
- codec.IndexOf("hevc", StringComparison.OrdinalIgnoreCase) != -1;
+ return codec.IndexOf("265", StringComparison.OrdinalIgnoreCase) != -1
+ || codec.IndexOf("hevc", StringComparison.OrdinalIgnoreCase) != -1;
}
public string GetBitStreamArgs(MediaStream stream)
@@ -523,27 +555,38 @@ namespace MediaBrowser.Controller.MediaEncoding
{
// With vpx when crf is used, b:v becomes a max rate
// https://trac.ffmpeg.org/wiki/vpxEncodingGuide.
- return string.Format(" -maxrate:v {0} -bufsize:v {1} -b:v {0}", bitrate.Value.ToString(_usCulture), (bitrate.Value * 2).ToString(_usCulture));
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ " -maxrate:v {0} -bufsize:v {1} -b:v {0}",
+ bitrate.Value,
+ bitrate.Value * 2);
}
if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
{
- return string.Format(" -b:v {0}", bitrate.Value.ToString(_usCulture));
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ " -b:v {0}",
+ bitrate.Value);
}
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase) ||
string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase))
{
// h264
- return string.Format(" -maxrate {0} -bufsize {1}",
- bitrate.Value.ToString(_usCulture),
- (bitrate.Value * 2).ToString(_usCulture));
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ " -maxrate {0} -bufsize {1}",
+ bitrate.Value,
+ bitrate.Value * 2);
}
// h264
- return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}",
- bitrate.Value.ToString(_usCulture),
- (bitrate.Value * 2).ToString(_usCulture));
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ " -b:v {0} -maxrate {0} -bufsize {1}",
+ bitrate.Value,
+ bitrate.Value * 2);
}
return string.Empty;
@@ -576,7 +619,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// hls always copies timestamps
var setPtsParam = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive
? string.Empty
- : string.Format(",setpts=PTS -{0}/TB", seconds.ToString(_usCulture));
+ : string.Format(CultureInfo.InvariantCulture, ",setpts=PTS -{0}/TB", seconds);
// TODO
// var fallbackFontPath = Path.Combine(_appPaths.ProgramDataPath, "fonts", "DroidSansFallback.ttf");
@@ -684,6 +727,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
encodeCrf = encodingOptions.H265Crf;
}
+
if (encodeCrf >= 0 && encodeCrf <= 51)
{
param += " -crf " + encodeCrf.ToString(CultureInfo.InvariantCulture);
@@ -695,12 +739,11 @@ namespace MediaBrowser.Controller.MediaEncoding
{
defaultCrf = "28";
}
+
param += " -crf " + defaultCrf;
}
}
-
- // h264 (h264_qsv)
- else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase))
+ else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)) // h264 (h264_qsv)
{
string[] valid_h264_qsv = { "veryslow", "slower", "slow", "medium", "fast", "faster", "veryfast" };
@@ -716,10 +759,8 @@ namespace MediaBrowser.Controller.MediaEncoding
param += " -look_ahead 0";
}
-
- // h264 (h264_nvenc)
- else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase))
+ else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc)
+ || string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase))
{
switch (encodingOptions.EncoderPreset)
{
@@ -750,9 +791,7 @@ namespace MediaBrowser.Controller.MediaEncoding
break;
}
}
-
- // webm
- else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase))
+ else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) // webm
{
// Values 0-3, 0 being highest quality but slower
var profileScore = 0;
@@ -778,18 +817,14 @@ namespace MediaBrowser.Controller.MediaEncoding
qmin,
qmax);
}
-
else if (string.Equals(videoEncoder, "mpeg4", StringComparison.OrdinalIgnoreCase))
{
param += "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2";
}
-
- // asf/wmv
- else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase))
+ else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase)) // asf/wmv
{
param += "-qmin 2";
}
-
else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase))
{
param += "-mbd 2";
@@ -805,21 +840,21 @@ namespace MediaBrowser.Controller.MediaEncoding
var targetVideoCodec = state.ActualOutputVideoCodec;
- var request = state.BaseRequest;
var profile = state.GetRequestedProfiles(targetVideoCodec).FirstOrDefault();
// vaapi does not support Baseline profile, force Constrained Baseline in this case,
// which is compatible (and ugly)
- if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) &&
- profile != null && profile.ToLowerInvariant().Contains("baseline"))
+ if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
+ && profile != null
+ && profile.IndexOf("baseline", StringComparison.OrdinalIgnoreCase) != -1)
{
- profile = "constrained_baseline";
+ profile = "constrained_baseline";
}
if (!string.IsNullOrEmpty(profile))
{
- if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
- !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
+ if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase)
+ && !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
{
// not supported by h264_omx
param += " -profile:v " + profile;
@@ -834,9 +869,9 @@ namespace MediaBrowser.Controller.MediaEncoding
// h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format
// also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307
- if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
{
switch (level)
{
@@ -872,11 +907,11 @@ namespace MediaBrowser.Controller.MediaEncoding
break;
}
}
- // nvenc doesn't decode with param -level set ?!
- else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase))
+ else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase))
{
- // todo param += "";
+ // nvenc doesn't decode with param -level set ?!
+ // TODO:
}
else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase))
{
@@ -894,10 +929,10 @@ namespace MediaBrowser.Controller.MediaEncoding
// todo
}
- if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
- !string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
- !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) &&
- !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
+ if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase)
+ && !string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)
+ && !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
+ && !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
{
param = "-pix_fmt yuv420p " + param;
}
@@ -919,12 +954,10 @@ namespace MediaBrowser.Controller.MediaEncoding
return false;
}
- if (videoStream.IsInterlaced)
+ if (videoStream.IsInterlaced
+ && state.DeInterlace(videoStream.Codec, false))
{
- if (state.DeInterlace(videoStream.Codec, false))
- {
- return false;
- }
+ return false;
}
if (videoStream.IsAnamorphic ?? false)
@@ -936,24 +969,23 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Can't stream copy if we're burning in subtitles
- if (request.SubtitleStreamIndex.HasValue)
+ if (request.SubtitleStreamIndex.HasValue
+ && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
{
- if (state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
- {
- return false;
- }
+ return false;
}
- if (string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase))
+ if (string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase)
+ && videoStream.IsAVC.HasValue
+ && !videoStream.IsAVC.Value
+ && request.RequireAvc)
{
- if (videoStream.IsAVC.HasValue && !videoStream.IsAVC.Value && request.RequireAvc)
- {
- return false;
- }
+ return false;
}
// Source and target codecs must match
- if (string.IsNullOrEmpty(videoStream.Codec) || !state.SupportedVideoCodecs.Contains(videoStream.Codec, StringComparer.OrdinalIgnoreCase))
+ if (string.IsNullOrEmpty(videoStream.Codec)
+ || !state.SupportedVideoCodecs.Contains(videoStream.Codec, StringComparer.OrdinalIgnoreCase))
{
return false;
}
@@ -983,21 +1015,17 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Video width must fall within requested value
- if (request.MaxWidth.HasValue)
+ if (request.MaxWidth.HasValue
+ && (!videoStream.Width.HasValue || videoStream.Width.Value > request.MaxWidth.Value))
{
- if (!videoStream.Width.HasValue || videoStream.Width.Value > request.MaxWidth.Value)
- {
- return false;
- }
+ return false;
}
// Video height must fall within requested value
- if (request.MaxHeight.HasValue)
+ if (request.MaxHeight.HasValue
+ && (!videoStream.Height.HasValue || videoStream.Height.Value > request.MaxHeight.Value))
{
- if (!videoStream.Height.HasValue || videoStream.Height.Value > request.MaxHeight.Value)
- {
- return false;
- }
+ return false;
}
// Video framerate must fall within requested value
@@ -1013,12 +1041,10 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Video bitrate must fall within requested value
- if (request.VideoBitRate.HasValue)
+ if (request.VideoBitRate.HasValue
+ && (!videoStream.BitRate.HasValue || videoStream.BitRate.Value > request.VideoBitRate.Value))
{
- if (!videoStream.BitRate.HasValue || videoStream.BitRate.Value > request.VideoBitRate.Value)
- {
- return false;
- }
+ return false;
}
var maxBitDepth = state.GetRequestedVideoBitDepth(videoStream.Codec);
@@ -1031,35 +1057,31 @@ namespace MediaBrowser.Controller.MediaEncoding
}
var maxRefFrames = state.GetRequestedMaxRefFrames(videoStream.Codec);
- if (maxRefFrames.HasValue)
+ if (maxRefFrames.HasValue
+ && videoStream.RefFrames.HasValue && videoStream.RefFrames.Value > maxRefFrames.Value)
{
- if (videoStream.RefFrames.HasValue && videoStream.RefFrames.Value > maxRefFrames.Value)
- {
- return false;
- }
+ return false;
}
// If a specific level was requested, the source must match or be less than
var level = state.GetRequestedLevel(videoStream.Codec);
- if (!string.IsNullOrEmpty(level))
+ if (!string.IsNullOrEmpty(level)
+ && double.TryParse(level, NumberStyles.Any, _usCulture, out var requestLevel))
{
- if (double.TryParse(level, NumberStyles.Any, _usCulture, out var requestLevel))
+ if (!videoStream.Level.HasValue)
{
- if (!videoStream.Level.HasValue)
- {
- //return false;
- }
+ //return false;
+ }
- if (videoStream.Level.HasValue && videoStream.Level.Value > requestLevel)
- {
- return false;
- }
+ if (videoStream.Level.HasValue && videoStream.Level.Value > requestLevel)
+ {
+ return false;
}
}
- if (string.Equals(state.InputContainer, "avi", StringComparison.OrdinalIgnoreCase) &&
- string.Equals(videoStream.Codec, "h264", StringComparison.OrdinalIgnoreCase) &&
- !(videoStream.IsAVC ?? false))
+ if (string.Equals(state.InputContainer, "avi", StringComparison.OrdinalIgnoreCase)
+ && string.Equals(videoStream.Codec, "h264", StringComparison.OrdinalIgnoreCase)
+ && !(videoStream.IsAVC ?? false))
{
// see Coach S01E01 - Kelly and the Professor(0).avi
return false;
@@ -1068,7 +1090,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return request.EnableAutoStreamCopy;
}
- public bool CanStreamCopyAudio(EncodingJobInfo state, MediaStream audioStream, string[] supportedAudioCodecs)
+ public bool CanStreamCopyAudio(EncodingJobInfo state, MediaStream audioStream, IEnumerable<string> supportedAudioCodecs)
{
var request = state.BaseRequest;
@@ -1078,16 +1100,16 @@ namespace MediaBrowser.Controller.MediaEncoding
}
var maxBitDepth = state.GetRequestedAudioBitDepth(audioStream.Codec);
- if (maxBitDepth.HasValue)
+ if (maxBitDepth.HasValue
+ && audioStream.BitDepth.HasValue
+ && audioStream.BitDepth.Value > maxBitDepth.Value)
{
- if (audioStream.BitDepth.HasValue && audioStream.BitDepth.Value > maxBitDepth.Value)
- {
- return false;
- }
+ return false;
}
// Source and target codecs must match
- if (string.IsNullOrEmpty(audioStream.Codec) || !supportedAudioCodecs.Contains(audioStream.Codec, StringComparer.OrdinalIgnoreCase))
+ if (string.IsNullOrEmpty(audioStream.Codec)
+ || !supportedAudioCodecs.Contains(audioStream.Codec, StringComparer.OrdinalIgnoreCase))
{
return false;
}
@@ -1100,6 +1122,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return false;
}
+
if (audioStream.Channels.Value > channels.Value)
{
return false;
@@ -1113,6 +1136,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return false;
}
+
if (audioStream.SampleRate.Value > request.AudioSampleRate.Value)
{
return false;
@@ -1126,6 +1150,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return false;
}
+
if (audioStream.BitRate.Value > request.AudioBitRate.Value)
{
return false;
@@ -1141,17 +1166,17 @@ namespace MediaBrowser.Controller.MediaEncoding
if (videoStream != null)
{
- var isUpscaling = request.Height.HasValue && videoStream.Height.HasValue &&
- request.Height.Value > videoStream.Height.Value && request.Width.HasValue && videoStream.Width.HasValue &&
- request.Width.Value > videoStream.Width.Value;
+ var isUpscaling = request.Height.HasValue
+ && videoStream.Height.HasValue
+ && request.Height.Value > videoStream.Height.Value
+ && request.Width.HasValue
+ && videoStream.Width.HasValue
+ && request.Width.Value > videoStream.Width.Value;
// Don't allow bitrate increases unless upscaling
- if (!isUpscaling)
+ if (!isUpscaling && bitrate.HasValue && videoStream.BitRate.HasValue)
{
- if (bitrate.HasValue && videoStream.BitRate.HasValue)
- {
- bitrate = GetMinBitrate(videoStream.BitRate.Value, bitrate.Value);
- }
+ bitrate = GetMinBitrate(videoStream.BitRate.Value, bitrate.Value);
}
}
@@ -1179,7 +1204,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
else if (sourceBitrate <= 3000000)
{
- sourceBitrate = Convert.ToInt32(sourceBitrate * 2);
+ sourceBitrate *= 2;
}
var bitrate = Math.Min(sourceBitrate, requestedBitrate);
@@ -1189,12 +1214,13 @@ namespace MediaBrowser.Controller.MediaEncoding
private static double GetVideoBitrateScaleFactor(string codec)
{
- if (StringHelper.EqualsIgnoreCase(codec, "h265") ||
- StringHelper.EqualsIgnoreCase(codec, "hevc") ||
- StringHelper.EqualsIgnoreCase(codec, "vp9"))
+ if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase))
{
return .5;
}
+
return 1;
}
@@ -1221,9 +1247,7 @@ namespace MediaBrowser.Controller.MediaEncoding
scaleFactor = Math.Max(scaleFactor, 2);
}
- var newBitrate = scaleFactor * bitrate;
-
- return Convert.ToInt32(newBitrate);
+ return Convert.ToInt32(scaleFactor * bitrate);
}
public int? GetAudioBitrateParam(BaseEncodingJobOptions request, MediaStream audioStream)
@@ -1235,7 +1259,6 @@ namespace MediaBrowser.Controller.MediaEncoding
// Don't encode any higher than this
return Math.Min(384000, request.AudioBitRate.Value);
- //return Math.Min(currentBitrate, request.AudioBitRate.Value);
}
return null;
@@ -1248,12 +1271,14 @@ namespace MediaBrowser.Controller.MediaEncoding
var filters = new List<string>();
// Boost volume to 200% when downsampling from 6ch to 2ch
- if (channels.HasValue && channels.Value <= 2)
+ if (channels.HasValue
+ && channels.Value <= 2
+ && state.AudioStream != null
+ && state.AudioStream.Channels.HasValue
+ && state.AudioStream.Channels.Value > 5
+ && !encodingOptions.DownMixAudioBoost.Equals(1))
{
- if (state.AudioStream != null && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5 && !encodingOptions.DownMixAudioBoost.Equals(1))
- {
- filters.Add("volume=" + encodingOptions.DownMixAudioBoost.ToString(_usCulture));
- }
+ filters.Add("volume=" + encodingOptions.DownMixAudioBoost.ToString(_usCulture));
}
var isCopyingTimestamps = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive;
@@ -1261,12 +1286,16 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var seconds = TimeSpan.FromTicks(state.StartTimeTicks ?? 0).TotalSeconds;
- filters.Add(string.Format("asetpts=PTS-{0}/TB", Math.Round(seconds).ToString(_usCulture)));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "asetpts=PTS-{0}/TB",
+ Math.Round(seconds)));
}
if (filters.Count > 0)
{
- return "-af \"" + string.Join(",", filters.ToArray()) + "\"";
+ return "-af \"" + string.Join(",", filters) + "\"";
}
return string.Empty;
@@ -1283,18 +1312,17 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var request = state.BaseRequest;
- var inputChannels = audioStream == null
- ? null
- : audioStream.Channels;
+ var inputChannels = audioStream?.Channels;
if (inputChannels <= 0)
{
inputChannels = null;
}
- int? transcoderChannelLimit = null;
var codec = outputAudioCodec ?? string.Empty;
+
+ int? transcoderChannelLimit;
if (codec.IndexOf("wma", StringComparison.OrdinalIgnoreCase) != -1)
{
// wmav2 currently only supports two channel output
@@ -1343,6 +1371,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return val2;
}
+
if (!val2.HasValue)
{
return val1;
@@ -1416,7 +1445,10 @@ namespace MediaBrowser.Controller.MediaEncoding
if (state.VideoStream != null)
{
- args += string.Format("-map 0:{0}", state.VideoStream.Index);
+ args += string.Format(
+ CultureInfo.InvariantCulture,
+ "-map 0:{0}",
+ state.VideoStream.Index);
}
else
{
@@ -1426,7 +1458,10 @@ namespace MediaBrowser.Controller.MediaEncoding
if (state.AudioStream != null)
{
- args += string.Format(" -map 0:{0}", state.AudioStream.Index);
+ args += string.Format(
+ CultureInfo.InvariantCulture,
+ " -map 0:{0}",
+ state.AudioStream.Index);
}
else
@@ -1441,7 +1476,10 @@ namespace MediaBrowser.Controller.MediaEncoding
}
else if (subtitleMethod == SubtitleDeliveryMethod.Embed)
{
- args += string.Format(" -map 0:{0}", state.SubtitleStream.Index);
+ args += string.Format(
+ CultureInfo.InvariantCulture,
+ " -map 0:{0}",
+ state.SubtitleStream.Index);
}
else if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)
{
@@ -1493,7 +1531,10 @@ namespace MediaBrowser.Controller.MediaEncoding
var request = state.BaseRequest;
// Add resolution params, if specified
- if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue)
+ if (request.Width.HasValue
+ || request.Height.HasValue
+ || request.MaxHeight.HasValue
+ || request.MaxWidth.HasValue)
{
outputSizeParam = GetOutputSizeParam(state, options, outputVideoCodec).TrimEnd('"');
@@ -1515,12 +1556,15 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
- if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && outputSizeParam.Length == 0)
+ if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
+ && outputSizeParam.Length == 0)
{
outputSizeParam = ",format=nv12|vaapi,hwupload";
// Add parameters to use VAAPI with burn-in subttiles (GH issue #642)
- if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) {
+ if (state.SubtitleStream != null
+ && state.SubtitleStream.IsTextSubtitleStream
+ && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) {
outputSizeParam += ",hwmap=mode=read+write+direct";
}
}
@@ -1529,7 +1573,11 @@ namespace MediaBrowser.Controller.MediaEncoding
if (state.VideoStream != null && state.VideoStream.Width.HasValue && state.VideoStream.Height.HasValue)
{
- videoSizeParam = string.Format("scale={0}:{1}", state.VideoStream.Width.Value.ToString(_usCulture), state.VideoStream.Height.Value.ToString(_usCulture));
+ videoSizeParam = string.Format(
+ CultureInfo.InvariantCulture,
+ "scale={0}:{1}",
+ state.VideoStream.Width.Value,
+ state.VideoStream.Height.Value);
videoSizeParam += ":force_original_aspect_ratio=decrease";
}
@@ -1542,15 +1590,18 @@ namespace MediaBrowser.Controller.MediaEncoding
? 0
: state.SubtitleStream.Index;
- return string.Format(" -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\"",
- mapPrefix.ToString(_usCulture),
- subtitleStreamIndex.ToString(_usCulture),
- state.VideoStream.Index.ToString(_usCulture),
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\"",
+ mapPrefix,
+ subtitleStreamIndex,
+ state.VideoStream.Index,
outputSizeParam,
videoSizeParam);
}
- private ValueTuple<int?, int?> GetFixedOutputSize(int? videoWidth,
+ private (int? width, int? height) GetFixedOutputSize(
+ int? videoWidth,
int? videoHeight,
int? requestedWidth,
int? requestedHeight,
@@ -1559,11 +1610,11 @@ namespace MediaBrowser.Controller.MediaEncoding
{
if (!videoWidth.HasValue && !requestedWidth.HasValue)
{
- return new ValueTuple<int?, int?>(null, null);
+ return (null, null);
}
if (!videoHeight.HasValue && !requestedHeight.HasValue)
{
- return new ValueTuple<int?, int?>(null, null);
+ return (null, null);
}
decimal inputWidth = Convert.ToDecimal(videoWidth ?? requestedWidth);
@@ -1583,7 +1634,7 @@ namespace MediaBrowser.Controller.MediaEncoding
outputWidth = 2 * Math.Truncate(outputWidth / 2);
outputHeight = 2 * Math.Truncate(outputHeight / 2);
- return new ValueTuple<int?, int?>(Convert.ToInt32(outputWidth), Convert.ToInt32(outputHeight));
+ return (Convert.ToInt32(outputWidth), Convert.ToInt32(outputHeight));
}
public List<string> GetScalingFilters(int? videoWidth,
@@ -1597,9 +1648,17 @@ namespace MediaBrowser.Controller.MediaEncoding
int? requestedMaxHeight)
{
var filters = new List<string>();
- var fixedOutputSize = GetFixedOutputSize(videoWidth, videoHeight, requestedWidth, requestedHeight, requestedMaxWidth, requestedMaxHeight);
-
- if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && fixedOutputSize.Item1.HasValue && fixedOutputSize.Item2.HasValue)
+ var (width, height) = GetFixedOutputSize(
+ videoWidth,
+ videoHeight,
+ requestedWidth,
+ requestedHeight,
+ requestedMaxWidth,
+ requestedMaxHeight);
+
+ if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
+ && width.HasValue
+ && height.HasValue)
{
// Work around vaapi's reduced scaling features
var scaler = "scale_vaapi";
@@ -1607,15 +1666,26 @@ namespace MediaBrowser.Controller.MediaEncoding
// Given the input dimensions (inputWidth, inputHeight), determine the output dimensions
// (outputWidth, outputHeight). The user may request precise output dimensions or maximum
// output dimensions. Output dimensions are guaranteed to be even.
- var outputWidth = fixedOutputSize.Item1.Value;
- var outputHeight = fixedOutputSize.Item2.Value;
+ var outputWidth = width.Value;
+ var outputHeight = height.Value;
- if (!videoWidth.HasValue || outputWidth != videoWidth.Value || !videoHeight.HasValue || outputHeight != videoHeight.Value)
+ if (!videoWidth.HasValue
+ || outputWidth != videoWidth.Value
+ || !videoHeight.HasValue
+ || outputHeight != videoHeight.Value)
{
- filters.Add(string.Format("{0}=w={1}:h={2}", scaler, outputWidth.ToString(_usCulture), outputHeight.ToString(_usCulture)));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "{0}=w={1}:h={2}",
+ scaler,
+ outputWidth,
+ outputHeight));
}
}
- else if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1 && fixedOutputSize.Item1.HasValue && fixedOutputSize.Item2.HasValue)
+ else if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1
+ && width.HasValue
+ && height.HasValue)
{
// Nothing to do, it's handled as an input resize filter
}
@@ -1631,7 +1701,12 @@ namespace MediaBrowser.Controller.MediaEncoding
var widthParam = requestedWidth.Value.ToString(_usCulture);
var heightParam = requestedHeight.Value.ToString(_usCulture);
- filters.Add(string.Format("scale=trunc({0}/64)*64:trunc({1}/2)*2", widthParam, heightParam));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "scale=trunc({0}/64)*64:trunc({1}/2)*2",
+ widthParam,
+ heightParam));
}
else
{
@@ -1647,11 +1722,21 @@ namespace MediaBrowser.Controller.MediaEncoding
if (isExynosV4L2)
{
- filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/64)*64:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/64)*64:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2",
+ maxWidthParam,
+ maxHeightParam));
}
else
{
- filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2",
+ maxWidthParam,
+ maxHeightParam));
}
}
@@ -1667,7 +1752,11 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var widthParam = requestedWidth.Value.ToString(_usCulture);
- filters.Add(string.Format("scale={0}:trunc(ow/a/2)*2", widthParam));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "scale={0}:trunc(ow/a/2)*2",
+ widthParam));
}
}
@@ -1678,11 +1767,19 @@ namespace MediaBrowser.Controller.MediaEncoding
if (isExynosV4L2)
{
- filters.Add(string.Format("scale=trunc(oh*a/64)*64:{0}", heightParam));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "scale=trunc(oh*a/64)*64:{0}",
+ heightParam));
}
else
{
- filters.Add(string.Format("scale=trunc(oh*a/2)*2:{0}", heightParam));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "scale=trunc(oh*a/2)*2:{0}",
+ heightParam));
}
}
@@ -1693,11 +1790,19 @@ namespace MediaBrowser.Controller.MediaEncoding
if (isExynosV4L2)
{
- filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/64)*64:trunc(ow/dar/2)*2", maxWidthParam));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "scale=trunc(min(max(iw\\,ih*dar)\\,{0})/64)*64:trunc(ow/dar/2)*2",
+ maxWidthParam));
}
else
{
- filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2",
+ maxWidthParam));
}
}
@@ -1708,11 +1813,19 @@ namespace MediaBrowser.Controller.MediaEncoding
if (isExynosV4L2)
{
- filters.Add(string.Format("scale=trunc(oh*a/64)*64:min(max(iw/dar\\,ih)\\,{0})", maxHeightParam));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "scale=trunc(oh*a/64)*64:min(max(iw/dar\\,ih)\\,{0})",
+ maxHeightParam));
}
else
{
- filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(max(iw/dar\\,ih)\\,{0})", maxHeightParam));
+ filters.Add(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "scale=trunc(oh*a/2)*2:min(max(iw/dar\\,ih)\\,{0})",
+ maxHeightParam));
}
}
}
@@ -1722,8 +1835,8 @@ namespace MediaBrowser.Controller.MediaEncoding
private string GetFixedSizeScalingFilter(Video3DFormat? threedFormat, int requestedWidth, int requestedHeight)
{
- var widthParam = requestedWidth.ToString(_usCulture);
- var heightParam = requestedHeight.ToString(_usCulture);
+ var widthParam = requestedWidth.ToString(CultureInfo.InvariantCulture);
+ var heightParam = requestedHeight.ToString(CultureInfo.InvariantCulture);
string filter = null;
@@ -1765,13 +1878,14 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
- return string.Format(filter, widthParam, heightParam);
+ return string.Format(CultureInfo.InvariantCulture, filter, widthParam, heightParam);
}
/// <summary>
/// If we're going to put a fixed size on the command line, this will calculate it
/// </summary>
- public string GetOutputSizeParam(EncodingJobInfo state,
+ public string GetOutputSizeParam(
+ EncodingJobInfo state,
EncodingOptions options,
string outputVideoCodec,
bool allowTimeStampCopy = true)
@@ -1780,25 +1894,45 @@ namespace MediaBrowser.Controller.MediaEncoding
var request = state.BaseRequest;
+ var videoStream = state.VideoStream;
var filters = new List<string>();
+ // If we're hardware VAAPI decoding and software encoding, download frames from the decoder first
+ var hwType = options.HardwareAccelerationType ?? string.Empty;
+ if (string.Equals(hwType, "vaapi", StringComparison.OrdinalIgnoreCase) && !options.EnableHardwareEncoding )
+ {
+ filters.Add("hwdownload");
+
+ // If transcoding from 10 bit, transform colour spaces too
+ if (!string.IsNullOrEmpty(videoStream.PixelFormat)
+ && videoStream.PixelFormat.IndexOf("p10", StringComparison.OrdinalIgnoreCase) != -1
+ && string.Equals(outputVideoCodec,"libx264", StringComparison.OrdinalIgnoreCase))
+ {
+ filters.Add("format=p010le");
+ filters.Add("format=nv12");
+ }
+ else
+ {
+ filters.Add("format=nv12");
+ }
+ }
+
if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
filters.Add("format=nv12|vaapi");
filters.Add("hwupload");
}
- if (state.DeInterlace("h264", true) && string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
+ if (state.DeInterlace("h264", true)
+ && string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
- filters.Add(string.Format("deinterlace_vaapi"));
+ filters.Add(string.Format(CultureInfo.InvariantCulture, "deinterlace_vaapi"));
}
- var videoStream = state.VideoStream;
-
- if ((state.DeInterlace("h264", true) || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true)) &&
- !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
+ if ((state.DeInterlace("h264", true) || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true))
+ && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
- var inputFramerate = videoStream == null ? null : videoStream.RealFrameRate;
+ var inputFramerate = videoStream?.RealFrameRate;
// If it is already 60fps then it will create an output framerate that is much too high for roku and others to handle
if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase) && (inputFramerate ?? 60) <= 30)
@@ -1811,11 +1945,11 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
- var inputWidth = videoStream == null ? null : videoStream.Width;
- var inputHeight = videoStream == null ? null : videoStream.Height;
+ var inputWidth = videoStream?.Width;
+ var inputHeight = videoStream?.Height;
var threeDFormat = state.MediaSource.Video3DFormat;
- var videoDecoder = this.GetHardwareAcceleratedVideoDecoder(state, options);
+ var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options);
filters.AddRange(GetScalingFilters(inputWidth, inputHeight, threeDFormat, videoDecoder, outputVideoCodec, request.Width, request.Height, request.MaxWidth, request.MaxHeight));
@@ -1833,6 +1967,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
filters.Add("hwmap");
}
+
if (allowTimeStampCopy)
{
output += " -copyts";
@@ -1841,7 +1976,10 @@ namespace MediaBrowser.Controller.MediaEncoding
if (filters.Count > 0)
{
- output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray()));
+ output += string.Format(
+ CultureInfo.InvariantCulture,
+ " -vf \"{0}\"",
+ string.Join(",", filters));
}
return output;
@@ -1889,7 +2027,8 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
- if (state.AudioStream != null && CanStreamCopyAudio(state, state.AudioStream, state.SupportedAudioCodecs))
+ if (state.AudioStream != null
+ && CanStreamCopyAudio(state, state.AudioStream, state.SupportedAudioCodecs))
{
state.OutputAudioCodec = "copy";
}
@@ -1906,14 +2045,10 @@ namespace MediaBrowser.Controller.MediaEncoding
}
public static string GetProbeSizeArgument(int numInputFiles)
- {
- return numInputFiles > 1 ? "-probesize 1G" : "";
- }
+ => numInputFiles > 1 ? "-probesize 1G" : "";
public static string GetAnalyzeDurationArgument(int numInputFiles)
- {
- return numInputFiles > 1 ? "-analyzeduration 200M" : "";
- }
+ => numInputFiles > 1 ? "-analyzeduration 200M" : "";
public string GetInputModifier(EncodingJobInfo state, EncodingOptions encodingOptions)
{
@@ -1981,18 +2116,22 @@ namespace MediaBrowser.Controller.MediaEncoding
{
flags.Add("+igndts");
}
+
if (state.IgnoreInputIndex)
{
flags.Add("+ignidx");
}
+
if (state.GenPtsInput || string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
{
flags.Add("+genpts");
}
+
if (state.DiscardCorruptFramesInput)
{
flags.Add("+discardcorrupt");
}
+
if (state.EnableFastSeekInput)
{
flags.Add("+fastseek");
@@ -2000,24 +2139,33 @@ namespace MediaBrowser.Controller.MediaEncoding
if (flags.Count > 0)
{
- inputModifier += " -fflags " + string.Join("", flags.ToArray());
+ inputModifier += " -fflags " + string.Join(string.Empty, flags);
}
- var videoDecoder = this.GetHardwareAcceleratedVideoDecoder(state, encodingOptions);
+ var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions);
if (!string.IsNullOrEmpty(videoDecoder))
{
inputModifier += " " + videoDecoder;
- var videoStream = state.VideoStream;
- var inputWidth = videoStream == null ? null : videoStream.Width;
- var inputHeight = videoStream == null ? null : videoStream.Height;
- var request = state.BaseRequest;
+ if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ var videoStream = state.VideoStream;
+ var inputWidth = videoStream?.Width;
+ var inputHeight = videoStream?.Height;
+ var request = state.BaseRequest;
- var fixedOutputSize = GetFixedOutputSize(inputWidth, inputHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight);
+ var (width, height) = GetFixedOutputSize(inputWidth, inputHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight);
- if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1 && fixedOutputSize.Item1.HasValue && fixedOutputSize.Item2.HasValue)
- {
- inputModifier += string.Format(" -resize {0}x{1}", fixedOutputSize.Item1.Value.ToString(_usCulture), fixedOutputSize.Item2.Value.ToString(_usCulture));
+ if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1
+ && width.HasValue
+ && height.HasValue)
+ {
+ inputModifier += string.Format(
+ CultureInfo.InvariantCulture,
+ " -resize {0}x{1}",
+ width.Value,
+ height.Value);
+ }
}
}
@@ -2026,9 +2174,9 @@ namespace MediaBrowser.Controller.MediaEncoding
var outputVideoCodec = GetVideoEncoder(state, encodingOptions);
// Important: If this is ever re-enabled, make sure not to use it with wtv because it breaks seeking
- if (!string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase) &&
- state.TranscodingType != TranscodingJobType.Progressive &&
- state.EnableBreakOnNonKeyFrames(outputVideoCodec))
+ if (!string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase)
+ && state.TranscodingType != TranscodingJobType.Progressive
+ && state.EnableBreakOnNonKeyFrames(outputVideoCodec))
{
inputModifier += " -noaccurate_seek";
}
@@ -2052,14 +2200,16 @@ namespace MediaBrowser.Controller.MediaEncoding
}
- public void AttachMediaSourceInfo(EncodingJobInfo state,
- MediaSourceInfo mediaSource,
- string requestedUrl)
+ public void AttachMediaSourceInfo(
+ EncodingJobInfo state,
+ MediaSourceInfo mediaSource,
+ string requestedUrl)
{
if (state == null)
{
throw new ArgumentNullException(nameof(state));
}
+
if (mediaSource == null)
{
throw new ArgumentNullException(nameof(mediaSource));
@@ -2117,15 +2267,16 @@ namespace MediaBrowser.Controller.MediaEncoding
state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate;
- if (state.ReadInputAtNativeFramerate ||
- mediaSource.Protocol == MediaProtocol.File && string.Equals(mediaSource.Container, "wtv", StringComparison.OrdinalIgnoreCase))
+ if (state.ReadInputAtNativeFramerate
+ || mediaSource.Protocol == MediaProtocol.File
+ && string.Equals(mediaSource.Container, "wtv", StringComparison.OrdinalIgnoreCase))
{
state.InputVideoSync = "-1";
state.InputAudioSync = "1";
}
- if (string.Equals(mediaSource.Container, "wma", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(mediaSource.Container, "asf", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(mediaSource.Container, "wma", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(mediaSource.Container, "asf", StringComparison.OrdinalIgnoreCase))
{
// Seeing some stuttering when transcoding wma to audio-only HLS
state.InputAudioSync = "1";
@@ -2237,7 +2388,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return null;
}
- return this.GetHardwareAcceleratedVideoDecoder(state.MediaSource.VideoType ?? VideoType.VideoFile, state.VideoStream, encodingOptions);
+ return GetHardwareAcceleratedVideoDecoder(state.MediaSource.VideoType ?? VideoType.VideoFile, state.VideoStream, encodingOptions);
}
public string GetHardwareAcceleratedVideoDecoder(VideoType videoType, MediaStream videoStream, EncodingOptions encodingOptions)
@@ -2250,9 +2401,9 @@ namespace MediaBrowser.Controller.MediaEncoding
return null;
}
- if (videoStream != null &&
- !string.IsNullOrEmpty(videoStream.Codec) &&
- !string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType))
+ if (videoStream != null
+ && !string.IsNullOrEmpty(videoStream.Codec)
+ && !string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType))
{
if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
{
@@ -2450,11 +2601,7 @@ namespace MediaBrowser.Controller.MediaEncoding
codec = format;
}
- var args = " -codec:s:0 " + codec;
-
- args += " -disposition:s:0 default";
-
- return args;
+ return " -codec:s:0 " + codec + " -disposition:s:0 default";
}
public string GetProgressiveVideoFullCommandLine(EncodingJobInfo state, EncodingOptions encodingOptions, string outputPath, string defaultPreset)
@@ -2465,8 +2612,8 @@ namespace MediaBrowser.Controller.MediaEncoding
var format = string.Empty;
var keyFrame = string.Empty;
- if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase) &&
- state.BaseRequest.Context == EncodingContext.Streaming)
+ if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase)
+ && state.BaseRequest.Context == EncodingContext.Streaming)
{
// Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js
format = " -f mp4 -movflags frag_keyframe+empty_moov";
@@ -2476,7 +2623,9 @@ namespace MediaBrowser.Controller.MediaEncoding
var inputModifier = GetInputModifier(state, encodingOptions);
- return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -map_chapters -1 -threads {5} {6}{7}{8} -y \"{9}\"",
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} {1}{2} {3} {4} -map_metadata -1 -map_chapters -1 -threads {5} {6}{7}{8} -y \"{9}\"",
inputModifier,
GetInputArgument(state, encodingOptions),
keyFrame,
@@ -2486,8 +2635,7 @@ namespace MediaBrowser.Controller.MediaEncoding
GetProgressiveVideoAudioArguments(state, encodingOptions),
GetSubtitleEmbedArguments(state),
format,
- outputPath
- ).Trim();
+ outputPath).Trim();
}
public string GetOutputFFlags(EncodingJobInfo state)
@@ -2500,7 +2648,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (flags.Count > 0)
{
- return " -fflags " + string.Join("", flags.ToArray());
+ return " -fflags " + string.Join("", flags);
}
return string.Empty;
@@ -2517,9 +2665,9 @@ namespace MediaBrowser.Controller.MediaEncoding
if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase))
{
- if (state.VideoStream != null &&
- string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) &&
- !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
+ if (state.VideoStream != null
+ && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase)
+ && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
{
string bitStreamArgs = GetBitStreamArgs(state.VideoStream);
if (!string.IsNullOrEmpty(bitStreamArgs))
@@ -2540,8 +2688,10 @@ namespace MediaBrowser.Controller.MediaEncoding
}
else
{
- var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"",
- 5.ToString(_usCulture));
+ var keyFrameArg = string.Format(
+ CultureInfo.InvariantCulture,
+ " -force_key_frames \"expr:gte(t,n_forced*{0})\"",
+ 5);
args += keyFrameArg;
@@ -2562,6 +2712,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
args += " -copyts";
}
+
args += " -avoid_negative_ts disabled -start_at_zero";
}
@@ -2662,39 +2813,22 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
- var albumCoverInput = string.Empty;
- var mapArgs = string.Empty;
- var metadata = string.Empty;
- var vn = string.Empty;
-
- var hasArt = !string.IsNullOrEmpty(state.AlbumCoverPath);
- hasArt = false;
-
- if (hasArt)
- {
- albumCoverInput = " -i \"" + state.AlbumCoverPath + "\"";
- mapArgs = " -map 0:a -map 1:v -c:1:v copy";
- metadata = " -metadata:s:v title=\"Album cover\" -metadata:s:v comment=\"Cover(Front)\"";
- }
- else
- {
- vn = " -vn";
- }
-
var threads = GetNumberOfThreads(state, encodingOptions, null);
var inputModifier = GetInputModifier(state, encodingOptions);
- return string.Format("{0} {1}{7}{8} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1{6} -y \"{5}\"",
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} {1}{7}{8} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1{6} -y \"{5}\"",
inputModifier,
GetInputArgument(state, encodingOptions),
threads,
- vn,
- string.Join(" ", audioTranscodeParams.ToArray()),
+ " -vn",
+ string.Join(" ", audioTranscodeParams),
outputPath,
- metadata,
- albumCoverInput,
- mapArgs).Trim();
+ string.Empty,
+ string.Empty,
+ string.Empty).Trim();
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
index 7f842c1d0..5cedc3d57 100644
--- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
+++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
@@ -1,8 +1,8 @@
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using MediaBrowser.Model.IO;
-using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Controller.MediaEncoding
{
@@ -16,31 +16,26 @@ namespace MediaBrowser.Controller.MediaEncoding
/// </summary>
/// <param name="fileSystem">The file system.</param>
/// <param name="videoPath">The video path.</param>
- /// <param name="protocol">The protocol.</param>
/// <param name="isoMount">The iso mount.</param>
/// <param name="playableStreamFileNames">The playable stream file names.</param>
- /// <returns>System.String[][].</returns>
- public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, MediaProtocol protocol, IIsoMount isoMount, string[] playableStreamFileNames)
+ /// <returns>string[].</returns>
+ public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, IIsoMount isoMount, IReadOnlyCollection<string> playableStreamFileNames)
{
- if (playableStreamFileNames.Length > 0)
+ if (playableStreamFileNames.Count > 0)
{
if (isoMount == null)
{
return GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames);
}
+
return GetPlayableStreamFiles(fileSystem, isoMount.MountedPath, playableStreamFileNames);
}
return new[] { videoPath };
}
- private static string[] GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, string[] filenames)
+ private static string[] GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, IEnumerable<string> filenames)
{
- if (filenames.Length == 0)
- {
- return new string[] { };
- }
-
var allFiles = fileSystem
.GetFilePaths(rootPath, true)
.ToArray();
diff --git a/MediaBrowser.Controller/Providers/AlbumInfo.cs b/MediaBrowser.Controller/Providers/AlbumInfo.cs
index b0b443fc0..ac6b86c1d 100644
--- a/MediaBrowser.Controller/Providers/AlbumInfo.cs
+++ b/MediaBrowser.Controller/Providers/AlbumInfo.cs
@@ -9,7 +9,7 @@ namespace MediaBrowser.Controller.Providers
/// Gets or sets the album artist.
/// </summary>
/// <value>The album artist.</value>
- public string[] AlbumArtists { get; set; }
+ public IReadOnlyList<string> AlbumArtists { get; set; }
/// <summary>
/// Gets or sets the artist provider ids.
diff --git a/MediaBrowser.Controller/Providers/MusicVideoInfo.cs b/MediaBrowser.Controller/Providers/MusicVideoInfo.cs
index 194b26484..9835351fc 100644
--- a/MediaBrowser.Controller/Providers/MusicVideoInfo.cs
+++ b/MediaBrowser.Controller/Providers/MusicVideoInfo.cs
@@ -1,7 +1,9 @@
+using System.Collections.Generic;
+
namespace MediaBrowser.Controller.Providers
{
public class MusicVideoInfo : ItemLookupInfo
{
- public string[] Artists { get; set; }
+ public IReadOnlyList<string> Artists { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Providers/SongInfo.cs b/MediaBrowser.Controller/Providers/SongInfo.cs
index 61e950130..50615b0bd 100644
--- a/MediaBrowser.Controller/Providers/SongInfo.cs
+++ b/MediaBrowser.Controller/Providers/SongInfo.cs
@@ -1,12 +1,15 @@
using System;
+using System.Collections.Generic;
namespace MediaBrowser.Controller.Providers
{
public class SongInfo : ItemLookupInfo
{
- public string[] AlbumArtists { get; set; }
+ public IReadOnlyList<string> AlbumArtists { get; set; }
+
public string Album { get; set; }
- public string[] Artists { get; set; }
+
+ public IReadOnlyList<string> Artists { get; set; }
public SongInfo()
{
diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
index 30a33b729..19009e577 100644
--- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
@@ -228,7 +228,7 @@ namespace MediaBrowser.LocalMetadata.Savers
}
}
- if (item.RemoteTrailers.Length > 0)
+ if (item.RemoteTrailers.Count > 0)
{
writer.WriteStartElement("Trailers");
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index a8874b6d0..75bb960c3 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -303,7 +303,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
var extractChapters = request.MediaType == DlnaProfileType.Video && request.ExtractChapters;
- var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.MediaSource.Path, request.MediaSource.Protocol, request.MountedIso, request.PlayableStreamFileNames);
+ var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.MediaSource.Path, request.MountedIso, request.PlayableStreamFileNames);
var probeSize = EncodingHelper.GetProbeSizeArgument(inputFiles.Length);
string analyzeDuration;
diff --git a/MediaBrowser.Model/Cryptography/PasswordHash.cs b/MediaBrowser.Model/Cryptography/PasswordHash.cs
index 4bcf0c117..6e66f2088 100644
--- a/MediaBrowser.Model/Cryptography/PasswordHash.cs
+++ b/MediaBrowser.Model/Cryptography/PasswordHash.cs
@@ -69,6 +69,13 @@ namespace MediaBrowser.Model.Cryptography
}
}
+ public PasswordHash(ICryptoProvider cryptoProvider)
+ {
+ _id = cryptoProvider.DefaultHashMethod;
+ _salt = cryptoProvider.GenerateSalt();
+ _hash = Array.Empty<Byte>();
+ }
+
public string Id { get => _id; set => _id = value; }
public Dictionary<string, string> Parameters { get => _parameters; set => _parameters = value; }
@@ -77,13 +84,6 @@ namespace MediaBrowser.Model.Cryptography
public byte[] Hash { get => _hash; set => _hash = value; }
- public PasswordHash(ICryptoProvider cryptoProvider)
- {
- _id = cryptoProvider.DefaultHashMethod;
- _salt = cryptoProvider.GenerateSalt();
- _hash = Array.Empty<Byte>();
- }
-
// TODO: move this class and use the HexHelper class
public static byte[] ConvertFromByteString(string byteString)
{
@@ -127,7 +127,7 @@ namespace MediaBrowser.Model.Cryptography
str.Append(_id);
SerializeParameters(str);
- if (_salt.Length == 0)
+ if (_salt.Length != 0)
{
str.Append('$');
str.Append(ConvertToByteString(_salt));
diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs
index b382d9d4a..4da5508b4 100644
--- a/MediaBrowser.Model/Dto/BaseItemDto.cs
+++ b/MediaBrowser.Model/Dto/BaseItemDto.cs
@@ -234,7 +234,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the trailer urls.
/// </summary>
/// <value>The trailer urls.</value>
- public MediaUrl[] RemoteTrailers { get; set; }
+ public IReadOnlyCollection<MediaUrl> RemoteTrailers { get; set; }
/// <summary>
/// Gets or sets the provider ids.
@@ -386,7 +386,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the artists.
/// </summary>
/// <value>The artists.</value>
- public string[] Artists { get; set; }
+ public IReadOnlyList<string> Artists { get; set; }
/// <summary>
/// Gets or sets the artist items.
diff --git a/MediaBrowser.Model/Dto/RecommendationDto.cs b/MediaBrowser.Model/Dto/RecommendationDto.cs
index 0a890573b..acfb85e9b 100644
--- a/MediaBrowser.Model/Dto/RecommendationDto.cs
+++ b/MediaBrowser.Model/Dto/RecommendationDto.cs
@@ -1,10 +1,11 @@
using System;
+using System.Collections.Generic;
namespace MediaBrowser.Model.Dto
{
public class RecommendationDto
{
- public BaseItemDto[] Items { get; set; }
+ public IReadOnlyCollection<BaseItemDto> Items { get; set; }
public RecommendationType RecommendationType { get; set; }
diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs
index d7bf956bb..de5e58d22 100644
--- a/MediaBrowser.Model/Net/MimeTypes.cs
+++ b/MediaBrowser.Model/Net/MimeTypes.cs
@@ -120,6 +120,7 @@ namespace MediaBrowser.Model.Net
{ ".m4b", "audio/m4b" },
{ ".xsp", "audio/xsp" },
{ ".dsp", "audio/dsp" },
+ { ".flac", "audio/flac" },
};
private static readonly Dictionary<string, string> _extensionLookup = CreateExtensionLookup();
diff --git a/MediaBrowser.Model/Querying/QueryResult.cs b/MediaBrowser.Model/Querying/QueryResult.cs
index e81f2b868..c007a45d6 100644
--- a/MediaBrowser.Model/Querying/QueryResult.cs
+++ b/MediaBrowser.Model/Querying/QueryResult.cs
@@ -1,3 +1,6 @@
+using System;
+using System.Collections.Generic;
+
namespace MediaBrowser.Model.Querying
{
public class QueryResult<T>
@@ -6,7 +9,7 @@ namespace MediaBrowser.Model.Querying
/// Gets or sets the items.
/// </summary>
/// <value>The items.</value>
- public T[] Items { get; set; }
+ public IReadOnlyList<T> Items { get; set; }
/// <summary>
/// The total number of records available
@@ -16,7 +19,7 @@ namespace MediaBrowser.Model.Querying
public QueryResult()
{
- Items = new T[] { };
+ Items = Array.Empty<T>();
}
}
}
diff --git a/MediaBrowser.Model/Search/SearchHint.cs b/MediaBrowser.Model/Search/SearchHint.cs
index 8a187f18e..8f4824903 100644
--- a/MediaBrowser.Model/Search/SearchHint.cs
+++ b/MediaBrowser.Model/Search/SearchHint.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace MediaBrowser.Model.Search
{
@@ -111,6 +112,7 @@ namespace MediaBrowser.Model.Search
/// </summary>
/// <value>The album.</value>
public string Album { get; set; }
+
public Guid AlbumId { get; set; }
/// <summary>
@@ -123,7 +125,7 @@ namespace MediaBrowser.Model.Search
/// Gets or sets the artists.
/// </summary>
/// <value>The artists.</value>
- public string[] Artists { get; set; }
+ public IReadOnlyList<string> Artists { get; set; }
/// <summary>
/// Gets or sets the song count.
diff --git a/MediaBrowser.Providers/Books/AudioBookMetadataService.cs b/MediaBrowser.Providers/Books/AudioBookMetadataService.cs
index 4820e12ab..0062d5ab3 100644
--- a/MediaBrowser.Providers/Books/AudioBookMetadataService.cs
+++ b/MediaBrowser.Providers/Books/AudioBookMetadataService.cs
@@ -11,14 +11,31 @@ namespace MediaBrowser.Providers.Books
{
public class AudioBookMetadataService : MetadataService<AudioBook, SongInfo>
{
- protected override void MergeData(MetadataResult<AudioBook> source, MetadataResult<AudioBook> target, MetadataFields[] lockedFields, bool replaceData, bool mergeMetadataSettings)
+ public AudioBookMetadataService(
+ IServerConfigurationManager serverConfigurationManager,
+ ILogger logger,
+ IProviderManager providerManager,
+ IFileSystem fileSystem,
+ IUserDataManager userDataManager,
+ ILibraryManager libraryManager)
+ : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
+ {
+ }
+
+ /// <inheritdoc />
+ protected override void MergeData(
+ MetadataResult<AudioBook> source,
+ MetadataResult<AudioBook> target,
+ MetadataFields[] lockedFields,
+ bool replaceData,
+ bool mergeMetadataSettings)
{
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
- if (replaceData || targetItem.Artists.Length == 0)
+ if (replaceData || targetItem.Artists.Count == 0)
{
targetItem.Artists = sourceItem.Artists;
}
@@ -28,9 +45,5 @@ namespace MediaBrowser.Providers.Books
targetItem.Album = sourceItem.Album;
}
}
-
- public AudioBookMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
- {
- }
}
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index a22eaaa51..6a8d03f6d 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -278,7 +278,7 @@ namespace MediaBrowser.Providers.Manager
var currentOptions = options;
var typeOptions = libraryOptions.GetTypeOptions(item.GetType().Name);
- var typeFetcherOrder = typeOptions == null ? null : typeOptions.ImageFetcherOrder;
+ var typeFetcherOrder = typeOptions?.ImageFetcherOrder;
return ImageProviders.Where(i => CanRefresh(i, item, libraryOptions, options, refreshOptions, includeDisabled))
.OrderBy(i =>
@@ -287,7 +287,6 @@ namespace MediaBrowser.Providers.Manager
if (!(i is ILocalImageProvider))
{
var fetcherOrder = typeFetcherOrder ?? currentOptions.ImageFetcherOrder;
-
var index = Array.IndexOf(fetcherOrder, i.Name);
if (index != -1)
diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs
index 2031449d9..8d1588c4e 100644
--- a/MediaBrowser.Providers/Manager/ProviderUtils.cs
+++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs
@@ -11,7 +11,8 @@ namespace MediaBrowser.Providers.Manager
{
public static class ProviderUtils
{
- public static void MergeBaseItemData<T>(MetadataResult<T> sourceResult,
+ public static void MergeBaseItemData<T>(
+ MetadataResult<T> sourceResult,
MetadataResult<T> targetResult,
MetadataFields[] lockedFields,
bool replaceData,
@@ -174,11 +175,11 @@ namespace MediaBrowser.Providers.Manager
}
}
- MergeAlbumArtist(source, target, lockedFields, replaceData);
- MergeCriticRating(source, target, lockedFields, replaceData);
- MergeTrailers(source, target, lockedFields, replaceData);
- MergeVideoInfo(source, target, lockedFields, replaceData);
- MergeDisplayOrder(source, target, lockedFields, replaceData);
+ MergeAlbumArtist(source, target, replaceData);
+ MergeCriticRating(source, target, replaceData);
+ MergeTrailers(source, target, replaceData);
+ MergeVideoInfo(source, target, replaceData);
+ MergeDisplayOrder(source, target, replaceData);
if (replaceData || string.IsNullOrEmpty(target.ForcedSortName))
{
@@ -196,7 +197,7 @@ namespace MediaBrowser.Providers.Manager
target.IsLocked = source.IsLocked;
// Grab the value if it's there, but if not then don't overwrite the default
- if (source.DateCreated != default(DateTime))
+ if (source.DateCreated != default)
{
target.DateCreated = source.DateCreated;
}
@@ -231,12 +232,10 @@ namespace MediaBrowser.Providers.Manager
}
}
- private static void MergeDisplayOrder(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData)
+ private static void MergeDisplayOrder(BaseItem source, BaseItem target, bool replaceData)
{
- var sourceHasDisplayOrder = source as IHasDisplayOrder;
- var targetHasDisplayOrder = target as IHasDisplayOrder;
-
- if (sourceHasDisplayOrder != null && targetHasDisplayOrder != null)
+ if (source is IHasDisplayOrder sourceHasDisplayOrder
+ && target is IHasDisplayOrder targetHasDisplayOrder)
{
if (replaceData || string.IsNullOrEmpty(targetHasDisplayOrder.DisplayOrder))
{
@@ -250,21 +249,19 @@ namespace MediaBrowser.Providers.Manager
}
}
- private static void MergeAlbumArtist(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData)
+ private static void MergeAlbumArtist(BaseItem source, BaseItem target, bool replaceData)
{
- var sourceHasAlbumArtist = source as IHasAlbumArtist;
- var targetHasAlbumArtist = target as IHasAlbumArtist;
-
- if (sourceHasAlbumArtist != null && targetHasAlbumArtist != null)
+ if (source is IHasAlbumArtist sourceHasAlbumArtist
+ && target is IHasAlbumArtist targetHasAlbumArtist)
{
- if (replaceData || targetHasAlbumArtist.AlbumArtists.Length == 0)
+ if (replaceData || targetHasAlbumArtist.AlbumArtists.Count == 0)
{
targetHasAlbumArtist.AlbumArtists = sourceHasAlbumArtist.AlbumArtists;
}
}
}
- private static void MergeCriticRating(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData)
+ private static void MergeCriticRating(BaseItem source, BaseItem target, bool replaceData)
{
if (replaceData || !target.CriticRating.HasValue)
{
@@ -272,20 +269,17 @@ namespace MediaBrowser.Providers.Manager
}
}
- private static void MergeTrailers(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData)
+ private static void MergeTrailers(BaseItem source, BaseItem target, bool replaceData)
{
- if (replaceData || target.RemoteTrailers.Length == 0)
+ if (replaceData || target.RemoteTrailers.Count == 0)
{
target.RemoteTrailers = source.RemoteTrailers;
}
}
- private static void MergeVideoInfo(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData)
+ private static void MergeVideoInfo(BaseItem source, BaseItem target, bool replaceData)
{
- var sourceCast = source as Video;
- var targetCast = target as Video;
-
- if (sourceCast != null && targetCast != null)
+ if (source is Video sourceCast && target is Video targetCast)
{
if (replaceData || targetCast.Video3DFormat == null)
{
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index ab4759c61..c7ecc59c9 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -24,4 +24,9 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
+ <PropertyGroup>
+ <!-- We need at least C# 7.1 -->
+ <LangVersion>latest</LangVersion>
+ </PropertyGroup>
+
</Project>
diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
index d80084acf..e0b23108f 100644
--- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
@@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.MediaInfo
{
var protocol = item.PathProtocol ?? MediaProtocol.File;
- var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, protocol, null, item.GetPlayableStreamFileNames(_mediaEncoder));
+ var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, null, item.GetPlayableStreamFileNames(_mediaEncoder));
var mediaStreams =
item.GetMediaStreams();
diff --git a/MediaBrowser.Providers/Movies/MovieExternalIds.cs b/MediaBrowser.Providers/Movies/MovieExternalIds.cs
index 3783c5032..09ed6034c 100644
--- a/MediaBrowser.Providers/Movies/MovieExternalIds.cs
+++ b/MediaBrowser.Providers/Movies/MovieExternalIds.cs
@@ -7,85 +7,6 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Providers.Movies
{
- public class MovieDbMovieExternalId : IExternalId
- {
- public const string BaseMovieDbUrl = "https://www.themoviedb.org/";
-
- public string Name => "TheMovieDb";
-
- public string Key => MetadataProviders.Tmdb.ToString();
-
- public string UrlFormatString => BaseMovieDbUrl + "movie/{0}";
-
- public bool Supports(IHasProviderIds item)
- {
- // Supports images for tv movies
- var tvProgram = item as LiveTvProgram;
- if (tvProgram != null && tvProgram.IsMovie)
- {
- return true;
- }
-
- return item is Movie || item is MusicVideo || item is Trailer;
- }
- }
-
- public class MovieDbSeriesExternalId : IExternalId
- {
- public string Name => "TheMovieDb";
-
- public string Key => MetadataProviders.Tmdb.ToString();
-
- public string UrlFormatString => MovieDbMovieExternalId.BaseMovieDbUrl + "tv/{0}";
-
- public bool Supports(IHasProviderIds item)
- {
- return item is Series;
- }
- }
-
- public class MovieDbMovieCollectionExternalId : IExternalId
- {
- public string Name => "TheMovieDb Collection";
-
- public string Key => MetadataProviders.TmdbCollection.ToString();
-
- public string UrlFormatString => MovieDbMovieExternalId.BaseMovieDbUrl + "collection/{0}";
-
- public bool Supports(IHasProviderIds item)
- {
- return item is Movie || item is MusicVideo || item is Trailer;
- }
- }
-
- public class MovieDbPersonExternalId : IExternalId
- {
- public string Name => "TheMovieDb";
-
- public string Key => MetadataProviders.Tmdb.ToString();
-
- public string UrlFormatString => MovieDbMovieExternalId.BaseMovieDbUrl + "person/{0}";
-
- public bool Supports(IHasProviderIds item)
- {
- return item is Person;
- }
- }
-
- public class MovieDbCollectionExternalId : IExternalId
- {
- public string Name => "TheMovieDb";
-
- public string Key => MetadataProviders.Tmdb.ToString();
-
- public string UrlFormatString => MovieDbMovieExternalId.BaseMovieDbUrl + "collection/{0}";
-
- public bool Supports(IHasProviderIds item)
- {
- return item is BoxSet;
- }
- }
-
public class ImdbExternalId : IExternalId
{
public string Name => "IMDb";
diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
index 33a6c2fa3..4e59b4119 100644
--- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs
+++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
@@ -15,12 +15,34 @@ namespace MediaBrowser.Providers.Music
{
public class AlbumMetadataService : MetadataService<MusicAlbum, AlbumInfo>
{
+ public AlbumMetadataService(
+ IServerConfigurationManager serverConfigurationManager,
+ ILogger logger,
+ IProviderManager providerManager,
+ IFileSystem fileSystem,
+ IUserDataManager userDataManager,
+ ILibraryManager libraryManager)
+ : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
+ {
+ }
+
+ /// <inheritdoc />
+ protected override bool EnableUpdatingPremiereDateFromChildren => true;
+
+ /// <inheritdoc />
+ protected override bool EnableUpdatingGenresFromChildren => true;
+
+ /// <inheritdoc />
+ protected override bool EnableUpdatingStudiosFromChildren => true;
+
+ /// <inheritdoc />
protected override IList<BaseItem> GetChildrenForMetadataUpdates(MusicAlbum item)
{
return item.GetRecursiveChildren(i => i is Audio)
.ToList();
}
+ /// <inheritdoc />
protected override ItemUpdateType UpdateMetadataFromChildren(MusicAlbum item, IList<BaseItem> children, bool isFullRefresh, ItemUpdateType currentUpdateType)
{
var updateType = base.UpdateMetadataFromChildren(item, children, isFullRefresh, currentUpdateType);
@@ -50,12 +72,6 @@ namespace MediaBrowser.Providers.Music
return updateType;
}
- protected override bool EnableUpdatingPremiereDateFromChildren => true;
-
- protected override bool EnableUpdatingGenresFromChildren => true;
-
- protected override bool EnableUpdatingStudiosFromChildren => true;
-
private ItemUpdateType SetAlbumArtistFromSongs(MusicAlbum item, IEnumerable<Audio> songs)
{
var updateType = ItemUpdateType.None;
@@ -94,21 +110,23 @@ namespace MediaBrowser.Providers.Music
return updateType;
}
- protected override void MergeData(MetadataResult<MusicAlbum> source, MetadataResult<MusicAlbum> target, MetadataFields[] lockedFields, bool replaceData, bool mergeMetadataSettings)
+ /// <inheritdoc />
+ protected override void MergeData(
+ MetadataResult<MusicAlbum> source,
+ MetadataResult<MusicAlbum> target,
+ MetadataFields[] lockedFields,
+ bool replaceData,
+ bool mergeMetadataSettings)
{
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
- if (replaceData || targetItem.Artists.Length == 0)
+ if (replaceData || targetItem.Artists.Count == 0)
{
targetItem.Artists = sourceItem.Artists;
}
}
-
- public AlbumMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
- {
- }
}
}
diff --git a/MediaBrowser.Providers/Music/AudioMetadataService.cs b/MediaBrowser.Providers/Music/AudioMetadataService.cs
index 1422a4eaa..3bf854b91 100644
--- a/MediaBrowser.Providers/Music/AudioMetadataService.cs
+++ b/MediaBrowser.Providers/Music/AudioMetadataService.cs
@@ -11,6 +11,18 @@ namespace MediaBrowser.Providers.Music
{
public class AudioMetadataService : MetadataService<Audio, SongInfo>
{
+ public AudioMetadataService(
+ IServerConfigurationManager serverConfigurationManager,
+ ILogger logger,
+ IProviderManager providerManager,
+ IFileSystem fileSystem,
+ IUserDataManager userDataManager,
+ ILibraryManager libraryManager)
+ : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
+ {
+ }
+
+ /// <inheritdoc />
protected override void MergeData(MetadataResult<Audio> source, MetadataResult<Audio> target, MetadataFields[] lockedFields, bool replaceData, bool mergeMetadataSettings)
{
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
@@ -18,7 +30,7 @@ namespace MediaBrowser.Providers.Music
var sourceItem = source.Item;
var targetItem = target.Item;
- if (replaceData || targetItem.Artists.Length == 0)
+ if (replaceData || targetItem.Artists.Count == 0)
{
targetItem.Artists = sourceItem.Artists;
}
@@ -28,9 +40,5 @@ namespace MediaBrowser.Providers.Music
targetItem.Album = sourceItem.Album;
}
}
-
- public AudioMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
- {
- }
}
}
diff --git a/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs b/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs
index 93412306f..c743ffcb0 100644
--- a/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs
+++ b/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs
@@ -11,7 +11,24 @@ namespace MediaBrowser.Providers.Music
{
public class MusicVideoMetadataService : MetadataService<MusicVideo, MusicVideoInfo>
{
- protected override void MergeData(MetadataResult<MusicVideo> source, MetadataResult<MusicVideo> target, MetadataFields[] lockedFields, bool replaceData, bool mergeMetadataSettings)
+ public MusicVideoMetadataService(
+ IServerConfigurationManager serverConfigurationManager,
+ ILogger logger,
+ IProviderManager providerManager,
+ IFileSystem fileSystem,
+ IUserDataManager userDataManager,
+ ILibraryManager libraryManager)
+ : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
+ {
+ }
+
+ /// <inheritdoc />
+ protected override void MergeData(
+ MetadataResult<MusicVideo> source,
+ MetadataResult<MusicVideo> target,
+ MetadataFields[] lockedFields,
+ bool replaceData,
+ bool mergeMetadataSettings)
{
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
@@ -23,14 +40,10 @@ namespace MediaBrowser.Providers.Music
targetItem.Album = sourceItem.Album;
}
- if (replaceData || targetItem.Artists.Length == 0)
+ if (replaceData || targetItem.Artists.Count == 0)
{
targetItem.Artists = sourceItem.Artists;
}
}
-
- public MusicVideoMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
- {
- }
}
}
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
index 1578e4341..10ed4f073 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Net;
@@ -312,14 +313,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB
}
sb.Replace(", the", string.Empty).Replace("the ", " ").Replace(" the ", " ");
- int prevLength;
- do
- {
- prevLength = sb.Length;
- sb.Replace(" ", " ");
- } while (name.Length != prevLength);
-
- return sb.ToString().Trim();
+ return Regex.Replace(sb.ToString().Trim(), @"\s+", " ");
}
private void MapSeriesToResult(MetadataResult<Series> result, TvDbSharper.Dto.Series tvdbSeries, string metadataLanguage)
diff --git a/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetExternalId.cs b/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetExternalId.cs
new file mode 100644
index 000000000..187295e1e
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetExternalId.cs
@@ -0,0 +1,25 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Providers.Tmdb.BoxSets
+{
+ public class TmdbBoxSetExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string Name => TmdbUtils.ProviderName;
+
+ /// <inheritdoc />
+ public string Key => MetadataProviders.TmdbCollection.ToString();
+
+ /// <inheritdoc />
+ public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "collection/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item)
+ {
+ return item is Movie || item is MusicVideo || item is Trailer;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs b/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs
index 4d12b2f4a..5db0edac2 100644
--- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs
@@ -11,21 +11,24 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.Collections;
+using MediaBrowser.Providers.Tmdb.Models.General;
+using MediaBrowser.Providers.Tmdb.Movies;
-namespace MediaBrowser.Providers.BoxSets
+namespace MediaBrowser.Providers.Tmdb.BoxSets
{
- public class MovieDbBoxSetImageProvider : IRemoteImageProvider, IHasOrder
+ public class TmdbBoxSetImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IHttpClient _httpClient;
- public MovieDbBoxSetImageProvider(IHttpClient httpClient)
+ public TmdbBoxSetImageProvider(IHttpClient httpClient)
{
_httpClient = httpClient;
}
public string Name => ProviderName;
- public static string ProviderName => "TheMovieDb";
+ public static string ProviderName => TmdbUtils.ProviderName;
public bool Supports(BaseItem item)
{
@@ -49,11 +52,11 @@ namespace MediaBrowser.Providers.BoxSets
{
var language = item.GetPreferredMetadataLanguage();
- var mainResult = await MovieDbBoxSetProvider.Current.GetMovieDbResult(tmdbId, null, cancellationToken).ConfigureAwait(false);
+ var mainResult = await TmdbBoxSetProvider.Current.GetMovieDbResult(tmdbId, null, cancellationToken).ConfigureAwait(false);
if (mainResult != null)
{
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
@@ -64,20 +67,20 @@ namespace MediaBrowser.Providers.BoxSets
return new List<RemoteImageInfo>();
}
- private IEnumerable<RemoteImageInfo> GetImages(MovieDbBoxSetProvider.RootObject obj, string language, string baseUrl)
+ private IEnumerable<RemoteImageInfo> GetImages(CollectionResult obj, string language, string baseUrl)
{
var list = new List<RemoteImageInfo>();
- var images = obj.images ?? new MovieDbBoxSetProvider.Images();
+ var images = obj.Images ?? new CollectionImages();
list.AddRange(GetPosters(images).Select(i => new RemoteImageInfo
{
- Url = baseUrl + i.file_path,
- CommunityRating = i.vote_average,
- VoteCount = i.vote_count,
- Width = i.width,
- Height = i.height,
- Language = MovieDbProvider.AdjustImageLanguage(i.iso_639_1, language),
+ Url = baseUrl + i.File_Path,
+ CommunityRating = i.Vote_Average,
+ VoteCount = i.Vote_Count,
+ Width = i.Width,
+ Height = i.Height,
+ Language = TmdbMovieProvider.AdjustImageLanguage(i.Iso_639_1, language),
ProviderName = Name,
Type = ImageType.Primary,
RatingType = RatingType.Score
@@ -85,11 +88,11 @@ namespace MediaBrowser.Providers.BoxSets
list.AddRange(GetBackdrops(images).Select(i => new RemoteImageInfo
{
- Url = baseUrl + i.file_path,
- CommunityRating = i.vote_average,
- VoteCount = i.vote_count,
- Width = i.width,
- Height = i.height,
+ Url = baseUrl + i.File_Path,
+ CommunityRating = i.Vote_Average,
+ VoteCount = i.Vote_Count,
+ Width = i.Width,
+ Height = i.Height,
ProviderName = Name,
Type = ImageType.Backdrop,
RatingType = RatingType.Score
@@ -125,9 +128,9 @@ namespace MediaBrowser.Providers.BoxSets
/// </summary>
/// <param name="images">The images.</param>
/// <returns>IEnumerable{MovieDbProvider.Poster}.</returns>
- private IEnumerable<MovieDbBoxSetProvider.Poster> GetPosters(MovieDbBoxSetProvider.Images images)
+ private IEnumerable<Poster> GetPosters(CollectionImages images)
{
- return images.posters ?? new List<MovieDbBoxSetProvider.Poster>();
+ return images.Posters ?? new List<Poster>();
}
/// <summary>
@@ -135,13 +138,13 @@ namespace MediaBrowser.Providers.BoxSets
/// </summary>
/// <param name="images">The images.</param>
/// <returns>IEnumerable{MovieDbProvider.Backdrop}.</returns>
- private IEnumerable<MovieDbBoxSetProvider.Backdrop> GetBackdrops(MovieDbBoxSetProvider.Images images)
+ private IEnumerable<Backdrop> GetBackdrops(CollectionImages images)
{
- var eligibleBackdrops = images.backdrops == null ? new List<MovieDbBoxSetProvider.Backdrop>() :
- images.backdrops;
+ var eligibleBackdrops = images.Backdrops == null ? new List<Backdrop>() :
+ images.Backdrops;
- return eligibleBackdrops.OrderByDescending(i => i.vote_average)
- .ThenByDescending(i => i.vote_count);
+ return eligibleBackdrops.OrderByDescending(i => i.Vote_Average)
+ .ThenByDescending(i => i.Vote_Count);
}
public int Order => 0;
diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetProvider.cs
index 4e41694c4..a215177a9 100644
--- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetProvider.cs
@@ -16,16 +16,18 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
-using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.Collections;
+using MediaBrowser.Providers.Tmdb.Models.General;
+using MediaBrowser.Providers.Tmdb.Movies;
using Microsoft.Extensions.Logging;
-namespace MediaBrowser.Providers.BoxSets
+namespace MediaBrowser.Providers.Tmdb.BoxSets
{
- public class MovieDbBoxSetProvider : IRemoteMetadataProvider<BoxSet, BoxSetInfo>
+ public class TmdbBoxSetProvider : IRemoteMetadataProvider<BoxSet, BoxSetInfo>
{
- private const string GetCollectionInfo3 = MovieDbProvider.BaseMovieDbUrl + @"3/collection/{0}?api_key={1}&append_to_response=images";
+ private const string GetCollectionInfo3 = TmdbUtils.BaseTmdbApiUrl + @"3/collection/{0}?api_key={1}&append_to_response=images";
- internal static MovieDbBoxSetProvider Current;
+ internal static TmdbBoxSetProvider Current;
private readonly ILogger _logger;
private readonly IJsonSerializer _json;
@@ -35,7 +37,7 @@ namespace MediaBrowser.Providers.BoxSets
private readonly IHttpClient _httpClient;
private readonly ILibraryManager _libraryManager;
- public MovieDbBoxSetProvider(ILogger logger, IJsonSerializer json, IServerConfigurationManager config, IFileSystem fileSystem, ILocalizationManager localization, IHttpClient httpClient, ILibraryManager libraryManager)
+ public TmdbBoxSetProvider(ILogger logger, IJsonSerializer json, IServerConfigurationManager config, IFileSystem fileSystem, ILocalizationManager localization, IHttpClient httpClient, ILibraryManager libraryManager)
{
_logger = logger;
_json = json;
@@ -58,29 +60,29 @@ namespace MediaBrowser.Providers.BoxSets
await EnsureInfo(tmdbId, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
var dataFilePath = GetDataFilePath(_config.ApplicationPaths, tmdbId, searchInfo.MetadataLanguage);
- var info = _json.DeserializeFromFile<RootObject>(dataFilePath);
+ var info = _json.DeserializeFromFile<CollectionResult>(dataFilePath);
- var images = (info.images ?? new Images()).posters ?? new List<Poster>();
+ var images = (info.Images ?? new CollectionImages()).Posters ?? new List<Poster>();
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
var result = new RemoteSearchResult
{
- Name = info.name,
+ Name = info.Name,
SearchProviderName = Name,
- ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path)
+ ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].File_Path)
};
- result.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture));
+ result.SetProviderId(MetadataProviders.Tmdb, info.Id.ToString(_usCulture));
return new[] { result };
}
- return await new MovieDbSearch(_logger, _json, _libraryManager).GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false);
+ return await new TmdbSearch(_logger, _json, _libraryManager).GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false);
}
public async Task<MetadataResult<BoxSet>> GetMetadata(BoxSetInfo id, CancellationToken cancellationToken)
@@ -90,7 +92,7 @@ namespace MediaBrowser.Providers.BoxSets
// We don't already have an Id, need to fetch it
if (string.IsNullOrEmpty(tmdbId))
{
- var searchResults = await new MovieDbSearch(_logger, _json, _libraryManager).GetSearchResults(id, cancellationToken).ConfigureAwait(false);
+ var searchResults = await new TmdbSearch(_logger, _json, _libraryManager).GetSearchResults(id, cancellationToken).ConfigureAwait(false);
var searchResult = searchResults.FirstOrDefault();
@@ -116,7 +118,7 @@ namespace MediaBrowser.Providers.BoxSets
return result;
}
- internal async Task<RootObject> GetMovieDbResult(string tmdbId, string language, CancellationToken cancellationToken)
+ internal async Task<CollectionResult> GetMovieDbResult(string tmdbId, string language, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(tmdbId))
{
@@ -129,21 +131,21 @@ namespace MediaBrowser.Providers.BoxSets
if (!string.IsNullOrEmpty(dataFilePath))
{
- return _json.DeserializeFromFile<RootObject>(dataFilePath);
+ return _json.DeserializeFromFile<CollectionResult>(dataFilePath);
}
return null;
}
- private BoxSet GetItem(RootObject obj)
+ private BoxSet GetItem(CollectionResult obj)
{
var item = new BoxSet
{
- Name = obj.name,
- Overview = obj.overview
+ Name = obj.Name,
+ Overview = obj.Overview
};
- item.SetProviderId(MetadataProviders.Tmdb, obj.id.ToString(_usCulture));
+ item.SetProviderId(MetadataProviders.Tmdb, obj.Id.ToString(_usCulture));
return item;
}
@@ -161,61 +163,61 @@ namespace MediaBrowser.Providers.BoxSets
_json.SerializeToFile(mainResult, dataFilePath);
}
- private async Task<RootObject> FetchMainResult(string id, string language, CancellationToken cancellationToken)
+ private async Task<CollectionResult> FetchMainResult(string id, string language, CancellationToken cancellationToken)
{
- var url = string.Format(GetCollectionInfo3, id, MovieDbProvider.ApiKey);
+ var url = string.Format(GetCollectionInfo3, id, TmdbUtils.ApiKey);
if (!string.IsNullOrEmpty(language))
{
- url += string.Format("&language={0}", MovieDbProvider.NormalizeLanguage(language));
+ url += string.Format("&language={0}", TmdbMovieProvider.NormalizeLanguage(language));
// Get images in english and with no language
- url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language);
+ url += "&include_image_language=" + TmdbMovieProvider.GetImageLanguagesParam(language);
}
cancellationToken.ThrowIfCancellationRequested();
- RootObject mainResult = null;
+ CollectionResult mainResult;
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = MovieDbSearch.AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
using (var json = response.Content)
{
- mainResult = await _json.DeserializeFromStreamAsync<RootObject>(json).ConfigureAwait(false);
+ mainResult = await _json.DeserializeFromStreamAsync<CollectionResult>(json).ConfigureAwait(false);
}
}
cancellationToken.ThrowIfCancellationRequested();
- if (mainResult != null && string.IsNullOrEmpty(mainResult.name))
+ if (mainResult != null && string.IsNullOrEmpty(mainResult.Name))
{
if (!string.IsNullOrEmpty(language) && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
{
- url = string.Format(GetCollectionInfo3, id, MovieDbSearch.ApiKey) + "&language=en";
+ url = string.Format(GetCollectionInfo3, id, TmdbUtils.ApiKey) + "&language=en";
if (!string.IsNullOrEmpty(language))
{
// Get images in english and with no language
- url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language);
+ url += "&include_image_language=" + TmdbMovieProvider.GetImageLanguagesParam(language);
}
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = MovieDbSearch.AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
using (var json = response.Content)
{
- mainResult = await _json.DeserializeFromStreamAsync<RootObject>(json).ConfigureAwait(false);
+ mainResult = await _json.DeserializeFromStreamAsync<CollectionResult>(json).ConfigureAwait(false);
}
}
}
@@ -241,7 +243,7 @@ namespace MediaBrowser.Providers.BoxSets
return DownloadInfo(tmdbId, preferredMetadataLanguage, cancellationToken);
}
- public string Name => "TheMovieDb";
+ public string Name => TmdbUtils.ProviderName;
private static string GetDataFilePath(IApplicationPaths appPaths, string tmdbId, string preferredLanguage)
{
@@ -266,54 +268,6 @@ namespace MediaBrowser.Providers.BoxSets
return dataPath;
}
- internal class Part
- {
- public string title { get; set; }
- public int id { get; set; }
- public string release_date { get; set; }
- public string poster_path { get; set; }
- public string backdrop_path { get; set; }
- }
-
- internal class Backdrop
- {
- public double aspect_ratio { get; set; }
- public string file_path { get; set; }
- public int height { get; set; }
- public string iso_639_1 { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- public int width { get; set; }
- }
-
- internal class Poster
- {
- public double aspect_ratio { get; set; }
- public string file_path { get; set; }
- public int height { get; set; }
- public string iso_639_1 { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- public int width { get; set; }
- }
-
- internal class Images
- {
- public List<Backdrop> backdrops { get; set; }
- public List<Poster> posters { get; set; }
- }
-
- internal class RootObject
- {
- public int id { get; set; }
- public string name { get; set; }
- public string overview { get; set; }
- public string poster_path { get; set; }
- public string backdrop_path { get; set; }
- public List<Part> parts { get; set; }
- public Images images { get; set; }
- }
-
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClient.GetResponse(new HttpRequestOptions
diff --git a/MediaBrowser.Providers/Tmdb/Models/Collections/CollectionImages.cs b/MediaBrowser.Providers/Tmdb/Models/Collections/CollectionImages.cs
new file mode 100644
index 000000000..18f26c397
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Collections/CollectionImages.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.Collections
+{
+ public class CollectionImages
+ {
+ public List<Backdrop> Backdrops { get; set; }
+ public List<Poster> Posters { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Collections/CollectionResult.cs b/MediaBrowser.Providers/Tmdb/Models/Collections/CollectionResult.cs
new file mode 100644
index 000000000..53d2599f8
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Collections/CollectionResult.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Tmdb.Models.Collections
+{
+ public class CollectionResult
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Overview { get; set; }
+ public string Poster_Path { get; set; }
+ public string Backdrop_Path { get; set; }
+ public List<Part> Parts { get; set; }
+ public CollectionImages Images { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Collections/Part.cs b/MediaBrowser.Providers/Tmdb/Models/Collections/Part.cs
new file mode 100644
index 000000000..ff19291c7
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Collections/Part.cs
@@ -0,0 +1,11 @@
+namespace MediaBrowser.Providers.Tmdb.Models.Collections
+{
+ public class Part
+ {
+ public string Title { get; set; }
+ public int Id { get; set; }
+ public string Release_Date { get; set; }
+ public string Poster_Path { get; set; }
+ public string Backdrop_Path { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Backdrop.cs b/MediaBrowser.Providers/Tmdb/Models/General/Backdrop.cs
new file mode 100644
index 000000000..db4cd6681
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Backdrop.cs
@@ -0,0 +1,13 @@
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Backdrop
+ {
+ public double Aspect_Ratio { get; set; }
+ public string File_Path { get; set; }
+ public int Height { get; set; }
+ public string Iso_639_1 { get; set; }
+ public double Vote_Average { get; set; }
+ public int Vote_Count { get; set; }
+ public int Width { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Crew.cs b/MediaBrowser.Providers/Tmdb/Models/General/Crew.cs
new file mode 100644
index 000000000..47b985403
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Crew.cs
@@ -0,0 +1,12 @@
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Crew
+ {
+ public int Id { get; set; }
+ public string Credit_Id { get; set; }
+ public string Name { get; set; }
+ public string Department { get; set; }
+ public string Job { get; set; }
+ public string Profile_Path { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/ExternalIds.cs b/MediaBrowser.Providers/Tmdb/Models/General/ExternalIds.cs
new file mode 100644
index 000000000..37e37b0be
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/ExternalIds.cs
@@ -0,0 +1,11 @@
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class ExternalIds
+ {
+ public string Imdb_Id { get; set; }
+ public object Freebase_Id { get; set; }
+ public string Freebase_Mid { get; set; }
+ public int Tvdb_Id { get; set; }
+ public int Tvrage_Id { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Genre.cs b/MediaBrowser.Providers/Tmdb/Models/General/Genre.cs
new file mode 100644
index 000000000..9a6686d50
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Genre.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Genre
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Images.cs b/MediaBrowser.Providers/Tmdb/Models/General/Images.cs
new file mode 100644
index 000000000..f1c99537d
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Images.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Images
+ {
+ public List<Backdrop> Backdrops { get; set; }
+ public List<Poster> Posters { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Keyword.cs b/MediaBrowser.Providers/Tmdb/Models/General/Keyword.cs
new file mode 100644
index 000000000..4e3011349
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Keyword.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Keyword
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Keywords.cs b/MediaBrowser.Providers/Tmdb/Models/General/Keywords.cs
new file mode 100644
index 000000000..1950a51b3
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Keywords.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Keywords
+ {
+ public List<Keyword> Results { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Poster.cs b/MediaBrowser.Providers/Tmdb/Models/General/Poster.cs
new file mode 100644
index 000000000..33401b15d
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Poster.cs
@@ -0,0 +1,13 @@
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Poster
+ {
+ public double Aspect_Ratio { get; set; }
+ public string File_Path { get; set; }
+ public int Height { get; set; }
+ public string Iso_639_1 { get; set; }
+ public double Vote_Average { get; set; }
+ public int Vote_Count { get; set; }
+ public int Width { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Profile.cs b/MediaBrowser.Providers/Tmdb/Models/General/Profile.cs
new file mode 100644
index 000000000..73a049c73
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Profile.cs
@@ -0,0 +1,11 @@
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Profile
+ {
+ public string File_Path { get; set; }
+ public int Width { get; set; }
+ public int Height { get; set; }
+ public object Iso_639_1 { get; set; }
+ public double Aspect_Ratio { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Still.cs b/MediaBrowser.Providers/Tmdb/Models/General/Still.cs
new file mode 100644
index 000000000..15ff4a099
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Still.cs
@@ -0,0 +1,14 @@
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Still
+ {
+ public double Aspect_Ratio { get; set; }
+ public string File_Path { get; set; }
+ public int Height { get; set; }
+ public string Id { get; set; }
+ public string Iso_639_1 { get; set; }
+ public double Vote_Average { get; set; }
+ public int Vote_Count { get; set; }
+ public int Width { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/StillImages.cs b/MediaBrowser.Providers/Tmdb/Models/General/StillImages.cs
new file mode 100644
index 000000000..266965c47
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/StillImages.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class StillImages
+ {
+ public List<Still> Stills { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Video.cs b/MediaBrowser.Providers/Tmdb/Models/General/Video.cs
new file mode 100644
index 000000000..fb69e7767
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Video.cs
@@ -0,0 +1,14 @@
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Video
+ {
+ public string Id { get; set; }
+ public string Iso_639_1 { get; set; }
+ public string Iso_3166_1 { get; set; }
+ public string Key { get; set; }
+ public string Name { get; set; }
+ public string Site { get; set; }
+ public string Size { get; set; }
+ public string Type { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Videos.cs b/MediaBrowser.Providers/Tmdb/Models/General/Videos.cs
new file mode 100644
index 000000000..26812780d
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/General/Videos.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Tmdb.Models.General
+{
+ public class Videos
+ {
+ public List<Video> Results { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/BelongsToCollection.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/BelongsToCollection.cs
new file mode 100644
index 000000000..ac673df61
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/BelongsToCollection.cs
@@ -0,0 +1,10 @@
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class BelongsToCollection
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Poster_Path { get; set; }
+ public string Backdrop_Path { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/Cast.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/Cast.cs
new file mode 100644
index 000000000..44af9e568
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/Cast.cs
@@ -0,0 +1,12 @@
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class Cast
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Character { get; set; }
+ public int Order { get; set; }
+ public int Cast_Id { get; set; }
+ public string Profile_Path { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/Casts.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/Casts.cs
new file mode 100644
index 000000000..7b5094fa3
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/Casts.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class Casts
+ {
+ public List<Cast> Cast { get; set; }
+ public List<Crew> Crew { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/Country.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/Country.cs
new file mode 100644
index 000000000..6f843addd
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/Country.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class Country
+ {
+ public string Iso_3166_1 { get; set; }
+ public string Certification { get; set; }
+ public DateTime Release_Date { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/MovieResult.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/MovieResult.cs
new file mode 100644
index 000000000..1b262946f
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/MovieResult.cs
@@ -0,0 +1,49 @@
+using System.Collections.Generic;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class MovieResult
+ {
+ public bool Adult { get; set; }
+ public string Backdrop_Path { get; set; }
+ public BelongsToCollection Belongs_To_Collection { get; set; }
+ public int Budget { get; set; }
+ public List<Genre> Genres { get; set; }
+ public string Homepage { get; set; }
+ public int Id { get; set; }
+ public string Imdb_Id { get; set; }
+ public string Original_Title { get; set; }
+ public string Original_Name { get; set; }
+ public string Overview { get; set; }
+ public double Popularity { get; set; }
+ public string Poster_Path { get; set; }
+ public List<ProductionCompany> Production_Companies { get; set; }
+ public List<ProductionCountry> Production_Countries { get; set; }
+ public string Release_Date { get; set; }
+ public int Revenue { get; set; }
+ public int Runtime { get; set; }
+ public List<SpokenLanguage> Spoken_Languages { get; set; }
+ public string Status { get; set; }
+ public string Tagline { get; set; }
+ public string Title { get; set; }
+ public string Name { get; set; }
+ public double Vote_Average { get; set; }
+ public int Vote_Count { get; set; }
+ public Casts Casts { get; set; }
+ public Releases Releases { get; set; }
+ public Images Images { get; set; }
+ public Keywords Keywords { get; set; }
+ public Trailers Trailers { get; set; }
+
+ public string GetOriginalTitle()
+ {
+ return Original_Name ?? Original_Title;
+ }
+
+ public string GetTitle()
+ {
+ return Name ?? Title ?? GetOriginalTitle();
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/ProductionCompany.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/ProductionCompany.cs
new file mode 100644
index 000000000..c3382f305
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/ProductionCompany.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class ProductionCompany
+ {
+ public string Name { get; set; }
+ public int Id { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/ProductionCountry.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/ProductionCountry.cs
new file mode 100644
index 000000000..78112c915
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/ProductionCountry.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class ProductionCountry
+ {
+ public string Iso_3166_1 { get; set; }
+ public string Name { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/Releases.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/Releases.cs
new file mode 100644
index 000000000..c44f31e46
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/Releases.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class Releases
+ {
+ public List<Country> Countries { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/SpokenLanguage.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/SpokenLanguage.cs
new file mode 100644
index 000000000..4bc5cfa48
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/SpokenLanguage.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class SpokenLanguage
+ {
+ public string Iso_639_1 { get; set; }
+ public string Name { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/Trailers.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/Trailers.cs
new file mode 100644
index 000000000..4bfa02f06
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/Trailers.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class Trailers
+ {
+ public List<Youtube> Youtube { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Movies/Youtube.cs b/MediaBrowser.Providers/Tmdb/Models/Movies/Youtube.cs
new file mode 100644
index 000000000..069572824
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Movies/Youtube.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Providers.Tmdb.Models.Movies
+{
+ public class Youtube
+ {
+ public string Name { get; set; }
+ public string Size { get; set; }
+ public string Source { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/People/PersonImages.cs b/MediaBrowser.Providers/Tmdb/Models/People/PersonImages.cs
new file mode 100644
index 000000000..113f410b2
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/People/PersonImages.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.People
+{
+ public class PersonImages
+ {
+ public List<Profile> Profiles { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/People/PersonResult.cs b/MediaBrowser.Providers/Tmdb/Models/People/PersonResult.cs
new file mode 100644
index 000000000..6e997050f
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/People/PersonResult.cs
@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.People
+{
+ public class PersonResult
+ {
+ public bool Adult { get; set; }
+ public List<string> Also_Known_As { get; set; }
+ public string Biography { get; set; }
+ public string Birthday { get; set; }
+ public string Deathday { get; set; }
+ public string Homepage { get; set; }
+ public int Id { get; set; }
+ public string Imdb_Id { get; set; }
+ public string Name { get; set; }
+ public string Place_Of_Birth { get; set; }
+ public double Popularity { get; set; }
+ public string Profile_Path { get; set; }
+ public PersonImages Images { get; set; }
+ public ExternalIds External_Ids { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Search/ExternalIdLookupResult.cs b/MediaBrowser.Providers/Tmdb/Models/Search/ExternalIdLookupResult.cs
new file mode 100644
index 000000000..6d9fe7081
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Search/ExternalIdLookupResult.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using MediaBrowser.Providers.Movies;
+
+namespace MediaBrowser.Providers.Tmdb.Models.Search
+{
+ public class ExternalIdLookupResult
+ {
+ public List<TvResult> Tv_Results { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Search/MovieResult.cs b/MediaBrowser.Providers/Tmdb/Models/Search/MovieResult.cs
new file mode 100644
index 000000000..25a211fa8
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Search/MovieResult.cs
@@ -0,0 +1,65 @@
+namespace MediaBrowser.Providers.Tmdb.Models.Search
+{
+ public class MovieResult
+ {
+ /// <summary>
+ /// Gets or sets a value indicating whether this <see cref="TmdbMovieSearchResult" /> is adult.
+ /// </summary>
+ /// <value><c>true</c> if adult; otherwise, <c>false</c>.</value>
+ public bool Adult { get; set; }
+ /// <summary>
+ /// Gets or sets the backdrop_path.
+ /// </summary>
+ /// <value>The backdrop_path.</value>
+ public string Backdrop_Path { get; set; }
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ public int Id { get; set; }
+ /// <summary>
+ /// Gets or sets the original_title.
+ /// </summary>
+ /// <value>The original_title.</value>
+ public string Original_Title { get; set; }
+ /// <summary>
+ /// Gets or sets the original_name.
+ /// </summary>
+ /// <value>The original_name.</value>
+ public string Original_Name { get; set; }
+ /// <summary>
+ /// Gets or sets the release_date.
+ /// </summary>
+ /// <value>The release_date.</value>
+ public string Release_Date { get; set; }
+ /// <summary>
+ /// Gets or sets the poster_path.
+ /// </summary>
+ /// <value>The poster_path.</value>
+ public string Poster_Path { get; set; }
+ /// <summary>
+ /// Gets or sets the popularity.
+ /// </summary>
+ /// <value>The popularity.</value>
+ public double Popularity { get; set; }
+ /// <summary>
+ /// Gets or sets the title.
+ /// </summary>
+ /// <value>The title.</value>
+ public string Title { get; set; }
+ /// <summary>
+ /// Gets or sets the vote_average.
+ /// </summary>
+ /// <value>The vote_average.</value>
+ public double Vote_Average { get; set; }
+ /// <summary>
+ /// For collection search results
+ /// </summary>
+ public string Name { get; set; }
+ /// <summary>
+ /// Gets or sets the vote_count.
+ /// </summary>
+ /// <value>The vote_count.</value>
+ public int Vote_Count { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Search/PersonSearchResult.cs b/MediaBrowser.Providers/Tmdb/Models/Search/PersonSearchResult.cs
new file mode 100644
index 000000000..93916068f
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Search/PersonSearchResult.cs
@@ -0,0 +1,29 @@
+namespace MediaBrowser.Providers.Tmdb.Models.Search
+{
+ public class PersonSearchResult
+ {
+ /// <summary>
+ /// Gets or sets a value indicating whether this <see cref="PersonSearchResult" /> is adult.
+ /// </summary>
+ /// <value><c>true</c> if adult; otherwise, <c>false</c>.</value>
+ public bool Adult { get; set; }
+
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ public int Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the profile_ path.
+ /// </summary>
+ /// <value>The profile_ path.</value>
+ public string Profile_Path { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Search/TmdbSearchResult.cs b/MediaBrowser.Providers/Tmdb/Models/Search/TmdbSearchResult.cs
new file mode 100644
index 000000000..a9f888e75
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Search/TmdbSearchResult.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Tmdb.Models.Search
+{
+ public class TmdbSearchResult<T>
+ {
+ /// <summary>
+ /// Gets or sets the page.
+ /// </summary>
+ /// <value>The page.</value>
+ public int Page { get; set; }
+
+ /// <summary>
+ /// Gets or sets the results.
+ /// </summary>
+ /// <value>The results.</value>
+ public List<T> Results { get; set; }
+
+ /// <summary>
+ /// Gets or sets the total_pages.
+ /// </summary>
+ /// <value>The total_pages.</value>
+ public int Total_Pages { get; set; }
+
+ /// <summary>
+ /// Gets or sets the total_results.
+ /// </summary>
+ /// <value>The total_results.</value>
+ public int Total_Results { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/Search/TvResult.cs b/MediaBrowser.Providers/Tmdb/Models/Search/TvResult.cs
new file mode 100644
index 000000000..ed140bedd
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/Search/TvResult.cs
@@ -0,0 +1,15 @@
+namespace MediaBrowser.Providers.Tmdb.Models.Search
+{
+ public class TvResult
+ {
+ public string Backdrop_Path { get; set; }
+ public string First_Air_Date { get; set; }
+ public int Id { get; set; }
+ public string Original_Name { get; set; }
+ public string Poster_Path { get; set; }
+ public double Popularity { get; set; }
+ public string Name { get; set; }
+ public double Vote_Average { get; set; }
+ public int Vote_Count { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/Cast.cs b/MediaBrowser.Providers/Tmdb/Models/TV/Cast.cs
new file mode 100644
index 000000000..c659df9ac
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/Cast.cs
@@ -0,0 +1,12 @@
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class Cast
+ {
+ public string Character { get; set; }
+ public string Credit_Id { get; set; }
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Profile_Path { get; set; }
+ public int Order { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/ContentRating.cs b/MediaBrowser.Providers/Tmdb/Models/TV/ContentRating.cs
new file mode 100644
index 000000000..3177cd71b
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/ContentRating.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class ContentRating
+ {
+ public string Iso_3166_1 { get; set; }
+ public string Rating { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/ContentRatings.cs b/MediaBrowser.Providers/Tmdb/Models/TV/ContentRatings.cs
new file mode 100644
index 000000000..883e605c9
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/ContentRatings.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class ContentRatings
+ {
+ public List<ContentRating> Results { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/CreatedBy.cs b/MediaBrowser.Providers/Tmdb/Models/TV/CreatedBy.cs
new file mode 100644
index 000000000..21588d897
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/CreatedBy.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class CreatedBy
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Profile_Path { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/Credits.cs b/MediaBrowser.Providers/Tmdb/Models/TV/Credits.cs
new file mode 100644
index 000000000..b62b5f605
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/Credits.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class Credits
+ {
+ public List<Cast> Cast { get; set; }
+ public List<Crew> Crew { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/Episode.cs b/MediaBrowser.Providers/Tmdb/Models/TV/Episode.cs
new file mode 100644
index 000000000..ab11a6cd2
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/Episode.cs
@@ -0,0 +1,14 @@
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class Episode
+ {
+ public string Air_Date { get; set; }
+ public int Episode_Number { get; set; }
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Overview { get; set; }
+ public string Still_Path { get; set; }
+ public double Vote_Average { get; set; }
+ public int Vote_Count { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/EpisodeCredits.cs b/MediaBrowser.Providers/Tmdb/Models/TV/EpisodeCredits.cs
new file mode 100644
index 000000000..1c86be0f4
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/EpisodeCredits.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class EpisodeCredits
+ {
+ public List<Cast> Cast { get; set; }
+ public List<Crew> Crew { get; set; }
+ public List<GuestStar> Guest_Stars { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/EpisodeResult.cs b/MediaBrowser.Providers/Tmdb/Models/TV/EpisodeResult.cs
new file mode 100644
index 000000000..0513ce7e2
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/EpisodeResult.cs
@@ -0,0 +1,23 @@
+using System;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class EpisodeResult
+ {
+ public DateTime Air_Date { get; set; }
+ public int Episode_Number { get; set; }
+ public string Name { get; set; }
+ public string Overview { get; set; }
+ public int Id { get; set; }
+ public object Production_Code { get; set; }
+ public int Season_Number { get; set; }
+ public string Still_Path { get; set; }
+ public double Vote_Average { get; set; }
+ public int Vote_Count { get; set; }
+ public StillImages Images { get; set; }
+ public ExternalIds External_Ids { get; set; }
+ public EpisodeCredits Credits { get; set; }
+ public Tmdb.Models.General.Videos Videos { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/GuestStar.cs b/MediaBrowser.Providers/Tmdb/Models/TV/GuestStar.cs
new file mode 100644
index 000000000..2dfe7a862
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/GuestStar.cs
@@ -0,0 +1,12 @@
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class GuestStar
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Credit_Id { get; set; }
+ public string Character { get; set; }
+ public int Order { get; set; }
+ public string Profile_Path { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/Network.cs b/MediaBrowser.Providers/Tmdb/Models/TV/Network.cs
new file mode 100644
index 000000000..f982682d1
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/Network.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class Network
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/Season.cs b/MediaBrowser.Providers/Tmdb/Models/TV/Season.cs
new file mode 100644
index 000000000..976e3c97e
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/Season.cs
@@ -0,0 +1,11 @@
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class Season
+ {
+ public string Air_Date { get; set; }
+ public int Episode_Count { get; set; }
+ public int Id { get; set; }
+ public string Poster_Path { get; set; }
+ public int Season_Number { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/SeasonImages.cs b/MediaBrowser.Providers/Tmdb/Models/TV/SeasonImages.cs
new file mode 100644
index 000000000..9a93dd6ae
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/SeasonImages.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class SeasonImages
+ {
+ public List<Poster> Posters { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/SeasonResult.cs b/MediaBrowser.Providers/Tmdb/Models/TV/SeasonResult.cs
new file mode 100644
index 000000000..bc9213c04
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/SeasonResult.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class SeasonResult
+ {
+ public DateTime Air_Date { get; set; }
+ public List<Episode> Episodes { get; set; }
+ public string Name { get; set; }
+ public string Overview { get; set; }
+ public int Id { get; set; }
+ public string Poster_Path { get; set; }
+ public int Season_Number { get; set; }
+ public Credits Credits { get; set; }
+ public SeasonImages Images { get; set; }
+ public ExternalIds External_Ids { get; set; }
+ public General.Videos Videos { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Tmdb/Models/TV/SeriesResult.cs b/MediaBrowser.Providers/Tmdb/Models/TV/SeriesResult.cs
new file mode 100644
index 000000000..ad95e502e
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Models/TV/SeriesResult.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb.Models.TV
+{
+ public class SeriesResult
+ {
+ public string Backdrop_Path { get; set; }
+ public List<CreatedBy> Created_By { get; set; }
+ public List<int> Episode_Run_Time { get; set; }
+ public DateTime First_Air_Date { get; set; }
+ public List<Genre> Genres { get; set; }
+ public string Homepage { get; set; }
+ public int Id { get; set; }
+ public bool In_Production { get; set; }
+ public List<string> Languages { get; set; }
+ public DateTime Last_Air_Date { get; set; }
+ public string Name { get; set; }
+ public List<Network> Networks { get; set; }
+ public int Number_Of_Episodes { get; set; }
+ public int Number_Of_Seasons { get; set; }
+ public string Original_Name { get; set; }
+ public List<string> Origin_Country { get; set; }
+ public string Overview { get; set; }
+ public string Popularity { get; set; }
+ public string Poster_Path { get; set; }
+ public List<Season> Seasons { get; set; }
+ public string Status { get; set; }
+ public double Vote_Average { get; set; }
+ public int Vote_Count { get; set; }
+ public Credits Credits { get; set; }
+ public Images Images { get; set; }
+ public Keywords Keywords { get; set; }
+ public ExternalIds External_Ids { get; set; }
+ public General.Videos Videos { get; set; }
+ public ContentRatings Content_Ratings { get; set; }
+ public string ResultLanguage { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Tmdb/Movies/GenericTmdbMovieInfo.cs
index 4300b84a9..b7b447b68 100644
--- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
+++ b/MediaBrowser.Providers/Tmdb/Movies/GenericTmdbMovieInfo.cs
@@ -14,11 +14,13 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
+using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.Movies;
using Microsoft.Extensions.Logging;
-namespace MediaBrowser.Providers.Movies
+namespace MediaBrowser.Providers.Tmdb.Movies
{
- public class GenericMovieDbInfo<T>
+ public class GenericTmdbMovieInfo<T>
where T : BaseItem, new()
{
private readonly ILogger _logger;
@@ -28,7 +30,7 @@ namespace MediaBrowser.Providers.Movies
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- public GenericMovieDbInfo(ILogger logger, IJsonSerializer jsonSerializer, ILibraryManager libraryManager, IFileSystem fileSystem)
+ public GenericTmdbMovieInfo(ILogger logger, IJsonSerializer jsonSerializer, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_logger = logger;
_jsonSerializer = jsonSerializer;
@@ -44,7 +46,7 @@ namespace MediaBrowser.Providers.Movies
// Don't search for music video id's because it is very easy to misidentify.
if (string.IsNullOrEmpty(tmdbId) && string.IsNullOrEmpty(imdbId) && typeof(T) != typeof(MusicVideo))
{
- var searchResults = await new MovieDbSearch(_logger, _jsonSerializer, _libraryManager).GetMovieSearchResults(itemId, cancellationToken).ConfigureAwait(false);
+ var searchResults = await new TmdbSearch(_logger, _jsonSerializer, _libraryManager).GetMovieSearchResults(itemId, cancellationToken).ConfigureAwait(false);
var searchResult = searchResults.FirstOrDefault();
@@ -81,17 +83,17 @@ namespace MediaBrowser.Providers.Movies
};
string dataFilePath = null;
- MovieDbProvider.CompleteMovieData movieInfo = null;
+ MovieResult movieInfo = null;
// Id could be ImdbId or TmdbId
if (string.IsNullOrEmpty(tmdbId))
{
- movieInfo = await MovieDbProvider.Current.FetchMainResult(imdbId, false, language, cancellationToken).ConfigureAwait(false);
+ movieInfo = await TmdbMovieProvider.Current.FetchMainResult(imdbId, false, language, cancellationToken).ConfigureAwait(false);
if (movieInfo != null)
{
- tmdbId = movieInfo.id.ToString(_usCulture);
+ tmdbId = movieInfo.Id.ToString(_usCulture);
- dataFilePath = MovieDbProvider.Current.GetDataFilePath(tmdbId, language);
+ dataFilePath = TmdbMovieProvider.Current.GetDataFilePath(tmdbId, language);
Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(movieInfo, dataFilePath);
}
@@ -99,12 +101,12 @@ namespace MediaBrowser.Providers.Movies
if (!string.IsNullOrWhiteSpace(tmdbId))
{
- await MovieDbProvider.Current.EnsureMovieInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
+ await TmdbMovieProvider.Current.EnsureMovieInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
- dataFilePath = dataFilePath ?? MovieDbProvider.Current.GetDataFilePath(tmdbId, language);
- movieInfo = movieInfo ?? _jsonSerializer.DeserializeFromFile<MovieDbProvider.CompleteMovieData>(dataFilePath);
+ dataFilePath = dataFilePath ?? TmdbMovieProvider.Current.GetDataFilePath(tmdbId, language);
+ movieInfo = movieInfo ?? _jsonSerializer.DeserializeFromFile<MovieResult>(dataFilePath);
- var settings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var settings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
ProcessMainInfo(item, settings, preferredCountryCode, movieInfo);
item.HasMetadata = true;
@@ -120,7 +122,7 @@ namespace MediaBrowser.Providers.Movies
/// <param name="settings">The settings.</param>
/// <param name="preferredCountryCode">The preferred country code.</param>
/// <param name="movieData">The movie data.</param>
- private void ProcessMainInfo(MetadataResult<T> resultItem, TmdbSettingsResult settings, string preferredCountryCode, MovieDbProvider.CompleteMovieData movieData)
+ private void ProcessMainInfo(MetadataResult<T> resultItem, TmdbSettingsResult settings, string preferredCountryCode, MovieResult movieData)
{
var movie = resultItem.Item;
@@ -128,41 +130,39 @@ namespace MediaBrowser.Providers.Movies
movie.OriginalTitle = movieData.GetOriginalTitle();
- movie.Overview = string.IsNullOrWhiteSpace(movieData.overview) ? null : WebUtility.HtmlDecode(movieData.overview);
+ movie.Overview = string.IsNullOrWhiteSpace(movieData.Overview) ? null : WebUtility.HtmlDecode(movieData.Overview);
movie.Overview = movie.Overview != null ? movie.Overview.Replace("\n\n", "\n") : null;
//movie.HomePageUrl = movieData.homepage;
- if (!string.IsNullOrEmpty(movieData.tagline))
+ if (!string.IsNullOrEmpty(movieData.Tagline))
{
- movie.Tagline = movieData.tagline;
+ movie.Tagline = movieData.Tagline;
}
- if (movieData.production_countries != null)
+ if (movieData.Production_Countries != null)
{
movie.ProductionLocations = movieData
- .production_countries
- .Select(i => i.name)
+ .Production_Countries
+ .Select(i => i.Name)
.ToArray();
}
- movie.SetProviderId(MetadataProviders.Tmdb, movieData.id.ToString(_usCulture));
- movie.SetProviderId(MetadataProviders.Imdb, movieData.imdb_id);
+ movie.SetProviderId(MetadataProviders.Tmdb, movieData.Id.ToString(_usCulture));
+ movie.SetProviderId(MetadataProviders.Imdb, movieData.Imdb_Id);
- if (movieData.belongs_to_collection != null)
+ if (movieData.Belongs_To_Collection != null)
{
movie.SetProviderId(MetadataProviders.TmdbCollection,
- movieData.belongs_to_collection.id.ToString(CultureInfo.InvariantCulture));
+ movieData.Belongs_To_Collection.Id.ToString(CultureInfo.InvariantCulture));
- var movieItem = movie as Movie;
-
- if (movieItem != null)
+ if (movie is Movie movieItem)
{
- movieItem.CollectionName = movieData.belongs_to_collection.name;
+ movieItem.CollectionName = movieData.Belongs_To_Collection.Name;
}
}
- string voteAvg = movieData.vote_average.ToString(CultureInfo.InvariantCulture);
+ string voteAvg = movieData.Vote_Average.ToString(CultureInfo.InvariantCulture);
if (float.TryParse(voteAvg, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var rating))
{
@@ -171,17 +171,17 @@ namespace MediaBrowser.Providers.Movies
//movie.VoteCount = movieData.vote_count;
- if (movieData.releases != null && movieData.releases.countries != null)
+ if (movieData.Releases != null && movieData.Releases.Countries != null)
{
- var releases = movieData.releases.countries.Where(i => !string.IsNullOrWhiteSpace(i.certification)).ToList();
+ var releases = movieData.Releases.Countries.Where(i => !string.IsNullOrWhiteSpace(i.Certification)).ToList();
- var ourRelease = releases.FirstOrDefault(c => string.Equals(c.iso_3166_1, preferredCountryCode, StringComparison.OrdinalIgnoreCase));
- var usRelease = releases.FirstOrDefault(c => string.Equals(c.iso_3166_1, "US", StringComparison.OrdinalIgnoreCase));
+ var ourRelease = releases.FirstOrDefault(c => string.Equals(c.Iso_3166_1, preferredCountryCode, StringComparison.OrdinalIgnoreCase));
+ var usRelease = releases.FirstOrDefault(c => string.Equals(c.Iso_3166_1, "US", StringComparison.OrdinalIgnoreCase));
if (ourRelease != null)
{
var ratingPrefix = string.Equals(preferredCountryCode, "us", StringComparison.OrdinalIgnoreCase) ? "" : preferredCountryCode + "-";
- var newRating = ratingPrefix + ourRelease.certification;
+ var newRating = ratingPrefix + ourRelease.Certification;
newRating = newRating.Replace("de-", "FSK-", StringComparison.OrdinalIgnoreCase);
@@ -189,14 +189,14 @@ namespace MediaBrowser.Providers.Movies
}
else if (usRelease != null)
{
- movie.OfficialRating = usRelease.certification;
+ movie.OfficialRating = usRelease.Certification;
}
}
- if (!string.IsNullOrWhiteSpace(movieData.release_date))
+ if (!string.IsNullOrWhiteSpace(movieData.Release_Date))
{
// These dates are always in this exact format
- if (DateTime.TryParse(movieData.release_date, _usCulture, DateTimeStyles.None, out var r))
+ if (DateTime.TryParse(movieData.Release_Date, _usCulture, DateTimeStyles.None, out var r))
{
movie.PremiereDate = r.ToUniversalTime();
movie.ProductionYear = movie.PremiereDate.Value.Year;
@@ -204,16 +204,16 @@ namespace MediaBrowser.Providers.Movies
}
//studios
- if (movieData.production_companies != null)
+ if (movieData.Production_Companies != null)
{
- movie.SetStudios(movieData.production_companies.Select(c => c.name));
+ movie.SetStudios(movieData.Production_Companies.Select(c => c.Name));
}
// genres
// Movies get this from imdb
- var genres = movieData.genres ?? new List<MovieDbProvider.GenreItem>();
+ var genres = movieData.Genres ?? new List<Tmdb.Models.General.Genre>();
- foreach (var genre in genres.Select(g => g.name))
+ foreach (var genre in genres.Select(g => g.Name))
{
movie.AddGenre(genre);
}
@@ -223,26 +223,26 @@ namespace MediaBrowser.Providers.Movies
//Actors, Directors, Writers - all in People
//actors come from cast
- if (movieData.casts != null && movieData.casts.cast != null)
+ if (movieData.Casts != null && movieData.Casts.Cast != null)
{
- foreach (var actor in movieData.casts.cast.OrderBy(a => a.order))
+ foreach (var actor in movieData.Casts.Cast.OrderBy(a => a.Order))
{
var personInfo = new PersonInfo
{
- Name = actor.name.Trim(),
- Role = actor.character,
+ Name = actor.Name.Trim(),
+ Role = actor.Character,
Type = PersonType.Actor,
- SortOrder = actor.order
+ SortOrder = actor.Order
};
- if (!string.IsNullOrWhiteSpace(actor.profile_path))
+ if (!string.IsNullOrWhiteSpace(actor.Profile_Path))
{
- personInfo.ImageUrl = tmdbImageUrl + actor.profile_path;
+ personInfo.ImageUrl = tmdbImageUrl + actor.Profile_Path;
}
- if (actor.id > 0)
+ if (actor.Id > 0)
{
- personInfo.SetProviderId(MetadataProviders.Tmdb, actor.id.ToString(CultureInfo.InvariantCulture));
+ personInfo.SetProviderId(MetadataProviders.Tmdb, actor.Id.ToString(CultureInfo.InvariantCulture));
}
resultItem.AddPerson(personInfo);
@@ -250,45 +250,41 @@ namespace MediaBrowser.Providers.Movies
}
//and the rest from crew
- if (movieData.casts != null && movieData.casts.crew != null)
+ if (movieData.Casts?.Crew != null)
{
var keepTypes = new[]
{
PersonType.Director,
- //PersonType.Writer,
- //PersonType.Producer
+ PersonType.Writer,
+ PersonType.Producer
};
- foreach (var person in movieData.casts.crew)
+ foreach (var person in movieData.Casts.Crew)
{
// Normalize this
- var type = person.department;
- if (string.Equals(type, "writing", StringComparison.OrdinalIgnoreCase))
- {
- type = PersonType.Writer;
- }
+ var type = TmdbUtils.MapCrewToPersonType(person);
- if (!keepTypes.Contains(type ?? string.Empty, StringComparer.OrdinalIgnoreCase) &&
- !keepTypes.Contains(person.job ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ if (!keepTypes.Contains(type, StringComparer.OrdinalIgnoreCase) &&
+ !keepTypes.Contains(person.Job ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
continue;
}
var personInfo = new PersonInfo
{
- Name = person.name.Trim(),
- Role = person.job,
+ Name = person.Name.Trim(),
+ Role = person.Job,
Type = type
};
- if (!string.IsNullOrWhiteSpace(person.profile_path))
+ if (!string.IsNullOrWhiteSpace(person.Profile_Path))
{
- personInfo.ImageUrl = tmdbImageUrl + person.profile_path;
+ personInfo.ImageUrl = tmdbImageUrl + person.Profile_Path;
}
- if (person.id > 0)
+ if (person.Id > 0)
{
- personInfo.SetProviderId(MetadataProviders.Tmdb, person.id.ToString(CultureInfo.InvariantCulture));
+ personInfo.SetProviderId(MetadataProviders.Tmdb, person.Id.ToString(CultureInfo.InvariantCulture));
}
resultItem.AddPerson(personInfo);
@@ -300,12 +296,12 @@ namespace MediaBrowser.Providers.Movies
// movie.Keywords = movieData.keywords.keywords.Select(i => i.name).ToList();
//}
- if (movieData.trailers != null && movieData.trailers.youtube != null)
+ if (movieData.Trailers != null && movieData.Trailers.Youtube != null)
{
- movie.RemoteTrailers = movieData.trailers.youtube.Select(i => new MediaUrl
+ movie.RemoteTrailers = movieData.Trailers.Youtube.Select(i => new MediaUrl
{
- Url = string.Format("https://www.youtube.com/watch?v={0}", i.source),
- Name = i.name
+ Url = string.Format("https://www.youtube.com/watch?v={0}", i.Source),
+ Name = i.Name
}).ToArray();
}
diff --git a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs b/MediaBrowser.Providers/Tmdb/Movies/TmdbImageProvider.cs
index 20b53d58a..cdb96e6ac 100644
--- a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/Movies/TmdbImageProvider.cs
@@ -13,16 +13,19 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
+using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.General;
+using MediaBrowser.Providers.Tmdb.Models.Movies;
-namespace MediaBrowser.Providers.Movies
+namespace MediaBrowser.Providers.Tmdb.Movies
{
- public class MovieDbImageProvider : IRemoteImageProvider, IHasOrder
+ public class TmdbImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
private readonly IFileSystem _fileSystem;
- public MovieDbImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem)
+ public TmdbImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
@@ -31,7 +34,7 @@ namespace MediaBrowser.Providers.Movies
public string Name => ProviderName;
- public static string ProviderName => "TheMovieDb";
+ public static string ProviderName => TmdbUtils.ProviderName;
public bool Supports(BaseItem item)
{
@@ -60,7 +63,7 @@ namespace MediaBrowser.Providers.Movies
return list;
}
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
@@ -70,12 +73,12 @@ namespace MediaBrowser.Providers.Movies
{
list.AddRange(GetPosters(results).Select(i => new RemoteImageInfo
{
- Url = tmdbImageUrl + i.file_path,
- CommunityRating = i.vote_average,
- VoteCount = i.vote_count,
- Width = i.width,
- Height = i.height,
- Language = MovieDbProvider.AdjustImageLanguage(i.iso_639_1, language),
+ Url = tmdbImageUrl + i.File_Path,
+ CommunityRating = i.Vote_Average,
+ VoteCount = i.Vote_Count,
+ Width = i.Width,
+ Height = i.Height,
+ Language = TmdbMovieProvider.AdjustImageLanguage(i.Iso_639_1, language),
ProviderName = Name,
Type = ImageType.Primary,
RatingType = RatingType.Score
@@ -86,11 +89,11 @@ namespace MediaBrowser.Providers.Movies
{
list.AddRange(GetBackdrops(results).Select(i => new RemoteImageInfo
{
- Url = tmdbImageUrl + i.file_path,
- CommunityRating = i.vote_average,
- VoteCount = i.vote_count,
- Width = i.width,
- Height = i.height,
+ Url = tmdbImageUrl + i.File_Path,
+ CommunityRating = i.Vote_Average,
+ VoteCount = i.Vote_Count,
+ Width = i.Width,
+ Height = i.Height,
ProviderName = Name,
Type = ImageType.Backdrop,
RatingType = RatingType.Score
@@ -127,9 +130,9 @@ namespace MediaBrowser.Providers.Movies
/// </summary>
/// <param name="images">The images.</param>
/// <returns>IEnumerable{MovieDbProvider.Poster}.</returns>
- private IEnumerable<MovieDbProvider.Poster> GetPosters(MovieDbProvider.Images images)
+ private IEnumerable<Poster> GetPosters(Images images)
{
- return images.posters ?? new List<MovieDbProvider.Poster>();
+ return images.Posters ?? new List<Poster>();
}
/// <summary>
@@ -137,13 +140,13 @@ namespace MediaBrowser.Providers.Movies
/// </summary>
/// <param name="images">The images.</param>
/// <returns>IEnumerable{MovieDbProvider.Backdrop}.</returns>
- private IEnumerable<MovieDbProvider.Backdrop> GetBackdrops(MovieDbProvider.Images images)
+ private IEnumerable<Backdrop> GetBackdrops(Images images)
{
- var eligibleBackdrops = images.backdrops == null ? new List<MovieDbProvider.Backdrop>() :
- images.backdrops;
+ var eligibleBackdrops = images.Backdrops == null ? new List<Backdrop>() :
+ images.Backdrops;
- return eligibleBackdrops.OrderByDescending(i => i.vote_average)
- .ThenByDescending(i => i.vote_count);
+ return eligibleBackdrops.OrderByDescending(i => i.Vote_Average)
+ .ThenByDescending(i => i.Vote_Count);
}
/// <summary>
@@ -154,7 +157,7 @@ namespace MediaBrowser.Providers.Movies
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{MovieImages}.</returns>
- private async Task<MovieDbProvider.Images> FetchImages(BaseItem item, string language, IJsonSerializer jsonSerializer, CancellationToken cancellationToken)
+ private async Task<Images> FetchImages(BaseItem item, string language, IJsonSerializer jsonSerializer, CancellationToken cancellationToken)
{
var tmdbId = item.GetProviderId(MetadataProviders.Tmdb);
@@ -163,10 +166,10 @@ namespace MediaBrowser.Providers.Movies
var imdbId = item.GetProviderId(MetadataProviders.Imdb);
if (!string.IsNullOrWhiteSpace(imdbId))
{
- var movieInfo = await MovieDbProvider.Current.FetchMainResult(imdbId, false, language, cancellationToken).ConfigureAwait(false);
+ var movieInfo = await TmdbMovieProvider.Current.FetchMainResult(imdbId, false, language, cancellationToken).ConfigureAwait(false);
if (movieInfo != null)
{
- tmdbId = movieInfo.id.ToString(CultureInfo.InvariantCulture);
+ tmdbId = movieInfo.Id.ToString(CultureInfo.InvariantCulture);
}
}
}
@@ -176,9 +179,9 @@ namespace MediaBrowser.Providers.Movies
return null;
}
- await MovieDbProvider.Current.EnsureMovieInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
+ await TmdbMovieProvider.Current.EnsureMovieInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
- var path = MovieDbProvider.Current.GetDataFilePath(tmdbId, language);
+ var path = TmdbMovieProvider.Current.GetDataFilePath(tmdbId, language);
if (!string.IsNullOrEmpty(path))
{
@@ -186,7 +189,7 @@ namespace MediaBrowser.Providers.Movies
if (fileInfo.Exists)
{
- return jsonSerializer.DeserializeFromFile<MovieDbProvider.CompleteMovieData>(path).images;
+ return jsonSerializer.DeserializeFromFile<MovieResult>(path).Images;
}
}
diff --git a/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieExternalId.cs b/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieExternalId.cs
new file mode 100644
index 000000000..fc7a4583f
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieExternalId.cs
@@ -0,0 +1,32 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Providers.Tmdb.Movies
+{
+ public class TmdbMovieExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string Name => TmdbUtils.ProviderName;
+
+ /// <inheritdoc />
+ public string Key => MetadataProviders.Tmdb.ToString();
+
+ /// <inheritdoc />
+ public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "movie/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item)
+ {
+ // Supports images for tv movies
+ if (item is LiveTvProgram tvProgram && tvProgram.IsMovie)
+ {
+ return true;
+ }
+
+ return item is Movie || item is MusicVideo || item is Trailer;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs
index 3ff63a4bf..a1bea5847 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs
@@ -19,16 +19,18 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
+using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.Movies;
using Microsoft.Extensions.Logging;
-namespace MediaBrowser.Providers.Movies
+namespace MediaBrowser.Providers.Tmdb.Movies
{
/// <summary>
/// Class MovieDbProvider
/// </summary>
- public class MovieDbProvider : IRemoteMetadataProvider<Movie, MovieInfo>, IHasOrder
+ public class TmdbMovieProvider : IRemoteMetadataProvider<Movie, MovieInfo>, IHasOrder
{
- internal static MovieDbProvider Current { get; private set; }
+ internal static TmdbMovieProvider Current { get; private set; }
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
@@ -41,7 +43,7 @@ namespace MediaBrowser.Providers.Movies
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- public MovieDbProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization, ILibraryManager libraryManager, IApplicationHost appHost)
+ public TmdbMovieProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization, ILibraryManager libraryManager, IApplicationHost appHost)
{
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
@@ -71,7 +73,7 @@ namespace MediaBrowser.Providers.Movies
var dataFilePath = GetDataFilePath(tmdbId, searchInfo.MetadataLanguage);
- var obj = _jsonSerializer.DeserializeFromFile<CompleteMovieData>(dataFilePath);
+ var obj = _jsonSerializer.DeserializeFromFile<MovieResult>(dataFilePath);
var tmdbSettings = await GetTmdbSettings(cancellationToken).ConfigureAwait(false);
@@ -81,30 +83,30 @@ namespace MediaBrowser.Providers.Movies
{
Name = obj.GetTitle(),
SearchProviderName = Name,
- ImageUrl = string.IsNullOrWhiteSpace(obj.poster_path) ? null : tmdbImageUrl + obj.poster_path
+ ImageUrl = string.IsNullOrWhiteSpace(obj.Poster_Path) ? null : tmdbImageUrl + obj.Poster_Path
};
- if (!string.IsNullOrWhiteSpace(obj.release_date))
+ if (!string.IsNullOrWhiteSpace(obj.Release_Date))
{
// These dates are always in this exact format
- if (DateTime.TryParse(obj.release_date, _usCulture, DateTimeStyles.None, out var r))
+ if (DateTime.TryParse(obj.Release_Date, _usCulture, DateTimeStyles.None, out var r))
{
remoteResult.PremiereDate = r.ToUniversalTime();
remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year;
}
}
- remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.id.ToString(_usCulture));
+ remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.Id.ToString(_usCulture));
- if (!string.IsNullOrWhiteSpace(obj.imdb_id))
+ if (!string.IsNullOrWhiteSpace(obj.Imdb_Id))
{
- remoteResult.SetProviderId(MetadataProviders.Imdb, obj.imdb_id);
+ remoteResult.SetProviderId(MetadataProviders.Imdb, obj.Imdb_Id);
}
return new[] { remoteResult };
}
- return await new MovieDbSearch(_logger, _jsonSerializer, _libraryManager).GetMovieSearchResults(searchInfo, cancellationToken).ConfigureAwait(false);
+ return await new TmdbSearch(_logger, _jsonSerializer, _libraryManager).GetMovieSearchResults(searchInfo, cancellationToken).ConfigureAwait(false);
}
public Task<MetadataResult<Movie>> GetMetadata(MovieInfo info, CancellationToken cancellationToken)
@@ -115,12 +117,12 @@ namespace MediaBrowser.Providers.Movies
public Task<MetadataResult<T>> GetItemMetadata<T>(ItemLookupInfo id, CancellationToken cancellationToken)
where T : BaseItem, new()
{
- var movieDb = new GenericMovieDbInfo<T>(_logger, _jsonSerializer, _libraryManager, _fileSystem);
+ var movieDb = new GenericTmdbMovieInfo<T>(_logger, _jsonSerializer, _libraryManager, _fileSystem);
return movieDb.GetMetadata(id, cancellationToken);
}
- public string Name => "TheMovieDb";
+ public string Name => TmdbUtils.ProviderName;
/// <summary>
/// The _TMDB settings task
@@ -140,9 +142,9 @@ namespace MediaBrowser.Providers.Movies
using (HttpResponseInfo response = await GetMovieDbResponse(new HttpRequestOptions
{
- Url = string.Format(TmdbConfigUrl, ApiKey),
+ Url = string.Format(TmdbConfigUrl, TmdbUtils.ApiKey),
CancellationToken = cancellationToken,
- AcceptHeader = AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
@@ -155,13 +157,8 @@ namespace MediaBrowser.Providers.Movies
}
}
- public const string BaseMovieDbUrl = "https://api.themoviedb.org/";
-
- private const string TmdbConfigUrl = BaseMovieDbUrl + "3/configuration?api_key={0}";
- private const string GetMovieInfo3 = BaseMovieDbUrl + @"3/movie/{0}?api_key={1}&append_to_response=casts,releases,images,keywords,trailers";
-
- internal static string ApiKey = "4219e299c89411838049ab0dab19ebd5";
- internal static string AcceptHeader = "application/json,image/*";
+ private const string TmdbConfigUrl = TmdbUtils.BaseTmdbApiUrl + "3/configuration?api_key={0}";
+ private const string GetMovieInfo3 = TmdbUtils.BaseTmdbApiUrl + @"3/movie/{0}?api_key={1}&append_to_response=casts,releases,images,keywords,trailers";
/// <summary>
/// Gets the movie data path.
@@ -314,9 +311,9 @@ namespace MediaBrowser.Providers.Movies
/// <param name="language">The language.</param>
/// <param name="cancellationToken">The cancellation token</param>
/// <returns>Task{CompleteMovieData}.</returns>
- internal async Task<CompleteMovieData> FetchMainResult(string id, bool isTmdbId, string language, CancellationToken cancellationToken)
+ internal async Task<MovieResult> FetchMainResult(string id, bool isTmdbId, string language, CancellationToken cancellationToken)
{
- var url = string.Format(GetMovieInfo3, id, ApiKey);
+ var url = string.Format(GetMovieInfo3, id, TmdbUtils.ApiKey);
if (!string.IsNullOrEmpty(language))
{
@@ -326,7 +323,7 @@ namespace MediaBrowser.Providers.Movies
url += "&include_image_language=" + GetImageLanguagesParam(language);
}
- CompleteMovieData mainResult;
+ MovieResult mainResult;
cancellationToken.ThrowIfCancellationRequested();
@@ -340,7 +337,7 @@ namespace MediaBrowser.Providers.Movies
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = AcceptHeader,
+ AcceptHeader = TmdbUtils.AcceptHeader,
CacheMode = cacheMode,
CacheLength = cacheLength
@@ -348,7 +345,7 @@ namespace MediaBrowser.Providers.Movies
{
using (var json = response.Content)
{
- mainResult = await _jsonSerializer.DeserializeFromStreamAsync<CompleteMovieData>(json).ConfigureAwait(false);
+ mainResult = await _jsonSerializer.DeserializeFromStreamAsync<MovieResult>(json).ConfigureAwait(false);
}
}
}
@@ -367,13 +364,13 @@ namespace MediaBrowser.Providers.Movies
// If the language preference isn't english, then have the overview fallback to english if it's blank
if (mainResult != null &&
- string.IsNullOrEmpty(mainResult.overview) &&
+ string.IsNullOrEmpty(mainResult.Overview) &&
!string.IsNullOrEmpty(language) &&
!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
{
_logger.LogInformation("MovieDbProvider couldn't find meta for language " + language + ". Trying English...");
- url = string.Format(GetMovieInfo3, id, ApiKey) + "&language=en";
+ url = string.Format(GetMovieInfo3, id, TmdbUtils.ApiKey) + "&language=en";
if (!string.IsNullOrEmpty(language))
{
@@ -385,7 +382,7 @@ namespace MediaBrowser.Providers.Movies
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = AcceptHeader,
+ AcceptHeader = TmdbUtils.AcceptHeader,
CacheMode = cacheMode,
CacheLength = cacheLength
@@ -393,9 +390,9 @@ namespace MediaBrowser.Providers.Movies
{
using (var json = response.Content)
{
- var englishResult = await _jsonSerializer.DeserializeFromStreamAsync<CompleteMovieData>(json).ConfigureAwait(false);
+ var englishResult = await _jsonSerializer.DeserializeFromStreamAsync<MovieResult>(json).ConfigureAwait(false);
- mainResult.overview = englishResult.overview;
+ mainResult.Overview = englishResult.Overview;
}
}
}
@@ -429,205 +426,6 @@ namespace MediaBrowser.Providers.Movies
return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
}
- /// <summary>
- /// Class TmdbTitle
- /// </summary>
- internal class TmdbTitle
- {
- /// <summary>
- /// Gets or sets the iso_3166_1.
- /// </summary>
- /// <value>The iso_3166_1.</value>
- public string iso_3166_1 { get; set; }
- /// <summary>
- /// Gets or sets the title.
- /// </summary>
- /// <value>The title.</value>
- public string title { get; set; }
- }
-
- /// <summary>
- /// Class TmdbAltTitleResults
- /// </summary>
- internal class TmdbAltTitleResults
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- public int id { get; set; }
- /// <summary>
- /// Gets or sets the titles.
- /// </summary>
- /// <value>The titles.</value>
- public List<TmdbTitle> titles { get; set; }
- }
-
- internal class BelongsToCollection
- {
- public int id { get; set; }
- public string name { get; set; }
- public string poster_path { get; set; }
- public string backdrop_path { get; set; }
- }
-
- internal class GenreItem
- {
- public int id { get; set; }
- public string name { get; set; }
- }
-
- internal class ProductionCompany
- {
- public string name { get; set; }
- public int id { get; set; }
- }
-
- internal class ProductionCountry
- {
- public string iso_3166_1 { get; set; }
- public string name { get; set; }
- }
-
- internal class SpokenLanguage
- {
- public string iso_639_1 { get; set; }
- public string name { get; set; }
- }
-
- internal class Cast
- {
- public int id { get; set; }
- public string name { get; set; }
- public string character { get; set; }
- public int order { get; set; }
- public int cast_id { get; set; }
- public string profile_path { get; set; }
- }
-
- internal class Crew
- {
- public int id { get; set; }
- public string name { get; set; }
- public string department { get; set; }
- public string job { get; set; }
- public string profile_path { get; set; }
- }
-
- internal class Casts
- {
- public List<Cast> cast { get; set; }
- public List<Crew> crew { get; set; }
- }
-
- internal class Country
- {
- public string iso_3166_1 { get; set; }
- public string certification { get; set; }
- public DateTime release_date { get; set; }
- }
-
- internal class Releases
- {
- public List<Country> countries { get; set; }
- }
-
- internal class Backdrop
- {
- public string file_path { get; set; }
- public int width { get; set; }
- public int height { get; set; }
- public object iso_639_1 { get; set; }
- public double aspect_ratio { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- }
-
- internal class Poster
- {
- public string file_path { get; set; }
- public int width { get; set; }
- public int height { get; set; }
- public string iso_639_1 { get; set; }
- public double aspect_ratio { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- }
-
- internal class Images
- {
- public List<Backdrop> backdrops { get; set; }
- public List<Poster> posters { get; set; }
- }
-
- internal class Keyword
- {
- public int id { get; set; }
- public string name { get; set; }
- }
-
- internal class Keywords
- {
- public List<Keyword> keywords { get; set; }
- }
-
- internal class Youtube
- {
- public string name { get; set; }
- public string size { get; set; }
- public string source { get; set; }
- }
-
- internal class Trailers
- {
- public List<object> quicktime { get; set; }
- public List<Youtube> youtube { get; set; }
- }
-
- internal class CompleteMovieData
- {
- public bool adult { get; set; }
- public string backdrop_path { get; set; }
- public BelongsToCollection belongs_to_collection { get; set; }
- public int budget { get; set; }
- public List<GenreItem> genres { get; set; }
- public string homepage { get; set; }
- public int id { get; set; }
- public string imdb_id { get; set; }
- public string original_title { get; set; }
- public string original_name { get; set; }
- public string overview { get; set; }
- public double popularity { get; set; }
- public string poster_path { get; set; }
- public List<ProductionCompany> production_companies { get; set; }
- public List<ProductionCountry> production_countries { get; set; }
- public string release_date { get; set; }
- public int revenue { get; set; }
- public int runtime { get; set; }
- public List<SpokenLanguage> spoken_languages { get; set; }
- public string status { get; set; }
- public string tagline { get; set; }
- public string title { get; set; }
- public string name { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- public Casts casts { get; set; }
- public Releases releases { get; set; }
- public Images images { get; set; }
- public Keywords keywords { get; set; }
- public Trailers trailers { get; set; }
-
- public string GetOriginalTitle()
- {
- return original_name ?? original_title;
- }
-
- public string GetTitle()
- {
- return name ?? title ?? GetOriginalTitle();
- }
- }
-
public int Order => 1;
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/Movies/MovieDbSearch.cs b/MediaBrowser.Providers/Tmdb/Movies/TmdbSearch.cs
index e466d40a0..223cef086 100644
--- a/MediaBrowser.Providers/Movies/MovieDbSearch.cs
+++ b/MediaBrowser.Providers/Tmdb/Movies/TmdbSearch.cs
@@ -11,23 +11,21 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
+using MediaBrowser.Providers.Tmdb.Models.Search;
using Microsoft.Extensions.Logging;
-namespace MediaBrowser.Providers.Movies
+namespace MediaBrowser.Providers.Tmdb.Movies
{
- public class MovieDbSearch
+ public class TmdbSearch
{
private static readonly CultureInfo EnUs = new CultureInfo("en-US");
- private const string Search3 = MovieDbProvider.BaseMovieDbUrl + @"3/search/{3}?api_key={1}&query={0}&language={2}";
-
- internal static string ApiKey = "4219e299c89411838049ab0dab19ebd5";
- internal static string AcceptHeader = "application/json,image/*";
+ private const string Search3 = TmdbUtils.BaseTmdbApiUrl + @"3/search/{3}?api_key={1}&query={0}&language={2}";
private readonly ILogger _logger;
private readonly IJsonSerializer _json;
private readonly ILibraryManager _libraryManager;
- public MovieDbSearch(ILogger logger, IJsonSerializer json, ILibraryManager libraryManager)
+ public TmdbSearch(ILogger logger, IJsonSerializer json, ILibraryManager libraryManager)
{
_logger = logger;
_json = json;
@@ -59,7 +57,7 @@ namespace MediaBrowser.Providers.Movies
return new List<RemoteSearchResult>();
}
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
@@ -152,43 +150,43 @@ namespace MediaBrowser.Providers.Movies
throw new ArgumentException("name");
}
- var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, type);
+ var url3 = string.Format(Search3, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, type);
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url3,
CancellationToken = cancellationToken,
- AcceptHeader = AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
using (var json = response.Content)
{
- var searchResults = await _json.DeserializeFromStreamAsync<TmdbMovieSearchResults>(json).ConfigureAwait(false);
+ var searchResults = await _json.DeserializeFromStreamAsync<TmdbSearchResult<MovieResult>>(json).ConfigureAwait(false);
- var results = searchResults.results ?? new List<TmdbMovieSearchResult>();
+ var results = searchResults.Results ?? new List<MovieResult>();
return results
.Select(i =>
{
var remoteResult = new RemoteSearchResult
{
- SearchProviderName = MovieDbProvider.Current.Name,
- Name = i.title ?? i.name ?? i.original_title,
- ImageUrl = string.IsNullOrWhiteSpace(i.poster_path) ? null : baseImageUrl + i.poster_path
+ SearchProviderName = TmdbMovieProvider.Current.Name,
+ Name = i.Title ?? i.Name ?? i.Original_Title,
+ ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path
};
- if (!string.IsNullOrWhiteSpace(i.release_date))
+ if (!string.IsNullOrWhiteSpace(i.Release_Date))
{
// These dates are always in this exact format
- if (DateTime.TryParseExact(i.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out var r))
+ if (DateTime.TryParseExact(i.Release_Date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out var r))
{
remoteResult.PremiereDate = r.ToUniversalTime();
remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year;
}
}
- remoteResult.SetProviderId(MetadataProviders.Tmdb, i.id.ToString(EnUs));
+ remoteResult.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(EnUs));
return remoteResult;
@@ -205,43 +203,43 @@ namespace MediaBrowser.Providers.Movies
throw new ArgumentException("name");
}
- var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, "tv");
+ var url3 = string.Format(Search3, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, "tv");
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url3,
CancellationToken = cancellationToken,
- AcceptHeader = AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
using (var json = response.Content)
{
- var searchResults = await _json.DeserializeFromStreamAsync<TmdbTvSearchResults>(json).ConfigureAwait(false);
+ var searchResults = await _json.DeserializeFromStreamAsync<TmdbSearchResult<TvResult>>(json).ConfigureAwait(false);
- var results = searchResults.results ?? new List<TvResult>();
+ var results = searchResults.Results ?? new List<TvResult>();
return results
.Select(i =>
{
var remoteResult = new RemoteSearchResult
{
- SearchProviderName = MovieDbProvider.Current.Name,
- Name = i.name ?? i.original_name,
- ImageUrl = string.IsNullOrWhiteSpace(i.poster_path) ? null : baseImageUrl + i.poster_path
+ SearchProviderName = TmdbMovieProvider.Current.Name,
+ Name = i.Name ?? i.Original_Name,
+ ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path
};
- if (!string.IsNullOrWhiteSpace(i.first_air_date))
+ if (!string.IsNullOrWhiteSpace(i.First_Air_Date))
{
// These dates are always in this exact format
- if (DateTime.TryParseExact(i.first_air_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out var r))
+ if (DateTime.TryParseExact(i.First_Air_Date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out var r))
{
remoteResult.PremiereDate = r.ToUniversalTime();
remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year;
}
}
- remoteResult.SetProviderId(MetadataProviders.Tmdb, i.id.ToString(EnUs));
+ remoteResult.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(EnUs));
return remoteResult;
@@ -250,145 +248,5 @@ namespace MediaBrowser.Providers.Movies
}
}
}
-
- /// <summary>
- /// Class TmdbMovieSearchResult
- /// </summary>
- public class TmdbMovieSearchResult
- {
- /// <summary>
- /// Gets or sets a value indicating whether this <see cref="TmdbMovieSearchResult" /> is adult.
- /// </summary>
- /// <value><c>true</c> if adult; otherwise, <c>false</c>.</value>
- public bool adult { get; set; }
- /// <summary>
- /// Gets or sets the backdrop_path.
- /// </summary>
- /// <value>The backdrop_path.</value>
- public string backdrop_path { get; set; }
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- public int id { get; set; }
- /// <summary>
- /// Gets or sets the original_title.
- /// </summary>
- /// <value>The original_title.</value>
- public string original_title { get; set; }
- /// <summary>
- /// Gets or sets the original_name.
- /// </summary>
- /// <value>The original_name.</value>
- public string original_name { get; set; }
- /// <summary>
- /// Gets or sets the release_date.
- /// </summary>
- /// <value>The release_date.</value>
- public string release_date { get; set; }
- /// <summary>
- /// Gets or sets the poster_path.
- /// </summary>
- /// <value>The poster_path.</value>
- public string poster_path { get; set; }
- /// <summary>
- /// Gets or sets the popularity.
- /// </summary>
- /// <value>The popularity.</value>
- public double popularity { get; set; }
- /// <summary>
- /// Gets or sets the title.
- /// </summary>
- /// <value>The title.</value>
- public string title { get; set; }
- /// <summary>
- /// Gets or sets the vote_average.
- /// </summary>
- /// <value>The vote_average.</value>
- public double vote_average { get; set; }
- /// <summary>
- /// For collection search results
- /// </summary>
- public string name { get; set; }
- /// <summary>
- /// Gets or sets the vote_count.
- /// </summary>
- /// <value>The vote_count.</value>
- public int vote_count { get; set; }
- }
-
- /// <summary>
- /// Class TmdbMovieSearchResults
- /// </summary>
- private class TmdbMovieSearchResults
- {
- /// <summary>
- /// Gets or sets the page.
- /// </summary>
- /// <value>The page.</value>
- public int page { get; set; }
- /// <summary>
- /// Gets or sets the results.
- /// </summary>
- /// <value>The results.</value>
- public List<TmdbMovieSearchResult> results { get; set; }
- /// <summary>
- /// Gets or sets the total_pages.
- /// </summary>
- /// <value>The total_pages.</value>
- public int total_pages { get; set; }
- /// <summary>
- /// Gets or sets the total_results.
- /// </summary>
- /// <value>The total_results.</value>
- public int total_results { get; set; }
- }
-
- public class TvResult
- {
- public string backdrop_path { get; set; }
- public string first_air_date { get; set; }
- public int id { get; set; }
- public string original_name { get; set; }
- public string poster_path { get; set; }
- public double popularity { get; set; }
- public string name { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- }
-
- /// <summary>
- /// Class TmdbTvSearchResults
- /// </summary>
- private class TmdbTvSearchResults
- {
- /// <summary>
- /// Gets or sets the page.
- /// </summary>
- /// <value>The page.</value>
- public int page { get; set; }
- /// <summary>
- /// Gets or sets the results.
- /// </summary>
- /// <value>The results.</value>
- public List<TvResult> results { get; set; }
- /// <summary>
- /// Gets or sets the total_pages.
- /// </summary>
- /// <value>The total_pages.</value>
- public int total_pages { get; set; }
- /// <summary>
- /// Gets or sets the total_results.
- /// </summary>
- /// <value>The total_results.</value>
- public int total_results { get; set; }
- }
-
- public class ExternalIdLookupResult
- {
- public List<object> movie_results { get; set; }
- public List<object> person_results { get; set; }
- public List<TvResult> tv_results { get; set; }
- }
}
}
diff --git a/MediaBrowser.Providers/Movies/TmdbSettings.cs b/MediaBrowser.Providers/Tmdb/Movies/TmdbSettings.cs
index 119bbfca6..dca406b99 100644
--- a/MediaBrowser.Providers/Movies/TmdbSettings.cs
+++ b/MediaBrowser.Providers/Tmdb/Movies/TmdbSettings.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace MediaBrowser.Providers.Movies
+namespace MediaBrowser.Providers.Tmdb.Movies
{
internal class TmdbImageSettings
{
diff --git a/MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs b/MediaBrowser.Providers/Tmdb/Music/TmdbMusicVideoProvider.cs
index 506cbfb89..f3f8a92cf 100644
--- a/MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/Music/TmdbMusicVideoProvider.cs
@@ -7,14 +7,15 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Providers;
using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Movies;
-namespace MediaBrowser.Providers.Music
+namespace MediaBrowser.Providers.Tmdb.Music
{
- public class MovieDbMusicVideoProvider : IRemoteMetadataProvider<MusicVideo, MusicVideoInfo>
+ public class TmdbMusicVideoProvider : IRemoteMetadataProvider<MusicVideo, MusicVideoInfo>
{
public Task<MetadataResult<MusicVideo>> GetMetadata(MusicVideoInfo info, CancellationToken cancellationToken)
{
- return MovieDbProvider.Current.GetItemMetadata<MusicVideo>(info, cancellationToken);
+ return TmdbMovieProvider.Current.GetItemMetadata<MusicVideo>(info, cancellationToken);
}
public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MusicVideoInfo searchInfo, CancellationToken cancellationToken)
@@ -22,7 +23,7 @@ namespace MediaBrowser.Providers.Music
return Task.FromResult((IEnumerable<RemoteSearchResult>)new List<RemoteSearchResult>());
}
- public string Name => MovieDbProvider.Current.Name;
+ public string Name => TmdbMovieProvider.Current.Name;
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
diff --git a/MediaBrowser.Providers/Tmdb/People/TmdbPersonExternalId.cs b/MediaBrowser.Providers/Tmdb/People/TmdbPersonExternalId.cs
new file mode 100644
index 000000000..2c61bc70a
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/People/TmdbPersonExternalId.cs
@@ -0,0 +1,24 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Providers.Tmdb.People
+{
+ public class TmdbPersonExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string Name => TmdbUtils.ProviderName;
+
+ /// <inheritdoc />
+ public string Key => MetadataProviders.Tmdb.ToString();
+
+ /// <inheritdoc />
+ public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "person/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item)
+ {
+ return item is Person;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs b/MediaBrowser.Providers/Tmdb/People/TmdbPersonImageProvider.cs
index 3019ee506..44ccbf453 100644
--- a/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/People/TmdbPersonImageProvider.cs
@@ -11,16 +11,19 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.General;
+using MediaBrowser.Providers.Tmdb.Models.People;
+using MediaBrowser.Providers.Tmdb.Movies;
-namespace MediaBrowser.Providers.People
+namespace MediaBrowser.Providers.Tmdb.People
{
- public class MovieDbPersonImageProvider : IRemoteImageProvider, IHasOrder
+ public class TmdbPersonImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
- public MovieDbPersonImageProvider(IServerConfigurationManager config, IJsonSerializer jsonSerializer, IHttpClient httpClient)
+ public TmdbPersonImageProvider(IServerConfigurationManager config, IJsonSerializer jsonSerializer, IHttpClient httpClient)
{
_config = config;
_jsonSerializer = jsonSerializer;
@@ -29,7 +32,7 @@ namespace MediaBrowser.Providers.People
public string Name => ProviderName;
- public static string ProviderName => "TheMovieDb";
+ public static string ProviderName => TmdbUtils.ProviderName;
public bool Supports(BaseItem item)
{
@@ -51,15 +54,15 @@ namespace MediaBrowser.Providers.People
if (!string.IsNullOrEmpty(id))
{
- await MovieDbPersonProvider.Current.EnsurePersonInfo(id, cancellationToken).ConfigureAwait(false);
+ await TmdbPersonProvider.Current.EnsurePersonInfo(id, cancellationToken).ConfigureAwait(false);
- var dataFilePath = MovieDbPersonProvider.GetPersonDataFilePath(_config.ApplicationPaths, id);
+ var dataFilePath = TmdbPersonProvider.GetPersonDataFilePath(_config.ApplicationPaths, id);
- var result = _jsonSerializer.DeserializeFromFile<MovieDbPersonProvider.PersonResult>(dataFilePath);
+ var result = _jsonSerializer.DeserializeFromFile<PersonResult>(dataFilePath);
- var images = result.images ?? new MovieDbPersonProvider.Images();
+ var images = result.Images ?? new PersonImages();
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
@@ -69,20 +72,20 @@ namespace MediaBrowser.Providers.People
return new List<RemoteImageInfo>();
}
- private IEnumerable<RemoteImageInfo> GetImages(MovieDbPersonProvider.Images images, string preferredLanguage, string baseImageUrl)
+ private IEnumerable<RemoteImageInfo> GetImages(PersonImages images, string preferredLanguage, string baseImageUrl)
{
var list = new List<RemoteImageInfo>();
- if (images.profiles != null)
+ if (images.Profiles != null)
{
- list.AddRange(images.profiles.Select(i => new RemoteImageInfo
+ list.AddRange(images.Profiles.Select(i => new RemoteImageInfo
{
ProviderName = Name,
Type = ImageType.Primary,
- Width = i.width,
- Height = i.height,
+ Width = i.Width,
+ Height = i.Height,
Language = GetLanguage(i),
- Url = baseImageUrl + i.file_path
+ Url = baseImageUrl + i.File_Path
}));
}
@@ -113,9 +116,9 @@ namespace MediaBrowser.Providers.People
.ThenByDescending(i => i.VoteCount ?? 0);
}
- private string GetLanguage(MovieDbPersonProvider.Profile profile)
+ private string GetLanguage(Profile profile)
{
- return profile.iso_639_1 == null ? null : profile.iso_639_1.ToString();
+ return profile.Iso_639_1?.ToString();
}
public int Order => 0;
diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs
index 6d9d66f80..130403e4d 100644
--- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs
@@ -17,16 +17,19 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
-using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.General;
+using MediaBrowser.Providers.Tmdb.Models.People;
+using MediaBrowser.Providers.Tmdb.Models.Search;
+using MediaBrowser.Providers.Tmdb.Movies;
using Microsoft.Extensions.Logging;
-namespace MediaBrowser.Providers.People
+namespace MediaBrowser.Providers.Tmdb.People
{
- public class MovieDbPersonProvider : IRemoteMetadataProvider<Person, PersonLookupInfo>
+ public class TmdbPersonProvider : IRemoteMetadataProvider<Person, PersonLookupInfo>
{
const string DataFileName = "info.json";
- internal static MovieDbPersonProvider Current { get; private set; }
+ internal static TmdbPersonProvider Current { get; private set; }
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
@@ -34,7 +37,7 @@ namespace MediaBrowser.Providers.People
private readonly IHttpClient _httpClient;
private readonly ILogger _logger;
- public MovieDbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger)
+ public TmdbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger)
{
_fileSystem = fileSystem;
_configurationManager = configurationManager;
@@ -44,13 +47,13 @@ namespace MediaBrowser.Providers.People
Current = this;
}
- public string Name => "TheMovieDb";
+ public string Name => TmdbUtils.ProviderName;
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken)
{
var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb);
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
@@ -61,19 +64,19 @@ namespace MediaBrowser.Providers.People
var dataFilePath = GetPersonDataFilePath(_configurationManager.ApplicationPaths, tmdbId);
var info = _jsonSerializer.DeserializeFromFile<PersonResult>(dataFilePath);
- var images = (info.images ?? new Images()).profiles ?? new List<Profile>();
+ var images = (info.Images ?? new PersonImages()).Profiles ?? new List<Profile>();
var result = new RemoteSearchResult
{
- Name = info.name,
+ Name = info.Name,
SearchProviderName = Name,
- ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path)
+ ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].File_Path)
};
- result.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture));
- result.SetProviderId(MetadataProviders.Imdb, info.imdb_id);
+ result.SetProviderId(MetadataProviders.Tmdb, info.Id.ToString(_usCulture));
+ result.SetProviderId(MetadataProviders.Imdb, info.Imdb_Id);
return new[] { result };
}
@@ -84,20 +87,20 @@ namespace MediaBrowser.Providers.People
return new List<RemoteSearchResult>();
}
- var url = string.Format(MovieDbProvider.BaseMovieDbUrl + @"3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), MovieDbProvider.ApiKey);
+ var url = string.Format(TmdbUtils.BaseTmdbApiUrl + @"3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), TmdbUtils.ApiKey);
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = MovieDbProvider.AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
using (var json = response.Content)
{
- var result = await _jsonSerializer.DeserializeFromStreamAsync<PersonSearchResults>(json).ConfigureAwait(false) ??
- new PersonSearchResults();
+ var result = await _jsonSerializer.DeserializeFromStreamAsync<TmdbSearchResult<PersonSearchResult>>(json).ConfigureAwait(false) ??
+ new TmdbSearchResult<PersonSearchResult>();
return result.Results.Select(i => GetSearchResult(i, tmdbImageUrl));
}
@@ -112,7 +115,7 @@ namespace MediaBrowser.Providers.People
Name = i.Name,
- ImageUrl = string.IsNullOrEmpty(i.Profile_Path) ? null : (baseImageUrl + i.Profile_Path)
+ ImageUrl = string.IsNullOrEmpty(i.Profile_Path) ? null : baseImageUrl + i.Profile_Path
};
result.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(_usCulture));
@@ -161,27 +164,27 @@ namespace MediaBrowser.Providers.People
//item.HomePageUrl = info.homepage;
- if (!string.IsNullOrWhiteSpace(info.place_of_birth))
+ if (!string.IsNullOrWhiteSpace(info.Place_Of_Birth))
{
- item.ProductionLocations = new string[] { info.place_of_birth };
+ item.ProductionLocations = new string[] { info.Place_Of_Birth };
}
- item.Overview = info.biography;
+ item.Overview = info.Biography;
- if (DateTime.TryParseExact(info.birthday, "yyyy-MM-dd", new CultureInfo("en-US"), DateTimeStyles.None, out var date))
+ if (DateTime.TryParseExact(info.Birthday, "yyyy-MM-dd", new CultureInfo("en-US"), DateTimeStyles.None, out var date))
{
item.PremiereDate = date.ToUniversalTime();
}
- if (DateTime.TryParseExact(info.deathday, "yyyy-MM-dd", new CultureInfo("en-US"), DateTimeStyles.None, out date))
+ if (DateTime.TryParseExact(info.Deathday, "yyyy-MM-dd", new CultureInfo("en-US"), DateTimeStyles.None, out date))
{
item.EndDate = date.ToUniversalTime();
}
- item.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture));
+ item.SetProviderId(MetadataProviders.Tmdb, info.Id.ToString(_usCulture));
- if (!string.IsNullOrEmpty(info.imdb_id))
+ if (!string.IsNullOrEmpty(info.Imdb_Id))
{
- item.SetProviderId(MetadataProviders.Imdb, info.imdb_id);
+ item.SetProviderId(MetadataProviders.Imdb, info.Imdb_Id);
}
result.HasMetadata = true;
@@ -217,13 +220,13 @@ namespace MediaBrowser.Providers.People
return;
}
- var url = string.Format(MovieDbProvider.BaseMovieDbUrl + @"3/person/{1}?api_key={0}&append_to_response=credits,images,external_ids", MovieDbProvider.ApiKey, id);
+ var url = string.Format(TmdbUtils.BaseTmdbApiUrl + @"3/person/{1}?api_key={0}&append_to_response=credits,images,external_ids", TmdbUtils.ApiKey, id);
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = MovieDbProvider.AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
@@ -256,133 +259,6 @@ namespace MediaBrowser.Providers.People
return Path.Combine(appPaths.CachePath, "tmdb-people");
}
- #region Result Objects
- /// <summary>
- /// Class PersonSearchResult
- /// </summary>
- public class PersonSearchResult
- {
- /// <summary>
- /// Gets or sets a value indicating whether this <see cref="PersonSearchResult" /> is adult.
- /// </summary>
- /// <value><c>true</c> if adult; otherwise, <c>false</c>.</value>
- public bool Adult { get; set; }
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- public int Id { get; set; }
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
- /// <summary>
- /// Gets or sets the profile_ path.
- /// </summary>
- /// <value>The profile_ path.</value>
- public string Profile_Path { get; set; }
- }
-
- /// <summary>
- /// Class PersonSearchResults
- /// </summary>
- public class PersonSearchResults
- {
- /// <summary>
- /// Gets or sets the page.
- /// </summary>
- /// <value>The page.</value>
- public int Page { get; set; }
- /// <summary>
- /// Gets or sets the results.
- /// </summary>
- /// <value>The results.</value>
- public List<PersonSearchResult> Results { get; set; }
- /// <summary>
- /// Gets or sets the total_ pages.
- /// </summary>
- /// <value>The total_ pages.</value>
- public int Total_Pages { get; set; }
- /// <summary>
- /// Gets or sets the total_ results.
- /// </summary>
- /// <value>The total_ results.</value>
- public int Total_Results { get; set; }
- }
-
- public class Cast
- {
- public int id { get; set; }
- public string title { get; set; }
- public string character { get; set; }
- public string original_title { get; set; }
- public string poster_path { get; set; }
- public string release_date { get; set; }
- public bool adult { get; set; }
- }
-
- public class Crew
- {
- public int id { get; set; }
- public string title { get; set; }
- public string original_title { get; set; }
- public string department { get; set; }
- public string job { get; set; }
- public string poster_path { get; set; }
- public string release_date { get; set; }
- public bool adult { get; set; }
- }
-
- public class Credits
- {
- public List<Cast> cast { get; set; }
- public List<Crew> crew { get; set; }
- }
-
- public class Profile
- {
- public string file_path { get; set; }
- public int width { get; set; }
- public int height { get; set; }
- public object iso_639_1 { get; set; }
- public double aspect_ratio { get; set; }
- }
-
- public class Images
- {
- public List<Profile> profiles { get; set; }
- }
-
- public class ExternalIds
- {
- public string imdb_id { get; set; }
- public string freebase_mid { get; set; }
- public string freebase_id { get; set; }
- public int tvrage_id { get; set; }
- }
-
- public class PersonResult
- {
- public bool adult { get; set; }
- public List<object> also_known_as { get; set; }
- public string biography { get; set; }
- public string birthday { get; set; }
- public string deathday { get; set; }
- public string homepage { get; set; }
- public int id { get; set; }
- public string imdb_id { get; set; }
- public string name { get; set; }
- public string place_of_birth { get; set; }
- public double popularity { get; set; }
- public string profile_path { get; set; }
- public Credits credits { get; set; }
- public Images images { get; set; }
- public ExternalIds external_ids { get; set; }
- }
-
- #endregion
-
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClient.GetResponse(new HttpRequestOptions
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs
index e4248afe1..51e7891a1 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs
@@ -14,16 +14,18 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.General;
+using MediaBrowser.Providers.Tmdb.Movies;
using Microsoft.Extensions.Logging;
-namespace MediaBrowser.Providers.TV.TheMovieDb
+namespace MediaBrowser.Providers.Tmdb.TV
{
- public class MovieDbEpisodeImageProvider :
- MovieDbProviderBase,
+ public class TmdbEpisodeImageProvider :
+ TmdbEpisodeProviderBase,
IRemoteImageProvider,
IHasOrder
{
- public MovieDbEpisodeImageProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
+ public TmdbEpisodeImageProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
: base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, loggerFactory)
{ }
@@ -62,18 +64,18 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
var response = await GetEpisodeInfo(seriesId, seasonNumber.Value, episodeNumber.Value,
language, cancellationToken).ConfigureAwait(false);
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
- list.AddRange(GetPosters(response.images).Select(i => new RemoteImageInfo
+ list.AddRange(GetPosters(response.Images).Select(i => new RemoteImageInfo
{
- Url = tmdbImageUrl + i.file_path,
- CommunityRating = i.vote_average,
- VoteCount = i.vote_count,
- Width = i.width,
- Height = i.height,
- Language = MovieDbProvider.AdjustImageLanguage(i.iso_639_1, language),
+ Url = tmdbImageUrl + i.File_Path,
+ CommunityRating = i.Vote_Average,
+ VoteCount = i.Vote_Count,
+ Width = i.Width,
+ Height = i.Height,
+ Language = TmdbMovieProvider.AdjustImageLanguage(i.Iso_639_1, language),
ProviderName = Name,
Type = ImageType.Primary,
RatingType = RatingType.Score
@@ -106,9 +108,9 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
}
- private IEnumerable<Still> GetPosters(Images images)
+ private IEnumerable<Still> GetPosters(StillImages images)
{
- return images.stills ?? new List<Still>();
+ return images.Stills ?? new List<Still>();
}
@@ -117,12 +119,13 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
return GetResponse(url, cancellationToken);
}
- public string Name => "TheMovieDb";
+ public string Name => TmdbUtils.ProviderName;
public bool Supports(BaseItem item)
{
return item is Controller.Entities.TV.Episode;
}
+
// After TheTvDb
public int Order => 1;
}
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProvider.cs
index 3d7745085..a17f5d17a 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProvider.cs
@@ -18,14 +18,14 @@ using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
-namespace MediaBrowser.Providers.TV.TheMovieDb
+namespace MediaBrowser.Providers.Tmdb.TV
{
- public class MovieDbEpisodeProvider :
- MovieDbProviderBase,
+ public class TmdbEpisodeProvider :
+ TmdbEpisodeProviderBase,
IRemoteMetadataProvider<Episode, EpisodeInfo>,
IHasOrder
{
- public MovieDbEpisodeProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
+ public TmdbEpisodeProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
: base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, loggerFactory)
{ }
@@ -93,7 +93,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
result.HasMetadata = true;
result.QueriedById = true;
- if (!string.IsNullOrEmpty(response.overview))
+ if (!string.IsNullOrEmpty(response.Overview))
{
// if overview is non-empty, we can assume that localized data was returned
result.ResultLanguage = info.MetadataLanguage;
@@ -107,30 +107,29 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
item.ParentIndexNumber = info.ParentIndexNumber;
item.IndexNumberEnd = info.IndexNumberEnd;
- if (response.external_ids.tvdb_id > 0)
+ if (response.External_Ids.Tvdb_Id > 0)
{
- item.SetProviderId(MetadataProviders.Tvdb, response.external_ids.tvdb_id.ToString(CultureInfo.InvariantCulture));
+ item.SetProviderId(MetadataProviders.Tvdb, response.External_Ids.Tvdb_Id.ToString(CultureInfo.InvariantCulture));
}
- item.PremiereDate = response.air_date;
+ item.PremiereDate = response.Air_Date;
item.ProductionYear = result.Item.PremiereDate.Value.Year;
- item.Name = response.name;
- item.Overview = response.overview;
+ item.Name = response.Name;
+ item.Overview = response.Overview;
- item.CommunityRating = (float)response.vote_average;
- //item.VoteCount = response.vote_count;
+ item.CommunityRating = (float)response.Vote_Average;
- if (response.videos != null && response.videos.results != null)
+ if (response.Videos?.Results != null)
{
- foreach (var video in response.videos.results)
+ foreach (var video in response.Videos.Results)
{
- if (video.type.Equals("trailer", System.StringComparison.OrdinalIgnoreCase)
- || video.type.Equals("clip", System.StringComparison.OrdinalIgnoreCase))
+ if (video.Type.Equals("trailer", System.StringComparison.OrdinalIgnoreCase)
+ || video.Type.Equals("clip", System.StringComparison.OrdinalIgnoreCase))
{
- if (video.site.Equals("youtube", System.StringComparison.OrdinalIgnoreCase))
+ if (video.Site.Equals("youtube", System.StringComparison.OrdinalIgnoreCase))
{
- var videoUrl = string.Format("http://www.youtube.com/watch?v={0}", video.key);
+ var videoUrl = string.Format("http://www.youtube.com/watch?v={0}", video.Key);
item.AddTrailerUrl(videoUrl);
}
}
@@ -139,54 +138,50 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
result.ResetPeople();
- var credits = response.credits;
+ var credits = response.Credits;
if (credits != null)
{
//Actors, Directors, Writers - all in People
//actors come from cast
- if (credits.cast != null)
+ if (credits.Cast != null)
{
- foreach (var actor in credits.cast.OrderBy(a => a.order))
+ foreach (var actor in credits.Cast.OrderBy(a => a.Order))
{
- result.AddPerson(new PersonInfo { Name = actor.name.Trim(), Role = actor.character, Type = PersonType.Actor, SortOrder = actor.order });
+ result.AddPerson(new PersonInfo { Name = actor.Name.Trim(), Role = actor.Character, Type = PersonType.Actor, SortOrder = actor.Order });
}
}
// guest stars
- if (credits.guest_stars != null)
+ if (credits.Guest_Stars != null)
{
- foreach (var guest in credits.guest_stars.OrderBy(a => a.order))
+ foreach (var guest in credits.Guest_Stars.OrderBy(a => a.Order))
{
- result.AddPerson(new PersonInfo { Name = guest.name.Trim(), Role = guest.character, Type = PersonType.GuestStar, SortOrder = guest.order });
+ result.AddPerson(new PersonInfo { Name = guest.Name.Trim(), Role = guest.Character, Type = PersonType.GuestStar, SortOrder = guest.Order });
}
}
//and the rest from crew
- if (credits.crew != null)
+ if (credits.Crew != null)
{
var keepTypes = new[]
{
PersonType.Director,
- //PersonType.Writer,
- //PersonType.Producer
+ PersonType.Writer,
+ PersonType.Producer
};
- foreach (var person in credits.crew)
+ foreach (var person in credits.Crew)
{
// Normalize this
- var type = person.department;
- if (string.Equals(type, "writing", StringComparison.OrdinalIgnoreCase))
- {
- type = PersonType.Writer;
- }
+ var type = TmdbUtils.MapCrewToPersonType(person);
- if (!keepTypes.Contains(type ?? string.Empty, StringComparer.OrdinalIgnoreCase) &&
- !keepTypes.Contains(person.job ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ if (!keepTypes.Contains(type, StringComparer.OrdinalIgnoreCase) &&
+ !keepTypes.Contains(person.Job ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
continue;
}
- result.AddPerson(new PersonInfo { Name = person.name.Trim(), Role = person.job, Type = type });
+ result.AddPerson(new PersonInfo { Name = person.Name.Trim(), Role = person.Job, Type = type });
}
}
}
@@ -211,6 +206,6 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
// After TheTvDb
public int Order => 1;
- public string Name => "TheMovieDb";
+ public string Name => TmdbUtils.ProviderName;
}
}
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs
index 6e438ebd8..2003261c9 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs
+++ b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading;
@@ -10,13 +9,15 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.TV;
+using MediaBrowser.Providers.Tmdb.Movies;
using Microsoft.Extensions.Logging;
-namespace MediaBrowser.Providers.TV.TheMovieDb
+namespace MediaBrowser.Providers.Tmdb.TV
{
- public abstract class MovieDbProviderBase
+ public abstract class TmdbEpisodeProviderBase
{
- private const string EpisodeUrlPattern = MovieDbProvider.BaseMovieDbUrl + @"3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos";
+ private const string EpisodeUrlPattern = TmdbUtils.BaseTmdbApiUrl + @"3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos";
private readonly IHttpClient _httpClient;
private readonly IServerConfigurationManager _configurationManager;
private readonly IJsonSerializer _jsonSerializer;
@@ -24,7 +25,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
private readonly ILocalizationManager _localization;
private readonly ILogger _logger;
- public MovieDbProviderBase(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
+ protected TmdbEpisodeProviderBase(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
{
_httpClient = httpClient;
_configurationManager = configurationManager;
@@ -36,7 +37,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
protected ILogger Logger => _logger;
- protected async Task<RootObject> GetEpisodeInfo(string seriesTmdbId, int season, int episodeNumber, string preferredMetadataLanguage,
+ protected async Task<EpisodeResult> GetEpisodeInfo(string seriesTmdbId, int season, int episodeNumber, string preferredMetadataLanguage,
CancellationToken cancellationToken)
{
await EnsureEpisodeInfo(seriesTmdbId, season, episodeNumber, preferredMetadataLanguage, cancellationToken)
@@ -44,7 +45,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
var dataFilePath = GetDataFilePath(seriesTmdbId, season, episodeNumber, preferredMetadataLanguage);
- return _jsonSerializer.DeserializeFromFile<RootObject>(dataFilePath);
+ return _jsonSerializer.DeserializeFromFile<EpisodeResult>(dataFilePath);
}
internal Task EnsureEpisodeInfo(string tmdbId, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken)
@@ -85,7 +86,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
throw new ArgumentNullException(nameof(preferredLanguage));
}
- var path = MovieDbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
+ var path = TmdbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
var filename = string.Format("season-{0}-episode-{1}-{2}.json",
seasonNumber.ToString(CultureInfo.InvariantCulture),
@@ -105,32 +106,32 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
- internal async Task<RootObject> FetchMainResult(string urlPattern, string id, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken)
+ internal async Task<EpisodeResult> FetchMainResult(string urlPattern, string id, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken)
{
- var url = string.Format(urlPattern, id, seasonNumber.ToString(CultureInfo.InvariantCulture), episodeNumber, MovieDbProvider.ApiKey);
+ var url = string.Format(urlPattern, id, seasonNumber.ToString(CultureInfo.InvariantCulture), episodeNumber, TmdbUtils.ApiKey);
if (!string.IsNullOrEmpty(language))
{
url += string.Format("&language={0}", language);
}
- var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language);
+ var includeImageLanguageParam = TmdbMovieProvider.GetImageLanguagesParam(language);
// Get images in english and with no language
url += "&include_image_language=" + includeImageLanguageParam;
cancellationToken.ThrowIfCancellationRequested();
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = MovieDbProvider.AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
using (var json = response.Content)
{
- return await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(json).ConfigureAwait(false);
+ return await _jsonSerializer.DeserializeFromStreamAsync<EpisodeResult>(json).ConfigureAwait(false);
}
}
}
@@ -143,103 +144,5 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
Url = url
});
}
-
- public class Still
- {
- public double aspect_ratio { get; set; }
- public string file_path { get; set; }
- public int height { get; set; }
- public string id { get; set; }
- public string iso_639_1 { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- public int width { get; set; }
- }
-
- public class Images
- {
- public List<Still> stills { get; set; }
- }
-
- public class ExternalIds
- {
- public string imdb_id { get; set; }
- public object freebase_id { get; set; }
- public string freebase_mid { get; set; }
- public int tvdb_id { get; set; }
- public int tvrage_id { get; set; }
- }
-
- public class Cast
- {
- public string character { get; set; }
- public string credit_id { get; set; }
- public int id { get; set; }
- public string name { get; set; }
- public string profile_path { get; set; }
- public int order { get; set; }
- }
-
- public class Crew
- {
- public int id { get; set; }
- public string credit_id { get; set; }
- public string name { get; set; }
- public string department { get; set; }
- public string job { get; set; }
- public string profile_path { get; set; }
- }
-
- public class GuestStar
- {
- public int id { get; set; }
- public string name { get; set; }
- public string credit_id { get; set; }
- public string character { get; set; }
- public int order { get; set; }
- public string profile_path { get; set; }
- }
-
- public class Credits
- {
- public List<Cast> cast { get; set; }
- public List<Crew> crew { get; set; }
- public List<GuestStar> guest_stars { get; set; }
- }
-
- public class Videos
- {
- public List<Video> results { get; set; }
- }
-
- public class Video
- {
- public string id { get; set; }
- public string iso_639_1 { get; set; }
- public string iso_3166_1 { get; set; }
- public string key { get; set; }
- public string name { get; set; }
- public string site { get; set; }
- public string size { get; set; }
- public string type { get; set; }
- }
-
- public class RootObject
- {
- public DateTime air_date { get; set; }
- public int episode_number { get; set; }
- public string name { get; set; }
- public string overview { get; set; }
- public int id { get; set; }
- public object production_code { get; set; }
- public int season_number { get; set; }
- public string still_path { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- public Images images { get; set; }
- public ExternalIds external_ids { get; set; }
- public Credits credits { get; set; }
- public Videos videos { get; set; }
- }
}
}
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs
index 6be1b101d..2f2ac58e8 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs
@@ -7,7 +7,6 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
@@ -16,13 +15,16 @@ using MediaBrowser.Model.Net;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.TV;
+using MediaBrowser.Providers.Tmdb.Movies;
using Microsoft.Extensions.Logging;
+using Season = MediaBrowser.Controller.Entities.TV.Season;
-namespace MediaBrowser.Providers.TV.TheMovieDb
+namespace MediaBrowser.Providers.Tmdb.TV
{
- public class MovieDbSeasonProvider : IRemoteMetadataProvider<Season, SeasonInfo>
+ public class TmdbSeasonProvider : IRemoteMetadataProvider<Season, SeasonInfo>
{
- private const string GetTvInfo3 = MovieDbProvider.BaseMovieDbUrl + @"3/tv/{0}/season/{1}?api_key={2}&append_to_response=images,keywords,external_ids,credits,videos";
+ private const string GetTvInfo3 = TmdbUtils.BaseTmdbApiUrl + @"3/tv/{0}/season/{1}?api_key={2}&append_to_response=images,keywords,external_ids,credits,videos";
private readonly IHttpClient _httpClient;
private readonly IServerConfigurationManager _configurationManager;
private readonly IJsonSerializer _jsonSerializer;
@@ -30,7 +32,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
private readonly ILocalizationManager _localization;
private readonly ILogger _logger;
- public MovieDbSeasonProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory)
+ public TmdbSeasonProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory)
{
_httpClient = httpClient;
_configurationManager = configurationManager;
@@ -65,31 +67,31 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
result.Item.IndexNumber = seasonNumber;
- result.Item.Overview = seasonInfo.overview;
+ result.Item.Overview = seasonInfo.Overview;
- if (seasonInfo.external_ids.tvdb_id > 0)
+ if (seasonInfo.External_Ids.Tvdb_Id > 0)
{
- result.Item.SetProviderId(MetadataProviders.Tvdb, seasonInfo.external_ids.tvdb_id.ToString(CultureInfo.InvariantCulture));
+ result.Item.SetProviderId(MetadataProviders.Tvdb, seasonInfo.External_Ids.Tvdb_Id.ToString(CultureInfo.InvariantCulture));
}
- var credits = seasonInfo.credits;
+ var credits = seasonInfo.Credits;
if (credits != null)
{
//Actors, Directors, Writers - all in People
//actors come from cast
- if (credits.cast != null)
+ if (credits.Cast != null)
{
//foreach (var actor in credits.cast.OrderBy(a => a.order)) result.Item.AddPerson(new PersonInfo { Name = actor.name.Trim(), Role = actor.character, Type = PersonType.Actor, SortOrder = actor.order });
}
//and the rest from crew
- if (credits.crew != null)
+ if (credits.Crew != null)
{
//foreach (var person in credits.crew) result.Item.AddPerson(new PersonInfo { Name = person.name.Trim(), Role = person.job, Type = person.department });
}
}
- result.Item.PremiereDate = seasonInfo.air_date;
+ result.Item.PremiereDate = seasonInfo.Air_Date;
result.Item.ProductionYear = result.Item.PremiereDate.Value.Year;
}
catch (HttpException ex)
@@ -108,7 +110,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
return result;
}
- public string Name => "TheMovieDb";
+ public string Name => TmdbUtils.ProviderName;
public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeasonInfo searchInfo, CancellationToken cancellationToken)
{
@@ -124,7 +126,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
});
}
- private async Task<RootObject> GetSeasonInfo(string seriesTmdbId, int season, string preferredMetadataLanguage,
+ private async Task<SeasonResult> GetSeasonInfo(string seriesTmdbId, int season, string preferredMetadataLanguage,
CancellationToken cancellationToken)
{
await EnsureSeasonInfo(seriesTmdbId, season, preferredMetadataLanguage, cancellationToken)
@@ -132,7 +134,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
var dataFilePath = GetDataFilePath(seriesTmdbId, season, preferredMetadataLanguage);
- return _jsonSerializer.DeserializeFromFile<RootObject>(dataFilePath);
+ return _jsonSerializer.DeserializeFromFile<SeasonResult>(dataFilePath);
}
internal Task EnsureSeasonInfo(string tmdbId, int seasonNumber, string language, CancellationToken cancellationToken)
@@ -173,7 +175,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
throw new ArgumentNullException(nameof(preferredLanguage));
}
- var path = MovieDbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
+ var path = TmdbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
var filename = string.Format("season-{0}-{1}.json",
seasonNumber.ToString(CultureInfo.InvariantCulture),
@@ -192,117 +194,34 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
- internal async Task<RootObject> FetchMainResult(string id, int seasonNumber, string language, CancellationToken cancellationToken)
+ internal async Task<SeasonResult> FetchMainResult(string id, int seasonNumber, string language, CancellationToken cancellationToken)
{
- var url = string.Format(GetTvInfo3, id, seasonNumber.ToString(CultureInfo.InvariantCulture), MovieDbProvider.ApiKey);
+ var url = string.Format(GetTvInfo3, id, seasonNumber.ToString(CultureInfo.InvariantCulture), TmdbUtils.ApiKey);
if (!string.IsNullOrEmpty(language))
{
- url += string.Format("&language={0}", MovieDbProvider.NormalizeLanguage(language));
+ url += string.Format("&language={0}", TmdbMovieProvider.NormalizeLanguage(language));
}
- var includeImageLanguageParam = MovieDbProvider.GetImageLanguagesParam(language);
+ var includeImageLanguageParam = TmdbMovieProvider.GetImageLanguagesParam(language);
// Get images in english and with no language
url += "&include_image_language=" + includeImageLanguageParam;
cancellationToken.ThrowIfCancellationRequested();
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = MovieDbProvider.AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
using (var json = response.Content)
{
- return await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(json).ConfigureAwait(false);
+ return await _jsonSerializer.DeserializeFromStreamAsync<SeasonResult>(json).ConfigureAwait(false);
}
}
}
-
- public class Episode
- {
- public string air_date { get; set; }
- public int episode_number { get; set; }
- public int id { get; set; }
- public string name { get; set; }
- public string overview { get; set; }
- public string still_path { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- }
-
- public class Cast
- {
- public string character { get; set; }
- public string credit_id { get; set; }
- public int id { get; set; }
- public string name { get; set; }
- public string profile_path { get; set; }
- public int order { get; set; }
- }
-
- public class Crew
- {
- public string credit_id { get; set; }
- public string department { get; set; }
- public int id { get; set; }
- public string name { get; set; }
- public string job { get; set; }
- public string profile_path { get; set; }
- }
-
- public class Credits
- {
- public List<Cast> cast { get; set; }
- public List<Crew> crew { get; set; }
- }
-
- public class Poster
- {
- public double aspect_ratio { get; set; }
- public string file_path { get; set; }
- public int height { get; set; }
- public string id { get; set; }
- public string iso_639_1 { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- public int width { get; set; }
- }
-
- public class Images
- {
- public List<Poster> posters { get; set; }
- }
-
- public class ExternalIds
- {
- public string freebase_id { get; set; }
- public string freebase_mid { get; set; }
- public int tvdb_id { get; set; }
- public object tvrage_id { get; set; }
- }
-
- public class Videos
- {
- public List<object> results { get; set; }
- }
-
- public class RootObject
- {
- public DateTime air_date { get; set; }
- public List<Episode> episodes { get; set; }
- public string name { get; set; }
- public string overview { get; set; }
- public int id { get; set; }
- public string poster_path { get; set; }
- public int season_number { get; set; }
- public Credits credits { get; set; }
- public Images images { get; set; }
- public ExternalIds external_ids { get; set; }
- public Videos videos { get; set; }
- }
}
}
diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesExternalId.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesExternalId.cs
new file mode 100644
index 000000000..524a3b05e
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesExternalId.cs
@@ -0,0 +1,24 @@
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Providers.Tmdb.TV
+{
+ public class TmdbSeriesExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string Name => TmdbUtils.ProviderName;
+
+ /// <inheritdoc />
+ public string Key => MetadataProviders.Tmdb.ToString();
+
+ /// <inheritdoc />
+ public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "tv/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item)
+ {
+ return item is Series;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesImageProvider.cs
index 26686356f..882ec7574 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesImageProvider.cs
@@ -13,16 +13,19 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.General;
+using MediaBrowser.Providers.Tmdb.Models.TV;
+using MediaBrowser.Providers.Tmdb.Movies;
-namespace MediaBrowser.Providers.TV.TheMovieDb
+namespace MediaBrowser.Providers.Tmdb.TV
{
- public class MovieDbSeriesImageProvider : IRemoteImageProvider, IHasOrder
+ public class TmdbSeriesImageProvider : IRemoteImageProvider, IHasOrder
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
private readonly IFileSystem _fileSystem;
- public MovieDbSeriesImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem)
+ public TmdbSeriesImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
@@ -31,7 +34,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
public string Name => ProviderName;
- public static string ProviderName => "TheMovieDb";
+ public static string ProviderName => TmdbUtils.ProviderName;
public bool Supports(BaseItem item)
{
@@ -58,7 +61,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
return list;
}
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
@@ -66,12 +69,12 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
list.AddRange(GetPosters(results).Select(i => new RemoteImageInfo
{
- Url = tmdbImageUrl + i.file_path,
- CommunityRating = i.vote_average,
- VoteCount = i.vote_count,
- Width = i.width,
- Height = i.height,
- Language = MovieDbProvider.AdjustImageLanguage(i.iso_639_1, language),
+ Url = tmdbImageUrl + i.File_Path,
+ CommunityRating = i.Vote_Average,
+ VoteCount = i.Vote_Count,
+ Width = i.Width,
+ Height = i.Height,
+ Language = TmdbMovieProvider.AdjustImageLanguage(i.Iso_639_1, language),
ProviderName = Name,
Type = ImageType.Primary,
RatingType = RatingType.Score
@@ -79,11 +82,11 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
list.AddRange(GetBackdrops(results).Select(i => new RemoteImageInfo
{
- Url = tmdbImageUrl + i.file_path,
- CommunityRating = i.vote_average,
- VoteCount = i.vote_count,
- Width = i.width,
- Height = i.height,
+ Url = tmdbImageUrl + i.File_Path,
+ CommunityRating = i.Vote_Average,
+ VoteCount = i.Vote_Count,
+ Width = i.Width,
+ Height = i.Height,
ProviderName = Name,
Type = ImageType.Backdrop,
RatingType = RatingType.Score
@@ -118,22 +121,21 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
/// Gets the posters.
/// </summary>
/// <param name="images">The images.</param>
- private IEnumerable<MovieDbSeriesProvider.Poster> GetPosters(MovieDbSeriesProvider.Images images)
+ private IEnumerable<Poster> GetPosters(Images images)
{
- return images.posters ?? new List<MovieDbSeriesProvider.Poster>();
+ return images.Posters ?? new List<Poster>();
}
/// <summary>
/// Gets the backdrops.
/// </summary>
/// <param name="images">The images.</param>
- private IEnumerable<MovieDbSeriesProvider.Backdrop> GetBackdrops(MovieDbSeriesProvider.Images images)
+ private IEnumerable<Backdrop> GetBackdrops(Images images)
{
- var eligibleBackdrops = images.backdrops == null ? new List<MovieDbSeriesProvider.Backdrop>() :
- images.backdrops;
+ var eligibleBackdrops = images.Backdrops ?? new List<Backdrop>();
- return eligibleBackdrops.OrderByDescending(i => i.vote_average)
- .ThenByDescending(i => i.vote_count);
+ return eligibleBackdrops.OrderByDescending(i => i.Vote_Average)
+ .ThenByDescending(i => i.Vote_Count);
}
/// <summary>
@@ -144,7 +146,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{MovieImages}.</returns>
- private async Task<MovieDbSeriesProvider.Images> FetchImages(BaseItem item, string language, IJsonSerializer jsonSerializer,
+ private async Task<Images> FetchImages(BaseItem item, string language, IJsonSerializer jsonSerializer,
CancellationToken cancellationToken)
{
var tmdbId = item.GetProviderId(MetadataProviders.Tmdb);
@@ -154,9 +156,9 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
return null;
}
- await MovieDbSeriesProvider.Current.EnsureSeriesInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
+ await TmdbSeriesProvider.Current.EnsureSeriesInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
- var path = MovieDbSeriesProvider.Current.GetDataFilePath(tmdbId, language);
+ var path = TmdbSeriesProvider.Current.GetDataFilePath(tmdbId, language);
if (!string.IsNullOrEmpty(path))
{
@@ -164,7 +166,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
if (fileInfo.Exists)
{
- return jsonSerializer.DeserializeFromFile<MovieDbSeriesProvider.RootObject>(path).images;
+ return jsonSerializer.DeserializeFromFile<SeriesResult>(path).Images;
}
}
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs
index b51fb6af8..304f34c25 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs
@@ -18,16 +18,19 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Models.Search;
+using MediaBrowser.Providers.Tmdb.Models.TV;
+using MediaBrowser.Providers.Tmdb.Movies;
using Microsoft.Extensions.Logging;
-namespace MediaBrowser.Providers.TV.TheMovieDb
+namespace MediaBrowser.Providers.Tmdb.TV
{
- public class MovieDbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder
+ public class TmdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder
{
- private const string GetTvInfo3 = MovieDbProvider.BaseMovieDbUrl + @"3/tv/{0}?api_key={1}&append_to_response=credits,images,keywords,external_ids,videos,content_ratings";
+ private const string GetTvInfo3 = TmdbUtils.BaseTmdbApiUrl + @"3/tv/{0}?api_key={1}&append_to_response=credits,images,keywords,external_ids,videos,content_ratings";
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- internal static MovieDbSeriesProvider Current { get; private set; }
+ internal static TmdbSeriesProvider Current { get; private set; }
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
@@ -37,7 +40,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
private readonly IHttpClient _httpClient;
private readonly ILibraryManager _libraryManager;
- public MovieDbSeriesProvider(IJsonSerializer jsonSerializer, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization, IHttpClient httpClient, ILibraryManager libraryManager)
+ public TmdbSeriesProvider(IJsonSerializer jsonSerializer, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization, IHttpClient httpClient, ILibraryManager libraryManager)
{
_jsonSerializer = jsonSerializer;
_fileSystem = fileSystem;
@@ -49,7 +52,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
Current = this;
}
- public string Name => "TheMovieDb";
+ public string Name => TmdbUtils.ProviderName;
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
{
@@ -63,24 +66,24 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
var dataFilePath = GetDataFilePath(tmdbId, searchInfo.MetadataLanguage);
- var obj = _jsonSerializer.DeserializeFromFile<RootObject>(dataFilePath);
+ var obj = _jsonSerializer.DeserializeFromFile<SeriesResult>(dataFilePath);
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
var remoteResult = new RemoteSearchResult
{
- Name = obj.name,
+ Name = obj.Name,
SearchProviderName = Name,
- ImageUrl = string.IsNullOrWhiteSpace(obj.poster_path) ? null : tmdbImageUrl + obj.poster_path
+ ImageUrl = string.IsNullOrWhiteSpace(obj.Poster_Path) ? null : tmdbImageUrl + obj.Poster_Path
};
- remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.id.ToString(_usCulture));
- remoteResult.SetProviderId(MetadataProviders.Imdb, obj.external_ids.imdb_id);
+ remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.Id.ToString(_usCulture));
+ remoteResult.SetProviderId(MetadataProviders.Imdb, obj.External_Ids.Imdb_Id);
- if (obj.external_ids.tvdb_id > 0)
+ if (obj.External_Ids.Tvdb_Id > 0)
{
- remoteResult.SetProviderId(MetadataProviders.Tvdb, obj.external_ids.tvdb_id.ToString(_usCulture));
+ remoteResult.SetProviderId(MetadataProviders.Tvdb, obj.External_Ids.Tvdb_Id.ToString(_usCulture));
}
return new[] { remoteResult };
@@ -110,7 +113,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
}
}
- return await new MovieDbSearch(_logger, _jsonSerializer, _libraryManager).GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false);
+ return await new TmdbSearch(_logger, _jsonSerializer, _libraryManager).GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false);
}
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
@@ -153,7 +156,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
if (string.IsNullOrEmpty(tmdbId))
{
result.QueriedById = false;
- var searchResults = await new MovieDbSearch(_logger, _jsonSerializer, _libraryManager).GetSearchResults(info, cancellationToken).ConfigureAwait(false);
+ var searchResults = await new TmdbSearch(_logger, _jsonSerializer, _libraryManager).GetSearchResults(info, cancellationToken).ConfigureAwait(false);
var searchResult = searchResults.FirstOrDefault();
@@ -177,14 +180,14 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
private async Task<MetadataResult<Series>> FetchMovieData(string tmdbId, string language, string preferredCountryCode, CancellationToken cancellationToken)
{
- RootObject seriesInfo = await FetchMainResult(tmdbId, language, cancellationToken).ConfigureAwait(false);
+ SeriesResult seriesInfo = await FetchMainResult(tmdbId, language, cancellationToken).ConfigureAwait(false);
if (seriesInfo == null)
{
return null;
}
- tmdbId = seriesInfo.id.ToString(_usCulture);
+ tmdbId = seriesInfo.Id.ToString(_usCulture);
string dataFilePath = GetDataFilePath(tmdbId, language);
Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
@@ -196,102 +199,102 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
result.Item = new Series();
result.ResultLanguage = seriesInfo.ResultLanguage;
- var settings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var settings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
ProcessMainInfo(result, seriesInfo, preferredCountryCode, settings);
return result;
}
- private void ProcessMainInfo(MetadataResult<Series> seriesResult, RootObject seriesInfo, string preferredCountryCode, TmdbSettingsResult settings)
+ private void ProcessMainInfo(MetadataResult<Series> seriesResult, SeriesResult seriesInfo, string preferredCountryCode, TmdbSettingsResult settings)
{
var series = seriesResult.Item;
- series.Name = seriesInfo.name;
- series.SetProviderId(MetadataProviders.Tmdb, seriesInfo.id.ToString(_usCulture));
+ series.Name = seriesInfo.Name;
+ series.SetProviderId(MetadataProviders.Tmdb, seriesInfo.Id.ToString(_usCulture));
//series.VoteCount = seriesInfo.vote_count;
- string voteAvg = seriesInfo.vote_average.ToString(CultureInfo.InvariantCulture);
+ string voteAvg = seriesInfo.Vote_Average.ToString(CultureInfo.InvariantCulture);
if (float.TryParse(voteAvg, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out float rating))
{
series.CommunityRating = rating;
}
- series.Overview = seriesInfo.overview;
+ series.Overview = seriesInfo.Overview;
- if (seriesInfo.networks != null)
+ if (seriesInfo.Networks != null)
{
- series.Studios = seriesInfo.networks.Select(i => i.name).ToArray();
+ series.Studios = seriesInfo.Networks.Select(i => i.Name).ToArray();
}
- if (seriesInfo.genres != null)
+ if (seriesInfo.Genres != null)
{
- series.Genres = seriesInfo.genres.Select(i => i.name).ToArray();
+ series.Genres = seriesInfo.Genres.Select(i => i.Name).ToArray();
}
//series.HomePageUrl = seriesInfo.homepage;
- series.RunTimeTicks = seriesInfo.episode_run_time.Select(i => TimeSpan.FromMinutes(i).Ticks).FirstOrDefault();
+ series.RunTimeTicks = seriesInfo.Episode_Run_Time.Select(i => TimeSpan.FromMinutes(i).Ticks).FirstOrDefault();
- if (string.Equals(seriesInfo.status, "Ended", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(seriesInfo.Status, "Ended", StringComparison.OrdinalIgnoreCase))
{
series.Status = SeriesStatus.Ended;
- series.EndDate = seriesInfo.last_air_date;
+ series.EndDate = seriesInfo.Last_Air_Date;
}
else
{
series.Status = SeriesStatus.Continuing;
}
- series.PremiereDate = seriesInfo.first_air_date;
+ series.PremiereDate = seriesInfo.First_Air_Date;
- var ids = seriesInfo.external_ids;
+ var ids = seriesInfo.External_Ids;
if (ids != null)
{
- if (!string.IsNullOrWhiteSpace(ids.imdb_id))
+ if (!string.IsNullOrWhiteSpace(ids.Imdb_Id))
{
- series.SetProviderId(MetadataProviders.Imdb, ids.imdb_id);
+ series.SetProviderId(MetadataProviders.Imdb, ids.Imdb_Id);
}
- if (ids.tvrage_id > 0)
+ if (ids.Tvrage_Id > 0)
{
- series.SetProviderId(MetadataProviders.TvRage, ids.tvrage_id.ToString(_usCulture));
+ series.SetProviderId(MetadataProviders.TvRage, ids.Tvrage_Id.ToString(_usCulture));
}
- if (ids.tvdb_id > 0)
+ if (ids.Tvdb_Id > 0)
{
- series.SetProviderId(MetadataProviders.Tvdb, ids.tvdb_id.ToString(_usCulture));
+ series.SetProviderId(MetadataProviders.Tvdb, ids.Tvdb_Id.ToString(_usCulture));
}
}
- var contentRatings = (seriesInfo.content_ratings ?? new ContentRatings()).results ?? new List<ContentRating>();
+ var contentRatings = (seriesInfo.Content_Ratings ?? new ContentRatings()).Results ?? new List<ContentRating>();
- var ourRelease = contentRatings.FirstOrDefault(c => string.Equals(c.iso_3166_1, preferredCountryCode, StringComparison.OrdinalIgnoreCase));
- var usRelease = contentRatings.FirstOrDefault(c => string.Equals(c.iso_3166_1, "US", StringComparison.OrdinalIgnoreCase));
+ var ourRelease = contentRatings.FirstOrDefault(c => string.Equals(c.Iso_3166_1, preferredCountryCode, StringComparison.OrdinalIgnoreCase));
+ var usRelease = contentRatings.FirstOrDefault(c => string.Equals(c.Iso_3166_1, "US", StringComparison.OrdinalIgnoreCase));
var minimumRelease = contentRatings.FirstOrDefault();
if (ourRelease != null)
{
- series.OfficialRating = ourRelease.rating;
+ series.OfficialRating = ourRelease.Rating;
}
else if (usRelease != null)
{
- series.OfficialRating = usRelease.rating;
+ series.OfficialRating = usRelease.Rating;
}
else if (minimumRelease != null)
{
- series.OfficialRating = minimumRelease.rating;
+ series.OfficialRating = minimumRelease.Rating;
}
- if (seriesInfo.videos != null && seriesInfo.videos.results != null)
+ if (seriesInfo.Videos != null && seriesInfo.Videos.Results != null)
{
- foreach (var video in seriesInfo.videos.results)
+ foreach (var video in seriesInfo.Videos.Results)
{
- if ((video.type.Equals("trailer", StringComparison.OrdinalIgnoreCase)
- || video.type.Equals("clip", StringComparison.OrdinalIgnoreCase))
- && video.site.Equals("youtube", StringComparison.OrdinalIgnoreCase))
+ if ((video.Type.Equals("trailer", StringComparison.OrdinalIgnoreCase)
+ || video.Type.Equals("clip", StringComparison.OrdinalIgnoreCase))
+ && video.Site.Equals("youtube", StringComparison.OrdinalIgnoreCase))
{
- series.AddTrailerUrl($"http://www.youtube.com/watch?v={video.key}");
+ series.AddTrailerUrl($"http://www.youtube.com/watch?v={video.Key}");
}
}
}
@@ -299,26 +302,26 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
seriesResult.ResetPeople();
var tmdbImageUrl = settings.images.GetImageUrl("original");
- if (seriesInfo.credits != null && seriesInfo.credits.cast != null)
+ if (seriesInfo.Credits != null && seriesInfo.Credits.Cast != null)
{
- foreach (var actor in seriesInfo.credits.cast.OrderBy(a => a.order))
+ foreach (var actor in seriesInfo.Credits.Cast.OrderBy(a => a.Order))
{
var personInfo = new PersonInfo
{
- Name = actor.name.Trim(),
- Role = actor.character,
+ Name = actor.Name.Trim(),
+ Role = actor.Character,
Type = PersonType.Actor,
- SortOrder = actor.order
+ SortOrder = actor.Order
};
- if (!string.IsNullOrWhiteSpace(actor.profile_path))
+ if (!string.IsNullOrWhiteSpace(actor.Profile_Path))
{
- personInfo.ImageUrl = tmdbImageUrl + actor.profile_path;
+ personInfo.ImageUrl = tmdbImageUrl + actor.Profile_Path;
}
- if (actor.id > 0)
+ if (actor.Id > 0)
{
- personInfo.SetProviderId(MetadataProviders.Tmdb, actor.id.ToString(CultureInfo.InvariantCulture));
+ personInfo.SetProviderId(MetadataProviders.Tmdb, actor.Id.ToString(CultureInfo.InvariantCulture));
}
seriesResult.AddPerson(personInfo);
@@ -342,7 +345,7 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
internal async Task DownloadSeriesInfo(string id, string preferredMetadataLanguage, CancellationToken cancellationToken)
{
- RootObject mainResult = await FetchMainResult(id, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
+ SeriesResult mainResult = await FetchMainResult(id, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
if (mainResult == null)
{
@@ -356,31 +359,31 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
- internal async Task<RootObject> FetchMainResult(string id, string language, CancellationToken cancellationToken)
+ internal async Task<SeriesResult> FetchMainResult(string id, string language, CancellationToken cancellationToken)
{
- var url = string.Format(GetTvInfo3, id, MovieDbProvider.ApiKey);
+ var url = string.Format(GetTvInfo3, id, TmdbUtils.ApiKey);
if (!string.IsNullOrEmpty(language))
{
- url += "&language=" + MovieDbProvider.NormalizeLanguage(language)
- + "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language); // Get images in english and with no language
+ url += "&language=" + TmdbMovieProvider.NormalizeLanguage(language)
+ + "&include_image_language=" + TmdbMovieProvider.GetImageLanguagesParam(language); // Get images in english and with no language
}
cancellationToken.ThrowIfCancellationRequested();
- RootObject mainResult;
+ SeriesResult mainResult;
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = MovieDbProvider.AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
using (var json = response.Content)
{
- mainResult = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(json).ConfigureAwait(false);
+ mainResult = await _jsonSerializer.DeserializeFromStreamAsync<SeriesResult>(json).ConfigureAwait(false);
if (!string.IsNullOrEmpty(language))
{
@@ -393,33 +396,33 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
// If the language preference isn't english, then have the overview fallback to english if it's blank
if (mainResult != null &&
- string.IsNullOrEmpty(mainResult.overview) &&
+ string.IsNullOrEmpty(mainResult.Overview) &&
!string.IsNullOrEmpty(language) &&
!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
{
_logger.LogInformation("MovieDbSeriesProvider couldn't find meta for language {Language}. Trying English...", language);
- url = string.Format(GetTvInfo3, id, MovieDbProvider.ApiKey) + "&language=en";
+ url = string.Format(GetTvInfo3, id, TmdbUtils.ApiKey) + "&language=en";
if (!string.IsNullOrEmpty(language))
{
// Get images in english and with no language
- url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language);
+ url += "&include_image_language=" + TmdbMovieProvider.GetImageLanguagesParam(language);
}
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = MovieDbProvider.AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
using (var json = response.Content)
{
- var englishResult = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(json).ConfigureAwait(false);
+ var englishResult = await _jsonSerializer.DeserializeFromStreamAsync<SeriesResult>(json).ConfigureAwait(false);
- mainResult.overview = englishResult.overview;
+ mainResult.Overview = englishResult.Overview;
mainResult.ResultLanguage = "en";
}
}
@@ -467,40 +470,40 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
private async Task<RemoteSearchResult> FindByExternalId(string id, string externalSource, CancellationToken cancellationToken)
{
- var url = string.Format(MovieDbProvider.BaseMovieDbUrl + @"3/find/{0}?api_key={1}&external_source={2}",
+ var url = string.Format(TmdbUtils.BaseTmdbApiUrl + @"3/find/{0}?api_key={1}&external_source={2}",
id,
- MovieDbProvider.ApiKey,
+ TmdbUtils.ApiKey,
externalSource);
- using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
- AcceptHeader = MovieDbProvider.AcceptHeader
+ AcceptHeader = TmdbUtils.AcceptHeader
}).ConfigureAwait(false))
{
using (var json = response.Content)
{
- var result = await _jsonSerializer.DeserializeFromStreamAsync<MovieDbSearch.ExternalIdLookupResult>(json).ConfigureAwait(false);
+ var result = await _jsonSerializer.DeserializeFromStreamAsync<ExternalIdLookupResult>(json).ConfigureAwait(false);
- if (result != null && result.tv_results != null)
+ if (result != null && result.Tv_Results != null)
{
- var tv = result.tv_results.FirstOrDefault();
+ var tv = result.Tv_Results.FirstOrDefault();
if (tv != null)
{
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
var remoteResult = new RemoteSearchResult
{
- Name = tv.name,
+ Name = tv.Name,
SearchProviderName = Name,
- ImageUrl = string.IsNullOrWhiteSpace(tv.poster_path) ? null : tmdbImageUrl + tv.poster_path
+ ImageUrl = string.IsNullOrWhiteSpace(tv.Poster_Path) ? null : tmdbImageUrl + tv.Poster_Path
};
- remoteResult.SetProviderId(MetadataProviders.Tmdb, tv.id.ToString(_usCulture));
+ remoteResult.SetProviderId(MetadataProviders.Tmdb, tv.Id.ToString(_usCulture));
return remoteResult;
}
@@ -511,163 +514,6 @@ namespace MediaBrowser.Providers.TV.TheMovieDb
return null;
}
- public class CreatedBy
- {
- public int id { get; set; }
- public string name { get; set; }
- public string profile_path { get; set; }
- }
-
- public class Genre
- {
- public int id { get; set; }
- public string name { get; set; }
- }
-
- public class Network
- {
- public int id { get; set; }
- public string name { get; set; }
- }
-
- public class Season
- {
- public string air_date { get; set; }
- public int episode_count { get; set; }
- public int id { get; set; }
- public string poster_path { get; set; }
- public int season_number { get; set; }
- }
-
- public class Cast
- {
- public string character { get; set; }
- public string credit_id { get; set; }
- public int id { get; set; }
- public string name { get; set; }
- public string profile_path { get; set; }
- public int order { get; set; }
- }
-
- public class Crew
- {
- public string credit_id { get; set; }
- public string department { get; set; }
- public int id { get; set; }
- public string name { get; set; }
- public string job { get; set; }
- public string profile_path { get; set; }
- }
-
- public class Credits
- {
- public List<Cast> cast { get; set; }
- public List<Crew> crew { get; set; }
- }
-
- public class Backdrop
- {
- public double aspect_ratio { get; set; }
- public string file_path { get; set; }
- public int height { get; set; }
- public string iso_639_1 { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- public int width { get; set; }
- }
-
- public class Poster
- {
- public double aspect_ratio { get; set; }
- public string file_path { get; set; }
- public int height { get; set; }
- public string iso_639_1 { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- public int width { get; set; }
- }
-
- public class Images
- {
- public List<Backdrop> backdrops { get; set; }
- public List<Poster> posters { get; set; }
- }
-
- public class Keywords
- {
- public List<object> results { get; set; }
- }
-
- public class ExternalIds
- {
- public string imdb_id { get; set; }
- public string freebase_id { get; set; }
- public string freebase_mid { get; set; }
- public int tvdb_id { get; set; }
- public int tvrage_id { get; set; }
- }
-
- public class Videos
- {
- public List<Video> results { get; set; }
- }
-
- public class Video
- {
- public string id { get; set; }
- public string iso_639_1 { get; set; }
- public string iso_3166_1 { get; set; }
- public string key { get; set; }
- public string name { get; set; }
- public string site { get; set; }
- public string size { get; set; }
- public string type { get; set; }
- }
-
- public class ContentRating
- {
- public string iso_3166_1 { get; set; }
- public string rating { get; set; }
- }
-
- public class ContentRatings
- {
- public List<ContentRating> results { get; set; }
- }
-
- public class RootObject
- {
- public string backdrop_path { get; set; }
- public List<CreatedBy> created_by { get; set; }
- public List<int> episode_run_time { get; set; }
- public DateTime first_air_date { get; set; }
- public List<Genre> genres { get; set; }
- public string homepage { get; set; }
- public int id { get; set; }
- public bool in_production { get; set; }
- public List<string> languages { get; set; }
- public DateTime last_air_date { get; set; }
- public string name { get; set; }
- public List<Network> networks { get; set; }
- public int number_of_episodes { get; set; }
- public int number_of_seasons { get; set; }
- public string original_name { get; set; }
- public List<string> origin_country { get; set; }
- public string overview { get; set; }
- public string popularity { get; set; }
- public string poster_path { get; set; }
- public List<Season> seasons { get; set; }
- public string status { get; set; }
- public double vote_average { get; set; }
- public int vote_count { get; set; }
- public Credits credits { get; set; }
- public Images images { get; set; }
- public Keywords keywords { get; set; }
- public ExternalIds external_ids { get; set; }
- public Videos videos { get; set; }
- public ContentRatings content_ratings { get; set; }
- public string ResultLanguage { get; set; }
- }
// After TheTVDB
public int Order => 1;
diff --git a/MediaBrowser.Providers/Tmdb/TmdbUtils.cs b/MediaBrowser.Providers/Tmdb/TmdbUtils.cs
new file mode 100644
index 000000000..035b99c1a
--- /dev/null
+++ b/MediaBrowser.Providers/Tmdb/TmdbUtils.cs
@@ -0,0 +1,31 @@
+using System;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Providers.Tmdb.Models.General;
+
+namespace MediaBrowser.Providers.Tmdb
+{
+ public static class TmdbUtils
+ {
+ public const string BaseTmdbUrl = "https://www.themoviedb.org/";
+ public const string BaseTmdbApiUrl = "https://api.themoviedb.org/";
+ public const string ProviderName = "TheMovieDb";
+ public const string ApiKey = "4219e299c89411838049ab0dab19ebd5";
+ public const string AcceptHeader = "application/json,image/*";
+
+ public static string MapCrewToPersonType(Crew crew)
+ {
+ if (crew.Department.Equals("production", StringComparison.InvariantCultureIgnoreCase)
+ && crew.Job.IndexOf("producer", StringComparison.InvariantCultureIgnoreCase) != -1)
+ {
+ return PersonType.Producer;
+ }
+
+ if (crew.Department.Equals("writing", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return PersonType.Writer;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs b/MediaBrowser.Providers/Tmdb/Trailers/TmdbTrailerProvider.cs
index 2a3cdf097..b0dec0245 100644
--- a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs
+++ b/MediaBrowser.Providers/Tmdb/Trailers/TmdbTrailerProvider.cs
@@ -5,29 +5,31 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Movies;
+using MediaBrowser.Providers.Tmdb.Movies;
-namespace MediaBrowser.Providers.Movies
+namespace MediaBrowser.Providers.Tmdb.Trailers
{
- public class MovieDbTrailerProvider : IHasOrder, IRemoteMetadataProvider<Trailer, TrailerInfo>
+ public class TmdbTrailerProvider : IHasOrder, IRemoteMetadataProvider<Trailer, TrailerInfo>
{
private readonly IHttpClient _httpClient;
- public MovieDbTrailerProvider(IHttpClient httpClient)
+ public TmdbTrailerProvider(IHttpClient httpClient)
{
_httpClient = httpClient;
}
public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken)
{
- return MovieDbProvider.Current.GetMovieSearchResults(searchInfo, cancellationToken);
+ return TmdbMovieProvider.Current.GetMovieSearchResults(searchInfo, cancellationToken);
}
public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
{
- return MovieDbProvider.Current.GetItemMetadata<Trailer>(info, cancellationToken);
+ return TmdbMovieProvider.Current.GetItemMetadata<Trailer>(info, cancellationToken);
}
- public string Name => MovieDbProvider.Current.Name;
+ public string Name => TmdbMovieProvider.Current.Name;
public int Order => 0;
diff --git a/MediaBrowser.WebDashboard/jellyfin-web b/MediaBrowser.WebDashboard/jellyfin-web
-Subproject 1d0fd79eb1e4d0bf6a9f62f769a951970383bcf
+Subproject 867a5e664cb968602b50dee4874fcb961eed480
diff --git a/MediaBrowser.XbmcMetadata/EntryPoint.cs b/MediaBrowser.XbmcMetadata/EntryPoint.cs
index 992991a7e..fe4d50efa 100644
--- a/MediaBrowser.XbmcMetadata/EntryPoint.cs
+++ b/MediaBrowser.XbmcMetadata/EntryPoint.cs
@@ -16,27 +16,30 @@ namespace MediaBrowser.XbmcMetadata
{
private readonly IUserDataManager _userDataManager;
private readonly ILogger _logger;
- private readonly ILibraryManager _libraryManager;
private readonly IProviderManager _providerManager;
private readonly IConfigurationManager _config;
- public EntryPoint(IUserDataManager userDataManager, ILibraryManager libraryManager, ILogger logger, IProviderManager providerManager, IConfigurationManager config)
+ public EntryPoint(
+ IUserDataManager userDataManager,
+ ILogger logger,
+ IProviderManager providerManager,
+ IConfigurationManager config)
{
_userDataManager = userDataManager;
- _libraryManager = libraryManager;
_logger = logger;
_providerManager = providerManager;
_config = config;
}
+ /// <inheritdoc />
public Task RunAsync()
{
- _userDataManager.UserDataSaved += _userDataManager_UserDataSaved;
+ _userDataManager.UserDataSaved += OnUserDataSaved;
return Task.CompletedTask;
}
- void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e)
+ private void OnUserDataSaved(object sender, UserDataSaveEventArgs e)
{
if (e.SaveReason == UserDataSaveReason.PlaybackFinished || e.SaveReason == UserDataSaveReason.TogglePlayed || e.SaveReason == UserDataSaveReason.UpdateUserRating)
{
@@ -47,9 +50,10 @@ namespace MediaBrowser.XbmcMetadata
}
}
+ /// <inheritdoc />
public void Dispose()
{
- _userDataManager.UserDataSaved -= _userDataManager_UserDataSaved;
+ _userDataManager.UserDataSaved -= OnUserDataSaved;
}
private void SaveMetadataForItem(BaseItem item, ItemUpdateType updateReason)
diff --git a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs
index 430b93199..a1905bf26 100644
--- a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs
@@ -15,16 +15,30 @@ namespace MediaBrowser.XbmcMetadata.Savers
{
public class AlbumNfoSaver : BaseNfoSaver
{
+ public AlbumNfoSaver(
+ IFileSystem fileSystem,
+ IServerConfigurationManager configurationManager,
+ ILibraryManager libraryManager,
+ IUserManager userManager,
+ IUserDataManager userDataManager,
+ ILogger logger)
+ : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
+ {
+ }
+
+ /// <inheritdoc />
protected override string GetLocalSavePath(BaseItem item)
{
return Path.Combine(item.Path, "album.nfo");
}
+ /// <inheritdoc />
protected override string GetRootElementName(BaseItem item)
{
return "album";
}
+ /// <inheritdoc />
public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType)
{
if (!item.SupportsLocalMetadata)
@@ -35,6 +49,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
return item is MusicAlbum && updateType >= MinimumUpdateType;
}
+ /// <inheritdoc />
protected override void WriteCustomElements(BaseItem item, XmlWriter writer)
{
var album = (MusicAlbum)item;
@@ -52,8 +67,6 @@ namespace MediaBrowser.XbmcMetadata.Savers
AddTracks(album.Tracks, writer);
}
- private readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
private void AddTracks(IEnumerable<BaseItem> tracks, XmlWriter writer)
{
foreach (var track in tracks.OrderBy(i => i.ParentIndexNumber ?? 0).ThenBy(i => i.IndexNumber ?? 0))
@@ -62,7 +75,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
if (track.IndexNumber.HasValue)
{
- writer.WriteElementString("position", track.IndexNumber.Value.ToString(UsCulture));
+ writer.WriteElementString("position", track.IndexNumber.Value.ToString(CultureInfo.InvariantCulture));
}
if (!string.IsNullOrEmpty(track.Name))
@@ -81,21 +94,19 @@ namespace MediaBrowser.XbmcMetadata.Savers
}
}
+ /// <inheritdoc />
protected override List<string> GetTagsUsed(BaseItem item)
{
var list = base.GetTagsUsed(item);
- list.AddRange(new string[]
- {
- "track",
- "artist",
- "albumartist"
- });
- return list;
- }
+ list.AddRange(
+ new string[]
+ {
+ "track",
+ "artist",
+ "albumartist"
+ });
- public AlbumNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger)
- : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
- {
+ return list;
}
}
}
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index 3ed86d65c..39839e273 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -1,4 +1,4 @@
-
+
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.3
@@ -41,8 +41,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Naming", "Emby.Naming\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.XmlTv", "Emby.XmlTv\Emby.XmlTv\Emby.XmlTv.csproj", "{6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IsoMounter", "Emby.IsoMounting\IsoMounter\IsoMounter.csproj", "{9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{960295EE-4AF4-4440-A525-B4C295B01A61}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Server", "Jellyfin.Server\Jellyfin.Server.csproj", "{07E39F42-A2C6-4B32-AF8C-725F957A73FF}"
@@ -141,10 +139,6 @@ Global
{6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Any CPU.Build.0 = Release|Any CPU
- {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Any CPU.Build.0 = Release|Any CPU
{960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Any CPU.Build.0 = Debug|Any CPU
{960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 500e6fe55..5f3fd8e50 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,4 +1,4 @@
using System.Reflection;
-[assembly: AssemblyVersion("10.3.7")]
-[assembly: AssemblyFileVersion("10.3.7")]
+[assembly: AssemblyVersion("10.4.0")]
+[assembly: AssemblyFileVersion("10.4.0")]
diff --git a/build.yaml b/build.yaml
index 2d4bc29f4..3cfccd337 100644
--- a/build.yaml
+++ b/build.yaml
@@ -1,7 +1,7 @@
---
# We just wrap `build` so this is really it
name: "jellyfin"
-version: "10.3.7"
+version: "10.4.0"
packages:
- debian-package-x64
- debian-package-armhf
diff --git a/bump_version b/bump_version
index 398caee15..590020864 100755
--- a/bump_version
+++ b/bump_version
@@ -24,7 +24,11 @@ fi
shared_version_file="./SharedVersion.cs"
build_file="./build.yaml"
-web_branch="$( git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/' )"
+if [[ -z $2 ]]; then
+ web_branch="$( git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/' )"
+else
+ web_branch="$2"
+fi
# Initialize submodules
git submodule update --init --recursive
@@ -80,7 +84,7 @@ fi
# Set the Dockerfile web version to the specified new_version
old_version="$(
grep "JELLYFIN_WEB_VERSION=" Dockerfile \
- | sed -E 's/ARG JELLYFIN_WEB_VERSION=([0-9\.]+[-a-z0-9]*)/\1/'
+ | sed -E 's/ARG JELLYFIN_WEB_VERSION=v([0-9\.]+[-a-z0-9]*)/\1/'
)"
echo $old_version
diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog
index aa15827a7..54d4cffba 100644
--- a/deployment/debian-package-x64/pkg-src/changelog
+++ b/deployment/debian-package-x64/pkg-src/changelog
@@ -1,3 +1,9 @@
+jellyfin (10.4.0-1) unstable; urgency=medium
+
+ * New upstream version 10.4.0; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.4.0
+
+ -- Jellyfin Packaging Team <packaging@jellyfin.org> Sat, 31 Aug 2019 21:38:56 -0400
+
jellyfin (10.3.7-1) unstable; urgency=medium
* New upstream version 10.3.7; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.7
diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec
index 91b74ffe1..d591a54e1 100644
--- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec
+++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec
@@ -7,7 +7,7 @@
%endif
Name: jellyfin
-Version: 10.3.7
+Version: 10.4.0
Release: 1%{?dist}
Summary: The Free Software Media Browser
License: GPLv2
@@ -68,7 +68,7 @@ EOF
%{__install} -D -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/%{name}
%{__install} -D -m 0600 %{SOURCE3} %{buildroot}%{_sysconfdir}/sudoers.d/%{name}-sudoers
%{__install} -D -m 0755 %{SOURCE4} %{buildroot}%{_libexecdir}/%{name}/restart.sh
-%{__install} -D -m 0644 %{SOURCE6} %{buildroot}%{_prefix}/lib/firewalld/service/%{name}.xml
+%{__install} -D -m 0644 %{SOURCE6} %{buildroot}%{_prefix}/lib/firewalld/services/%{name}.xml
%files
%{_libdir}/%{name}/jellyfin-web/*
@@ -83,7 +83,7 @@ EOF
%{_libdir}/%{name}/sosdocsunix.txt
%{_unitdir}/%{name}.service
%{_libexecdir}/%{name}/restart.sh
-%{_prefix}/lib/firewalld/service/%{name}.xml
+%{_prefix}/lib/firewalld/services/%{name}.xml
%attr(755,jellyfin,jellyfin) %dir %{_sysconfdir}/%{name}
%config %{_sysconfdir}/sysconfig/%{name}
%config(noreplace) %attr(600,root,root) %{_sysconfdir}/sudoers.d/%{name}-sudoers
@@ -140,6 +140,8 @@ fi
%systemd_postun_with_restart jellyfin.service
%changelog
+* Sat Aug 31 2019 Jellyfin Packaging Team <packaging@jellyfin.org>
+- New upstream version 10.4.0; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.4.0
* Wed Jul 24 2019 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.3.7; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.7
* Sat Jul 06 2019 Jellyfin Packaging Team <packaging@jellyfin.org>