/// <summary>
        /// Finds vob files and populates the dvd stream file properties
        /// </summary>
        /// <param name="video">The video.</param>
        /// <param name="isoMount">The iso mount.</param>
        private void PopulateDvdStreamFiles(Video video, IIsoMount isoMount)
        {
            // min size 300 mb
            const long minPlayableSize = 314572800;

            var root = isoMount != null ? isoMount.MountedPath : video.Path;

            // Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size
            // Once we reach a file that is at least the minimum, return all subsequent ones
            var files = Directory.EnumerateFiles(root, "*.vob", SearchOption.AllDirectories).SkipWhile(f => new FileInfo(f).Length < minPlayableSize).ToList();

            // Assuming they're named "vts_05_01", take all files whose second part matches that of the first file
            if (files.Count > 0)
            {
                var parts = Path.GetFileNameWithoutExtension(files[0]).Split('_');

                if (parts.Length == 3)
                {
                    var title = parts[1];

                    files = files.TakeWhile(f =>
                    {
                        var fileParts = Path.GetFileNameWithoutExtension(f).Split('_');

                        return(fileParts.Length == 3 && string.Equals(title, fileParts[1], StringComparison.OrdinalIgnoreCase));
                    }).ToList();
                }
            }

            video.PlayableStreamFileNames = files.Select(Path.GetFileName).ToList();
        }
예제 #2
0
        private async Task <PlayableItem> GetPlayableItem(BaseItemDto item, long?startTimeTicks, CancellationToken cancellationToken)
        {
            IIsoMount mountedIso = null;

            if (item.VideoType.HasValue && item.VideoType.Value == VideoType.Iso && item.IsoType.HasValue && _isoManager.CanMount(item.Path))
            {
                try
                {
                    mountedIso = await _isoManager.Mount(item.Path, cancellationToken);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error mounting iso {0}", ex, item.Path);
                }
            }

            var apiClient    = _connectionManager.GetApiClient(item);
            var mediaSources = item.MediaSources;

            try
            {
                var result = await apiClient.GetLiveMediaInfo(item.Id, apiClient.CurrentUserId);

                mediaSources = result.MediaSources;
            }
            catch
            {
            }

            return(PlayablePathBuilder.GetPlayableItem(item, mediaSources, mountedIso, apiClient, startTimeTicks, _config.Configuration.MaxStreamingBitrate));
        }
예제 #3
0
        async void process_Exited(object sender, EventArgs e)
        {
            var process = (Process)sender;

            if (_isoMount != null)
            {
                _isoMount.Dispose();
                _isoMount = null;
            }

            DisposeLogFileStream();

            try
            {
                _logger.Info("FFMpeg exited with code {0} for {1}", process.ExitCode, _task.Request.OutputPath);
            }
            catch
            {
                _logger.Info("FFMpeg exited with an error for {0}", _task.Request.OutputPath);
            }

            _task.OnCompleted();

            if (!string.IsNullOrEmpty(_task.LiveTvStreamId))
            {
                try
                {
                    await _liveTvManager.CloseLiveStream(_task.LiveTvStreamId, CancellationToken.None).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error closing live tv stream", ex);
                }
            }
        }
예제 #4
0
        private async Task <Model.MediaInfo.MediaInfo> GetMediaInfo(Video item,
                                                                    IIsoMount isoMount,
                                                                    CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var protocol = item.LocationType == LocationType.Remote
                ? MediaProtocol.Http
                : MediaProtocol.File;

            var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
            {
                PlayableStreamFileNames = item.PlayableStreamFileNames,
                MountedIso      = isoMount,
                ExtractChapters = true,
                VideoType       = item.VideoType,
                MediaType       = DlnaProfileType.Video,
                InputPath       = item.Path,
                Protocol        = protocol
            }, cancellationToken).ConfigureAwait(false);

            //Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
            //_json.SerializeToFile(result, cachePath);

            return(result);
        }
예제 #5
0
        private async Task <InternalMediaInfoResult> GetMediaInfo(Video item,
                                                                  IIsoMount isoMount,
                                                                  CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var idString  = item.Id.ToString("N");
            var cachePath = Path.Combine(_appPaths.CachePath,
                                         "ffprobe-video",
                                         idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");

            try
            {
                return(_json.DeserializeFromFile <InternalMediaInfoResult>(cachePath));
            }
            catch (FileNotFoundException)
            {
            }
            catch (DirectoryNotFoundException)
            {
            }

            var protocol = item.LocationType == LocationType.Remote
                ? MediaProtocol.Http
                : MediaProtocol.File;

            var inputPath = MediaEncoderHelpers.GetInputArgument(item.Path, protocol, isoMount, item.PlayableStreamFileNames);

            var result = await _mediaEncoder.GetMediaInfo(inputPath, protocol, false, cancellationToken).ConfigureAwait(false);

            Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
            _json.SerializeToFile(result, cachePath);

            return(result);
        }
예제 #6
0
        /// <summary>
        /// Gets the playable path.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="apiClient">The API client.</param>
        /// <param name="startTimeTicks">The start time ticks.</param>
        /// <returns>System.String.</returns>
        public static string GetPlayablePath(BaseItemDto item, IIsoMount isoMount, IApiClient apiClient, long? startTimeTicks)
        {
            // Check the mounted path first
            if (isoMount != null)
            {
                if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay)
                {
                    return GetBlurayPath(isoMount.MountedPath);
                }

                return isoMount.MountedPath;
            }

            // Stream remote items through the api
            if (item.LocationType == LocationType.Remote)
            {
                return GetStreamedPath(item, apiClient, startTimeTicks);
            }

            // Stream if we can't access the file system
            if (!File.Exists(item.Path) && !Directory.Exists(item.Path))
            {
                return GetStreamedPath(item, apiClient, startTimeTicks);
            }

            if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay)
            {
                return GetBlurayPath(item.Path);
            }

            return item.Path;
        }
        /// <summary>
        /// Gets the playable path.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="apiClient">The API client.</param>
        /// <param name="startTimeTicks">The start time ticks.</param>
        /// <returns>System.String.</returns>
        public static string GetPlayablePath(BaseItemDto item, IIsoMount isoMount, IApiClient apiClient, long? startTimeTicks, int? maxBitrate)
        {
            // Check the mounted path first
            if (isoMount != null)
            {
                if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay)
                {
                    return GetBlurayPath(isoMount.MountedPath);
                }

                return isoMount.MountedPath;
            }

            if (item.LocationType == LocationType.FileSystem)
            {
                if (File.Exists(item.Path) || Directory.Exists(item.Path))
                {
                    if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay)
                    {
                        return GetBlurayPath(item.Path);
                    }

                    return item.Path;
                }
            }

            return GetStreamedPath(item, apiClient, startTimeTicks, maxBitrate);
        }
