diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..0c0ab960a0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +CONTRIBUTORS.md merge=union diff --git a/Build-JellyFin.ps1 b/Build-JellyFin.ps1 deleted file mode 100644 index d89eb485f0..0000000000 --- a/Build-JellyFin.ps1 +++ /dev/null @@ -1,68 +0,0 @@ -[CmdletBinding()] -param( - [switch]$InstallFFMPEG, - [switch]$GenerateZip, - [string]$InstallLocation = "$Env:AppData/JellyFin-Server/", - [ValidateSet('Debug','Release')][string]$BuildType = 'Release', - [ValidateSet('Quiet','Minimal', 'Normal')][string]$DotNetVerbosity = 'Minimal', - [ValidateSet('win','win7', 'win8','win81','win10')][string]$WindowsVersion = 'win', - [ValidateSet('x64','x86', 'arm', 'arm64')][string]$Architecture = 'x64' -) -function Build-JellyFin { - if($Architecture -eq 'arm64'){ - if($WindowsVersion -ne 'win10'){ - Write-Error "arm64 only supported with Windows10 Version" - exit - } - } - if($Architecture -eq 'arm'){ - if($WindowsVersion -notin @('win10','win81','win8')){ - Write-Error "arm only supported with Windows 8 or higher" - exit - } - } - dotnet publish -c $BuildType -r "$windowsversion-$Architecture" MediaBrowser.sln -o $InstallLocation -v $DotNetVerbosity -} - -function Install-FFMPEG { - param( - [string]$InstallLocation, - [string]$Architecture - ) - Write-Verbose "Checking Architecture" - if($Architecture -notin @('x86','x64')){ - Write-Warning "No builds available for your selected architecture of $Architecture" - Write-Warning "FFMPEG will not be installed" - }elseif($Architecture -eq 'x64'){ - Write-Verbose "Downloading 64 bit FFMPEG" - Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-4.1-win64-static.zip -UseBasicParsing -OutFile "$env:TEMP/fmmpeg.zip" | Write-Verbose - }else{ - Write-Verbose "Downloading 32 bit FFMPEG" - Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-4.1-win32-static.zip -UseBasicParsing -OutFile "$env:TEMP/fmmpeg.zip" | Write-Verbose - } - - Expand-Archive "$env:TEMP/fmmpeg.zip" -DestinationPath "$env:TEMP/ffmpeg/" | Write-Verbose - if($Architecture -eq 'x64'){ - Write-Verbose "Copying Binaries to Jellyfin location" - Get-ChildItem "$env:temp/ffmpeg/ffmpeg-4.1-win64-static/bin" | ForEach-Object { - Copy-Item $_.FullName -Destination $installLocation | Write-Verbose - } - }else{ - Write-Verbose "Copying Binaries to Jellyfin location" - Get-ChildItem "$env:temp/ffmpeg/ffmpeg-4.1-win32-static/bin" | ForEach-Object { - Copy-Item $_.FullName -Destination $installLocation | Write-Verbose - } - } - Remove-Item "$env:TEMP/ffmpeg/" -Recurse -Force -ErrorAction Continue | Write-Verbose - Remove-Item "$env:TEMP/fmmpeg.zip" -Force -ErrorAction Continue | Write-Verbose -} -Write-Verbose "Starting Build Process: Selected Environment is $WindowsVersion-$Architecture" -Build-JellyFin -if($InstallFFMPEG.IsPresent -or ($InstallFFMPEG -eq $true)){ - Write-Verbose "Starting FFMPEG Install" - Install-FFMPEG $InstallLocation $Architecture -} -if($GenerateZip.IsPresent -or ($GenerateZip -eq $true)){ - Compress-Archive -Path $InstallLocation -DestinationPath "$InstallLocation/jellyfin.zip" -Force -} -Write-Verbose "Finished" \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index b902f2476a..0000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,4 +0,0 @@ -1. Don't sneakily relicense free software. -2. Don't continually nag users to give you money. -3. Don't hide binary blobs in otherwise free software. -4. Don't needlessly obfuscate the build process or any other part of free software. diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index fd9bab8ccd..467ba15229 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -4,6 +4,9 @@ - [nvllsvm](https://github.com/nvllsvm) - [JustAMan](https://github.com/JustAMan) - [dcrdev](https://github.com/dcrdev) + - [EraYaN](https://github.com/EraYaN) + - [flemse](https://github.com/flemse) + - [bfayers](https://github.com/bfayers) # Emby Contributors diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 91ec54b55d..bf9c48ac70 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -467,7 +467,7 @@ namespace Emby.Dlna.ContentDirectory IsMissing = false, ExcludeItemTypes = new[] { typeof(Game).Name, typeof(Book).Name }, IsFolder = isFolder, - MediaTypes = mediaTypes.ToArray(mediaTypes.Count), + MediaTypes = mediaTypes.ToArray(), DtoOptions = GetDtoOptions() }); } @@ -676,7 +676,7 @@ namespace Emby.Dlna.ContentDirectory return new QueryResult { - Items = list.ToArray(list.Count), + Items = list.ToArray(), TotalRecordCount = list.Count }; } @@ -754,7 +754,7 @@ namespace Emby.Dlna.ContentDirectory return new QueryResult { - Items = list.ToArray(list.Count), + Items = list.ToArray(), TotalRecordCount = list.Count }; } @@ -859,7 +859,7 @@ namespace Emby.Dlna.ContentDirectory return new QueryResult { - Items = list.ToArray(list.Count), + Items = list.ToArray(), TotalRecordCount = list.Count }; } @@ -1026,7 +1026,7 @@ namespace Emby.Dlna.ContentDirectory var result = new QueryResult { TotalRecordCount = genresResult.TotalRecordCount, - Items = genresResult.Items.Select(i => i.Item1).ToArray(genresResult.Items.Length) + Items = genresResult.Items.Select(i => i.Item1).ToArray() }; return ToResult(result); @@ -1044,7 +1044,7 @@ namespace Emby.Dlna.ContentDirectory var result = new QueryResult { TotalRecordCount = genresResult.TotalRecordCount, - Items = genresResult.Items.Select(i => i.Item1).ToArray(genresResult.Items.Length) + Items = genresResult.Items.Select(i => i.Item1).ToArray() }; return ToResult(result); @@ -1062,7 +1062,7 @@ namespace Emby.Dlna.ContentDirectory var result = new QueryResult { TotalRecordCount = artists.TotalRecordCount, - Items = artists.Items.Select(i => i.Item1).ToArray(artists.Items.Length) + Items = artists.Items.Select(i => i.Item1).ToArray() }; return ToResult(result); @@ -1080,7 +1080,7 @@ namespace Emby.Dlna.ContentDirectory var result = new QueryResult { TotalRecordCount = artists.TotalRecordCount, - Items = artists.Items.Select(i => i.Item1).ToArray(artists.Items.Length) + Items = artists.Items.Select(i => i.Item1).ToArray() }; return ToResult(result); @@ -1099,7 +1099,7 @@ namespace Emby.Dlna.ContentDirectory var result = new QueryResult { TotalRecordCount = artists.TotalRecordCount, - Items = artists.Items.Select(i => i.Item1).ToArray(artists.Items.Length) + Items = artists.Items.Select(i => i.Item1).ToArray() }; return ToResult(result); @@ -1247,7 +1247,7 @@ namespace Emby.Dlna.ContentDirectory { var serverItems = result .Select(i => new ServerItem(i)) - .ToArray(result.Length); + .ToArray(); return new QueryResult { diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 42727bb927..8d59ea3ffd 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -512,7 +512,7 @@ namespace Emby.Dlna.Didl streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions { ItemId = audio.Id, - MediaSources = sources.ToArray(sources.Count), + MediaSources = sources.ToArray(), Profile = _profile, DeviceId = deviceId }); diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 9a861b8c7f..47e3196e12 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -941,7 +941,7 @@ namespace Emby.Dlna.PlayTo if (room != null && !string.IsNullOrWhiteSpace(room.Value)) friendlyNames.Add(room.Value); - deviceProperties.Name = string.Join(" ", friendlyNames.ToArray(friendlyNames.Count)); + deviceProperties.Name = string.Join(" ", friendlyNames.ToArray()); var model = document.Descendants(uPnpNamespaces.ud.GetName("modelName")).FirstOrDefault(); if (model != null) diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index ce22a0af2d..2d0d7c99c1 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -571,7 +571,7 @@ namespace Emby.Dlna.PlayTo StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions { ItemId = item.Id, - MediaSources = mediaSources.ToArray(mediaSources.Count), + MediaSources = mediaSources.ToArray(), Profile = profile, DeviceId = deviceId, MaxBitrate = profile.MaxStreamingBitrate, diff --git a/Emby.Dlna/Profiles/DefaultProfile.cs b/Emby.Dlna/Profiles/DefaultProfile.cs index b60a664ba6..1295c2f9a8 100644 --- a/Emby.Dlna/Profiles/DefaultProfile.cs +++ b/Emby.Dlna/Profiles/DefaultProfile.cs @@ -173,7 +173,7 @@ namespace Emby.Dlna.Profiles Value = value }); - XmlRootAttributes = list.ToArray(list.Count); + XmlRootAttributes = list.ToArray(); } } } diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs index b2b742b102..4509414894 100644 --- a/Emby.Dlna/Service/BaseControlHandler.cs +++ b/Emby.Dlna/Service/BaseControlHandler.cs @@ -242,7 +242,7 @@ namespace Emby.Dlna.Service } var originalHeaders = request.Headers; - var headers = string.Join(", ", originalHeaders.Select(i => string.Format("{0}={1}", i.Key, i.Value)).ToArray(originalHeaders.Count)); + var headers = string.Join(", ", originalHeaders.Select(i => string.Format("{0}={1}", i.Key, i.Value)).ToArray()); Logger.Debug("Control request. Headers: {0}", headers); } diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index eeb5b8f9f6..495ba99a65 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -564,7 +564,7 @@ namespace Emby.Drawing var cacheKeys = imageEnhancers.Select(i => i.GetConfigurationCacheKey(item, imageType)).ToList(); cacheKeys.Add(originalImagePath + dateModified.Ticks); - return string.Join("|", cacheKeys.ToArray(cacheKeys.Count)).GetMD5().ToString("N"); + return string.Join("|", cacheKeys.ToArray()).GetMD5().ToString("N"); } private async Task> GetSupportedImage(string originalImagePath, DateTime dateModified) @@ -919,4 +919,4 @@ namespace Emby.Drawing } } } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 079d0af0ad..e4b65b58dd 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -466,7 +466,7 @@ namespace Emby.Server.Implementations.Activity { Name = string.Format(_localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name), Type = NotificationType.TaskFailed.ToString(), - Overview = string.Join(Environment.NewLine, vals.ToArray(vals.Count)), + Overview = string.Join(Environment.NewLine, vals.ToArray()), ShortOverview = runningTime, Severity = LogSeverity.Error }); diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs index ce9f460ffb..7f76d724be 100644 --- a/Emby.Server.Implementations/Activity/ActivityRepository.cs +++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs @@ -189,13 +189,13 @@ namespace Emby.Server.Implementations.Activity var whereTextWithoutPaging = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); + " where " + string.Join(" AND ", whereClauses.ToArray()); if (startIndex.HasValue && startIndex.Value > 0) { var pagingWhereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); + " where " + string.Join(" AND ", whereClauses.ToArray()); whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLog {0} ORDER BY DateCreated DESC LIMIT {1})", pagingWhereText, @@ -204,7 +204,7 @@ namespace Emby.Server.Implementations.Activity var whereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); + " where " + string.Join(" AND ", whereClauses.ToArray()); commandText += whereText; @@ -249,7 +249,7 @@ namespace Emby.Server.Implementations.Activity result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); } - result.Items = list.ToArray(list.Count); + result.Items = list.ToArray(); return result; }, ReadTransactionMode); diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index c6cfe72141..ad15b015de 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -728,7 +728,7 @@ namespace Emby.Server.Implementations Logger.Info("ServerId: {0}", SystemId); - var entryPoints = GetExports().ToList(); + var entryPoints = GetExports(); RunEntryPoints(entryPoints, true); Logger.Info("Core startup complete"); @@ -1962,6 +1962,7 @@ namespace Emby.Server.Implementations public async Task GetSystemInfo(CancellationToken cancellationToken) { var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false); + var wanAddress = await GetWanApiUrl(cancellationToken).ConfigureAwait(false); return new SystemInfo { @@ -1984,8 +1985,7 @@ namespace Emby.Server.Implementations CanSelfRestart = CanSelfRestart, CanSelfUpdate = CanSelfUpdate, CanLaunchWebBrowser = CanLaunchWebBrowser, - // TODO - remove WanAddress - WanAddress = "0.0.0.0", + WanAddress = wanAddress, HasUpdateAvailable = HasUpdateAvailable, SupportsAutoRunAtStartup = SupportsAutoRunAtStartup, TranscodingTempPath = ApplicationPaths.TranscodingTempPath, @@ -2012,14 +2012,13 @@ namespace Emby.Server.Implementations public async Task GetPublicSystemInfo(CancellationToken cancellationToken) { var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false); - + var wanAddress = await GetWanApiUrl(cancellationToken).ConfigureAwait(false); return new PublicSystemInfo { Version = ApplicationVersion.ToString(), Id = SystemId, OperatingSystem = EnvironmentInfo.OperatingSystem.ToString(), - // TODO - remove WanAddress - WanAddress = "0.0.0.0", + WanAddress = wanAddress, ServerName = FriendlyName, LocalAddress = localAddress }; @@ -2060,6 +2059,32 @@ namespace Emby.Server.Implementations return null; } + public async Task GetWanApiUrl(CancellationToken cancellationToken) + { + var url = "http://ipv4.icanhazip.com"; + try + { + using (var response = await HttpClient.Get(new HttpRequestOptions + { + Url = url, + LogErrorResponseBody = false, + LogErrors = false, + LogRequest = false, + TimeoutMs = 10000, + BufferContent = false, + CancellationToken = cancellationToken + })) + { + return GetLocalApiUrl(response.ReadToEnd().Trim()); + } + } + catch(Exception ex) + { + Logger.ErrorException("Error getting WAN Ip address information", ex); + } + return null; + } + public string GetLocalApiUrl(IpAddressInfo ipAddress) { if (ipAddress.AddressFamily == IpAddressFamily.InterNetworkV6) diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index e61c5e2832..dfc9c34744 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -239,7 +239,7 @@ namespace Emby.Server.Implementations.Channels all = all.Take(query.Limit.Value).ToList(); } - var returnItems = all.ToArray(all.Count); + var returnItems = all.ToArray(); if (query.RefreshLatestChannelItems) { @@ -1011,7 +1011,7 @@ namespace Emby.Server.Implementations.Channels { item.Name = info.Name; item.Genres = info.Genres.ToArray(); - item.Studios = info.Studios.ToArray(info.Studios.Count); + item.Studios = info.Studios.ToArray(); item.CommunityRating = info.CommunityRating; item.Overview = info.Overview; item.IndexNumber = info.IndexNumber; @@ -1021,7 +1021,7 @@ namespace Emby.Server.Implementations.Channels item.ProviderIds = info.ProviderIds; item.OfficialRating = info.OfficialRating; item.DateCreated = info.DateCreated ?? DateTime.UtcNow; - item.Tags = info.Tags.ToArray(info.Tags.Count); + item.Tags = info.Tags.ToArray(); item.OriginalTitle = info.OriginalTitle; } else if (info.Type == ChannelItemType.Folder && info.FolderType == ChannelFolderType.Container) @@ -1043,7 +1043,7 @@ namespace Emby.Server.Implementations.Channels var hasAlbumArtists = item as IHasAlbumArtist; if (hasAlbumArtists != null) { - hasAlbumArtists.AlbumArtists = info.AlbumArtists.ToArray(info.AlbumArtists.Count); + hasAlbumArtists.AlbumArtists = info.AlbumArtists.ToArray(); } var trailer = item as Trailer; diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 675a726e55..bcfc58ca15 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -219,7 +219,7 @@ namespace Emby.Server.Implementations.Collections { var newList = collection.LinkedChildren.ToList(); newList.AddRange(list); - collection.LinkedChildren = newList.ToArray(newList.Count); + collection.LinkedChildren = newList.ToArray(); collection.UpdateRatingToItems(linkedChildrenList); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index c9495c5747..50cd693044 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1148,7 +1148,7 @@ namespace Emby.Server.Implementations.Data } } - item.ImageInfos = list.ToArray(list.Count); + item.ImageInfos = list.ToArray(); } public string ToValueString(ItemImageInfo image) @@ -2566,7 +2566,7 @@ namespace Emby.Server.Implementations.Data excludeIds.Add(item.Id); excludeIds.AddRange(item.ExtraIds); - query.ExcludeItemIds = excludeIds.ToArray(excludeIds.Count); + query.ExcludeItemIds = excludeIds.ToArray(); query.ExcludeProviderIds = item.ProviderIds; } @@ -2587,7 +2587,7 @@ namespace Emby.Server.Implementations.Data list.Add(builder.ToString()); } - return list.ToArray(list.Count); + return list.ToArray(); } private void BindSearchParams(InternalItemsQuery query, IStatement statement) @@ -2666,7 +2666,7 @@ namespace Emby.Server.Implementations.Data if (groups.Count > 0) { - return " Group by " + string.Join(",", groups.ToArray(groups.Count)); + return " Group by " + string.Join(",", groups.ToArray()); } return string.Empty; @@ -2703,7 +2703,7 @@ namespace Emby.Server.Implementations.Data var whereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); + " where " + string.Join(" AND ", whereClauses.ToArray()); commandText += whereText; @@ -2761,7 +2761,7 @@ namespace Emby.Server.Implementations.Data var whereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); + " where " + string.Join(" AND ", whereClauses.ToArray()); commandText += whereText; @@ -2938,7 +2938,7 @@ namespace Emby.Server.Implementations.Data var returnList = GetItemList(query); return new QueryResult { - Items = returnList.ToArray(returnList.Count), + Items = returnList.ToArray(), TotalRecordCount = returnList.Count }; } @@ -2961,7 +2961,7 @@ namespace Emby.Server.Implementations.Data var whereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); + " where " + string.Join(" AND ", whereClauses.ToArray()); var whereTextWithoutPaging = whereText; @@ -3079,7 +3079,7 @@ namespace Emby.Server.Implementations.Data LogQueryTime("GetItems", commandText, now); - result.Items = list.ToArray(list.Count); + result.Items = list.ToArray(); return result; }, ReadTransactionMode); @@ -3227,7 +3227,7 @@ namespace Emby.Server.Implementations.Data var whereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); + " where " + string.Join(" AND ", whereClauses.ToArray()); commandText += whereText; @@ -3299,7 +3299,7 @@ namespace Emby.Server.Implementations.Data var whereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); + " where " + string.Join(" AND ", whereClauses.ToArray()); commandText += whereText; @@ -3372,7 +3372,7 @@ namespace Emby.Server.Implementations.Data var returnList = GetItemIdsList(query); return new QueryResult { - Items = returnList.ToArray(returnList.Count), + Items = returnList.ToArray(), TotalRecordCount = returnList.Count }; } @@ -3387,7 +3387,7 @@ namespace Emby.Server.Implementations.Data var whereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); + " where " + string.Join(" AND ", whereClauses.ToArray()); var whereTextWithoutPaging = whereText; @@ -3495,7 +3495,7 @@ namespace Emby.Server.Implementations.Data LogQueryTime("GetItemIds", commandText, now); - result.Items = list.ToArray(list.Count); + result.Items = list.ToArray(); return result; }, ReadTransactionMode); @@ -3690,7 +3690,7 @@ namespace Emby.Server.Implementations.Data statement.TryBind("@IsMovie", true); } - whereClauses.Add("(" + string.Join(" OR ", programAttribtues.ToArray(programAttribtues.Count)) + ")"); + whereClauses.Add("(" + string.Join(" OR ", programAttribtues.ToArray()) + ")"); } else if (query.IsMovie.HasValue) { @@ -5813,7 +5813,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type { result.TotalRecordCount = list.Count; } - result.Items = list.ToArray(list.Count); + result.Items = list.ToArray(); return result; diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index 0fac886ef3..5c84590ae2 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -289,7 +289,7 @@ namespace Emby.Server.Implementations.Devices var list = history.FilesUploaded.ToList(); list.Add(file); - history.FilesUploaded = list.ToArray(list.Count); + history.FilesUploaded = list.ToArray(); _json.SerializeToFile(history, path); } @@ -501,4 +501,4 @@ namespace Emby.Server.Implementations.Devices return config.GetConfiguration("devices"); } } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 437917c45c..0831b10753 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -648,7 +648,7 @@ namespace Emby.Server.Implementations.Dto } } - dto.People = list.ToArray(list.Count); + dto.People = list.ToArray(); } /// diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 6801b2823b..aa672a1b7a 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -12,7 +12,6 @@ using MediaBrowser.Model.Events; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Threading; using Mono.Nat; -using MediaBrowser.Model.Extensions; using System.Threading; namespace Emby.Server.Implementations.EntryPoints @@ -59,7 +58,7 @@ namespace Emby.Server.Implementations.EntryPoints values.Add(_appHost.EnableHttps.ToString()); values.Add((config.EnableRemoteAccess).ToString()); - return string.Join("|", values.ToArray(values.Count)); + return string.Join("|", values.ToArray()); } void _config_ConfigurationUpdated(object sender, EventArgs e) @@ -316,4 +315,4 @@ namespace Emby.Server.Implementations.EntryPoints } } } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs index 97feb32c08..4507640409 100644 --- a/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs @@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.EntryPoints session.ApplicationVersion }; - var key = string.Join("_", keys.ToArray(keys.Count)).GetMD5(); + var key = string.Join("_", keys.ToArray()).GetMD5(); ClientInfo info; if (!_apps.TryGetValue(key, out info)) diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 0093258e39..70a233c6fe 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -825,7 +825,7 @@ namespace Emby.Server.Implementations.HttpServer }); } - return routes.ToArray(routes.Count); + return routes.ToArray(); } public Func GetParseFn(Type propertyType) @@ -954,4 +954,4 @@ namespace Emby.Server.Implementations.HttpServer _listener.Start(UrlPrefixes); } } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index df493b4c3e..a0a471cb26 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -112,12 +112,15 @@ namespace Emby.Server.Implementations.HttpServer /// private IHasHeaders GetHttpResult(IRequest requestContext, byte[] content, string contentType, bool addCachePrevention, IDictionary responseHeaders = null) { - IHasHeaders result; - - var compressionType = requestContext == null ? null : GetCompressionType(requestContext, content, contentType); + string compressionType = null; + bool isHeadRequest = false; - var isHeadRequest = string.Equals(requestContext.Verb, "head", StringComparison.OrdinalIgnoreCase); + if (requestContext != null) { + compressionType = GetCompressionType(requestContext, content, contentType); + isHeadRequest = string.Equals(requestContext.Verb, "head", StringComparison.OrdinalIgnoreCase); + } + IHasHeaders result; if (string.IsNullOrEmpty(compressionType)) { var contentLength = content.Length; @@ -791,4 +794,4 @@ namespace Emby.Server.Implementations.HttpServer { byte[] Compress(byte[] content); } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/Collections.cs b/Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/Collections.cs index 4432e62fb0..8560a2dc24 100644 --- a/Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/Collections.cs +++ b/Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/Collections.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +// TODO: @bond Remove namespace SharpCifs.Util.Sharpen { internal static class Collections diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 17516d6b90..bd823e0c11 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -730,7 +730,7 @@ namespace Emby.Server.Implementations.Library _fileSystem.CreateDirectory(rootFolderPath); - var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath)); + var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? ((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath))).DeepCopy(); // In case program data folder was moved if (!string.Equals(rootFolder.Path, rootFolderPath, StringComparison.Ordinal)) @@ -799,7 +799,7 @@ namespace Emby.Server.Implementations.Library if (tmpItem == null) { - tmpItem = (UserRootFolder)ResolvePath(_fileSystem.GetDirectoryInfo(userRootPath)); + tmpItem = ((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(userRootPath))).DeepCopy(); } // In case program data folder was moved @@ -1493,7 +1493,7 @@ namespace Emby.Server.Implementations.Library return new QueryResult { - Items = list.ToArray(list.Count) + Items = list.ToArray() }; } diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index 7f04ac5bcc..a7db46ef2d 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -161,8 +161,8 @@ namespace Emby.Server.Implementations.Library var searchQuery = new InternalItemsQuery(user) { SearchTerm = searchTerm, - ExcludeItemTypes = excludeItemTypes.ToArray(excludeItemTypes.Count), - IncludeItemTypes = includeItemTypes.ToArray(includeItemTypes.Count), + ExcludeItemTypes = excludeItemTypes.ToArray(), + IncludeItemTypes = includeItemTypes.ToArray(), Limit = query.Limit, IncludeItemsByName = string.IsNullOrEmpty(query.ParentId), ParentId = string.IsNullOrEmpty(query.ParentId) ? Guid.Empty : new Guid(query.ParentId), diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index 42f9227107..aae5751de1 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -354,7 +354,7 @@ namespace Emby.Server.Implementations.Library Limit = limit * 5, IsPlayed = isPlayed, DtoOptions = options, - MediaTypes = mediaTypes.ToArray(mediaTypes.Count) + MediaTypes = mediaTypes.ToArray() }; if (parents.Count == 0) diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index 56b3b5e4bd..b0ffd057d4 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.LiveTv dto.ProgramId = GetInternalProgramId(info.ProgramId).ToString("N"); } - dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days.ToArray(info.Days.Count)); + dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days.ToArray()); FillImages(dto, info.Name, info.SeriesId); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 9cdf105d70..2e96796784 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1140,7 +1140,7 @@ namespace Emby.Server.Implementations.LiveTv var dtoOptions = new DtoOptions(); var fields = dtoOptions.Fields.ToList(); fields.Remove(ItemFields.BasicSyncInfo); - dtoOptions.Fields = fields.ToArray(fields.Count); + dtoOptions.Fields = fields.ToArray(); progress.Report(100); } @@ -1458,16 +1458,16 @@ namespace Emby.Server.Implementations.LiveTv { MediaTypes = new[] { MediaType.Video }, Recursive = true, - AncestorIds = folderIds.ToArray(folderIds.Count), + AncestorIds = folderIds.ToArray(), IsFolder = false, IsVirtualItem = false, Limit = limit, StartIndex = query.StartIndex, OrderBy = new[] { new ValueTuple(ItemSortBy.DateCreated, SortOrder.Descending) }, EnableTotalRecordCount = query.EnableTotalRecordCount, - IncludeItemTypes = includeItemTypes.ToArray(includeItemTypes.Count), - ExcludeItemTypes = excludeItemTypes.ToArray(excludeItemTypes.Count), - Genres = genres.ToArray(genres.Count), + IncludeItemTypes = includeItemTypes.ToArray(), + ExcludeItemTypes = excludeItemTypes.ToArray(), + Genres = genres.ToArray(), DtoOptions = dtoOptions }); @@ -1791,7 +1791,7 @@ namespace Emby.Server.Implementations.LiveTv var returnArray = returnList .OrderBy(i => i.StartDate) - .ToArray(returnList.Count); + .ToArray(); return new QueryResult { @@ -2338,7 +2338,7 @@ namespace Emby.Server.Implementations.LiveTv fields.Remove(ItemFields.CanDownload); fields.Remove(ItemFields.DisplayPreferencesId); fields.Remove(ItemFields.Etag); - options.Fields = fields.ToArray(fields.Count); + options.Fields = fields.ToArray(); } public Folder GetInternalLiveTvFolder(CancellationToken cancellationToken) @@ -2373,7 +2373,7 @@ namespace Emby.Server.Implementations.LiveTv { info.Id = Guid.NewGuid().ToString("N"); list.Add(info); - config.TunerHosts = list.ToArray(list.Count); + config.TunerHosts = list.ToArray(); } else { @@ -2412,7 +2412,7 @@ namespace Emby.Server.Implementations.LiveTv { info.Id = Guid.NewGuid().ToString("N"); list.Add(info); - config.ListingProviders = list.ToArray(list.Count); + config.ListingProviders = list.ToArray(); } else { @@ -2451,7 +2451,7 @@ namespace Emby.Server.Implementations.LiveTv Name = tunerChannelId, Value = providerChannelId }); - listingsProviderInfo.ChannelMappings = list.ToArray(list.Count); + listingsProviderInfo.ChannelMappings = list.ToArray(); } _config.SaveConfiguration("livetv", config); @@ -2602,4 +2602,4 @@ namespace Emby.Server.Implementations.LiveTv return folders.Cast().ToList(); } } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 808672d462..26a84a2750 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -106,7 +106,7 @@ namespace Emby.Server.Implementations.LiveTv openKeys.Add(item.GetType().Name); openKeys.Add(item.Id.ToString("N")); openKeys.Add(source.Id ?? string.Empty); - source.OpenToken = string.Join(StreamIdDelimeterString, openKeys.ToArray(openKeys.Count)); + source.OpenToken = string.Join(StreamIdDelimeterString, openKeys.ToArray()); } // Dummy this up so that direct play checks can still run diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index 20abaf27c2..4699b5bd48 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -706,7 +706,7 @@ namespace Emby.Server.Implementations.Networking public async Task GetHostAddressesAsync(string host) { var addresses = await Dns.GetHostAddressesAsync(host).ConfigureAwait(false); - return addresses.Select(ToIpAddressInfo).ToArray(addresses.Length); + return addresses.Select(ToIpAddressInfo).ToArray(); } /// diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index e0a6f56ecf..1e8d30ab9e 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -208,7 +208,7 @@ namespace Emby.Server.Implementations.Playlists var newList = playlist.LinkedChildren.ToList(); newList.AddRange(list); - playlist.LinkedChildren = newList.ToArray(newList.Count); + playlist.LinkedChildren = newList.ToArray(); playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); @@ -290,7 +290,7 @@ namespace Emby.Server.Implementations.Playlists newList.Insert(newIndex, item); } - playlist.LinkedChildren = newList.ToArray(newList.Count); + playlist.LinkedChildren = newList.ToArray(); playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); diff --git a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs index 7a5efded3f..8ed2dbaedf 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs @@ -145,7 +145,7 @@ namespace Emby.Server.Implementations.ScheduledTasks _fileSystem.CreateDirectory(parentPath); - _fileSystem.WriteAllText(failHistoryPath, string.Join("|", previouslyFailedImages.ToArray(previouslyFailedImages.Count))); + _fileSystem.WriteAllText(failHistoryPath, string.Join("|", previouslyFailedImages.ToArray())); } numComplete++; diff --git a/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs deleted file mode 100644 index 6911126386..0000000000 --- a/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs +++ /dev/null @@ -1,142 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Updates; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Progress; -using MediaBrowser.Model.Tasks; - -namespace Emby.Server.Implementations.ScheduledTasks -{ - /// - /// Plugin Update Task - /// - public class PluginUpdateTask : IScheduledTask, IConfigurableScheduledTask - { - /// - /// The _logger - /// - private readonly ILogger _logger; - - private readonly IInstallationManager _installationManager; - - private readonly IApplicationHost _appHost; - - public PluginUpdateTask(ILogger logger, IInstallationManager installationManager, IApplicationHost appHost) - { - _logger = logger; - _installationManager = installationManager; - _appHost = appHost; - } - - /// - /// Creates the triggers that define when the task will run - /// - /// IEnumerable{BaseTaskTrigger}. - public IEnumerable GetDefaultTriggers() - { - return new[] { - - // At startup - new TaskTriggerInfo {Type = TaskTriggerInfo.TriggerStartup}, - - // Every so often - new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks} - }; - } - - public string Key - { - get { return "PluginUpdates"; } - } - - /// - /// Update installed plugins - /// - /// The cancellation token. - /// The progress. - /// Task. - public async Task Execute(CancellationToken cancellationToken, IProgress progress) - { - progress.Report(0); - - var packagesToInstall = (await _installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, true, cancellationToken).ConfigureAwait(false)).ToList(); - - progress.Report(10); - - var numComplete = 0; - - foreach (var package in packagesToInstall) - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - await _installationManager.InstallPackage(package, true, new SimpleProgress(), cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // InstallPackage has it's own inner cancellation token, so only throw this if it's ours - if (cancellationToken.IsCancellationRequested) - { - throw; - } - } - catch (HttpException ex) - { - _logger.ErrorException("Error downloading {0}", ex, package.name); - } - catch (IOException ex) - { - _logger.ErrorException("Error updating {0}", ex, package.name); - } - - // Update progress - lock (progress) - { - numComplete++; - double percent = numComplete; - percent /= packagesToInstall.Count; - - progress.Report(90 * percent + 10); - } - } - - progress.Report(100); - } - - /// - /// Gets the name of the task - /// - /// The name. - public string Name - { - get { return "Check for plugin updates"; } - } - - /// - /// Gets the description. - /// - /// The description. - public string Description - { - get { return "Downloads and installs updates for plugins that are configured to update automatically."; } - } - - public string Category - { - get { return "Application"; } - } - - public bool IsHidden => true; - - public bool IsEnabled => true; - - public bool IsLogged => true; - } -} \ No newline at end of file diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index f6397b6700..eeb38bf540 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -9,7 +9,6 @@ using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Progress; using MediaBrowser.Model.Events; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; @@ -276,7 +275,7 @@ namespace Emby.Server.Implementations.ScheduledTasks get { var triggers = InternalTriggers; - return triggers.Select(i => i.Item1).ToArray(triggers.Length); + return triggers.Select(i => i.Item1).ToArray(); } set { @@ -290,7 +289,7 @@ namespace Emby.Server.Implementations.ScheduledTasks SaveTriggers(triggerList); - InternalTriggers = triggerList.Select(i => new Tuple(i, GetTrigger(i))).ToArray(triggerList.Length); + InternalTriggers = triggerList.Select(i => new Tuple(i, GetTrigger(i))).ToArray(); } } diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs index 45f7f1e958..f75eb63649 100644 --- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs +++ b/Emby.Server.Implementations/Security/AuthenticationRepository.cs @@ -241,7 +241,7 @@ namespace Emby.Server.Implementations.Security var whereTextWithoutPaging = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); + " where " + string.Join(" AND ", whereClauses.ToArray()); commandText += whereTextWithoutPaging; @@ -298,7 +298,7 @@ namespace Emby.Server.Implementations.Security } } - result.Items = list.ToArray(list.Count); + result.Items = list.ToArray(); return result; }, ReadTransactionMode); diff --git a/Emby.Server.Implementations/Services/ServiceExec.cs b/Emby.Server.Implementations/Services/ServiceExec.cs index 79b57438ca..9516c1e389 100644 --- a/Emby.Server.Implementations/Services/ServiceExec.cs +++ b/Emby.Server.Implementations/Services/ServiceExec.cs @@ -181,7 +181,7 @@ namespace Emby.Server.Implementations.Services } if (reqFilters.Count > 0) - actionCtx.RequestFilters = reqFilters.OrderBy(i => i.Priority).ToArray(reqFilters.Count); + actionCtx.RequestFilters = reqFilters.OrderBy(i => i.Priority).ToArray(); actions.Add(actionCtx); } @@ -220,4 +220,4 @@ namespace Emby.Server.Implementations.Services } } } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/Services/ServicePath.cs b/Emby.Server.Implementations/Services/ServicePath.cs index 282269e7b1..f0e80c2169 100644 --- a/Emby.Server.Implementations/Services/ServicePath.cs +++ b/Emby.Server.Implementations/Services/ServicePath.cs @@ -132,13 +132,13 @@ namespace Emby.Server.Implementations.Services } } - var components = componentsList.ToArray(componentsList.Count); + var components = componentsList.ToArray(); this.TotalComponentsCount = components.Length; this.literalsToMatch = new string[this.TotalComponentsCount]; this.variablesNames = new string[this.TotalComponentsCount]; this.isWildcard = new bool[this.TotalComponentsCount]; - this.componentsWithSeparators = hasSeparators.ToArray(hasSeparators.Count); + this.componentsWithSeparators = hasSeparators.ToArray(); this.PathComponentsCount = this.componentsWithSeparators.Length; string firstLiteralMatch = null; @@ -297,7 +297,7 @@ namespace Emby.Server.Implementations.Services if (mi != null && mi.IsStatic) continue; pis.Add(pi); } - return pis.ToArray(pis.Count); + return pis.ToArray(); } /// @@ -463,7 +463,7 @@ namespace Emby.Server.Implementations.Services } } - withPathInfoParts = totalComponents.ToArray(totalComponents.Count); + withPathInfoParts = totalComponents.ToArray(); return true; } @@ -574,4 +574,4 @@ namespace Emby.Server.Implementations.Services } } } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index df7f231c7b..a2102dc452 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1042,7 +1042,7 @@ namespace Emby.Server.Implementations.Session command.PlayCommand = PlayCommand.PlayNow; } - command.ItemIds = items.Select(i => i.Id).ToArray(items.Count); + command.ItemIds = items.Select(i => i.Id).ToArray(); if (user != null) { @@ -1070,7 +1070,7 @@ namespace Emby.Server.Implementations.Session if (episodes.Count > 0) { - command.ItemIds = episodes.Select(i => i.Id).ToArray(episodes.Count); + command.ItemIds = episodes.Select(i => i.Id).ToArray(); } } } @@ -1316,7 +1316,7 @@ namespace Emby.Server.Implementations.Session UserName = user.Name }); - session.AdditionalUsers = list.ToArray(list.Count); + session.AdditionalUsers = list.ToArray(); } } @@ -1345,7 +1345,7 @@ namespace Emby.Server.Implementations.Session var list = session.AdditionalUsers.ToList(); list.Remove(user); - session.AdditionalUsers = list.ToArray(list.Count); + session.AdditionalUsers = list.ToArray(); } } @@ -1669,7 +1669,7 @@ namespace Emby.Server.Implementations.Session fields.Remove(ItemFields.Tags); fields.Remove(ItemFields.ExtraIds); - dtoOptions.Fields = fields.ToArray(fields.Count); + dtoOptions.Fields = fields.ToArray(); _itemInfoDtoOptions = dtoOptions; } diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index db6af0c4bd..e243927a0c 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -143,7 +143,7 @@ namespace MediaBrowser.Api { var list = options.Fields.ToList(); list.Add(Model.Querying.ItemFields.RecursiveItemCount); - options.Fields = list.ToArray(list.Count); + options.Fields = list.ToArray(); } if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 || @@ -156,7 +156,7 @@ namespace MediaBrowser.Api { var list = options.Fields.ToList(); list.Add(Model.Querying.ItemFields.ChildCount); - options.Fields = list.ToArray(list.Count); + options.Fields = list.ToArray(); } } diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 510c5f135b..06c0c6862c 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -974,7 +974,7 @@ namespace MediaBrowser.Api.LiveTv fields.Remove(ItemFields.CanDownload); fields.Remove(ItemFields.DisplayPreferencesId); fields.Remove(ItemFields.Etag); - options.Fields = fields.ToArray(fields.Count); + options.Fields = fields.ToArray(); } public object Get(GetChannel request) @@ -1265,4 +1265,4 @@ namespace MediaBrowser.Api.LiveTv return _liveTvManager.ResetTuner(request.Id, CancellationToken.None); } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 7112806011..e8d9712de1 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -123,7 +123,7 @@ namespace MediaBrowser.Api.Movies var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user) { Limit = request.Limit, - IncludeItemTypes = itemTypes.ToArray(itemTypes.Count), + IncludeItemTypes = itemTypes.ToArray(), IsMovie = true, SimilarTo = item, EnableGroupByMetadataKey = true, @@ -177,12 +177,12 @@ namespace MediaBrowser.Api.Movies var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user) { - IncludeItemTypes = itemTypes.ToArray(itemTypes.Count), + IncludeItemTypes = itemTypes.ToArray(), IsMovie = true, OrderBy = new[] { ItemSortBy.Random }.Select(i => new ValueTuple(i, SortOrder.Descending)).ToArray(), Limit = 10, IsFavoriteOrLiked = true, - ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id).ToArray(recentlyPlayedMovies.Count), + ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id).ToArray(), EnableGroupByMetadataKey = true, ParentId = parentIdGuid, Recursive = true, @@ -265,7 +265,7 @@ namespace MediaBrowser.Api.Movies // Account for duplicates by imdb id, since the database doesn't support this yet Limit = itemLimit + 2, PersonTypes = new[] { PersonType.Director }, - IncludeItemTypes = itemTypes.ToArray(itemTypes.Count), + IncludeItemTypes = itemTypes.ToArray(), IsMovie = true, EnableGroupByMetadataKey = true, DtoOptions = dtoOptions @@ -305,7 +305,7 @@ namespace MediaBrowser.Api.Movies Person = name, // Account for duplicates by imdb id, since the database doesn't support this yet Limit = itemLimit + 2, - IncludeItemTypes = itemTypes.ToArray(itemTypes.Count), + IncludeItemTypes = itemTypes.ToArray(), IsMovie = true, EnableGroupByMetadataKey = true, DtoOptions = dtoOptions @@ -343,7 +343,7 @@ namespace MediaBrowser.Api.Movies var similar = _libraryManager.GetItemList(new InternalItemsQuery(user) { Limit = itemLimit, - IncludeItemTypes = itemTypes.ToArray(itemTypes.Count), + IncludeItemTypes = itemTypes.ToArray(), IsMovie = true, SimilarTo = item, EnableGroupByMetadataKey = true, diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs index be9c1a4c58..db5908f769 100644 --- a/MediaBrowser.Api/SimilarItemsHelper.cs +++ b/MediaBrowser.Api/SimilarItemsHelper.cs @@ -11,7 +11,6 @@ using System.Linq; using System.Threading.Tasks; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Services; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Api { @@ -81,7 +80,7 @@ namespace MediaBrowser.Api var query = new InternalItemsQuery(user) { - IncludeItemTypes = includeTypes.Select(i => i.Name).ToArray(includeTypes.Length), + IncludeItemTypes = includeTypes.Select(i => i.Name).ToArray(), Recursive = true, DtoOptions = dtoOptions }; diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index fe8b446a1f..eee27ac8e8 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -206,7 +206,7 @@ namespace MediaBrowser.Api.UserLibrary return new QueryResult { - Items = dtos.ToArray(result.Items.Length), + Items = dtos.ToArray(), TotalRecordCount = result.TotalRecordCount }; } diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs index 5e9270e0bf..a65cc18ebb 100644 --- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs +++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs @@ -93,7 +93,7 @@ namespace MediaBrowser.Api.UserLibrary fields.Add(ItemFields.PrimaryImageAspectRatio); fields.Add(ItemFields.DisplayPreferencesId); fields.Remove(ItemFields.BasicSyncInfo); - dtoOptions.Fields = fields.ToArray(fields.Count); + dtoOptions.Fields = fields.ToArray(); var user = _userManager.GetUserById(request.UserId); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 053ee1b965..e3b5b51178 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1295,7 +1295,7 @@ namespace MediaBrowser.Controller.Entities } } - return string.Join("/", terms.ToArray(terms.Count)); + return string.Join("/", terms.ToArray()); } /// @@ -1536,7 +1536,7 @@ namespace MediaBrowser.Controller.Entities { var newThemeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService); - var newThemeVideoIds = newThemeVideos.Select(i => i.Id).ToArray(newThemeVideos.Length); + var newThemeVideoIds = newThemeVideos.Select(i => i.Id).ToArray(); var themeVideosChanged = !item.ThemeVideoIds.SequenceEqual(newThemeVideoIds); @@ -1573,7 +1573,7 @@ namespace MediaBrowser.Controller.Entities private async Task RefreshThemeSongs(BaseItem item, MetadataRefreshOptions options, List fileSystemChildren, CancellationToken cancellationToken) { var newThemeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService); - var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToArray(newThemeSongs.Length); + var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToArray(); var themeSongsChanged = !item.ThemeSongIds.SequenceEqual(newThemeSongIds); @@ -2110,9 +2110,8 @@ namespace MediaBrowser.Controller.Entities } else { - var list = current.ToArray(current.Length + 1); - list[list.Length - 1] = name; - Studios = list; + var list = + Studios = current.Concat(new [] { name }).ToArray(); } } } @@ -2252,9 +2251,7 @@ namespace MediaBrowser.Controller.Entities else { var currentCount = ImageInfos.Length; - var newList = ImageInfos.ToArray(currentCount + 1); - newList[currentCount] = image; - ImageInfos = newList; + ImageInfos = ImageInfos.Concat(new [] { image }) .ToArray(); } } @@ -2269,10 +2266,7 @@ namespace MediaBrowser.Controller.Entities if (image == null) { - var currentCount = ImageInfos.Length; - var newList = ImageInfos.ToArray(currentCount + 1); - newList[currentCount] = GetImageInfo(file, type); - ImageInfos = newList; + ImageInfos = ImageInfos.Concat(new [] { GetImageInfo(file, type) }) .ToArray(); } else { @@ -2486,16 +2480,7 @@ namespace MediaBrowser.Controller.Entities if (newImageList.Count > 0) { - var currentCount = ImageInfos.Length; - var newList = ImageInfos.ToArray(currentCount + newImageList.Count); - - foreach (var image in newImageList) - { - newList[currentCount] = GetImageInfo(image, imageType); - currentCount++; - } - - ImageInfos = newList; + ImageInfos = ImageInfos.Concat(newImageList.Select(i => GetImageInfo(i, imageType))).ToArray(); } return imageUpdated || newImageList.Count > 0; @@ -2537,7 +2522,7 @@ namespace MediaBrowser.Controller.Entities var extensions = new List { ".nfo", ".xml", ".srt", ".vtt", ".sub", ".idx", ".txt", ".edl", ".bif", ".smi", ".ttml" }; extensions.AddRange(SupportedImageExtensions); - return FileSystem.GetFiles(FileSystem.GetDirectoryName(Path), extensions.ToArray(extensions.Count), false, false) + return FileSystem.GetFiles(FileSystem.GetDirectoryName(Path), extensions.ToArray(), false, false) .Where(i => System.IO.Path.GetFileNameWithoutExtension(i.FullName).StartsWith(filename, StringComparison.OrdinalIgnoreCase)) .ToList(); } @@ -2776,7 +2761,7 @@ namespace MediaBrowser.Controller.Entities { var list = GetEtagValues(user); - return string.Join("|", list.ToArray(list.Count)).GetMD5().ToString("N"); + return string.Join("|", list.ToArray()).GetMD5().ToString("N"); } protected virtual List GetEtagValues(User user) diff --git a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs index c56a370a86..8ab1788b57 100644 --- a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs +++ b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -61,5 +62,46 @@ namespace MediaBrowser.Controller.Entities item.SetImagePath(imageType, BaseItem.FileSystem.GetFileInfo(file)); } } + + /// + /// Copies all properties on object. Skips properties that do not exist. + /// + /// The source object. + /// The destination object. + public static void DeepCopy(this T source, TU dest) + where T : BaseItem + where TU : BaseItem + { + var sourceProps = typeof (T).GetProperties().Where(x => x.CanRead).ToList(); + var destProps = typeof(TU).GetProperties() + .Where(x => x.CanWrite) + .ToList(); + + foreach (var sourceProp in sourceProps) + { + if (destProps.Any(x => x.Name == sourceProp.Name)) + { + var p = destProps.First(x => x.Name == sourceProp.Name); + p.SetValue(dest, sourceProp.GetValue(source, null), null); + } + + } + + } + + /// + /// Copies all properties on newly created object. Skips properties that do not exist. + /// + /// The source object. + public static TU DeepCopy(this T source) + where T : BaseItem + where TU : BaseItem, new() + { + var dest = new TU(); + source.DeepCopy(dest); + return dest; + } + + } } diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 8240a68ff7..19a8c24b8a 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -275,7 +275,7 @@ namespace MediaBrowser.Controller.Entities var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer(FileSystem)); - LinkedChildren = linkedChildren.ToArray(linkedChildren.Count); + LinkedChildren = linkedChildren.ToArray(); var folderIds = PhysicalFolderIds; var newFolderIds = physicalFolders.Select(i => i.Id).ToArray(); diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs index c706cf36ce..ee135a14e9 100644 --- a/MediaBrowser.Controller/Entities/Extensions.cs +++ b/MediaBrowser.Controller/Entities/Extensions.cs @@ -35,10 +35,7 @@ namespace MediaBrowser.Controller.Entities } else { - var list = item.RemoteTrailers.ToArray(item.RemoteTrailers.Length + 1); - list[list.Length - 1] = mediaUrl; - - item.RemoteTrailers = list; + item.RemoteTrailers = item.RemoteTrailers.Concat(new [] { mediaUrl }).ToArray(); } } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 8b9aa5fc3a..81072b6e77 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -914,7 +914,7 @@ namespace MediaBrowser.Controller.Entities // Try to preserve order return result.OrderBy(i => ids.IndexOf(i.Id)).ToArray(); } - return result.ToArray(result.Count); + return result.ToArray(); } return GetItemsInternal(query).Items; @@ -1608,7 +1608,7 @@ namespace MediaBrowser.Controller.Entities Logger.Info("Shortcut links have changed for {0}", Path); newShortcutLinks.AddRange(LinkedChildren.Where(i => i.Type == LinkedChildType.Manual)); - LinkedChildren = newShortcutLinks.ToArray(newShortcutLinks.Count); + LinkedChildren = newShortcutLinks.ToArray(); return true; } } diff --git a/MediaBrowser.Controller/Entities/TagExtensions.cs b/MediaBrowser.Controller/Entities/TagExtensions.cs index e5d8f35d92..84e61be4fc 100644 --- a/MediaBrowser.Controller/Entities/TagExtensions.cs +++ b/MediaBrowser.Controller/Entities/TagExtensions.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities { @@ -24,10 +22,7 @@ namespace MediaBrowser.Controller.Entities } else { - var list = current.ToArray(current.Length + 1); - list[list.Length - 1] = name; - - item.Tags = list; + item.Tags = current.Concat(new [] { name }).ToArray(); } } } diff --git a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs index 33eb75edb1..891a3ad3fd 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Xml; using MediaBrowser.Model.IO; using MediaBrowser.Model.Xml; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.LocalMetadata.Parsers { @@ -85,7 +84,7 @@ namespace MediaBrowser.LocalMetadata.Parsers } } - item.Item.LinkedChildren = list.ToArray(list.Count); + item.Item.LinkedChildren = list.ToArray(); } public BoxSetXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem) diff --git a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs index 10f46e5a4a..8b25dd3bdb 100644 --- a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs @@ -95,7 +95,7 @@ namespace MediaBrowser.LocalMetadata.Parsers } } - item.LinkedChildren = list.ToArray(list.Count); + item.LinkedChildren = list.ToArray(); } public PlaylistXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem) diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 64ab6831c5..d9d2b4bf95 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -1,33 +1,20 @@  + netstandard2.0 false + - - Properties\SharedVersion.cs - + + - - {88ae38df-19d7-406f-a6a9-09527719a21e} - BDInfo - - - {9142eefa-7570-41e1-bfcc-468bb571af2f} - MediaBrowser.Common - - - {17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2} - MediaBrowser.Controller - - - {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} - MediaBrowser.Model - - - {4a4402d4-e910-443b-b8fc-2c18286a2ca0} - OpenSubtitlesHandler - + + + + + + diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 58a8391678..cc12750352 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -246,7 +246,7 @@ namespace MediaBrowser.Model.Configuration SortRemoveCharacters = new[] { ",", "&", "-", "{", "}", "'" }; SortRemoveWords = new[] { "the", "a", "an" }; - UICulture = "en-us"; + UICulture = "en-US"; MetadataOptions = new[] { @@ -310,4 +310,4 @@ namespace MediaBrowser.Model.Configuration public string From { get; set; } public string To { get; set; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index b6f3293874..81d58336bf 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -101,7 +101,7 @@ namespace MediaBrowser.Model.Dlna { list.Add(MediaFormatProfile.MPEG_TS_JP_T); } - return list.ToArray(list.Count); + return list.ToArray(); } if (StringHelper.EqualsIgnoreCase(videoCodec, "h264")) { diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 46a1cd68b7..c927cd31cc 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -186,7 +186,7 @@ namespace MediaBrowser.Model.Dlna list.Add(string.Format("{0}={1}", pair.Name, encodedValue)); } - string queryString = string.Join("&", list.ToArray(list.Count)); + string queryString = string.Join("&", list.ToArray()); return GetUrl(baseUrl, queryString); } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index fc208459df..35369fbbb9 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Extensions; @@ -104,7 +105,7 @@ namespace MediaBrowser.Model.Entities attributes.Add("Default"); } - return string.Join(" ", attributes.ToArray(attributes.Count)); + return string.Join(" ", attributes.ToArray()); } if (Type == MediaStreamType.Video) @@ -123,7 +124,7 @@ namespace MediaBrowser.Model.Entities attributes.Add(Codec.ToUpper()); } - return string.Join(" ", attributes.ToArray(attributes.Count)); + return string.Join(" ", attributes.ToArray()); } if (Type == MediaStreamType.Subtitle) @@ -154,7 +155,7 @@ namespace MediaBrowser.Model.Entities attributes.Add("Forced"); } - string name = string.Join(" ", attributes.ToArray(attributes.Count)); + string name = string.Join(" ", attributes.ToArray()); return name; } diff --git a/MediaBrowser.Model/Extensions/LinqExtensions.cs b/MediaBrowser.Model/Extensions/LinqExtensions.cs index 09ace42e81..1223e689e3 100644 --- a/MediaBrowser.Model/Extensions/LinqExtensions.cs +++ b/MediaBrowser.Model/Extensions/LinqExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; +// TODO: @bond Remove namespace MediaBrowser.Model.Extensions { // MoreLINQ - Extensions to LINQ to Objects @@ -42,19 +43,6 @@ namespace MediaBrowser.Model.Extensions return source.DistinctBy(keySelector, null); } - public static TSource[] ToArray(this IEnumerable source, int count) - { - if (source == null) throw new ArgumentNullException("source"); - if (count < 0) throw new ArgumentOutOfRangeException("count"); - var array = new TSource[count]; - int i = 0; - foreach (var item in source) - { - array[i++] = item; - } - return array; - } - /// /// Returns all distinct elements of the given source, where "distinctness" /// is determined via a projection and the specified comparer for the projected type. diff --git a/MediaBrowser.Model/Services/HttpUtility.cs b/MediaBrowser.Model/Services/HttpUtility.cs index 5cc0cc37d3..f8fd968018 100644 --- a/MediaBrowser.Model/Services/HttpUtility.cs +++ b/MediaBrowser.Model/Services/HttpUtility.cs @@ -2,8 +2,6 @@ using System.Collections; using System.Collections.Generic; using System.Text; -using MediaBrowser.Model.Services; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Services { @@ -586,7 +584,7 @@ namespace MediaBrowser.Model.Services WriteCharBytes(bytes, ch, e); } - byte[] buf = bytes.ToArray(bytes.Count); + byte[] buf = bytes.ToArray(); bytes = null; return e.GetString(buf, 0, buf.Length); diff --git a/MediaBrowser.Model/Services/QueryParamCollection.cs b/MediaBrowser.Model/Services/QueryParamCollection.cs index 6f8a765988..4dd4303a8e 100644 --- a/MediaBrowser.Model/Services/QueryParamCollection.cs +++ b/MediaBrowser.Model/Services/QueryParamCollection.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Services { @@ -221,7 +220,7 @@ namespace MediaBrowser.Model.Services public override String ToString() { - var vals = this.Select(GetQueryStringValue).ToArray(this.Count); + var vals = this.Select(GetQueryStringValue).ToArray(); return string.Join("&", vals); } diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index c4d0c49293..f50dcf1c50 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -551,7 +551,7 @@ namespace MediaBrowser.Providers.Manager { list.Add(Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(UsCulture) + extension)); } - return list.ToArray(list.Count); + return list.ToArray(); } if (type == ImageType.Primary) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 4c9312b83b..8697c7c57a 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -522,7 +522,7 @@ namespace MediaBrowser.Providers.Manager Type = MetadataPluginType.SubtitleFetcher })); - summary.Plugins = pluginList.ToArray(pluginList.Count); + summary.Plugins = pluginList.ToArray(); var supportedImageTypes = imageProviders.OfType() .SelectMany(i => i.GetSupportedImages(dummy)) @@ -1160,4 +1160,4 @@ namespace MediaBrowser.Providers.Manager } } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs index 8a409f9cfe..12f78a950a 100644 --- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs +++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs @@ -145,7 +145,7 @@ namespace MediaBrowser.Providers.Movies movie.ProductionLocations = movieData .production_countries .Select(i => i.name) - .ToArray(movieData.production_countries.Count); + .ToArray(); } movie.SetProviderId(MetadataProviders.Tmdb, movieData.id.ToString(_usCulture)); diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index e68ce19deb..e16e6aa8ca 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -279,7 +279,7 @@ namespace MediaBrowser.Providers.Movies languages.Add("en"); } - return string.Join(",", languages.ToArray(languages.Count)); + return string.Join(",", languages.ToArray()); } public static string NormalizeLanguage(string language) diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index c676f91982..d163764265 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -17,7 +17,6 @@ using System.Threading.Tasks; using System.Xml; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Xml; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Providers.Music { @@ -846,4 +845,4 @@ namespace MediaBrowser.Providers.Music public int throttleMs { get; set; } } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs index 6e9b9b239a..7f9465f1cb 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs @@ -236,7 +236,7 @@ namespace MediaBrowser.Providers.TV if (seriesInfo.networks != null) { - series.Studios = seriesInfo.networks.Select(i => i.name).ToArray(seriesInfo.networks.Count); + series.Studios = seriesInfo.networks.Select(i => i.name).ToArray(); } if (seriesInfo.genres != null) diff --git a/Mono.Nat/Pmp/PmpNatDevice.cs b/Mono.Nat/Pmp/PmpNatDevice.cs index bf27bfebcb..dc0e2c89b5 100644 --- a/Mono.Nat/Pmp/PmpNatDevice.cs +++ b/Mono.Nat/Pmp/PmpNatDevice.cs @@ -95,7 +95,7 @@ namespace Mono.Nat.Pmp try { - byte[] buffer = package.ToArray(package.Count); + byte[] buffer = package.ToArray(); int attempt = 0; int delay = PmpConstants.RetryDelay; diff --git a/build-jellyfin.ps1 b/build-jellyfin.ps1 new file mode 100644 index 0000000000..5544df88af --- /dev/null +++ b/build-jellyfin.ps1 @@ -0,0 +1,110 @@ +[CmdletBinding()] +param( + [switch]$InstallFFMPEG, + [switch]$InstallNSSM, + [switch]$GenerateZip, + [string]$InstallLocation = "$Env:AppData/Jellyfin-Server/", + [ValidateSet('Debug','Release')][string]$BuildType = 'Release', + [ValidateSet('Quiet','Minimal', 'Normal')][string]$DotNetVerbosity = 'Minimal', + [ValidateSet('win','win7', 'win8','win81','win10')][string]$WindowsVersion = 'win', + [ValidateSet('x64','x86', 'arm', 'arm64')][string]$Architecture = 'x64' +) + +#PowershellCore and *nix check to make determine which temp dir to use. +if(($PSVersionTable.PSEdition -eq 'Core') -and (-not $IsWindows)){ + $TempDir = mktemp -d +}else{ + $TempDir = $env:Temp +} + +function Build-JellyFin { + if(($Architecture -eq 'arm64') -and ($WindowsVersion -ne 'win10')){ + Write-Error "arm64 only supported with Windows10 Version" + exit + } + if(($Architecture -eq 'arm') -and ($WindowsVersion -notin @('win10','win81','win8'))){ + Write-Error "arm only supported with Windows 8 or higher" + exit + } + dotnet publish -c $BuildType -r "$windowsversion-$Architecture" MediaBrowser.sln -o $InstallLocation -v $DotNetVerbosity +} + +function Install-FFMPEG { + param( + [string]$InstallLocation, + [string]$Architecture + ) + Write-Verbose "Checking Architecture" + if($Architecture -notin @('x86','x64')){ + Write-Warning "No builds available for your selected architecture of $Architecture" + Write-Warning "FFMPEG will not be installed" + }elseif($Architecture -eq 'x64'){ + Write-Verbose "Downloading 64 bit FFMPEG" + Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-4.1-win64-static.zip -UseBasicParsing -OutFile "$tempdir/fmmpeg.zip" | Write-Verbose + }else{ + Write-Verbose "Downloading 32 bit FFMPEG" + Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-4.1-win32-static.zip -UseBasicParsing -OutFile "$tempdir/fmmpeg.zip" | Write-Verbose + } + + Expand-Archive "$tempdir/fmmpeg.zip" -DestinationPath "$tempdir/ffmpeg/" | Write-Verbose + if($Architecture -eq 'x64'){ + Write-Verbose "Copying Binaries to Jellyfin location" + Get-ChildItem "$tempdir/ffmpeg/ffmpeg-4.1-win64-static/bin" | ForEach-Object { + Copy-Item $_.FullName -Destination $installLocation | Write-Verbose + } + }else{ + Write-Verbose "Copying Binaries to Jellyfin location" + Get-ChildItem "$tempdir/ffmpeg/ffmpeg-4.1-win32-static/bin" | ForEach-Object { + Copy-Item $_.FullName -Destination $installLocation | Write-Verbose + } + } + Remove-Item "$tempdir/ffmpeg/" -Recurse -Force -ErrorAction Continue | Write-Verbose + Remove-Item "$tempdir/fmmpeg.zip" -Force -ErrorAction Continue | Write-Verbose +} + +function Install-NSSM { + param( + [string]$InstallLocation, + [string]$Architecture + ) + Write-Verbose "Checking Architecture" + if($Architecture -notin @('x86','x64')){ + Write-Warning "No builds available for your selected architecture of $Architecture" + Write-Warning "NSSM will not be installed" + }else{ + Write-Verbose "Downloading NSSM" + Invoke-WebRequest -Uri https://nssm.cc/ci/nssm-2.24-101-g897c7ad.zip -UseBasicParsing -OutFile "$tempdir/nssm.zip" | Write-Verbose + } + + Expand-Archive "$tempdir/nssm.zip" -DestinationPath "$tempdir/nssm/" | Write-Verbose + if($Architecture -eq 'x64'){ + Write-Verbose "Copying Binaries to Jellyfin location" + Get-ChildItem "$tempdir/nssm/nssm-2.24-101-g897c7ad/win64" | ForEach-Object { + Copy-Item $_.FullName -Destination $installLocation | Write-Verbose + } + }else{ + Write-Verbose "Copying Binaries to Jellyfin location" + Get-ChildItem "$tempdir/nssm/nssm-2.24-101-g897c7ad/win32" | ForEach-Object { + Copy-Item $_.FullName -Destination $installLocation | Write-Verbose + } + } + Remove-Item "$tempdir/nssm/" -Recurse -Force -ErrorAction Continue | Write-Verbose + Remove-Item "$tempdir/nssm.zip" -Force -ErrorAction Continue | Write-Verbose +} + +Write-Verbose "Starting Build Process: Selected Environment is $WindowsVersion-$Architecture" +Build-JellyFin +if($InstallFFMPEG.IsPresent -or ($InstallFFMPEG -eq $true)){ + Write-Verbose "Starting FFMPEG Install" + Install-FFMPEG $InstallLocation $Architecture +} +if($InstallNSSM.IsPresent -or ($InstallNSSM -eq $true)){ + Write-Verbose "Starting NSSM Install" + Install-NSSM $InstallLocation $Architecture +} +Copy-Item .\install-jellyfin.ps1 $InstallLocation\install-jellyfin.ps1 +Copy-Item .\installjellyfin.bat $InstallLocation\installjellyfin.bat +if($GenerateZip.IsPresent -or ($GenerateZip -eq $true)){ + Compress-Archive -Path $InstallLocation -DestinationPath "$InstallLocation/jellyfin.zip" -Force +} +Write-Verbose "Finished" diff --git a/debian/changelog b/debian/changelog index e4176123d7..9dc21d467e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +jellyfin (3.5.2-5) unstable; urgency=medium + + * Fully GPL'd release - remove tainted code from MediaBrowser.Common + * Several code cleanups and tweaks + + -- Joshua Boniface Fri, 28 Dec 2018 10:26:30 -0500 + jellyfin (3.5.2-4) unstable; urgency=medium * Correct manifest.json bug and vdpau diff --git a/debian/jellyfin.service b/debian/jellyfin.service index d5a999cf53..4c37399092 100644 --- a/debian/jellyfin.service +++ b/debian/jellyfin.service @@ -7,8 +7,8 @@ Type = simple EnvironmentFile = /etc/default/jellyfin User = jellyfin ExecStart = /usr/bin/jellyfin -programdata ${JELLYFIN_DATA} -restartpath ${JELLYFIN_RESTART_SCRIPT} ${JELLYFIN_ADD_OPTS} -Restart = on-abort -TimeoutSec = 20 +Restart = on-failure +TimeoutSec = 15 [Install] WantedBy = multi-user.target diff --git a/debian/rules b/debian/rules index 6c915af6f4..10a3a84864 100755 --- a/debian/rules +++ b/debian/rules @@ -2,6 +2,7 @@ CONFIG := Release TERM := xterm SHELL := /bin/bash +DOTNETRUNTIME := linux-x64 export DH_VERBOSE=1 export DOTNET_CLI_TELEMETRY_OPTOUT=1 @@ -15,7 +16,7 @@ override_dh_auto_test: override_dh_clistrip: override_dh_auto_build: - dotnet publish --configuration $(CONFIG) --output='$(CURDIR)/usr/lib/jellyfin/bin' --self-contained --runtime linux-x64 + dotnet publish --configuration $(CONFIG) --output='$(CURDIR)/usr/lib/jellyfin/bin' --self-contained --runtime $(DOTNETRUNTIME) override_dh_auto_clean: dotnet clean -maxcpucount:1 --configuration $(CONFIG) || true diff --git a/install-jellyfin.ps1 b/install-jellyfin.ps1 new file mode 100644 index 0000000000..56c0984620 --- /dev/null +++ b/install-jellyfin.ps1 @@ -0,0 +1,460 @@ +[CmdletBinding()] + +param( + [Switch]$Quiet, + [Switch]$InstallAsService, + [pscredential]$ServiceUser, + [switch]$CreateDesktopShorcut, + [switch]$LaunchJellyfin, + [switch]$MigrateEmbyLibrary, + [string]$InstallLocation, + [string]$EmbyLibraryLocation, + [string]$JellyfinLibraryLocation +) +<# This form was created using POSHGUI.com a free online gui designer for PowerShell +.NAME + Install-Jellyfin +#> + +#This doesn't need to be used by default anymore, but I am keeping it in as a function for future use. +function Elevate-Window { + # Get the ID and security principal of the current user account + $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent() + $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID) + + # Get the security principal for the Administrator role + $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator + + # Check to see if we are currently running "as Administrator" + if ($myWindowsPrincipal.IsInRole($adminRole)) + { + # We are running "as Administrator" - so change the title and background color to indicate this + $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)" + $Host.UI.RawUI.BackgroundColor = "DarkBlue" + clear-host + } + else + { + # We are not running "as Administrator" - so relaunch as administrator + + # Create a new process object that starts PowerShell + $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell"; + + # Specify the current script path and name as a parameter + $newProcess.Arguments = $myInvocation.MyCommand.Definition; + + # Indicate that the process should be elevated + $newProcess.Verb = "runas"; + + # Start the new process + [System.Diagnostics.Process]::Start($newProcess); + + # Exit from the current, unelevated, process + exit + } +} + +#FIXME The install methods should be a function that takes all the params, the quiet flag should be a paramset + +if($Quiet.IsPresent -or $Quiet -eq $true){ + if([string]::IsNullOrEmpty($JellyfinLibraryLocation)){ + $Script:JellyfinDataDir = "$env:AppData\jellyfin\" + }else{ + $Script:JellyfinDataDir = $JellyfinLibraryLocation + } + if([string]::IsNullOrEmpty($InstallLocation)){ + $Script:DefaultJellyfinInstallDirectory = "$env:Appdata\jellyfin\" + }else{ + $Script:DefaultJellyfinInstallDirectory = $InstallLocation + } + + if([string]::IsNullOrEmpty($EmbyLibraryLocation)){ + $Script:defaultEmbyDataDir = "$env:Appdata\Emby-Server\data\" + }else{ + $Script:defaultEmbyDataDir = $EmbyLibraryLocation + } + + if($InstallAsService.IsPresent -or $InstallAsService -eq $true){ + $Script:InstallAsService = $true + }else{$Script:InstallAsService = $false} + if($null -eq $ServiceUser){ + $Script:InstallServiceAsUser = $false + }else{ + $Script:InstallServiceAsUser = $true + $Script:UserCredentials = $ServiceUser + $Script:JellyfinDataDir = "C:\Users\$($Script:UserCredentials.UserName)\Appdata\Roaming\jellyfin\"} + if($CreateDesktopShorcut.IsPresent -or $CreateDesktopShorcut -eq $true) {$Script:CreateShortcut = $true}else{$Script:CreateShortcut = $false} + if($MigrateEmbyLibrary.IsPresent -or $MigrateEmbyLibrary -eq $true){$Script:MigrateLibrary = $true}else{$Script:MigrateLibrary = $false} + if($LaunchJellyfin.IsPresent -or $LaunchJellyfin -eq $true){$Script:StartJellyfin = $true}else{$Script:StartJellyfin = $false} + + if(-not (Test-Path $Script:DefaultJellyfinInstallDirectory)){ + mkdir $Script:DefaultJellyfinInstallDirectory + } + Copy-Item -Path $PSScriptRoot/* -DestinationPath "$Script:DefaultJellyfinInstallDirectory/" -Force -Recurse + if($Script:InstallAsService){ + if($Script:InstallServiceAsUser){ + &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" -programdata `"$Script:JellyfinDataDir`" + Start-Sleep -Milliseconds 500 + &sc.exe config Jellyfin obj=".\$($Script:UserCredentials.UserName)" password="$($Script:UserCredentials.GetNetworkCredential().Password)" + &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START + }else{ + &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" -programdata `"$Script:JellyfinDataDir`" + Start-Sleep -Milliseconds 500 + #&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin ObjectName $Script:UserCredentials.UserName $Script:UserCredentials.GetNetworkCredential().Password + #Set-Service -Name Jellyfin -Credential $Script:UserCredentials + &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START + } + } + if($Script:MigrateLibrary){ + Copy-Item -Path $Script:defaultEmbyDataDir/config -Destination $Script:JellyfinDataDir -force -Recurse + Copy-Item -Path $Script:defaultEmbyDataDir/cache -Destination $Script:JellyfinDataDir -force -Recurse + Copy-Item -Path $Script:defaultEmbyDataDir/data -Destination $Script:JellyfinDataDir -force -Recurse + Copy-Item -Path $Script:defaultEmbyDataDir/metadata -Destination $Script:JellyfinDataDir -force -Recurse + Copy-Item -Path $Script:defaultEmbyDataDir/root -Destination $Script:JellyfinDataDir -force -Recurse + } + if($Script:CreateShortcut){ + $WshShell = New-Object -comObject WScript.Shell + $Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Jellyfin.lnk") + $Shortcut.TargetPath = "$Script:DefaultJellyfinInstallDirectory\jellyfin.exe" + $Shortcut.Save() + } + if($Script:StartJellyfin){ + if($Script:InstallAsService){ + Get-Service Jellyfin | Start-Service + }else{ + Start-Process -FilePath $Script:DefaultJellyfinInstallDirectory\jellyfin.exe -PassThru + } + } +}else{ + +} +Add-Type -AssemblyName System.Windows.Forms +[System.Windows.Forms.Application]::EnableVisualStyles() + +$Script:JellyFinDataDir = "$env:AppData\jellyfin\" +$Script:DefaultJellyfinInstallDirectory = "$env:Appdata\jellyfin\" +$Script:defaultEmbyDataDir = "$env:Appdata\Emby-Server\" +$Script:InstallAsService = $False +$Script:InstallServiceAsUser = $false +$Script:CreateShortcut = $false +$Script:MigrateLibrary = $false +$Script:StartJellyfin = $false + +function InstallJellyfin { + Write-Host "Install as service: $Script:InstallAsService" + Write-Host "Install as serviceuser: $Script:InstallServiceAsUser" + Write-Host "Create Shortcut: $Script:CreateShortcut" + Write-Host "MigrateLibrary: $Script:MigrateLibrary" + $GUIElementsCollection | ForEach-Object { + $_.Enabled = $false + } + Write-Host "Making Jellyfin directory" + $ProgressBar.Minimum = 1 + $ProgressBar.Maximum = 100 + $ProgressBar.Value = 1 + if($Script:DefaultJellyfinInstallDirectory -ne $InstallLocationBox.Text){ + Write-Host "Custom Install Location Chosen: $($InstallLocationBox.Text)" + $Script:DefaultJellyfinInstallDirectory = $InstallLocationBox.Text + } + if($Script:JellyfinDataDir -ne $CustomLibraryBox.Text){ + Write-Host "Custom Library Location Chosen: $($CustomLibraryBox.Text)" + $Script:JellyfinDataDir = $CustomLibraryBox.Text + } + if(-not (Test-Path $Script:DefaultJellyfinInstallDirectory)){ + mkdir $Script:DefaultJellyfinInstallDirectory + } + Write-Host "Copying Jellyfin Data" + $progressbar.Value = 10 + Copy-Item -Path $PSScriptRoot/* -Destination $Script:DefaultJellyfinInstallDirectory/ -Force -Recurse + Write-Host "Finished Copying" + $ProgressBar.Value = 50 + if($Script:InstallAsService){ + if($Script:InstallServiceAsUser){ + Write-Host "Installing Service as user $($Script:UserCredentials.UserName)" + &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" -programdata `"$Script:JellyfinDataDir`" + Start-Sleep -Milliseconds 2000 + &sc.exe config Jellyfin obj=".\$($Script:UserCredentials.UserName)" password="$($Script:UserCredentials.GetNetworkCredential().Password)" + &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START + }else{ + Write-Host "Installing Service as LocalSystem" + &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" -programdata `"$Script:JellyfinDataDir`" + Start-Sleep -Milliseconds 2000 + &"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START + } + } + $progressbar.Value = 60 + if($Script:MigrateLibrary){ + if($Script:defaultEmbyDataDir -ne $LibraryLocationBox.Text){ + Write-Host "Custom location defined for emby library: $($LibraryLocationBox.Text)" + $Script:defaultEmbyDataDir = $LibraryLocationBox.Text + } + Write-Host "Copying emby library from $Script:defaultEmbyDataDir to $Script:JellyFinDataDir" + Write-Host "This could take a while depending on the size of your library. Please be patient" + Write-Host "Copying config" + Copy-Item -Path $Script:defaultEmbyDataDir/config -Destination $Script:JellyfinDataDir -force -Recurse + Write-Host "Copying cache" + Copy-Item -Path $Script:defaultEmbyDataDir/cache -Destination $Script:JellyfinDataDir -force -Recurse + Write-Host "Copying data" + Copy-Item -Path $Script:defaultEmbyDataDir/data -Destination $Script:JellyfinDataDir -force -Recurse + Write-Host "Copying metadata" + Copy-Item -Path $Script:defaultEmbyDataDir/metadata -Destination $Script:JellyfinDataDir -force -Recurse + Write-Host "Copying root dir" + Copy-Item -Path $Script:defaultEmbyDataDir/root -Destination $Script:JellyfinDataDir -force -Recurse + } + $progressbar.Value = 80 + if($Script:CreateShortcut){ + Write-Host "Creating Shortcut" + $WshShell = New-Object -comObject WScript.Shell + $Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Jellyfin.lnk") + $Shortcut.TargetPath = "$Script:DefaultJellyfinInstallDirectory\jellyfin.exe" + $Shortcut.Save() + } + $ProgressBar.Value = 90 + if($Script:StartJellyfin){ + if($Script:InstallAsService){ + Write-Host "Starting Jellyfin Service" + Get-Service Jellyfin | Start-Service + }else{ + Write-Host "Starting Jellyfin" + Start-Process -FilePath $Script:DefaultJellyfinInstallDirectory\jellyfin.exe -PassThru + } + } + $progressbar.Value = 100 + Write-Host Finished + $wshell = New-Object -ComObject Wscript.Shell + $wshell.Popup("Operation Completed",0,"Done",0x1) + $InstallForm.Close() +} +function ServiceBoxCheckChanged { + if($InstallAsServiceCheck.Checked){ + $Script:InstallAsService = $true + $ServiceUserLabel.Visible = $true + $ServiceUserLabel.Enabled = $true + $ServiceUserBox.Visible = $true + $ServiceUserBox.Enabled = $true + }else{ + $Script:InstallAsService = $false + $ServiceUserLabel.Visible = $false + $ServiceUserLabel.Enabled = $false + $ServiceUserBox.Visible = $false + $ServiceUserBox.Enabled = $false + } +} +function UserSelect { + if($ServiceUserBox.Text -eq 'Local System') + { + $Script:InstallServiceAsUser = $false + $Script:UserCredentials = $null + $ServiceUserBox.Items.RemoveAt(1) + $ServiceUserBox.Items.Add("Custom User") + }elseif($ServiceUserBox.Text -eq 'Custom User'){ + $Script:InstallServiceAsUser = $true + $Script:UserCredentials = Get-Credential -Message "Please enter the credentials of the user you with to run Jellyfin Service as" -UserName $env:USERNAME + $ServiceUserBox.Items[1] = "$($Script:UserCredentials.UserName)" + } +} +function CreateShortcutBoxCheckChanged { + if($CreateShortcutCheck.Checked){ + $Script:CreateShortcut = $true + }else{ + $Script:CreateShortcut = $False + } +} +function StartJellyFinBoxCheckChanged { + if($StartProgramCheck.Checked){ + $Script:StartJellyfin = $true + }else{ + $Script:StartJellyfin = $false + } +} + +function CustomLibraryCheckChanged { + if($CustomLibraryCheck.Checked){ + $Script:UseCustomLibrary = $true + $CustomLibraryBox.Enabled = $true + }else{ + $Script:UseCustomLibrary = $false + $CustomLibraryBox.Enabled = $false + } +} + +function MigrateLibraryCheckboxChanged { + + if($MigrateLibraryCheck.Checked){ + $Script:MigrateLibrary = $true + $LibraryMigrationLabel.Visible = $true + $LibraryMigrationLabel.Enabled = $true + $LibraryLocationBox.Visible = $true + $LibraryLocationBox.Enabled = $true + }else{ + $Script:MigrateLibrary = $false + $LibraryMigrationLabel.Visible = $false + $LibraryMigrationLabel.Enabled = $false + $LibraryLocationBox.Visible = $false + $LibraryLocationBox.Enabled = $false + } + +} + + +#region begin GUI{ + +$InstallForm = New-Object system.Windows.Forms.Form +$InstallForm.ClientSize = '320,240' +$InstallForm.text = "Terrible Jellyfin Installer" +$InstallForm.TopMost = $false + +$GUIElementsCollection = @() + +$InstallButton = New-Object system.Windows.Forms.Button +$InstallButton.text = "Install" +$InstallButton.width = 60 +$InstallButton.height = 30 +$InstallButton.location = New-Object System.Drawing.Point(5,5) +$InstallButton.Font = 'Microsoft Sans Serif,10' +$GUIElementsCollection += $InstallButton + +$ProgressBar = New-Object system.Windows.Forms.ProgressBar +$ProgressBar.width = 245 +$ProgressBar.height = 30 +$ProgressBar.location = New-Object System.Drawing.Point(70,5) + +$InstallLocationLabel = New-Object system.Windows.Forms.Label +$InstallLocationLabel.text = "Install Location" +$InstallLocationLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft +$InstallLocationLabel.AutoSize = $true +$InstallLocationLabel.width = 100 +$InstallLocationLabel.height = 20 +$InstallLocationLabel.location = New-Object System.Drawing.Point(5,50) +$InstallLocationLabel.Font = 'Microsoft Sans Serif,10' +$GUIElementsCollection += $InstallLocationLabel + +$InstallLocationBox = New-Object system.Windows.Forms.TextBox +$InstallLocationBox.multiline = $false +$InstallLocationBox.width = 205 +$InstallLocationBox.height = 20 +$InstallLocationBox.location = New-Object System.Drawing.Point(110,50) +$InstallLocationBox.Text = $Script:DefaultJellyfinInstallDirectory +$InstallLocationBox.Font = 'Microsoft Sans Serif,10' +$GUIElementsCollection += $InstallLocationBox + +$CustomLibraryCheck = New-Object system.Windows.Forms.CheckBox +$CustomLibraryCheck.text = "Custom Library Location:" +$CustomLibraryCheck.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft +$CustomLibraryCheck.AutoSize = $false +$CustomLibraryCheck.width = 180 +$CustomLibraryCheck.height = 20 +$CustomLibraryCheck.location = New-Object System.Drawing.Point(5,75) +$CustomLibraryCheck.Font = 'Microsoft Sans Serif,10' +$GUIElementsCollection += $CustomLibraryCheck + +$CustomLibraryBox = New-Object system.Windows.Forms.TextBox +$CustomLibraryBox.multiline = $false +$CustomLibraryBox.width = 130 +$CustomLibraryBox.height = 20 +$CustomLibraryBox.location = New-Object System.Drawing.Point(185,75) +$CustomLibraryBox.Text = $Script:JellyFinDataDir +$CustomLibraryBox.Font = 'Microsoft Sans Serif,10' +$CustomLibraryBox.Enabled = $false +$GUIElementsCollection += $CustomLibraryBox + +$InstallAsServiceCheck = New-Object system.Windows.Forms.CheckBox +$InstallAsServiceCheck.text = "Install as Service" +$InstallAsServiceCheck.AutoSize = $false +$InstallAsServiceCheck.width = 140 +$InstallAsServiceCheck.height = 20 +$InstallAsServiceCheck.location = New-Object System.Drawing.Point(5,125) +$InstallAsServiceCheck.Font = 'Microsoft Sans Serif,10' +$GUIElementsCollection += $InstallAsServiceCheck + +$ServiceUserLabel = New-Object system.Windows.Forms.Label +$ServiceUserLabel.text = "Run Service As:" +$ServiceUserLabel.AutoSize = $true +$ServiceUserLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft +$ServiceUserLabel.width = 100 +$ServiceUserLabel.height = 20 +$ServiceUserLabel.location = New-Object System.Drawing.Point(15,145) +$ServiceUserLabel.Font = 'Microsoft Sans Serif,10' +$ServiceUserLabel.Visible = $false +$ServiceUserLabel.Enabled = $false +$GUIElementsCollection += $ServiceUserLabel + +$ServiceUserBox = New-Object system.Windows.Forms.ComboBox +$ServiceUserBox.text = "Run Service As" +$ServiceUserBox.width = 195 +$ServiceUserBox.height = 20 +@('Local System','Custom User') | ForEach-Object {[void] $ServiceUserBox.Items.Add($_)} +$ServiceUserBox.location = New-Object System.Drawing.Point(120,145) +$ServiceUserBox.Font = 'Microsoft Sans Serif,10' +$ServiceUserBox.Visible = $false +$ServiceUserBox.Enabled = $false +$ServiceUserBox.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList +$GUIElementsCollection += $ServiceUserBox + +$MigrateLibraryCheck = New-Object system.Windows.Forms.CheckBox +$MigrateLibraryCheck.text = "Import Emby Library" +$MigrateLibraryCheck.AutoSize = $false +$MigrateLibraryCheck.width = 160 +$MigrateLibraryCheck.height = 20 +$MigrateLibraryCheck.location = New-Object System.Drawing.Point(5,170) +$MigrateLibraryCheck.Font = 'Microsoft Sans Serif,10' +$GUIElementsCollection += $MigrateLibraryCheck + +$LibraryMigrationLabel = New-Object system.Windows.Forms.Label +$LibraryMigrationLabel.text = "Emby Library Path" +$LibraryMigrationLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft +$LibraryMigrationLabel.AutoSize = $false +$LibraryMigrationLabel.width = 120 +$LibraryMigrationLabel.height = 20 +$LibraryMigrationLabel.location = New-Object System.Drawing.Point(15,190) +$LibraryMigrationLabel.Font = 'Microsoft Sans Serif,10' +$LibraryMigrationLabel.Visible = $false +$LibraryMigrationLabel.Enabled = $false +$GUIElementsCollection += $LibraryMigrationLabel + +$LibraryLocationBox = New-Object system.Windows.Forms.TextBox +$LibraryLocationBox.multiline = $false +$LibraryLocationBox.width = 175 +$LibraryLocationBox.height = 20 +$LibraryLocationBox.location = New-Object System.Drawing.Point(140,190) +$LibraryLocationBox.Text = $Script:defaultEmbyDataDir +$LibraryLocationBox.Font = 'Microsoft Sans Serif,10' +$LibraryLocationBox.Visible = $false +$LibraryLocationBox.Enabled = $false +$GUIElementsCollection += $LibraryLocationBox + +$CreateShortcutCheck = New-Object system.Windows.Forms.CheckBox +$CreateShortcutCheck.text = "Desktop Shortcut" +$CreateShortcutCheck.AutoSize = $false +$CreateShortcutCheck.width = 150 +$CreateShortcutCheck.height = 20 +$CreateShortcutCheck.location = New-Object System.Drawing.Point(5,215) +$CreateShortcutCheck.Font = 'Microsoft Sans Serif,10' +$GUIElementsCollection += $CreateShortcutCheck + +$StartProgramCheck = New-Object system.Windows.Forms.CheckBox +$StartProgramCheck.text = "Start Jellyfin" +$StartProgramCheck.AutoSize = $false +$StartProgramCheck.width = 160 +$StartProgramCheck.height = 20 +$StartProgramCheck.location = New-Object System.Drawing.Point(160,215) +$StartProgramCheck.Font = 'Microsoft Sans Serif,10' +$GUIElementsCollection += $StartProgramCheck + +$InstallForm.controls.AddRange($GUIElementsCollection) +$InstallForm.Controls.Add($ProgressBar) + +#region gui events { +$InstallButton.Add_Click({ InstallJellyfin }) +$CustomLibraryCheck.Add_CheckedChanged({CustomLibraryCheckChanged}) +$InstallAsServiceCheck.Add_CheckedChanged({ServiceBoxCheckChanged}) +$ServiceUserBox.Add_SelectedValueChanged({ UserSelect }) +$MigrateLibraryCheck.Add_CheckedChanged({MigrateLibraryCheckboxChanged}) +$CreateShortcutCheck.Add_CheckedChanged({CreateShortcutBoxCheckChanged}) +$StartProgramCheck.Add_CheckedChanged({StartJellyFinBoxCheckChanged}) +#endregion events } + +#endregion GUI } + + +[void]$InstallForm.ShowDialog() \ No newline at end of file diff --git a/install.bat b/install.bat new file mode 100644 index 0000000000..e21479a79a --- /dev/null +++ b/install.bat @@ -0,0 +1 @@ +powershell.exe -executionpolicy Bypass -file install-jellyfin.ps1 diff --git a/new-file-header.txt b/new-file-header.txt new file mode 100644 index 0000000000..4247a8e246 --- /dev/null +++ b/new-file-header.txt @@ -0,0 +1,22 @@ +### This header should be used to start new files. +### It provides an explicit per-file license reference that should be present on all new files. +### To use this header, delete these lines and the following empty line, modify to +### the proper full path, and then add new code following the header and a single empty line. + +// +// Part of the Jellyfin project (https://jellyfin.media) +// +// All copyright belongs to the Jellyfin contributors; a full list can +// be found in the file CONTRIBUTORS.md +// +// 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, version 2. +// +// 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, see .