예제 #1
0
        public async Task <Stream> GetListingsStream(TunerHostInfo info, CancellationToken cancellationToken)
        {
            if (info == null)
            {
                throw new ArgumentNullException(nameof(info));
            }

            if (!info.Url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
            {
                return(AsyncFile.OpenRead(info.Url));
            }

            using var requestMessage = new HttpRequestMessage(HttpMethod.Get, info.Url);
            if (!string.IsNullOrEmpty(info.UserAgent))
            {
                requestMessage.Headers.UserAgent.TryParseAdd(info.UserAgent);
            }

            // Set HttpCompletionOption.ResponseHeadersRead to prevent timeouts on larger files
            var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                           .SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, cancellationToken)
                           .ConfigureAwait(false);

            response.EnsureSuccessStatusCode();

            return(await response.Content.ReadAsStreamAsync(cancellationToken));
        }
예제 #2
0
        internal async Task <SeasonRootObject> GetSeasonRootObject(string imdbId, int seasonId, CancellationToken cancellationToken)
        {
            var path = await EnsureSeasonInfo(imdbId, seasonId, cancellationToken).ConfigureAwait(false);

            await using var stream = AsyncFile.OpenRead(path);
            return(await JsonSerializer.DeserializeAsync <SeasonRootObject>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false));
        }
예제 #3
0
        /// <summary>
        /// Sets the ass font.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <c>System.Threading.CancellationToken.None</c>.</param>
        /// <returns>Task.</returns>
        private async Task SetAssFont(string file, CancellationToken cancellationToken = default)
        {
            _logger.LogInformation("Setting ass font within {File}", file);

            string   text;
            Encoding encoding;

            using (var fileStream = AsyncFile.OpenRead(file))
                using (var reader = new StreamReader(fileStream, true))
                {
                    encoding = reader.CurrentEncoding;

                    text = await reader.ReadToEndAsync().ConfigureAwait(false);
                }

            var newText = text.Replace(",Arial,", ",Arial Unicode MS,", StringComparison.Ordinal);

            if (!string.Equals(text, newText, StringComparison.Ordinal))
            {
                var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
                var writer     = new StreamWriter(fileStream, encoding);
                await using (fileStream.ConfigureAwait(false))
                    await using (writer.ConfigureAwait(false))
                    {
                        await writer.WriteAsync(newText.AsMemory(), cancellationToken).ConfigureAwait(false);
                    }
            }
        }
예제 #4
0
 private async Task<Stream> GetAttachmentStream(
     MediaSourceInfo mediaSource,
     MediaAttachment mediaAttachment,
     CancellationToken cancellationToken)
 {
     var attachmentPath = await GetReadableFile(mediaSource.Path, mediaSource.Path, mediaSource, mediaAttachment, cancellationToken).ConfigureAwait(false);
     return AsyncFile.OpenRead(attachmentPath);
 }
예제 #5
0
        /// <inheritdoc />
        public async Task ProcessImage(ImageProcessingOptions options, Stream toStream)
        {
            var file = await ProcessImage(options).ConfigureAwait(false);

            using (var fileStream = AsyncFile.OpenRead(file.Path))
            {
                await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
            }
        }
예제 #6
0
 public async Task Test(string fileName)
 {
     var path = Path.Join("Test Data", fileName);
     await using (var stream = AsyncFile.OpenRead(path))
     {
         var res = await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream, JsonDefaults.Options).ConfigureAwait(false);
         Assert.NotNull(res);
     }
 }
예제 #7
0
        public Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int?imageIndex, bool?saveLocallyWithMedia, CancellationToken cancellationToken)
        {
            if (string.IsNullOrWhiteSpace(source))
            {
                throw new ArgumentNullException(nameof(source));
            }

            var fileStream = AsyncFile.OpenRead(source);

            return(new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken));
        }
예제 #8
0
        public async Task <List <ChannelInfo> > GetChannels(bool enableCache, CancellationToken cancellationToken)
        {
            var list = new List <ChannelInfo>();

            var hosts = GetTunerHosts();

            foreach (var host in hosts)
            {
                var channelCacheFile = Path.Combine(Config.ApplicationPaths.CachePath, host.Id + "_channels");

                try
                {
                    var channels = await GetChannels(host, enableCache, cancellationToken).ConfigureAwait(false);

                    var newChannels = channels.Where(i => !list.Any(l => string.Equals(i.Id, l.Id, StringComparison.OrdinalIgnoreCase))).ToList();

                    list.AddRange(newChannels);

                    if (!enableCache)
                    {
                        try
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(channelCacheFile));
                            await using var writeStream = AsyncFile.OpenWrite(channelCacheFile);
                            await JsonSerializer.SerializeAsync(writeStream, channels, cancellationToken : cancellationToken).ConfigureAwait(false);
                        }
                        catch (IOException)
                        {
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex, "Error getting channel list");

                    if (enableCache)
                    {
                        try
                        {
                            await using var readStream = AsyncFile.OpenRead(channelCacheFile);
                            var channels = await JsonSerializer.DeserializeAsync <List <ChannelInfo> >(readStream, cancellationToken : cancellationToken)
                                           .ConfigureAwait(false);

                            list.AddRange(channels);
                        }
                        catch (IOException)
                        {
                        }
                    }
                }
            }

            return(list);
        }
예제 #9
0
        /// <inheritdoc />
        public async Task <PinRedeemResult> RedeemPasswordResetPin(string pin)
        {
            var userManager = _appHost.Resolve <IUserManager>();
            var usersReset  = new List <string>();

            foreach (var resetFile in Directory.EnumerateFiles(_passwordResetFileBaseDir, $"{BaseResetFileName}*"))
            {
                SerializablePasswordReset spr;
                await using (var str = AsyncFile.OpenRead(resetFile))
                {
                    spr = await JsonSerializer.DeserializeAsync <SerializablePasswordReset>(str).ConfigureAwait(false)
                          ?? throw new ResourceNotFoundException($"Provided path ({resetFile}) is not valid.");
                }

                if (spr.ExpirationDate < DateTime.UtcNow)
                {
                    File.Delete(resetFile);
                }
                else if (string.Equals(
                             spr.Pin.Replace("-", string.Empty, StringComparison.Ordinal),
                             pin.Replace("-", string.Empty, StringComparison.Ordinal),
                             StringComparison.OrdinalIgnoreCase))
                {
                    var resetUser = userManager.GetUserByName(spr.UserName)
                                    ?? throw new ResourceNotFoundException($"User with a username of {spr.UserName} not found");

                    await userManager.ChangePassword(resetUser, pin).ConfigureAwait(false);

                    usersReset.Add(resetUser.Username);
                    File.Delete(resetFile);
                }
            }

            if (usersReset.Count < 1)
            {
                throw new ResourceNotFoundException($"No Users found with a password reset request matching pin {pin}");
            }

            return(new PinRedeemResult
            {
                Success = true,
                UsersReset = usersReset.ToArray()
            });
        }
예제 #10
0
        private async Task <Stream> GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken)
        {
            switch (protocol)
            {
            case MediaProtocol.Http:
            {
                using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                                     .GetAsync(new Uri(path), cancellationToken)
                                     .ConfigureAwait(false);

                return(await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false));
            }

            case MediaProtocol.File:
                return(AsyncFile.OpenRead(path));

            default:
                throw new ArgumentOutOfRangeException(nameof(protocol));
            }
        }
예제 #11
0
        public async Task <IEnumerable <RemoteImageInfo> > GetImages(BaseItem item, CancellationToken cancellationToken)
        {
            var id = item.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup);

            if (!string.IsNullOrWhiteSpace(id))
            {
                await AudioDbAlbumProvider.Current.EnsureInfo(id, cancellationToken).ConfigureAwait(false);

                var path = AudioDbAlbumProvider.GetAlbumInfoPath(_config.ApplicationPaths, id);

                await using FileStream jsonStream = AsyncFile.OpenRead(path);
                var obj = await JsonSerializer.DeserializeAsync <AudioDbAlbumProvider.RootObject>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);

                if (obj != null && obj.album != null && obj.album.Count > 0)
                {
                    return(GetImages(obj.album[0]));
                }
            }

            return(new List <RemoteImageInfo>());
        }
예제 #12
0
        private async Task <Stream> GetSubtitleStream(SubtitleInfo fileInfo, CancellationToken cancellationToken)
        {
            if (fileInfo.IsExternal)
            {
                using (var stream = await GetStream(fileInfo.Path, fileInfo.Protocol, cancellationToken).ConfigureAwait(false))
                {
                    var result = CharsetDetector.DetectFromStream(stream).Detected;
                    stream.Position = 0;

                    if (result != null)
                    {
                        _logger.LogDebug("charset {CharSet} detected for {Path}", result.EncodingName, fileInfo.Path);

                        using var reader = new StreamReader(stream, result.Encoding);
                        var text = await reader.ReadToEndAsync().ConfigureAwait(false);

                        return(new MemoryStream(Encoding.UTF8.GetBytes(text)));
                    }
                }
            }

            return(AsyncFile.OpenRead(fileInfo.Path));
        }
예제 #13
0
        public async Task <MetadataResult <MusicAlbum> > GetMetadata(AlbumInfo info, CancellationToken cancellationToken)
        {
            var result = new MetadataResult <MusicAlbum>();
            var id     = info.GetReleaseGroupId();

            if (!string.IsNullOrWhiteSpace(id))
            {
                await EnsureInfo(id, cancellationToken).ConfigureAwait(false);

                var path = GetAlbumInfoPath(_config.ApplicationPaths, id);

                await using FileStream jsonStream = AsyncFile.OpenRead(path);
                var obj = await JsonSerializer.DeserializeAsync <RootObject>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);

                if (obj != null && obj.album != null && obj.album.Count > 0)
                {
                    result.Item        = new MusicAlbum();
                    result.HasMetadata = true;
                    ProcessResult(result.Item, obj.album[0], info.MetadataLanguage);
                }
            }

            return(result);
        }
예제 #14
0
        public ActionResult GetGeneralImage([FromRoute, Required] string name, [FromRoute, Required] string type)
        {
            var filename = string.Equals(type, "primary", StringComparison.OrdinalIgnoreCase)
                ? "folder"
                : type;

            var path = BaseItem.SupportedImageExtensions
                       .Select(i => Path.GetFullPath(Path.Combine(_applicationPaths.GeneralPath, name, filename + i)))
                       .FirstOrDefault(System.IO.File.Exists);

            if (path == null)
            {
                return(NotFound());
            }

            if (!path.StartsWith(_applicationPaths.GeneralPath))
            {
                return(BadRequest("Invalid image path."));
            }

            var contentType = MimeTypes.GetMimeType(path);

            return(File(AsyncFile.OpenRead(path), contentType));
        }