예제 #8
0
        /// <summary>
        /// Finds vob files and populates the dvd stream file properties
        /// </summary>
        /// <param name="video">The video.</param>
        /// <param name="isoMount">The iso mount.</param>
        private void PopulateDvdStreamFiles(Video video, IIsoMount isoMount)
        {
            // min size 300 mb
            const long minPlayableSize = 314572800;

            var root = isoMount != null ? isoMount.MountedPath : video.Path;

            // Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size
            // Once we reach a file that is at least the minimum, return all subsequent ones
            video.PlayableStreamFileNames = Directory.EnumerateFiles(root, "*.vob", SearchOption.AllDirectories).SkipWhile(f => new FileInfo(f).Length < minPlayableSize).Select(Path.GetFileName).ToList();
        }
예제 #9
0
        /// <summary>
        /// Gets the input argument.
        /// </summary>
        /// <param name="fileSystem">The file system.</param>
        /// <param name="videoPath">The video path.</param>
        /// <param name="protocol">The protocol.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="playableStreamFileNames">The playable stream file names.</param>
        /// <returns>System.String[][].</returns>
        public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, MediaProtocol protocol, IIsoMount isoMount, List<string> playableStreamFileNames)
        {
            if (playableStreamFileNames.Count > 0)
            {
                if (isoMount == null)
                {
                    return GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames).ToArray();
                }
                return GetPlayableStreamFiles(fileSystem, isoMount.MountedPath, playableStreamFileNames).ToArray();
            }

            return new[] {videoPath};
        }
        /// <summary>
        /// Called when [pre fetch].
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="mount">The mount.</param>
        protected override void OnPreFetch(Video item, IIsoMount mount)
        {
            if (item.VideoType == VideoType.Iso)
            {
                item.IsoType = DetermineIsoType(mount);
            }

            if (item.VideoType == VideoType.Dvd || (item.IsoType.HasValue && item.IsoType == IsoType.Dvd))
            {
                PopulateDvdStreamFiles(item, mount);
            }

            base.OnPreFetch(item, mount);
        }
        /// <summary>
        /// Determines the type of the iso.
        /// </summary>
        /// <param name="isoMount">The iso mount.</param>
        /// <returns>System.Nullable{IsoType}.</returns>
        private IsoType?DetermineIsoType(IIsoMount isoMount)
        {
            var folders = Directory.EnumerateDirectories(isoMount.MountedPath).Select(Path.GetFileName).ToList();

            if (folders.Contains("video_ts", StringComparer.OrdinalIgnoreCase))
            {
                return(IsoType.Dvd);
            }
            if (folders.Contains("bdmv", StringComparer.OrdinalIgnoreCase))
            {
                return(IsoType.BluRay);
            }

            return(null);
        }
예제 #12
0
        /// <summary>
        /// Gets the input argument.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="mount">The mount.</param>
        /// <returns>System.String.</returns>
        public string GetInputArgument(Video item, IIsoMount mount)
        {
            if (item.VideoType == VideoType.Iso && item.IsoType.HasValue)
            {
                if (item.IsoType.Value == IsoType.BluRay)
                {
                    return(GetBlurayInputArgument(mount.MountedPath));
                }
                if (item.IsoType.Value == IsoType.Dvd)
                {
                    return(GetDvdInputArgument(item.GetPlayableStreamFiles(mount.MountedPath)));
                }
            }

            return(GetInputArgument(item));
        }
예제 #13
0
        /// <summary>
        /// Gets the media info.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task{MediaInfoResult}.</returns>
        /// <exception cref="System.ArgumentNullException">inputPath
        /// or
        /// cache</exception>
        protected async Task <MediaInfoResult> GetMediaInfo(BaseItem item, IIsoMount isoMount, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var type      = InputType.AudioFile;
            var inputPath = isoMount == null ? new[] { item.Path } : new[] { isoMount.MountedPath };

            var video = item as Video;

            if (video != null)
            {
                inputPath = MediaEncoderHelpers.GetInputArgument(video, isoMount, out type);
            }

            return(await MediaEncoder.GetMediaInfo(inputPath, type, cancellationToken).ConfigureAwait(false));
        }
예제 #14
0
        /// <summary>
        /// Determines the type of the iso.
        /// </summary>
        /// <param name="isoMount">The iso mount.</param>
        /// <returns>System.Nullable{IsoType}.</returns>
        private IsoType?DetermineIsoType(IIsoMount isoMount)
        {
            var fileSystemEntries = _fileSystem.GetFileSystemEntryPaths(isoMount.MountedPath).Select(Path.GetFileName).ToList();

            if (fileSystemEntries.Contains("video_ts", StringComparer.OrdinalIgnoreCase) ||
                fileSystemEntries.Contains("VIDEO_TS.IFO", StringComparer.OrdinalIgnoreCase))
            {
                return(IsoType.Dvd);
            }
            if (fileSystemEntries.Contains("bdmv", StringComparer.OrdinalIgnoreCase))
            {
                return(IsoType.BluRay);
            }

            return(null);
        }
