/* QueryGenerator.cs $ This file is part of the HandBrake source code. Homepage: . It may be used under the terms of the GNU General Public License. */ using System; using System.Windows.Forms; using System.Globalization; using System.IO; using System.Collections.Generic; using Handbrake.Model; namespace Handbrake.Functions { class QueryGenerator { /// /// Generates a full CLI query for either encoding or previe encoeds if duration and preview are defined. /// /// The Main Window /// What Mode. (Point to Point Encoding) Chapters, Seconds, Frames OR Preview Encode /// time in seconds for preview mode /// --start-at-preview (int) /// CLI Query public static string GenerateCLIQuery(frmMain mainWindow, int mode, int duration, string preview) { string query = ""; if (!string.IsNullOrEmpty(mainWindow.sourcePath) && mainWindow.sourcePath.Trim() != "Select \"Source\" to continue") query = " -i " + '"' + mainWindow.sourcePath + '"'; if (mainWindow.drp_dvdtitle.Text != "") { string[] titleInfo = mainWindow.drp_dvdtitle.Text.Split(' '); query += " -t " + titleInfo[0]; } if (!Properties.Settings.Default.noDvdNav && mainWindow.drop_angle.Items.Count != 0) query += " --angle " + mainWindow.drop_angle.SelectedItem; // Decide what part of the video we want to encode. switch (mode) { case 0: // Chapters if (mainWindow.drop_chapterFinish.Text == mainWindow.drop_chapterStart.Text && mainWindow.drop_chapterStart.Text != "") query += string.Format(" -c {0}", mainWindow.drop_chapterStart.Text); else if (mainWindow.drop_chapterStart.Text != "" && mainWindow.drop_chapterFinish.Text != "") query += string.Format(" -c {0}-{1}", mainWindow.drop_chapterStart.Text, mainWindow.drop_chapterFinish.Text); break; case 1: // Seconds int start, end; int.TryParse(mainWindow.drop_chapterStart.Text, out start); int.TryParse(mainWindow.drop_chapterFinish.Text, out end); int calculatedDuration = end - start; query += string.Format(" --start-at duration:{0} --stop-at duration:{1}", mainWindow.drop_chapterStart.Text, calculatedDuration); break; case 2: // Frames int.TryParse(mainWindow.drop_chapterStart.Text, out start); int.TryParse(mainWindow.drop_chapterFinish.Text, out end); calculatedDuration = end - start; query += string.Format(" --start-at frame:{0} --stop-at frame:{1}", mainWindow.drop_chapterStart.Text, calculatedDuration); break; case 3: // Preview query += " --previews " + Properties.Settings.Default.previewScanCount + " "; query += " --start-at-preview " + preview; query += " --stop-at duration:" + duration + " "; if (mainWindow.text_destination.Text != "") query += string.Format(" -o \"{0}\" ", mainWindow.text_destination.Text.Replace(".m", "_sample.m")); break; default: break; } if (mode != 3) query += string.Format(" -o \"{0}\" ", mainWindow.text_destination.Text); query += GenerateTabbedComponentsQuery(mainWindow); return query; } /// /// Generates part of the CLI query, for the tabbed components only. /// /// /// public static string GenerateTabbedComponentsQuery(frmMain mainWindow) { string query = ""; #region Output Settings Box query += " -f " + mainWindow.drop_format.Text.ToLower().Replace(" file", ""); // These are output settings features if (mainWindow.check_largeFile.Checked) query += " -4 "; if (mainWindow.check_iPodAtom.Checked) query += " -I "; if (mainWindow.check_optimiseMP4.Checked) query += " -O "; #endregion #region Picture Settings Tab // Use MaxWidth for built-in presets and width for user settings. if (mainWindow.PictureSettings.PresetMaximumResolution.Width == 0) { if (mainWindow.PictureSettings.text_width.Value != 0) if (mainWindow.PictureSettings.drp_anamorphic.SelectedIndex != 1) // Prevent usage for strict anamorphic query += " -w " + mainWindow.PictureSettings.text_width.Text; } else { if (mainWindow.PictureSettings.text_width.Value != 0) if (mainWindow.PictureSettings.drp_anamorphic.SelectedIndex != 1) query += " -X " + mainWindow.PictureSettings.text_width.Text; } // Use MaxHeight for built-in presets and height for user settings. if (mainWindow.PictureSettings.PresetMaximumResolution.Height == 0) { if (mainWindow.PictureSettings.text_height.Value != 0) if (mainWindow.PictureSettings.text_height.Text != "") if (mainWindow.PictureSettings.drp_anamorphic.SelectedIndex == 0 || mainWindow.PictureSettings.drp_anamorphic.SelectedIndex == 3) // Prevent usage for strict anamorphic query += " -l " + mainWindow.PictureSettings.text_height.Text; } else { if (mainWindow.PictureSettings.text_height.Value != 0) if (mainWindow.PictureSettings.drp_anamorphic.SelectedIndex == 0 || mainWindow.PictureSettings.drp_anamorphic.SelectedIndex == 3) query += " -Y " + mainWindow.PictureSettings.text_height.Text; } string cropTop = mainWindow.PictureSettings.crop_top.Text; string cropBottom = mainWindow.PictureSettings.crop_bottom.Text; string cropLeft = mainWindow.PictureSettings.crop_left.Text; string cropRight = mainWindow.PictureSettings.crop_right.Text; if (mainWindow.PictureSettings.check_customCrop.Checked) { if (mainWindow.PictureSettings.crop_top.Text == string.Empty) cropTop = "0"; if (mainWindow.PictureSettings.crop_bottom.Text == string.Empty) cropBottom = "0"; if (mainWindow.PictureSettings.crop_left.Text == string.Empty) cropLeft = "0"; if (mainWindow.PictureSettings.crop_right.Text == string.Empty) cropRight = "0"; query += " --crop " + cropTop + ":" + cropBottom + ":" + cropLeft + ":" + cropRight; } switch (mainWindow.PictureSettings.drp_anamorphic.SelectedIndex) { case 1: query += " --strict-anamorphic "; break; case 2: query += " --loose-anamorphic "; break; case 3: query += " --custom-anamorphic "; if (mainWindow.PictureSettings.drp_modulus.SelectedIndex != 0) query += " --modulus " + mainWindow.PictureSettings.drp_modulus.SelectedItem; if (mainWindow.PictureSettings.check_KeepAR.Checked) query += " --display-width " + mainWindow.PictureSettings.updownDisplayWidth.Text + " "; if (mainWindow.PictureSettings.check_KeepAR.Checked) query += " --keep-display-aspect "; if (!mainWindow.PictureSettings.check_KeepAR.Checked) if (mainWindow.PictureSettings.updownParWidth.Text != "" && mainWindow.PictureSettings.updownParHeight.Text != "") query += " --pixel-aspect " + mainWindow.PictureSettings.updownParWidth.Text + ":" + mainWindow.PictureSettings.updownParHeight.Text + " "; break; } #endregion #region Filters query += mainWindow.Filters.GetCLIQuery; #endregion #region Video Settings Tab switch (mainWindow.drp_videoEncoder.Text) { case "MPEG-4 (FFmpeg)": query += " -e ffmpeg"; break; case "H.264 (x264)": query += " -e x264"; break; case "VP3 (Theora)": query += " -e theora"; break; default: query += " -e x264"; break; } // Video Settings if (mainWindow.radio_avgBitrate.Checked) query += " -b " + mainWindow.text_bitrate.Text; if (mainWindow.radio_targetFilesize.Checked) query += " -S " + mainWindow.text_filesize.Text; // Video Quality Setting if (mainWindow.radio_cq.Checked) { double cqStep = Properties.Settings.Default.x264cqstep; double value; switch (mainWindow.drp_videoEncoder.Text) { case "MPEG-4 (FFmpeg)": value = 31 - (mainWindow.slider_videoQuality.Value - 1); query += " -q " + value.ToString(new CultureInfo("en-US")); break; case "H.264 (x264)": CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US"); value = 51 - mainWindow.slider_videoQuality.Value * cqStep; value = Math.Round(value, 2); query += " -q " + value.ToString(culture); break; case "VP3 (Theora)": value = mainWindow.slider_videoQuality.Value; query += " -q " + value.ToString(new CultureInfo("en-US")); break; } } if (mainWindow.check_2PassEncode.Checked) query += " -2 "; if (mainWindow.check_turbo.Checked) query += " -T "; if (mainWindow.drp_videoFramerate.Text != "Same as source") query += " -r " + mainWindow.drp_videoFramerate.Text; #endregion #region Audio Settings Tab ListView audioTracks = mainWindow.AudioSettings.GetAudioPanel(); List tracks = new List(); List codecs = new List(); List mixdowns = new List(); List samplerates = new List(); List bitrates = new List(); List drcs = new List(); // No Audio if (audioTracks.Items.Count == 0) query += " -a none "; // Gather information about each audio track and store them in the declared lists. foreach (ListViewItem row in audioTracks.Items) { // Audio Track (-a) if (row.SubItems[1].Text == "Automatic") tracks.Add("1"); else if (row.Text != "None") { string[] tempSub = row.SubItems[1].Text.Split(' '); tracks.Add(tempSub[0]); } // Audio Codec (-E) if (row.SubItems[2].Text != String.Empty) codecs.Add(GetAudioEncoder(row.SubItems[2].Text)); // Audio Mixdown (-6) if (row.SubItems[3].Text != String.Empty) mixdowns.Add(GetMixDown(row.SubItems[3].Text)); // Sample Rate (-R) if (row.SubItems[4].Text != String.Empty) samplerates.Add(row.SubItems[4].Text); // Audio Bitrate (-B) if (row.SubItems[5].Text != String.Empty) bitrates.Add(row.SubItems[5].Text.Replace("Auto", "auto")); // DRC (-D) if (row.SubItems[6].Text != String.Empty) drcs.Add(row.SubItems[6].Text); } // Audio Track (-a) String audioItems = ""; Boolean firstLoop = true; foreach (String item in tracks) { if (firstLoop) { audioItems = item; firstLoop = false; } else audioItems += "," + item; } if (audioItems.Trim() != String.Empty) query += " -a " + audioItems; firstLoop = true; audioItems = ""; // Reset for another pass. // Audio Codec (-E) foreach (String item in codecs) { if (firstLoop) { audioItems = item; firstLoop = false; } else audioItems += "," + item; } if (audioItems.Trim() != String.Empty) query += " -E " + audioItems; firstLoop = true; audioItems = ""; // Reset for another pass. // Audio Mixdown (-6) foreach (String item in mixdowns) { if (firstLoop) { audioItems = item; firstLoop = false; } else audioItems += "," + item; } if (audioItems.Trim() != String.Empty) query += " -6 " + audioItems; firstLoop = true; audioItems = ""; // Reset for another pass. // Sample Rate (-R) foreach (String item in samplerates) { if (firstLoop) { audioItems = item; firstLoop = false; } else audioItems += "," + item; } if (audioItems.Trim() != String.Empty) query += " -R " + audioItems; firstLoop = true; audioItems = ""; // Reset for another pass. // Audio Bitrate (-B) foreach (String item in bitrates) { if (firstLoop) { audioItems = item; firstLoop = false; } else audioItems += "," + item; } if (audioItems.Trim() != String.Empty) query += " -B " + audioItems; firstLoop = true; audioItems = ""; // Reset for another pass. // DRC (-D) foreach (var itm in drcs) { string item = itm.ToString(new CultureInfo("en-US")); if (firstLoop) { audioItems = item; firstLoop = false; } else audioItems += "," + item; } if (audioItems.Trim() != String.Empty) query += " -D " + audioItems; #endregion #region Subtitles Tab if (mainWindow.Subtitles.lv_subList.Items.Count != 0) // If we have subtitle tracks { IDictionary langMap = Main.MapLanguages(); // BitMap and CC's string subtitleTracks = String.Empty; string subtitleForced = String.Empty; string subtitleBurn = String.Empty; string subtitleDefault = String.Empty; // SRT string srtFile = String.Empty; string srtCodeset = String.Empty; string srtOffset = String.Empty; string srtLang = String.Empty; string srtDefault = String.Empty; int srtCount = 0; List SubList = mainWindow.Subtitles.GetSubtitleInfoList(); foreach (var item in SubList) { string itemToAdd, trackID; if (item.SrtPath != "-") // We have an SRT file { srtCount++; // SRT track id. srtLang += srtLang == "" ? langMap[item.SrtLang] : "," + langMap[item.SrtLang]; srtCodeset += srtCodeset == "" ? item.SrtCharCode : "," + item.SrtCharCode; if (item.Default == "Yes") // default srtDefault = srtCount.ToString(); itemToAdd = item.SrtPath; srtFile += srtFile == "" ? itemToAdd : "," + itemToAdd; itemToAdd = item.SrtOffset.ToString(); srtOffset += srtOffset == "" ? itemToAdd : "," + itemToAdd; } else // We have Bitmap or CC { string[] tempSub; // Find --subtitle if (item.Track.Contains("Foreign Audio Search")) itemToAdd = "scan"; else { tempSub = item.Track.Split(' '); itemToAdd = tempSub[0]; } subtitleTracks += subtitleTracks == "" ? itemToAdd : "," + itemToAdd; // Find --subtitle-forced itemToAdd = ""; tempSub = item.Track.Split(' '); trackID = tempSub[0]; if (item.Forced == "Yes") itemToAdd = "scan"; if (itemToAdd != "") subtitleForced += subtitleForced == "" ? itemToAdd : "," + itemToAdd; // Find --subtitle-burn and --subtitle-default trackID = tempSub[0]; if (trackID.Trim() == "Foreign") trackID = "scan"; if (item.Burned == "Yes") // burn subtitleBurn = trackID; if (item.Default == "Yes") // default subtitleDefault = trackID; } } // Build The CLI Subtitles Query if (subtitleTracks != "") { query += " --subtitle " + subtitleTracks; if (subtitleForced != "") query += " --subtitle-forced=" + subtitleForced; if (subtitleBurn != "") query += " --subtitle-burn=" + subtitleBurn; if (subtitleDefault != "") query += " --subtitle-default=" + subtitleDefault; } if (srtFile != "") // SRTs { query += " --srt-file " + "\"" + srtFile + "\""; if (srtCodeset != "") query += " --srt-codeset " + srtCodeset; if (srtOffset != "") query += " --srt-offset " + srtOffset; if (srtLang != "") query += " --srt-lang " + srtLang; if (srtDefault != "") query += " --srt-default=" + srtDefault; } } #endregion #region Chapter Markers // Attach Source name and dvd title to the start of the chapters.csv filename. // This is for the queue. It allows different chapter name files for each title. string[] destName = mainWindow.text_destination.Text.Split('\\'); string dest_name = destName[destName.Length - 1]; dest_name = dest_name.Replace("\"", ""); dest_name = dest_name.Replace(".mp4", "").Replace(".m4v", "").Replace(".mkv", ""); string source_title = mainWindow.drp_dvdtitle.Text; string[] titlesplit = source_title.Split(' '); source_title = titlesplit[0]; if (mainWindow.Check_ChapterMarkers.Checked && mainWindow.Check_ChapterMarkers.Enabled) { if (dest_name.Trim() != String.Empty) { string path = source_title != "Automatic" ? Path.Combine(Path.GetTempPath(), dest_name + "-" + source_title + "-chapters.csv") : Path.Combine(Path.GetTempPath(), dest_name + "-chapters.csv"); if (ChapterCSVSave(mainWindow, path) == false) query += " -m "; else query += " --markers=" + "\"" + path + "\""; } else query += " -m"; } #endregion #region H264 Tab if (mainWindow.x264Panel.X264Query != "") query += " -x " + mainWindow.x264Panel.X264Query; #endregion #region Processors / Other string processors = Properties.Settings.Default.Processors; if (processors != "Automatic") query += " -C " + processors + " "; query += " -v " + Properties.Settings.Default.verboseLevel; if (Properties.Settings.Default.noDvdNav) query += " --no-dvdnav"; #endregion return query; } /// /// Return the CLI Mixdown name /// /// GUI mixdown name /// CLI mixdown name private static string GetMixDown(string selectedAudio) { switch (selectedAudio) { case "Automatic": return "auto"; case "Mono": return "mono"; case "Stereo": return "stereo"; case "Dolby Surround": return "dpl1"; case "Dolby Pro Logic II": return "dpl2"; case "6 Channel Discrete": return "6ch"; default: return "auto"; } } /// /// Get the CLI Audio Encoder name /// /// string The GUI Encode name /// string CLI encoder name private static string GetAudioEncoder(string selectedEncoder) { switch (selectedEncoder) { case "AAC (faac)": return "faac"; case "MP3 (lame)": return "lame"; case "Vorbis (vorbis)": return "vorbis"; case "AC3 Passthru": return "ac3"; case "DTS Passthru": return "dts"; default: return ""; } } /// /// Create a CSV file with the data from the Main Window Chapters tab /// /// Main Window /// Path to save the csv file /// True if successful private static Boolean ChapterCSVSave(frmMain mainWindow, string filePathName) { try { string csv = ""; foreach (DataGridViewRow row in mainWindow.data_chpt.Rows) { csv += row.Cells[0].Value.ToString(); csv += ","; csv += row.Cells[1].Value.ToString().Replace(",","\\,"); csv += Environment.NewLine; } StreamWriter file = new StreamWriter(filePathName); file.Write(csv); file.Close(); file.Dispose(); return true; } catch (Exception exc) { MessageBox.Show("Unable to save Chapter Makrers file! \nChapter marker names will NOT be saved in your encode \n\n" + exc, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } } } }