예제 #1
0
 /// <summary>
 /// Constructor
 /// </summary>
 public JobController(IJobRepository jobRepository, ICommandRepository commandRepository, ITimeProvider timeProvider, IMediaInfoFacade mediaInfoFacade, ILogging logging)
 {
     _jobRepository     = jobRepository;
     _commandRepository = commandRepository;
     _timeProvider      = timeProvider;
     _mediaInfoFacade   = mediaInfoFacade;
     _logging           = logging;
 }
예제 #2
0
        private static void ValidateAlternateAudioToVideo(IMediaInfoFacade mediaInfoFacade, string audioPath)
        {
            var             result = new MediaInfoValidationResult();
            MediaInfoResult mi;

            try
            {
                mi = mediaInfoFacade.Read(audioPath);
            }
            catch (Exception ex)
            {
                throw new OrderException("Error while reading metadata from file. " + ex.Message);
            }
            ValidateAudioInVideo(mi);
        }
예제 #3
0
        private static int?ValidateStichAttachments(string value, string propertyName, IMediaInfoFacade mediaInfoFacade)
        {
            if (string.IsNullOrEmpty(value))
            {
                return(null);
            }

            if (!(value.EndsWith(".wav", StringComparison.InvariantCultureIgnoreCase) || value.EndsWith(".mp3", StringComparison.InvariantCultureIgnoreCase)))
            {
                throw new OrderException($"{propertyName} must be wav or mp3 file.");
            }

            if (!File.Exists(value))
            {
                throw new OrderException($"{propertyName} does not exist.");
            }

            try
            {
                var res = MediaInfoValidation(mediaInfoFacade, value, skipAsceptRatioValidation: true, skipResolutionValidation: true);
                #if DEBUG
                Console.WriteLine($"{res.Format} {res.CustomFormat??""}");
                #endif
                return(res.Duration);
            }
            catch (Exception ex)
            {
                throw new OrderException($"{propertyName}: " + ex.Message);
            }
        }
예제 #4
0
        private static MediaInfoValidationResult MediaInfoValidation(IMediaInfoFacade mediaInfoFacade, string filePath, bool skipAsceptRatioValidation = false, bool skipResolutionValidation = false)
        {
            var             result = new MediaInfoValidationResult();
            MediaInfoResult mi;

            try
            {
                mi = mediaInfoFacade.Read(filePath);
            }
            catch (Exception ex)
            {
                throw new OrderException("Error while reading metadata from file. " + ex.Message);
            }

            if (mi != null)
            {
                result.Duration = mi.Duration;
            }

            if (mi?.Video != null)
            {
                var         videoStream = mi.Video;
                StateFormat temp;
                if (Enum.TryParse(videoStream.CodecId, out temp))
                {
                    result.Format = temp;
                }
                else
                {
                    // TODO: Temp work around , allows unknow formats. Should rather throw when we know all allowed formats.
                    //throw new OrderException("File is not in a valid format. Source file must be dvpp, dv5p or xd5c format.");
                    result.Format       = StateFormat.custom;
                    result.CustomFormat = videoStream.CodecId;
                }
                if (!skipAsceptRatioValidation)
                {
                    switch (videoStream.DisplayAspectRatio)
                    {
                    case DisplayAspectRatio.ratio_4x3:
                        result.AspectRatio = AspectRatio.ratio_4x3;
                        break;

                    case DisplayAspectRatio.ratio_16x9:
                        result.AspectRatio = AspectRatio.ratio_16x9;
                        break;

                    case DisplayAspectRatio.unknown:
                    default:
                        throw new OrderException("Unsupport aspect ratio. Only 16x9 and 4x3 is supported.");
                    }
                }

                if (!skipResolutionValidation)
                {
                    switch (videoStream.Resolution)
                    {
                    case MediaInfoService.Resolution.sd:
                        result.Resolution = Resolution.sd;
                        break;

                    case MediaInfoService.Resolution.hd:
                        result.Resolution = Resolution.hd;
                        break;

                    case MediaInfoService.Resolution.full_hd:
                        result.Resolution = Resolution.fullhd;
                        break;

                    case MediaInfoService.Resolution.unknown:
                    default:
                        throw new OrderException("Unsupport resultion. Only sd, hd and fullhd is supported.");
                    }
                }

                ValidateAudioInVideo(mi);
            }
            else if (mi?.Audio != null)
            {
                var         audioStream = mi.Audio;
                StateFormat temp;

                if (Enum.TryParse(audioStream.Format, out temp))
                {
                    result.Format = temp;
                }
                else
                {
                    // TODO: Temp work around , allows unknow formats. Should rather throw when we know all allowed formats.
                    result.Format       = StateFormat.custom;
                    result.CustomFormat = audioStream.Format;
                }
            }
            else
            {
                throw new OrderException("File is not a valid media file. Source file must be dv5p or xd5c for video or wma, mpeg or pcm for audio format or wav for alternate audio.");
            }

            return(result);
        }