예제 #15
0
        /// <summary>
        /// Gets the input argument.
        /// </summary>
        /// <param name="video">The video.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="type">The type.</param>
        /// <returns>System.String[][].</returns>
        public static string[] GetInputArgument(Video video, IIsoMount isoMount, out InputType type)
        {
            var inputPath = isoMount == null ? new[] { video.Path } : new[] { isoMount.MountedPath };

            type = InputType.VideoFile;

            switch (video.VideoType)
            {
            case VideoType.BluRay:
                type = InputType.Bluray;
                break;

            case VideoType.Dvd:
                type      = InputType.Dvd;
                inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray();
                break;

            case VideoType.Iso:
                if (video.IsoType.HasValue)
                {
                    switch (video.IsoType.Value)
                    {
                    case IsoType.BluRay:
                        type = InputType.Bluray;
                        break;

                    case IsoType.Dvd:
                        type      = InputType.Dvd;
                        inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray();
                        break;
                    }
                }
                break;

            case VideoType.VideoFile:
            {
                if (video.LocationType == LocationType.Remote)
                {
                    type = InputType.Url;
                }
                break;
            }
            }

            return(inputPath);
        }
예제 #16
0
        /// <summary>
        /// Called when [pre fetch].
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="mount">The mount.</param>
        /// <param name="blurayDiscInfo">The bluray disc information.</param>
        private void OnPreFetch(Video item, IIsoMount mount, BlurayDiscInfo blurayDiscInfo)
        {
            if (item.VideoType == VideoType.Iso)
            {
                item.IsoType = DetermineIsoType(mount);
            }

            if (item.VideoType == VideoType.Dvd || (item.IsoType.HasValue && item.IsoType == IsoType.Dvd))
            {
                FetchFromDvdLib(item, mount);
            }

            if (item.VideoType == VideoType.BluRay || (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay))
            {
                item.PlayableStreamFileNames = blurayDiscInfo.Files.ToList();
            }
        }
예제 #17
0
        /// <summary>
        /// Gets the input argument.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <returns>System.String.</returns>
        protected string GetInputArgument(BaseItem item, IIsoMount isoMount)
        {
            var type = InputType.AudioFile;

            var inputPath = new[] { item.Path };

            var video = item as Video;

            if (video != null)
            {
                if (!(video.VideoType == VideoType.Iso && isoMount == null))
                {
                    inputPath = MediaEncoderHelpers.GetInputArgument(video, isoMount, out type);
                }
            }

            return(MediaEncoder.GetInputArgument(inputPath, type));
        }
예제 #18
0
        private async Task <IIsoMount> GetIsoMount(BaseItemDto item, CancellationToken cancellationToken)
        {
            IIsoMount mountedIso = null;

            if (item.VideoType.HasValue && item.VideoType.Value == VideoType.Iso && item.IsoType.HasValue && _isoManager.CanMount(item.Path))
            {
                try
                {
                    mountedIso = await _isoManager.Mount(item.Path, cancellationToken);
                }
                catch (Exception ex)
                {
                    Logger.ErrorException("Error mounting iso {0}", ex, item.Path);
                }
            }

            return(mountedIso);
        }
예제 #19
0
        /// <summary>
        /// Gets the input argument.
        /// </summary>
        /// <param name="videoPath">The video path.</param>
        /// <param name="isRemote">if set to <c>true</c> [is remote].</param>
        /// <param name="videoType">Type of the video.</param>
        /// <param name="isoType">Type of the iso.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="playableStreamFileNames">The playable stream file names.</param>
        /// <param name="type">The type.</param>
        /// <returns>System.String[][].</returns>
        public static string[] GetInputArgument(string videoPath, bool isRemote, VideoType videoType, IsoType? isoType, IIsoMount isoMount, IEnumerable<string> playableStreamFileNames, out InputType type)
        {
            var inputPath = isoMount == null ? new[] { videoPath } : new[] { isoMount.MountedPath };

            type = InputType.File;

            switch (videoType)
            {
                case VideoType.BluRay:
                    type = InputType.Bluray;
                    inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray();
                    break;
                case VideoType.Dvd:
                    type = InputType.Dvd;
                    inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray();
                    break;
                case VideoType.Iso:
                    if (isoType.HasValue)
                    {
                        switch (isoType.Value)
                        {
                            case IsoType.BluRay:
                                type = InputType.Bluray;
                                inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray();
                                break;
                            case IsoType.Dvd:
                                type = InputType.Dvd;
                                inputPath = GetPlayableStreamFiles(inputPath[0], playableStreamFileNames).ToArray();
                                break;
                        }
                    }
                    break;
                case VideoType.VideoFile:
                    {
                        if (isRemote)
                        {
                            type = InputType.Url;
                        }
                        break;
                    }
            }

            return inputPath;
        }
예제 #20
0
        private void FetchFromDvdLib(Video item, IIsoMount mount)
        {
            var path = mount == null ? item.Path : mount.MountedPath;
            var dvd  = new Dvd(path);

            var primaryTitle = dvd.Titles.OrderByDescending(GetRuntime).FirstOrDefault();

            byte?titleNumber = null;

            if (primaryTitle != null)
            {
                titleNumber       = primaryTitle.VideoTitleSetNumber;
                item.RunTimeTicks = GetRuntime(primaryTitle);
            }

            item.PlayableStreamFileNames = GetPrimaryPlaylistVobFiles(item, mount, titleNumber)
                                           .Select(Path.GetFileName)
                                           .ToList();
        }
예제 #21
0
        private string[] FetchFromDvdLib(Video item, IIsoMount mount)
        {
            var path = mount == null ? item.Path : mount.MountedPath;
            var dvd  = new Dvd(path, _fileSystem);

            var primaryTitle = dvd.Titles.OrderByDescending(GetRuntime).FirstOrDefault();

            byte?titleNumber = null;

            if (primaryTitle != null)
            {
                titleNumber       = primaryTitle.VideoTitleSetNumber;
                item.RunTimeTicks = GetRuntime(primaryTitle);
            }

            return(_mediaEncoder.GetPrimaryPlaylistVobFiles(item.Path, mount, titleNumber)
                   .Select(Path.GetFileName)
                   .ToArray());
        }
예제 #22
0
        private async Task <Model.MediaInfo.MediaInfo> GetMediaInfo(Video item,
                                                                    IIsoMount isoMount,
                                                                    CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var idString  = item.Id.ToString("N");
            var cachePath = Path.Combine(_appPaths.CachePath,
                                         "ffprobe-video",
                                         idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");

            try
            {
                return(_json.DeserializeFromFile <Model.MediaInfo.MediaInfo>(cachePath));
            }
            catch (FileNotFoundException)
            {
            }
            catch (DirectoryNotFoundException)
            {
            }

            var protocol = item.LocationType == LocationType.Remote
                ? MediaProtocol.Http
                : MediaProtocol.File;

            var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
            {
                PlayableStreamFileNames = item.PlayableStreamFileNames,
                MountedIso              = isoMount,
                ExtractChapters         = true,
                VideoType               = item.VideoType,
                MediaType               = DlnaProfileType.Video,
                InputPath               = item.Path,
                Protocol                = protocol,
                ExtractKeyFrameInterval = true
            }, cancellationToken).ConfigureAwait(false);

            Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
            _json.SerializeToFile(result, cachePath);

            return(result);
        }
예제 #23
0
        /// <summary>
        /// Plays the specified options.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns>Task.</returns>
        public async Task Play(PlayOptions options)
        {
            _currentIsoMount = options.Items.Count == 1 && options.Configuration.IsoMethod == IsoConfiguration.Mount ?
                               await GetIsoMount(options.Items[0], CancellationToken.None) :
                               null;

            CurrentPlaylistIndex = 0;
            CurrentPlayOptions   = options;

            _playlist = options.Items.ToList();

            var process = new Process
            {
                EnableRaisingEvents = true,
                StartInfo           = GetProcessStartInfo(options.Items, options, _currentIsoMount)
            };

            Logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);

            try
            {
                process.Start();
            }
            catch (Exception ex)
            {
                Logger.ErrorException("Error starting player", ex);

                _playlist.Clear();

                throw;
            }

            if (options.Configuration.CloseOnStopButton && !CanCloseAutomaticallyOnStopButton)
            {
                _userInput.GlobalKeyDown += KeyboardListener_KeyDown;
            }

            process.Exited += CurrentProcess_Exited;

            _currentProcess = process;

            OnPlayerLaunched();
        }
        /// <summary>
        /// Gets the input argument.
        /// </summary>
        /// <param name="video">The video.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="type">The type.</param>
        /// <returns>System.String[][].</returns>
        public static string[] GetInputArgument(Video video, IIsoMount isoMount, out InputType type)
        {
            var inputPath = isoMount == null ? new[] { video.Path } : new[] { isoMount.MountedPath };

            type = InputType.VideoFile;

            switch (video.VideoType)
            {
                case VideoType.BluRay:
                    type = InputType.Bluray;
                    break;
                case VideoType.Dvd:
                    type = InputType.Dvd;
                    inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray();
                    break;
                case VideoType.Iso:
                    if (video.IsoType.HasValue)
                    {
                        switch (video.IsoType.Value)
                        {
                            case IsoType.BluRay:
                                type = InputType.Bluray;
                                break;
                            case IsoType.Dvd:
                                type = InputType.Dvd;
                                inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray();
                                break;
                        }
                    }
                    break;
                case VideoType.VideoFile:
                    {
                        if (video.LocationType == LocationType.Remote)
                        {
                            type = InputType.Url;
                        }
                        break;
                    }
            }

            return inputPath;
        }
        /// <summary>
        /// Gets the playable path.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="apiClient">The API client.</param>
        /// <returns>System.String.</returns>
        public static string GetPlayablePath(BaseItemDto item, IIsoMount isoMount, IApiClient apiClient)
        {
            // Check the mounted path first
            if (isoMount != null)
            {
                if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay)
                {
                    return GetBlurayPath(isoMount.MountedPath);
                }

                return isoMount.MountedPath;
            }

            // Stream remote items through the api
            if (item.LocationType == LocationType.Remote)
            {
                return apiClient.GetVideoStreamUrl(new VideoStreamOptions
                {
                    ItemId = item.Id,
                    Static = true
                });
            }

            // Stream if we can't access the file system
            if (!File.Exists(item.Path) && !Directory.Exists(item.Path))
            {
                return apiClient.GetVideoStreamUrl(new VideoStreamOptions
                {
                    Static = true,
                    ItemId = item.Id
                });
            }

            if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay)
            {
                return GetBlurayPath(item.Path);
            }

            return item.Path;
        }
예제 #26
0
        /// <summary>
        /// Gets the playable path.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="apiClient">The API client.</param>
        /// <returns>System.String.</returns>
        public static string GetPlayablePath(BaseItemDto item, IIsoMount isoMount, IApiClient apiClient)
        {
            // Check the mounted path first
            if (isoMount != null)
            {
                if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay)
                {
                    return(GetBlurayPath(isoMount.MountedPath));
                }

                return(isoMount.MountedPath);
            }

            // Stream remote items through the api
            if (item.LocationType == LocationType.Remote)
            {
                return(apiClient.GetVideoStreamUrl(new VideoStreamOptions
                {
                    ItemId = item.Id,
                    Static = true
                }));
            }

            // Stream if we can't access the file system
            if (!File.Exists(item.Path) && !Directory.Exists(item.Path))
            {
                return(apiClient.GetVideoStreamUrl(new VideoStreamOptions
                {
                    Static = true,
                    ItemId = item.Id
                }));
            }

            if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay)
            {
                return(GetBlurayPath(item.Path));
            }

            return(item.Path);
        }
        private async Task <PlayableItem> GetPlayableItem(BaseItemDto item, CancellationToken cancellationToken)
        {
            IIsoMount mountedIso = null;

            if (item.VideoType.HasValue && item.VideoType.Value == VideoType.Iso && item.IsoType.HasValue && _isoManager.CanMount(item.Path))
            {
                try
                {
                    mountedIso = await _isoManager.Mount(item.Path, cancellationToken);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error mounting iso {0}", ex, item.Path);
                }
            }

            return(new PlayableItem
            {
                OriginalItem = item,
                PlayablePath = PlayablePathBuilder.GetPlayablePath(item, mountedIso, _apiClient)
            });
        }
