FFmpegEncoder CreateEncoder() { FFmpegEncoder encoder = new FFmpegEncoder(Settings.FFmpegPath); try { encoder.FileFormat = fileFormatBox.Text; // Must be letters, numbers, and underscores only if (!Regex.IsMatch(encoder.FileFormat, @"^\w*$")) throw new ControlValueException(fileFormatBox, "file format"); encoder.FilenameExtension = fileExtBox.Text .TrimStart('.'); if (encoder.FilenameExtension.ContainsAny(Path.GetInvalidFileNameChars())) throw new ControlValueException(fileExtBox, "file name extension"); encoder.OutputFolder = outputFolderBox.Text .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); if (encoder.OutputFolder.ContainsAny(Path.GetInvalidPathChars()) || !Path.IsPathRooted(encoder.OutputFolder) || !Directory.Exists(encoder.OutputFolder)) throw new ControlValueException(outputFolderBox, "output folder"); encoder.IncludeVideo = includeVideoCheck.Checked; if (encoder.IncludeVideo) { if (!String.IsNullOrEmpty(videoStreamsBox.Text)) { encoder.VideoStreams = videoStreamsBox.Text .Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) .Select(index => { int i; if (!Int32.TryParse(index, out i) || i < 0) throw new ControlValueException(videoStreamsBox, "video streams list"); return i; }) .ToArray(); } encoder.VideoCodec = videoCodecBox.Text; // Must be letters, numbers, and underscores only if (!Regex.IsMatch(encoder.VideoCodec, @"^\w*$")) throw new ControlValueException(videoCodecBox, "video codec"); if (!String.IsNullOrEmpty(widthBox.Text)) { int width; if (!Int32.TryParse(widthBox.Text, out width) || width <= 0) throw new ControlValueException(widthBox, "video width"); encoder.Width = width; } if (!String.IsNullOrEmpty(heightBox.Text)) { int height; if (!Int32.TryParse(heightBox.Text, out height) || height <= 0) throw new ControlValueException(heightBox, "video height"); encoder.Height = height; } if (!String.IsNullOrEmpty(videoBitrateBox.Text)) { double bitrate; if (!Double.TryParse(videoBitrateBox.Text, out bitrate) || bitrate <= 0) throw new ControlValueException(videoBitrateBox, "video bitrate"); encoder.VideoBitrate = bitrate; } if (!String.IsNullOrEmpty(darBox.Text)) { var e = new ControlValueException(darBox, "display aspect ratio"); string[] parts = darBox.Text.Split(":/\\".ToCharArray(), 2); double numerator; if (!Double.TryParse(parts[0], out numerator)) throw e; encoder.DisplayAspectRatio = numerator; if (parts.Length > 1) { double denominator; if (!Double.TryParse(parts[1], out denominator) || denominator == 0) throw e; encoder.DisplayAspectRatio /= denominator; } if (encoder.DisplayAspectRatio <= 0) throw e; } if (!String.IsNullOrEmpty(frameRateBox.Text)) { double frameRate; if (!Double.TryParse(frameRateBox.Text, out frameRate) || frameRate <= 0) throw new ControlValueException(frameRateBox, "frame rate"); encoder.FrameRate = frameRate; } if (!String.IsNullOrEmpty(topBox.Text)) { int top; if (!Int32.TryParse(topBox.Text, out top) || top < 0) throw new ControlValueException(topBox, "top crop margin"); encoder.CropTop = top; } if (!String.IsNullOrEmpty(leftBox.Text)) { int left; if (!Int32.TryParse(leftBox.Text, out left) || left < 0) throw new ControlValueException(leftBox, "left crop margin"); encoder.CropLeft = left; } if (!String.IsNullOrEmpty(rightBox.Text)) { int right; if (!Int32.TryParse(rightBox.Text, out right) || right < 0) throw new ControlValueException(rightBox, "right crop margin"); encoder.CropRight = right; } if (!String.IsNullOrEmpty(bottomBox.Text)) { int bottom; if (!Int32.TryParse(bottomBox.Text, out bottom) || bottom < 0) throw new ControlValueException(bottomBox, "bottom crop margin"); encoder.CropBottom = bottom; } encoder.VideoFilters = videoFiltersBox.Text; } encoder.IncludeAudio = includeAudioCheck.Checked; if (encoder.IncludeAudio) { if (!String.IsNullOrEmpty(audioStreamsBox.Text)) { encoder.AudioStreams = audioStreamsBox.Text .Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) .Select(index => { int i; if (!Int32.TryParse(index, out i) || i < 0) throw new ControlValueException(audioStreamsBox, "audio streams list"); return i; }) .ToArray(); } encoder.AudioCodec = audioCodecBox.Text; // Must be letters, numbers, and underscores only if (!Regex.IsMatch(encoder.AudioCodec, @"^\w*$")) throw new ControlValueException(audioCodecBox, "audio codec"); if (!String.IsNullOrEmpty(audioBitrateBox.Text)) { double bitrate; if (!Double.TryParse(audioBitrateBox.Text, out bitrate) || bitrate <= 0) throw new ControlValueException(audioBitrateBox, "audio bitrate"); encoder.AudioBitrate = bitrate; } if (!String.IsNullOrEmpty(channelCountBox.Text)) { int channelCount; if (!Int32.TryParse(channelCountBox.Text, out channelCount) || channelCount <= 0) throw new ControlValueException(channelCountBox, "channel count"); encoder.ChannelCount = channelCount; } if (!String.IsNullOrEmpty(sampleRateBox.Text)) { double sampleRate; if (!Double.TryParse(sampleRateBox.Text, out sampleRate) || sampleRate <= 0) throw new ControlValueException(sampleRateBox, "sample rate"); encoder.SampleRate = sampleRate; } if (!String.IsNullOrEmpty(volumeBox.Text)) { double volume; if (!Double.TryParse(volumeBox.Text, out volume) || volume < 0 || // LAME will violently crash if volume is increased too much // Someone should probbably report that volume > 10000000) throw new ControlValueException(volumeBox, "volume"); encoder.Volume = volume / 100; } encoder.AudioFilters = audioFiltersBox.Text; } encoder.IncludeSubtitles = includeSubtitlesCheck.Checked; if (encoder.IncludeSubtitles && !String.IsNullOrEmpty(subtitlesStreamsBox.Text)) { encoder.SubtitlesStreams = subtitlesStreamsBox.Text .Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) .Select(index => { int i; if (!Int32.TryParse(index, out i) || i < 0) throw new ControlValueException(subtitlesStreamsBox, "subtitles streams list"); return i; }) .ToArray(); } encoder.GlobalParams = globalParamsBox.Text; encoder.InputParams = inputParamsBox.Text; encoder.OutputParams = outputParamsBox.Text; } catch (ControlValueException e) { e.Focus(); e.ShowMessage(this); return null; } return encoder; }
FFmpegEncoder CreateEncoder() { FFmpegEncoder encoder = new FFmpegEncoder(Settings.FFmpegPath); try { encoder.FileFormat = fileFormatBox.Text; // Must be letters, numbers, and underscores only if (!Regex.IsMatch(encoder.FileFormat, @"^\w*$")) { throw new ControlValueException(fileFormatBox, "file format"); } encoder.FilenameExtension = fileExtBox.Text .TrimStart('.'); if (encoder.FilenameExtension.ContainsAny(Path.GetInvalidFileNameChars())) { throw new ControlValueException(fileExtBox, "file name extension"); } encoder.OutputFolder = outputFolderBox.Text .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); if (encoder.OutputFolder.ContainsAny(Path.GetInvalidPathChars()) || !Path.IsPathRooted(encoder.OutputFolder) || !Directory.Exists(encoder.OutputFolder)) { throw new ControlValueException(outputFolderBox, "output folder"); } encoder.IncludeVideo = includeVideoCheck.Checked; if (encoder.IncludeVideo) { if (!String.IsNullOrEmpty(videoStreamsBox.Text)) { encoder.VideoStreams = videoStreamsBox.Text .Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) .Select(index => { int i; if (!Int32.TryParse(index, out i) || i < 0) { throw new ControlValueException(videoStreamsBox, "video streams list"); } return(i); }) .ToArray(); } encoder.VideoCodec = videoCodecBox.Text; // Must be letters, numbers, and underscores only if (!Regex.IsMatch(encoder.VideoCodec, @"^\w*$")) { throw new ControlValueException(videoCodecBox, "video codec"); } if (!String.IsNullOrEmpty(widthBox.Text)) { int width; if (!Int32.TryParse(widthBox.Text, out width) || width <= 0) { throw new ControlValueException(widthBox, "video width"); } encoder.Width = width; } if (!String.IsNullOrEmpty(heightBox.Text)) { int height; if (!Int32.TryParse(heightBox.Text, out height) || height <= 0) { throw new ControlValueException(heightBox, "video height"); } encoder.Height = height; } if (!String.IsNullOrEmpty(videoBitrateBox.Text)) { double bitrate; if (!Double.TryParse(videoBitrateBox.Text, out bitrate) || bitrate <= 0) { throw new ControlValueException(videoBitrateBox, "video bitrate"); } encoder.VideoBitrate = bitrate; } if (!String.IsNullOrEmpty(darBox.Text)) { var e = new ControlValueException(darBox, "display aspect ratio"); string[] parts = darBox.Text.Split(":/\\".ToCharArray(), 2); double numerator; if (!Double.TryParse(parts[0], out numerator)) { throw e; } encoder.DisplayAspectRatio = numerator; if (parts.Length > 1) { double denominator; if (!Double.TryParse(parts[1], out denominator) || denominator == 0) { throw e; } encoder.DisplayAspectRatio /= denominator; } if (encoder.DisplayAspectRatio <= 0) { throw e; } } if (!String.IsNullOrEmpty(frameRateBox.Text)) { double frameRate; if (!Double.TryParse(frameRateBox.Text, out frameRate) || frameRate <= 0) { throw new ControlValueException(frameRateBox, "frame rate"); } encoder.FrameRate = frameRate; } if (!String.IsNullOrEmpty(topBox.Text)) { int top; if (!Int32.TryParse(topBox.Text, out top) || top < 0) { throw new ControlValueException(topBox, "top crop margin"); } encoder.CropTop = top; } if (!String.IsNullOrEmpty(leftBox.Text)) { int left; if (!Int32.TryParse(leftBox.Text, out left) || left < 0) { throw new ControlValueException(leftBox, "left crop margin"); } encoder.CropLeft = left; } if (!String.IsNullOrEmpty(rightBox.Text)) { int right; if (!Int32.TryParse(rightBox.Text, out right) || right < 0) { throw new ControlValueException(rightBox, "right crop margin"); } encoder.CropRight = right; } if (!String.IsNullOrEmpty(bottomBox.Text)) { int bottom; if (!Int32.TryParse(bottomBox.Text, out bottom) || bottom < 0) { throw new ControlValueException(bottomBox, "bottom crop margin"); } encoder.CropBottom = bottom; } encoder.VideoFilters = videoFiltersBox.Text; } encoder.IncludeAudio = includeAudioCheck.Checked; if (encoder.IncludeAudio) { if (!String.IsNullOrEmpty(audioStreamsBox.Text)) { encoder.AudioStreams = audioStreamsBox.Text .Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) .Select(index => { int i; if (!Int32.TryParse(index, out i) || i < 0) { throw new ControlValueException(audioStreamsBox, "audio streams list"); } return(i); }) .ToArray(); } encoder.AudioCodec = audioCodecBox.Text; // Must be letters, numbers, and underscores only if (!Regex.IsMatch(encoder.AudioCodec, @"^\w*$")) { throw new ControlValueException(audioCodecBox, "audio codec"); } if (!String.IsNullOrEmpty(audioBitrateBox.Text)) { double bitrate; if (!Double.TryParse(audioBitrateBox.Text, out bitrate) || bitrate <= 0) { throw new ControlValueException(audioBitrateBox, "audio bitrate"); } encoder.AudioBitrate = bitrate; } if (!String.IsNullOrEmpty(channelCountBox.Text)) { int channelCount; if (!Int32.TryParse(channelCountBox.Text, out channelCount) || channelCount <= 0) { throw new ControlValueException(channelCountBox, "channel count"); } encoder.ChannelCount = channelCount; } if (!String.IsNullOrEmpty(sampleRateBox.Text)) { double sampleRate; if (!Double.TryParse(sampleRateBox.Text, out sampleRate) || sampleRate <= 0) { throw new ControlValueException(sampleRateBox, "sample rate"); } encoder.SampleRate = sampleRate; } if (!String.IsNullOrEmpty(volumeBox.Text)) { double volume; if (!Double.TryParse(volumeBox.Text, out volume) || volume < 0 || // LAME will violently crash if volume is increased too much // Someone should probbably report that volume > 10000000) { throw new ControlValueException(volumeBox, "volume"); } encoder.Volume = volume / 100; } encoder.AudioFilters = audioFiltersBox.Text; } encoder.IncludeSubtitles = includeSubtitlesCheck.Checked; if (encoder.IncludeSubtitles && !String.IsNullOrEmpty(subtitlesStreamsBox.Text)) { encoder.SubtitlesStreams = subtitlesStreamsBox.Text .Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) .Select(index => { int i; if (!Int32.TryParse(index, out i) || i < 0) { throw new ControlValueException(subtitlesStreamsBox, "subtitles streams list"); } return(i); }) .ToArray(); } encoder.GlobalParams = globalParamsBox.Text; encoder.InputParams = inputParamsBox.Text; encoder.OutputParams = outputParamsBox.Text; } catch (ControlValueException e) { e.Focus(); e.ShowMessage(this); return(null); } return(encoder); }
void BeginConvert() { FFmpegEncoder encoder = CreateEncoder(); if (encoder == null) { return; } if (fileListBox.Items.Count <= 0) { MessageBox.Show(this, "The list of files to convert is empty.", "No Files", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } InputFile[] files = fileListBox.Items .OfType <InputFile>() .ToArray(); bool saveLog = saveLogCheck.Checked; BackgroundWorker worker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true, }; ProgressDialog progressDialog = new ProgressDialog { TotalFiles = files.Length, Worker = worker, }; Log log = new Log(); Log errorLog = new Log(); string error = null; bool critical = false; bool runErrors = false; worker.DoWork += (sender, e) => { DateTime startTime = DateTime.Now; if (saveLog) { log.OpenFile(String.Format( "{0}{1}Yaffmi Log {2:yyyy'.'MM'.'dd HH'.'mm'.'ss}.txt", encoder.OutputFolder, Path.DirectorySeparatorChar, startTime)); if (!log.FileIsOpen) { error = String.Format("Could not save \"{0}\".", log.FilePath); critical = true; return; } } log.WriteLine(Settings.Title); log.WriteLine("Start time: {0:G}", startTime); log.WriteLine("FFmpeg path: {0}", encoder.FFmpegPath); log.WriteLine("Output directory: {0}", encoder.OutputFolder); log.WriteLine(); int fileCtr = 0; foreach (InputFile file in files) { DateTime fileStartTime = DateTime.Now; int tempFileCtr = fileCtr; log.WriteLine("Item {0} of {1}", tempFileCtr + 1, files.Length); log.WriteLine("Item start time: {0:G}", fileStartTime); FFmpegOperation operation = encoder.BeginEncode(file.FilePath); log.WriteLine("Input file: {0}", operation.InputFilePath); log.WriteLine("Output file: {0}", operation.OutputFilePath); log.WriteLine("Command: \"{0}\" {1}", operation.FFmpegPath, operation.Arguments); if (operation.Status != FFmpegOperationStatus.ProcessStartError) { operation.ProgressChanged += (operation_sender, operation_e) => worker.ReportProgress(0, new ConvertProgress(tempFileCtr, // Don't let it hit 100% until we are done (operation.Progress < 0.994) ? operation.Progress : 0.994)); operation.BeginStatusReporting(); // This seems kind of ugly, but BackgroundWorker doesn't expose any other method of // detecting cancelations besides polling CancellationPending while (true) { if (worker.CancellationPending) { operation.Cancel(); operation.WaitForFinish(); break; } if (operation.WaitForFinish(15)) { break; } } } DateTime fileEndTime = DateTime.Now; foreach (string line in operation.Log) { log.WriteLine("> {0}", line); } log.WriteLine("Result: {0}", operation.Status); log.WriteLine("Item end time: {0:G}", fileEndTime); log.WriteLine(); if (worker.CancellationPending) { break; } // If the first file fails before processing starts, don't try to keep going if (!Settings.NeverAbortOnError && tempFileCtr == 0 && (operation.Status == FFmpegOperationStatus.ProcessStartError || operation.Status == FFmpegOperationStatus.InitializationError)) { error = operation.Error; critical = operation.Status == FFmpegOperationStatus.ProcessStartError; break; } // If something fails later on, log it and continue if (operation.Status != FFmpegOperationStatus.Success) { // If we don't have a log file yet, create an error log if (!log.FileIsOpen && !errorLog.FileIsOpen) { errorLog.OpenFile(String.Format( "{0}{1}Yaffmi Errors {2:yyyy'.'MM'.'dd HH'.'mm'.'ss}.txt", encoder.OutputFolder, Path.DirectorySeparatorChar, startTime)); errorLog.WriteLine(Settings.Title); errorLog.WriteLine("Error log"); errorLog.WriteLine(); } errorLog.WriteLine("Item {0} of {1}", tempFileCtr + 1, files.Length); errorLog.WriteLine("Input file: {0}", operation.InputFilePath); errorLog.WriteLine("Error: {0}", operation.Error); errorLog.WriteLine(); runErrors = true; } worker.ReportProgress(0, new ConvertProgress(tempFileCtr, 1)); fileCtr++; } DateTime endTime = DateTime.Now; errorLog.CloseFile(); log.WriteLine("Yaffmi finished."); log.WriteLine("End time: {0:G}", endTime); log.CloseFile(); }; worker.ProgressChanged += (sender, e) => { ConvertProgress progress = (ConvertProgress)e.UserState; progressDialog.CurrentFile = progress.FileCtr + 1; progressDialog.CurrentFileProgress = progress.FileProgress; }; worker.RunWorkerCompleted += (sender, e) => { progressDialog.Finished = true; if (error != null) { progressDialog.Close(); MessageBox.Show(this, error, "Convert Error", MessageBoxButtons.OK, (critical) ? MessageBoxIcon.Error : MessageBoxIcon.Warning); return; } if (runErrors) { if ((errorLog.FilePath != null && errorLog.GetLastError(false) == null) || (log.FilePath != null && log.GetLastError(false) == null)) { MessageBox.Show(this, String.Format( "One or more files were not converted successfully. See \"{0}\" in the output folder for more information.", Path.GetFileName(errorLog.FilePath ?? log.FilePath)), "Convert Errors", MessageBoxButtons.OK, MessageBoxIcon.Warning); } else { MessageBox.Show(this, "One or more files were not converted successfully. There was a problem creating files in the output folder.", "Convert Errors", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }; progressDialog.ShowDialog(this); }