예제 #5
0
        /// <summary>
        /// Validate the order instance, may throw OrderException if the order cannot be procesed.
        /// </summary>
        /// <exception cref="OrderException">If the order is unacceptable (:lemon:)</exception>
        public void Validate(IMediaInfoFacade mediaInfoFacade, ITimeProvider timeProvider)
        {
            if (!File.Exists(FilePath))
            {
                throw new OrderException("Filepath does not exist.");
            }

            //Call Media Info for source format and valid source file check
            var arForced   = ForceAspectRatio.HasValue && ForceAspectRatio != AspectRatio.unknown;
            var rForced    = ForceResolution.HasValue && ForceResolution != Resolution.unknown;
            var infoResult = MediaInfoValidation(mediaInfoFacade, FilePath, arForced, rForced);

            if (!arForced)
            {
                AspectRatio = infoResult.AspectRatio;
            }
            CustomFormat = infoResult.CustomFormat;
            Duration     = infoResult.Duration;
            Format       = infoResult.Format;
            if (!rForced)
            {
                Resolution = infoResult.Resolution;
            }


            if (BurnInLogo.GetValueOrDefault(false))
            {
                if (!string.IsNullOrEmpty(LogoPath))
                {
                    if (!File.Exists(LogoPath))
                    {
                        throw new OrderException("LogoPath does not exist.");
                    }

                    if (!(LogoPath.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase) || LogoPath.EndsWith(".jpg", StringComparison.InvariantCultureIgnoreCase) ||
                          LogoPath.EndsWith(".jpeg", StringComparison.InvariantCultureIgnoreCase)))
                    {
                        throw new OrderException("LogoPath is not a supported file type. Must be png/jpg/jpeg");
                    }
                }
            }

            if (!string.IsNullOrEmpty(AlternateAudioPath))
            {
                if (!File.Exists(AlternateAudioPath))
                {
                    throw new OrderException("AlternateAudioPath does not exist.");
                }

                if (!(AlternateAudioPath.EndsWith(".wav", StringComparison.InvariantCultureIgnoreCase)))
                {
                    throw new OrderException("AlternateAudioPath is not a supported file type. Must be wav format");
                }

                var audioInfo = MediaInfoValidation(mediaInfoFacade, AlternateAudioPath);
                if (audioInfo.Format == StateFormat.custom)
                {
                    throw new OrderException("AlternateAudioPath is not a supported encoding.");
                }

                ValidateAlternateAudioToVideo(mediaInfoFacade, AlternateAudioPath);
                if (!FFMpeg.SupportedAudioMuxingVideoSourceFormats.Contains(Format) ||
                    !FFMpeg.SupportedAudioSourceFormats.Contains(audioInfo.Format))
                {
                    throw new OrderException($"Alternative audio format {audioInfo.Format} mux to {Format} is invalid.");
                }
            }

            if (BurnInSubtitles.GetValueOrDefault(false))
            {
                if (!File.Exists(SubtitlesPath))
                {
                    throw new OrderException("SubtitlesPath does not exist.");
                }

                if (!FFMpeg.SupportedSubtitleExtensions.Any(e => SubtitlesPath.EndsWith(e, StringComparison.InvariantCultureIgnoreCase)))
                {
                    throw new OrderException($"SubtitlesPath is not a supported file type. Must be one of {FFMpeg.SupportedSubtitleExtensions.Aggregate((c,n)=>$"{c}, {n}")}");
                }
            }
            if ((FFMpeg.SupportedAudioDestinationFormats.Contains(DestinationFormat) && !FFMpeg.SupportedAudioSourceFormats.Contains(Format)) ||
                (Wfs.SupportedDestinationFormats.Contains(DestinationFormat) && !Wfs.SupportedSourceFormats.Contains(Format)))
            {
                throw new OrderException($"DestinationFormat {DestinationFormat} is invalid for source format {Format}.");
            }
            if (DestinationFormat == StateFormat.unknown)
            {
                throw new OrderException("DestinationFormat is invalid.");
            }

            if (DestinationFormat.GetType().GetField(DestinationFormat.ToString()).CustomAttributes.ToList()
                .Find(a => a.AttributeType == typeof(ObsoleteAttribute)) != null)
            {
                throw new OrderException($"DestinationFormat is obsolete. {DestinationFormat}");
            }

            if (!Directory.Exists(DestinationPath))
            {
                throw new OrderException("DestinationPath does not exist.");
            }

            IntroDuration = ValidateStichAttachments(IntroFilePath, nameof(IntroFilePath), mediaInfoFacade);
            OutroDuration = ValidateStichAttachments(OutroFilePath, nameof(OutroFilePath), mediaInfoFacade);

            //TODO: Disabled until further notice. This check fails as it doens't check "Everyone". We might need to rethink this entirely. :bomb:
            ////Check if we have write permission on destination
            //var acc = new NTAccount(Environment.UserName);
            //var accessGranted = false;
            //string rights = $"Rights found on {acc.Value}: ";
            //var secId = acc.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier;
            //if (secId == null)
            //    throw new OrderException($"Unable to read SecurityIdentifier from {Environment.UserName}");
            //var dInfo = new DirectoryInfo(DestinationPath);
            //var dSecurity = dInfo.GetAccessControl();
            //var rules = dSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier));

            //foreach (FileSystemAccessRule ar in rules)
            //{
            //    if (secId.CompareTo(ar.IdentityReference as SecurityIdentifier) == 0)
            //    {
            //        Debug.WriteLine($"We found the rights for the user: {ar.FileSystemRights}");
            //        rights += ar.FileSystemRights + " ";
            //        if ((ar.FileSystemRights & FileSystemRights.Write) == FileSystemRights.Write)
            //        {
            //            Debug.WriteLine("ACCESS GRANTED!");
            //            accessGranted = true;
            //        }
            //    }
            //}
            //if (!accessGranted) throw new OrderException("Can't write to destination. Only found following: "+ rights);

            if (!Priority.HasValue)
            {
                Priority = Marvin.Model.Priority.low;
            }

            if (!string.IsNullOrEmpty(CallbackUrl) && !Uri.IsWellFormedUriString(CallbackUrl, UriKind.Absolute))
            {
                throw new OrderException("Callback URL is not valid");
            }

            if (!string.IsNullOrEmpty(DestinationFilename))
            {
                var invalidChars = Path.GetInvalidFileNameChars();
                foreach (var c in DestinationFilename.Where(c => invalidChars.Contains(c)))
                {
                    throw new OrderException($"{DestinationFilename} contains illigal character: {c}");
                }
            }

            Issued = timeProvider.GetUtcNow();
            if (!DueDate.HasValue || DueDate.Value < Issued)
            {
                DueDate = Issued;
            }

            if (string.IsNullOrEmpty(Name))
            {
                Name = new FileInfo(FilePath).Name;
            }

            if (string.IsNullOrEmpty(SourceUrn))
            {
                SourceUrn = null;
            }
            else if (!_urnValidation.IsMatch(SourceUrn))
            {
                throw new OrderException($"Invalid source urn {SourceUrn} supplied");
            }

            Validated = true;
        }