예제 #28
0
        private async Task <InternalMediaInfoResult> GetMediaInfo(BaseItem item,
                                                                  IIsoMount isoMount,
                                                                  CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var idString  = item.Id.ToString("N");
            var cachePath = Path.Combine(_appPaths.CachePath,
                                         "ffprobe-video",
                                         idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");

            try
            {
                return(_json.DeserializeFromFile <InternalMediaInfoResult>(cachePath));
            }
            catch (FileNotFoundException)
            {
            }
            catch (DirectoryNotFoundException)
            {
            }

            var type      = InputType.File;
            var inputPath = isoMount == null ? new[] { item.Path } : new[] { isoMount.MountedPath };

            var video = item as Video;

            if (video != null)
            {
                inputPath = MediaEncoderHelpers.GetInputArgument(video.Path, video.LocationType == LocationType.Remote, video.VideoType, video.IsoType, isoMount, video.PlayableStreamFileNames, out type);
            }

            var result = await _mediaEncoder.GetMediaInfo(inputPath, type, false, cancellationToken).ConfigureAwait(false);

            Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
            _json.SerializeToFile(result, cachePath);

            return(result);
        }
예제 #29
0
        private Task <Model.MediaInfo.MediaInfo> GetMediaInfo(Video item,
                                                              IIsoMount isoMount,
                                                              List <string> streamFileNames,
                                                              CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var protocol = item.LocationType == LocationType.Remote
                ? MediaProtocol.Http
                : MediaProtocol.File;

            return(_mediaEncoder.GetMediaInfo(new MediaInfoRequest
            {
                PlayableStreamFileNames = streamFileNames,
                MountedIso = isoMount,
                ExtractChapters = true,
                VideoType = item.VideoType,
                MediaType = DlnaProfileType.Video,
                InputPath = item.Path,
                Protocol = protocol
            }, cancellationToken));
        }
예제 #30
0
        /// <summary>
        /// Gets the playable path.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="apiClient">The API client.</param>
        /// <param name="startTimeTicks">The start time ticks.</param>
        /// <returns>System.String.</returns>
        public static string GetPlayablePath(BaseItemDto item, IIsoMount isoMount, IApiClient apiClient, long?startTimeTicks, int?maxBitrate)
        {
            // Check the mounted path first
            if (isoMount != null)
            {
                if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay)
                {
                    return(GetBlurayPath(isoMount.MountedPath));
                }

                return(isoMount.MountedPath);
            }

            if (item.LocationType == LocationType.FileSystem)
            {
                if (File.Exists(item.Path) || Directory.Exists(item.Path))
                {
                    if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay)
                    {
                        return(GetBlurayPath(item.Path));
                    }

                    if (item.VideoType.HasValue && item.VideoType.Value == VideoType.Dvd)
                    {
                        return(item.Path);
                    }

                    if (item.VideoType.HasValue && item.VideoType.Value == VideoType.HdDvd)
                    {
                        return(item.Path);
                    }

                    //return item.Path;
                }
            }

            return(GetStreamedPath(item, apiClient, startTimeTicks, maxBitrate));
        }
예제 #31
0
        /// <summary>
        /// Handles the Exited event of the CurrentProcess control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        void CurrentProcess_Exited(object sender, EventArgs e)
        {
            _currentProcess = null;

            _userInput.GlobalKeyDown -= KeyboardListener_KeyDown;

            var process = (Process)sender;

            var playlist = _playlist.ToList();
            var index    = CurrentPlaylistIndex;
            var ticks    = CurrentPositionTicks;

            process.Dispose();

            if (_currentIsoMount != null)
            {
                _currentIsoMount.Dispose();
                _currentIsoMount = null;
            }

            var media = index != -1 && playlist.Count > 0 ? playlist[index] : null;

            var args = new PlaybackStopEventArgs
            {
                Playlist            = playlist,
                Player              = this,
                EndingPlaylistIndex = index,
                EndingPositionTicks = ticks,
                EndingMedia         = media
            };

            EventHelper.QueueEventIfNotNull(PlaybackCompleted, this, args, Logger);

            _playbackManager.ReportPlaybackCompleted(args);

            OnPlayerExited();
        }
예제 #32
0
        /// <summary>
        /// Handles the Exited event of the CurrentProcess control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        void CurrentProcess_Exited(object sender, EventArgs e)
        {
            _currentProcess = null;

            _userInput.GlobalKeyDown -= KeyboardListener_KeyDown;

            var process = (Process)sender;

            var playlist = _playlist.ToList();
            var index = CurrentPlaylistIndex;
            var ticks = CurrentPositionTicks;

            process.Dispose();

            if (_currentIsoMount != null)
            {
                _currentIsoMount.Dispose();
                _currentIsoMount = null;
            }

            var media = index != -1 && playlist.Count > 0 ? playlist[index] : null;

            var args = new PlaybackStopEventArgs
            {
                Playlist = playlist,
                Player = this,
                EndingPlaylistIndex = index,
                EndingPositionTicks = ticks,
                EndingMedia = media
            };

            EventHelper.QueueEventIfNotNull(PlaybackCompleted, this, args, Logger);

            _playbackManager.ReportPlaybackCompleted(args);

            OnPlayerExited();
        }