예제 #15
0
        public async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, string cacheKey, bool addProbeDelay, CancellationToken cancellationToken)
        {
            var originalRuntime = mediaSource.RunTimeTicks;

            var now = DateTime.UtcNow;

            MediaInfo mediaInfo     = null;
            var       cacheFilePath = string.IsNullOrEmpty(cacheKey) ? null : Path.Combine(_appPaths.CachePath, "mediainfo", cacheKey.GetMD5().ToString("N", CultureInfo.InvariantCulture) + ".json");

            if (!string.IsNullOrEmpty(cacheKey))
            {
                try
                {
                    await using FileStream jsonStream = AsyncFile.OpenRead(cacheFilePath);
                    mediaInfo = await JsonSerializer.DeserializeAsync <MediaInfo>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);

                    // _logger.LogDebug("Found cached media info");
                }
                catch
                {
                }
            }

            if (mediaInfo == null)
            {
                if (addProbeDelay)
                {
                    var delayMs = mediaSource.AnalyzeDurationMs ?? 0;
                    delayMs = Math.Max(3000, delayMs);
                    _logger.LogInformation("Waiting {0}ms before probing the live stream", delayMs);
                    await Task.Delay(delayMs, cancellationToken).ConfigureAwait(false);
                }

                mediaSource.AnalyzeDurationMs = 3000;

                mediaInfo = await _mediaEncoder.GetMediaInfo(
                    new MediaInfoRequest
                {
                    MediaSource     = mediaSource,
                    MediaType       = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
                    ExtractChapters = false
                },
                    cancellationToken).ConfigureAwait(false);

                if (cacheFilePath != null)
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
                    await using FileStream createStream = AsyncFile.OpenWrite(cacheFilePath);
                    await JsonSerializer.SerializeAsync(createStream, mediaInfo, _jsonOptions, cancellationToken).ConfigureAwait(false);

                    // _logger.LogDebug("Saved media info to {0}", cacheFilePath);
                }
            }

            var mediaStreams = mediaInfo.MediaStreams;

            if (!string.IsNullOrEmpty(cacheKey))
            {
                var newList = new List <MediaStream>();
                newList.AddRange(mediaStreams.Where(i => i.Type == MediaStreamType.Video).Take(1));
                newList.AddRange(mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Take(1));

                foreach (var stream in newList)
                {
                    stream.Index    = -1;
                    stream.Language = null;
                }

                mediaStreams = newList;
            }

            _logger.LogInformation("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture));

            mediaSource.Bitrate       = mediaInfo.Bitrate;
            mediaSource.Container     = mediaInfo.Container;
            mediaSource.Formats       = mediaInfo.Formats;
            mediaSource.MediaStreams  = mediaStreams;
            mediaSource.RunTimeTicks  = mediaInfo.RunTimeTicks;
            mediaSource.Size          = mediaInfo.Size;
            mediaSource.Timestamp     = mediaInfo.Timestamp;
            mediaSource.Video3DFormat = mediaInfo.Video3DFormat;
            mediaSource.VideoType     = mediaInfo.VideoType;

            mediaSource.DefaultSubtitleStreamIndex = null;

            // Null this out so that it will be treated like a live stream
            if (!originalRuntime.HasValue)
            {
                mediaSource.RunTimeTicks = null;
            }

            var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);

            if (audioStream == null || audioStream.Index == -1)
            {
                mediaSource.DefaultAudioStreamIndex = null;
            }
            else
            {
                mediaSource.DefaultAudioStreamIndex = audioStream.Index;
            }

            var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);

            if (videoStream != null)
            {
                if (!videoStream.BitRate.HasValue)
                {
                    var width = videoStream.Width ?? 1920;

                    if (width >= 3000)
                    {
                        videoStream.BitRate = 30000000;
                    }
                    else if (width >= 1900)
                    {
                        videoStream.BitRate = 20000000;
                    }
                    else if (width >= 1200)
                    {
                        videoStream.BitRate = 8000000;
                    }
                    else if (width >= 700)
                    {
                        videoStream.BitRate = 2000000;
                    }
                }

                // This is coming up false and preventing stream copy
                videoStream.IsAVC = null;
            }

            mediaSource.AnalyzeDurationMs = 3000;

            // Try to estimate this
            mediaSource.InferTotalBitrate(true);
        }
예제 #16
0
        private async Task RefreshFromProvider(
            BaseItem item,
            IDynamicImageProvider provider,
            ImageRefreshOptions refreshOptions,
            TypeOptions savedOptions,
            ICollection <ImageType> downloadedImages,
            RefreshResult result,
            CancellationToken cancellationToken)
        {
            try
            {
                var images = provider.GetSupportedImages(item);

                foreach (var imageType in images)
                {
                    if (!savedOptions.IsEnabled(imageType))
                    {
                        continue;
                    }

                    if (!item.HasImage(imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
                    {
                        _logger.LogDebug("Running {Provider} for {Item}", provider.GetType().Name, item.Path ?? item.Name);

                        var response = await provider.GetImage(item, imageType, cancellationToken).ConfigureAwait(false);

                        if (response.HasImage)
                        {
                            if (string.IsNullOrEmpty(response.Path))
                            {
                                var mimeType = response.Format.GetMimeType();

                                await _providerManager.SaveImage(item, response.Stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false);
                            }
                            else
                            {
                                if (response.Protocol == MediaProtocol.Http)
                                {
                                    _logger.LogDebug("Setting image url into item {Item}", item.Id);
                                    var index = item.AllowsMultipleImages(imageType) ? item.GetImages(imageType).Count() : 0;
                                    item.SetImage(
                                        new ItemImageInfo
                                    {
                                        Path = response.Path,
                                        Type = imageType
                                    },
                                        index);
                                }
                                else
                                {
                                    var mimeType = MimeTypes.GetMimeType(response.Path);

                                    var stream = AsyncFile.OpenRead(response.Path);

                                    await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false);
                                }
                            }

                            downloadedImages.Add(imageType);
                            result.UpdateType |= ItemUpdateType.ImageUpdate;
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                result.ErrorMessage = ex.Message;
                _logger.LogError(ex, "Error in {Provider}", provider.Name);
            }
        }