예제 #33
0
        protected async Task Fetch(Video video,
                                   CancellationToken cancellationToken,
                                   InternalMediaInfoResult data,
                                   IIsoMount isoMount,
                                   BlurayDiscInfo blurayInfo,
                                   MetadataRefreshOptions options)
        {
            var mediaInfo    = MediaEncoderHelpers.GetMediaInfo(data);
            var mediaStreams = mediaInfo.MediaStreams;

            video.TotalBitrate = mediaInfo.TotalBitrate;
            video.FormatName   = (mediaInfo.Format ?? string.Empty)
                                 .Replace("matroska", "mkv", StringComparison.OrdinalIgnoreCase);

            if (data.format != null)
            {
                // For dvd's this may not always be accurate, so don't set the runtime if the item already has one
                var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0;

                if (needToSetRuntime && !string.IsNullOrEmpty(data.format.duration))
                {
                    video.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.format.duration, _usCulture)).Ticks;
                }

                if (video.VideoType == VideoType.VideoFile)
                {
                    var extension = (Path.GetExtension(video.Path) ?? string.Empty).TrimStart('.');

                    video.Container = extension;
                }
                else
                {
                    video.Container = null;
                }

                if (!string.IsNullOrEmpty(data.format.size))
                {
                    video.Size = long.Parse(data.format.size, _usCulture);
                }
                else
                {
                    video.Size = null;
                }
            }

            var mediaChapters = (data.Chapters ?? new MediaChapter[] { }).ToList();
            var chapters      = mediaChapters.Select(GetChapterInfo).ToList();

            if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay))
            {
                FetchBdInfo(video, chapters, mediaStreams, blurayInfo);
            }

            await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);

            FetchWtvInfo(video, data);

            video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270);

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

            video.VideoBitRate            = videoStream == null ? null : videoStream.BitRate;
            video.DefaultVideoStreamIndex = videoStream == null ? (int?)null : videoStream.Index;

            video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle);

            ExtractTimestamp(video);
            UpdateFromMediaInfo(video, videoStream);

            await _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken).ConfigureAwait(false);

            if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh ||
                options.MetadataRefreshMode == MetadataRefreshMode.Default)
            {
                var chapterOptions = _chapterManager.GetConfiguration();

                try
                {
                    var remoteChapters = await DownloadChapters(video, chapters, chapterOptions, cancellationToken).ConfigureAwait(false);

                    if (remoteChapters.Count > 0)
                    {
                        chapters = remoteChapters;
                    }
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error downloading chapters", ex);
                }

                if (chapters.Count == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
                {
                    AddDummyChapters(video, chapters);
                }

                NormalizeChapterNames(chapters);

                await _encodingManager.RefreshChapterImages(new ChapterImageRefreshOptions
                {
                    Chapters      = chapters,
                    Video         = video,
                    ExtractImages = chapterOptions.ExtractDuringLibraryScan,
                    SaveChapters  = false
                }, cancellationToken).ConfigureAwait(false);

                await _chapterManager.SaveChapters(video.Id.ToString(), chapters, cancellationToken).ConfigureAwait(false);
            }
        }
예제 #34
0
 /// <summary>
 /// Gets the process start info.
 /// </summary>
 /// <param name="items">The items.</param>
 /// <param name="options">The options.</param>
 /// <param name="isoMount">The iso mount.</param>
 /// <returns>ProcessStartInfo.</returns>
 protected virtual ProcessStartInfo GetProcessStartInfo(IEnumerable<BaseItemDto> items, PlayOptions options, IIsoMount isoMount)
 {
     return new ProcessStartInfo
     {
         FileName = options.Configuration.Command,
         Arguments = GetCommandArguments(items, options, isoMount)
     };
 }
예제 #35
0
 /// <summary>
 /// Gets the command arguments.
 /// </summary>
 /// <param name="items">The items.</param>
 /// <param name="options">The options.</param>
 /// <param name="isoMount">The iso mount.</param>
 /// <returns>System.String.</returns>
 protected virtual string GetCommandArguments(IEnumerable<BaseItemDto> items, PlayOptions options, IIsoMount isoMount)
 {
     return GetCommandArguments(items, options.Configuration.Args, isoMount);
 }
예제 #36
0
        protected async Task Fetch(Video video,
                                   CancellationToken cancellationToken,
                                   Model.MediaInfo.MediaInfo mediaInfo,
                                   IIsoMount isoMount,
                                   BlurayDiscInfo blurayInfo,
                                   MetadataRefreshOptions options)
        {
            var mediaStreams = mediaInfo.MediaStreams;

            video.TotalBitrate = mediaInfo.Bitrate;
            //video.FormatName = (mediaInfo.Container ?? string.Empty)
            //    .Replace("matroska", "mkv", StringComparison.OrdinalIgnoreCase);

            // For dvd's this may not always be accurate, so don't set the runtime if the item already has one
            var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0;

            if (needToSetRuntime)
            {
                video.RunTimeTicks = mediaInfo.RunTimeTicks;
            }

            if (video.VideoType == VideoType.VideoFile)
            {
                var extension = (Path.GetExtension(video.Path) ?? string.Empty).TrimStart('.');

                video.Container = extension;
            }
            else
            {
                video.Container = null;
            }

            var chapters = mediaInfo.Chapters ?? new List <ChapterInfo>();

            if (blurayInfo != null)
            {
                FetchBdInfo(video, chapters, mediaStreams, blurayInfo);
            }

            await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);

            var libraryOptions = _libraryManager.GetLibraryOptions(video);

            FetchEmbeddedInfo(video, mediaInfo, options, libraryOptions);
            await FetchPeople(video, mediaInfo, options).ConfigureAwait(false);

            video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1260);

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

            video.DefaultVideoStreamIndex = videoStream == null ? (int?)null : videoStream.Index;

            video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle);
            video.Timestamp    = mediaInfo.Timestamp;

            video.Video3DFormat = video.Video3DFormat ?? mediaInfo.Video3DFormat;

            await _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken).ConfigureAwait(false);

            if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh ||
                options.MetadataRefreshMode == MetadataRefreshMode.Default)
            {
                if (chapters.Count == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
                {
                    AddDummyChapters(video, chapters);
                }

                NormalizeChapterNames(chapters);

                var extractDuringScan = false;
                if (libraryOptions != null)
                {
                    extractDuringScan = libraryOptions.ExtractChapterImagesDuringLibraryScan;
                }

                await _encodingManager.RefreshChapterImages(new ChapterImageRefreshOptions
                {
                    Chapters      = chapters,
                    Video         = video,
                    ExtractImages = extractDuringScan,
                    SaveChapters  = false
                }, cancellationToken).ConfigureAwait(false);

                await _chapterManager.SaveChapters(video.Id.ToString(), chapters, cancellationToken).ConfigureAwait(false);
            }
        }
예제 #37
0
 public IEnumerable <string> GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint?titleNumber)
 {
     throw new NotImplementedException();
 }
예제 #38
0
        /// <summary>
        /// Gets the input argument.
        /// </summary>
        /// <param name="fileSystem">The file system.</param>
        /// <param name="videoPath">The video path.</param>
        /// <param name="protocol">The protocol.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="playableStreamFileNames">The playable stream file names.</param>
        /// <returns>System.String[][].</returns>
        public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, MediaProtocol protocol, IIsoMount isoMount, string[] playableStreamFileNames)
        {
            if (playableStreamFileNames.Length > 0)
            {
                if (isoMount == null)
                {
                    return(GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames));
                }
                return(GetPlayableStreamFiles(fileSystem, isoMount.MountedPath, playableStreamFileNames));
            }

            return(new[] { videoPath });
        }
예제 #39
0
        async void process_Exited(object sender, EventArgs e)
        {
            var process = (Process)sender;

            if (_isoMount != null)
            {
                _isoMount.Dispose();
                _isoMount = null;
            }

            DisposeLogFileStream();

            try
            {
                _logger.Info("FFMpeg exited with code {0} for {1}", process.ExitCode, _task.Request.OutputPath);
            }
            catch
            {
                _logger.Info("FFMpeg exited with an error for {0}", _task.Request.OutputPath);
            }

            _task.OnCompleted();
            
            if (!string.IsNullOrEmpty(_task.LiveTvStreamId))
            {
                try
                {
                    await _liveTvManager.CloseLiveStream(_task.LiveTvStreamId, CancellationToken.None).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error closing live tv stream", ex);
                }
            }
        }
예제 #40
0
 /// <summary>
 /// Gets the path for command line.
 /// </summary>
 /// <param name="item">The item.</param>
 /// <param name="isoMount">The iso mount.</param>
 /// <returns>System.String.</returns>
 protected virtual string GetPathForCommandLine(BaseItemDto item, IIsoMount isoMount)
 {
     return isoMount == null ? item.Path : isoMount.MountedPath;
 }
예제 #41
0
        public async Task Start(InternalEncodingTask task, Func<InternalEncodingTask,string,string> argumentsFactory)
        {
            _task = task;
            if (!File.Exists(_ffmpegPath))
            {
                throw new InvalidOperationException("ffmpeg was not found at " + _ffmpegPath);
            }

            Directory.CreateDirectory(Path.GetDirectoryName(task.Request.OutputPath));

            string mountedPath = null;
            if (task.InputVideoType.HasValue && task.InputVideoType == VideoType.Iso && task.IsoType.HasValue)
            {
                if (_isoManager.CanMount(task.MediaPath))
                {
                    _isoMount = await _isoManager.Mount(task.MediaPath, CancellationToken.None).ConfigureAwait(false);
                    mountedPath = _isoMount.MountedPath;
                }
            }
            
            var process = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    CreateNoWindow = true,
                    UseShellExecute = false,

                    // Must consume both stdout and stderr or deadlocks may occur
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,

                    FileName = _ffmpegPath,
                    WorkingDirectory = Path.GetDirectoryName(_ffmpegPath),
                    Arguments = argumentsFactory(task, mountedPath),

                    WindowStyle = ProcessWindowStyle.Hidden,
                    ErrorDialog = false
                },

                EnableRaisingEvents = true
            };

            _logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments);

            var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-" + task.Id + ".txt");
            Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));

            // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
            _logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true);

            process.Exited += process_Exited;

            try
            {
                process.Start();
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error starting ffmpeg", ex);

                task.OnError();

                DisposeLogFileStream();

                process.Dispose();

                throw;
            }

            task.OnBegin();

            // MUST read both stdout and stderr asynchronously or a deadlock may occurr
            process.BeginOutputReadLine();

#pragma warning disable 4014
            // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
            process.StandardError.BaseStream.CopyToAsync(_logFileStream);
#pragma warning restore 4014
        }
예제 #42
0
        /// <summary>
        /// Plays the specified options.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns>Task.</returns>
        public async Task Play(PlayOptions options)
        {
            _currentIsoMount = options.Items.Count == 1 && options.Configuration.IsoMethod == IsoConfiguration.Mount ?
                await GetIsoMount(options.Items[0], CancellationToken.None) :
                null;

            CurrentPlaylistIndex = 0;
            CurrentPlayOptions = options;

            _playlist = options.Items.ToList();

            var process = new Process
            {
                EnableRaisingEvents = true,
                StartInfo = GetProcessStartInfo(options.Items, options, _currentIsoMount)
            };

            Logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);

            try
            {
                process.Start();
            }
            catch (Exception ex)
            {
                Logger.ErrorException("Error starting player", ex);

                _playlist.Clear();

                throw;
            }

            if (options.Configuration.CloseOnStopButton && !CanCloseAutomaticallyOnStopButton)
            {
                _userInput.GlobalKeyDown += KeyboardListener_KeyDown;
            }

            process.Exited += CurrentProcess_Exited;

            _currentProcess = process;

            OnPlayerLaunched();
        }
예제 #43
0
        private IEnumerable <string> GetPrimaryPlaylistVobFiles(Video video, IIsoMount isoMount, uint?titleNumber)
        {
            // min size 300 mb
            const long minPlayableSize = 314572800;

            var root = isoMount != null ? isoMount.MountedPath : video.Path;

            // Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size
            // Once we reach a file that is at least the minimum, return all subsequent ones
            var allVobs = new DirectoryInfo(root).EnumerateFiles("*", SearchOption.AllDirectories)
                          .Where(file => string.Equals(file.Extension, ".vob", StringComparison.OrdinalIgnoreCase))
                          .OrderBy(i => i.FullName)
                          .ToList();

            // If we didn't find any satisfying the min length, just take them all
            if (allVobs.Count == 0)
            {
                _logger.Error("No vobs found in dvd structure.");
                return(new List <string>());
            }

            if (titleNumber.HasValue)
            {
                var prefix = string.Format("VTS_0{0}_", titleNumber.Value.ToString(_usCulture));
                var vobs   = allVobs.Where(i => i.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)).ToList();

                if (vobs.Count > 0)
                {
                    var minSizeVobs = vobs
                                      .SkipWhile(f => f.Length < minPlayableSize)
                                      .ToList();

                    return(minSizeVobs.Count == 0 ? vobs.Select(i => i.FullName) : minSizeVobs.Select(i => i.FullName));
                }

                _logger.Debug("Could not determine vob file list for {0} using DvdLib. Will scan using file sizes.", video.Path);
            }

            var files = allVobs
                        .SkipWhile(f => f.Length < minPlayableSize)
                        .ToList();

            // If we didn't find any satisfying the min length, just take them all
            if (files.Count == 0)
            {
                _logger.Warn("Vob size filter resulted in zero matches. Taking all vobs.");
                files = allVobs;
            }

            // Assuming they're named "vts_05_01", take all files whose second part matches that of the first file
            if (files.Count > 0)
            {
                var parts = _fileSystem.GetFileNameWithoutExtension(files[0]).Split('_');

                if (parts.Length == 3)
                {
                    var title = parts[1];

                    files = files.TakeWhile(f =>
                    {
                        var fileParts = _fileSystem.GetFileNameWithoutExtension(f).Split('_');

                        return(fileParts.Length == 3 && string.Equals(title, fileParts[1], StringComparison.OrdinalIgnoreCase));
                    }).ToList();

                    // If this resulted in not getting any vobs, just take them all
                    if (files.Count == 0)
                    {
                        _logger.Warn("Vob filename filter resulted in zero matches. Taking all vobs.");
                        files = allVobs;
                    }
                }
            }

            return(files.Select(i => i.FullName));
        }
        /// <summary>
        /// Gets the input argument.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <returns>System.String.</returns>
        protected string GetInputArgument(BaseItem item, IIsoMount isoMount)
        {
            var type = InputType.AudioFile;

            var inputPath = new[] { item.Path };

            var video = item as Video;

            if (video != null)
            {
                if (!(video.VideoType == VideoType.Iso && isoMount == null))
                {
                    inputPath = MediaEncoderHelpers.GetInputArgument(video, isoMount, out type);
                }
            }

            return MediaEncoder.GetInputArgument(inputPath, type);
        }
예제 #45
0
        /// <summary>
        /// Gets the command arguments.
        /// </summary>
        /// <param name="items">The items.</param>
        /// <param name="formatString">The format string.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <returns>System.String.</returns>
        protected string GetCommandArguments(IEnumerable<BaseItemDto> items, string formatString, IIsoMount isoMount)
        {
            var list = items.ToList();

            string path;

            if (list.Count == 1 || !SupportsMultiFilePlayback || isoMount != null)
            {
                path = "\"" + GetPathForCommandLine(list[0], isoMount) + "\"";
            }
            else
            {
                var paths = list.Select(i => "\"" + GetPathForCommandLine(i, null) + "\"");

                path = string.Join(" ", paths.ToArray());
            }

            return formatString.Replace("{PATH}", path);
        }
        /// <summary>
        /// Gets the playable path.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="isoMount">The iso mount.</param>
        /// <param name="apiClient">The API client.</param>
        /// <param name="startTimeTicks">The start time ticks.</param>
        /// <returns>System.String.</returns>
        public static PlayableItem GetPlayableItem(BaseItemDto item, List<MediaSourceInfo> mediaSources, IIsoMount isoMount, IApiClient apiClient, long? startTimeTicks, int? maxBitrate)
        {
            // Check the mounted path first
            if (isoMount != null)
            {
                if (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay)
                {
                    return new PlayableItem
                    {
                        OriginalItem = item,
                        PlayablePath = GetBlurayPath(isoMount.MountedPath),
                        IsoMount = isoMount,
                        MediaSource = item.MediaSources.First()
                    };
                }

                return new PlayableItem
                {
                    OriginalItem = item,
                    PlayablePath = isoMount.MountedPath,
                    IsoMount = isoMount,
                    MediaSource = item.MediaSources.First()
                };
            }

            if (item.LocationType == LocationType.FileSystem)
            {
                if (File.Exists(item.Path) || Directory.Exists(item.Path))
                {
                    if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay)
                    {
                        return new PlayableItem
                        {
                            OriginalItem = item,
                            PlayablePath = GetBlurayPath(item.Path),
                            MediaSource = item.MediaSources.First()
                        };
                    }

                    if (item.VideoType.HasValue && item.VideoType.Value == VideoType.Dvd)
                    {
                        return new PlayableItem
                        {
                            OriginalItem = item,
                            PlayablePath = item.Path,
                            MediaSource = item.MediaSources.First()
                        };
                    }

                    if (item.VideoType.HasValue && item.VideoType.Value == VideoType.HdDvd)
                    {
                        return new PlayableItem
                        {
                            OriginalItem = item,
                            PlayablePath = item.Path,
                            MediaSource = item.MediaSources.First()
                        };
                    }

                    //return item.Path;
                }
            }

            return GetStreamedItem(item, mediaSources, apiClient, startTimeTicks, maxBitrate);
        }