/* AudioPanel.cs $ This file is part of the HandBrake source code. Homepage: . It may be used under the terms of the GNU General Public License. */ namespace Handbrake.Controls { using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Windows.Forms; using HandBrake.ApplicationServices.Functions; using HandBrake.ApplicationServices.Model; using HandBrake.ApplicationServices.Model.Encoding; using HandBrake.ApplicationServices.Parsing; using HandBrake.ApplicationServices.Utilities; using AudioTrack = HandBrake.ApplicationServices.Model.Encoding.AudioTrack; /// /// The AudioPanel Control /// public partial class AudioPanel : UserControl { private static readonly CultureInfo Culture = new CultureInfo("en-US", false); private const string AC3Passthru = "AC3 Passthru"; private const string DTSPassthru = "DTS Passthru"; /// /// Initializes a new instance of the class. /// Create a new instance of the Audio Panel /// public AudioPanel() { InitializeComponent(); drp_audioMix.SelectedItem = "Dolby Pro Logic II"; drp_audioSample.SelectedIndex = 1; } /// /// The audio list has changed /// public event EventHandler AudioListChanged; #region Public Methods /// /// Get the audio panel /// /// A listview containing the audio tracks public DataGridView GetAudioPanel() { return audioList; } /// /// Set the File Container. This funciton is used to limit the available options for each file container. /// /// /// the file path /// public void SetContainer(string path) { string oldval = drp_audioEncoder.Text; drp_audioEncoder.Items.Clear(); drp_audioEncoder.Items.Add("AAC (faac)"); drp_audioEncoder.Items.Add("MP3 (lame)"); drp_audioEncoder.Items.Add(AC3Passthru); drp_audioEncoder.Items.Add("AC3 (ffmpeg)"); if (path.Contains("MKV")) { drp_audioEncoder.Items.Add(DTSPassthru); drp_audioEncoder.Items.Add("Vorbis (vorbis)"); } if (!drp_audioEncoder.Text.Contains(oldval)) drp_audioEncoder.SelectedIndex = 0; else drp_audioEncoder.SelectedItem = oldval; // Make sure the table is updated with new audio codecs // Defaults to AAC encoding. foreach (DataGridViewRow row in audioList.Rows) { if (!drp_audioEncoder.Items.Contains(row.Cells[2].Value)) row.Cells[2].Value = drp_audioEncoder.Items[0].ToString(); } } /// /// Checks if the settings used required the .m4v (rather than .mp4) extension /// /// True if m4v is required public bool RequiresM4V() { return this.audioList.Rows.Cast().Any(row => row.Cells[2].Value.ToString().Contains("AC3")); } /// /// Load an arraylist of AudioTrack items into the list. /// /// List of audio tracks public void LoadTracks(List audioTracks) { ClearAudioList(); if (audioTracks == null) return; foreach (AudioTrack track in audioTracks) { DataGridViewRow newTrack = new DataGridViewRow(); newTrack.CreateCells(audioList); newTrack.Cells[0].Value = GetNewID().ToString(); newTrack.Cells[1].Value = "Automatic"; newTrack.Cells[2].Value = EnumHelper.GetDescription(track.Encoder); newTrack.Cells[3].Value = EnumHelper.GetDescription(track.MixDown); newTrack.Cells[4].Value = (track.Encoder == AudioEncoder.Ac3Passthrough || track.Encoder == AudioEncoder.DtsPassthrough || track.SampleRate == 0.0) ? "Auto" : track.SampleRate.ToString(); newTrack.Cells[5].Value = (track.Encoder == AudioEncoder.Ac3Passthrough || track.Encoder == AudioEncoder.DtsPassthrough) ? "Auto" : track.Bitrate.ToString(); newTrack.Cells[6].Value = (track.Encoder == AudioEncoder.Ac3Passthrough || track.Encoder == AudioEncoder.DtsPassthrough) ? string.Empty : track.DRC.ToString(); AddTrackForPreset(newTrack); } this.AutomaticTrackSelection(); } /// /// Set the Track list dropdown from the parsed title captured during the scan /// /// The selected title /// A preset public void SetTrackListFromPreset(Title selectedTitle, Preset preset) { if (selectedTitle.AudioTracks.Count == 0) { audioList.Rows.Clear(); drp_audioTrack.Items.Clear(); drp_audioTrack.Items.Add("None Found"); drp_audioTrack.SelectedIndex = 0; return; } // Setup the Audio track source dropdown with the new audio tracks. drp_audioTrack.Items.Clear(); drp_audioTrack.Items.AddRange(selectedTitle.AudioTracks.ToArray()); // Add any tracks the preset has, if there is a preset and no audio tracks in the list currently if (audioList.Rows.Count == 0 && preset != null) { EncodeTask parsed = QueryParserUtility.Parse(preset.Query); foreach (AudioTrack audioTrack in parsed.AudioTracks) { DataGridViewRow newTrack = new DataGridViewRow(); newTrack.CreateCells(audioList); newTrack.Cells[0].Value = GetNewID().ToString(); newTrack.Cells[1].Value = (audioTrack.Track); newTrack.Cells[2].Value = (audioTrack.Encoder); newTrack.Cells[3].Value = (audioTrack.MixDown); newTrack.Cells[4].Value = (audioTrack.SampleRate); newTrack.Cells[5].Value = (audioTrack.Bitrate); newTrack.Cells[6].Value = (audioTrack.DRC); audioList.Rows.Add(newTrack); } } this.AutomaticTrackSelection(); } #endregion #region Control and ListView /// /// one of the controls has changed. Event handler /// /// /// The sender. /// /// /// The e. /// private void ControlChanged(object sender, EventArgs e) { Control ctl = (Control)sender; switch (ctl.Name) { case "drp_audioTrack": if (audioList.Rows.Count != 0 && audioList.SelectedRows.Count != 0) { audioList.SelectedRows[0].Cells[1].Value = drp_audioTrack.Text; // If the track isn't AC3, and the encoder is, change it. if (audioList.SelectedRows[0].Cells[2].Value.ToString().Contains(AC3Passthru) && !audioList.SelectedRows[0].Cells[1].Value.ToString().Contains("(AC3)")) { // Switch to AAC drp_audioEncoder.SelectedIndex = 0; } // If the track isn't DTS, and the encoder is, change it. if (audioList.SelectedRows[0].Cells[2].Value.ToString().Contains(DTSPassthru) && !audioList.SelectedRows[0].Cells[1].Value.ToString().Contains("DTS")) { // Switch to AAC drp_audioEncoder.SelectedIndex = 0; } } break; case "drp_audioEncoder": SetMixDown(); SetBitrate(); // Configure the widgets with values if (drp_audioEncoder.Text.Contains(AC3Passthru) || drp_audioEncoder.Text.Contains(DTSPassthru)) { drp_audioMix.Enabled = drp_audioBitrate.Enabled = drp_audioSample.Enabled = tb_drc.Enabled = false; lbl_bitrate.Enabled = lbl_drc.Enabled = lbl_drcHeader.Enabled = lbl_mixdown.Enabled = lbl_sampleRate.Enabled = false; } else { drp_audioMix.Enabled = drp_audioBitrate.Enabled = drp_audioSample.Enabled = tb_drc.Enabled = true; lbl_bitrate.Enabled = lbl_drc.Enabled = lbl_drcHeader.Enabled = lbl_mixdown.Enabled = lbl_sampleRate.Enabled = true; } // Update an item in the Audio list if required. if (audioList.Rows.Count != 0 && audioList.SelectedRows.Count != 0) audioList.SelectedRows[0].Cells[2].Value = drp_audioEncoder.Text; break; case "drp_audioMix": SetBitrate(); if (audioList.Rows.Count != 0 && audioList.SelectedRows.Count != 0) audioList.SelectedRows[0].Cells[3].Value = drp_audioMix.Text; break; case "drp_audioSample": if (audioList.Rows.Count != 0 && audioList.SelectedRows.Count != 0) audioList.SelectedRows[0].Cells[4].Value = drp_audioSample.Text; break; case "drp_audioBitrate": // Update an item in the Audio list if required. if (audioList.Rows.Count != 0 && audioList.SelectedRows.Count != 0) audioList.SelectedRows[0].Cells[5].Value = drp_audioBitrate.Text; break; case "tb_drc": double value; if (tb_drc.Value == 0) value = 0; else value = ((tb_drc.Value - 1) / 10.0) + 1; lbl_drc.Text = value.ToString(); // Update an item in the Audio list if required. if (audioList.Rows.Count != 0 && audioList.SelectedRows.Count != 0) { audioList.SelectedRows[0].Cells[6].Value = value.ToString(); audioList.Select(); } break; } audioList.Select(); } /// /// The Audio List selected index changed event handler /// /// /// The sender. /// /// /// The e. /// private void audioList_SelectionChanged(object sender, EventArgs e) { // Set the dropdown controls based on the selected item in the Audio List. if (audioList.Rows.Count != 0 && audioList.SelectedRows.Count != 0) { drp_audioTrack.SelectedItem = audioList.SelectedRows[0].Cells[1].Value; drp_audioEncoder.SelectedItem = audioList.SelectedRows[0].Cells[2].Value; drp_audioMix.SelectedItem = audioList.SelectedRows[0].Cells[3].Value; drp_audioSample.SelectedItem = audioList.SelectedRows[0].Cells[4].Value; drp_audioBitrate.SelectedItem = audioList.SelectedRows[0].Cells[5].Value; double drcValue; int drcCalculated; double.TryParse(audioList.SelectedRows[0].Cells[6].Value.ToString(), out drcValue); if (drcValue != 0) drcValue = ((drcValue * 10) + 1) - 10; int.TryParse(drcValue.ToString(Culture), out drcCalculated); tb_drc.Value = drcCalculated; lbl_drc.Text = audioList.SelectedRows[0].Cells[6].Value.ToString(); AudioTrackGroup.Text = "Selected Track: " + audioList.SelectedRows[0].Cells[0].Value; } else AudioTrackGroup.Text = "Selected Track: None (Click \"Add Track\" to add)"; } #endregion #region Track Controls /// /// The Add Audio Track button event handler /// /// /// The sender. /// /// /// The e. /// private void btn_addAudioTrack_Click(object sender, EventArgs e) { if (drp_audioTrack.Text == "None Found") { MessageBox.Show( "Your source appears to have no audio tracks that HandBrake supports.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } double value = 0; if (tb_drc.Value != 0) value = ((tb_drc.Value - 1) / 10.0) + 1; // Create a new row for the Audio list based on the currently selected items in the dropdown. DataGridViewRow newTrack = new DataGridViewRow(); newTrack.CreateCells(audioList); newTrack.Cells[0].Value = GetNewID().ToString(); newTrack.Cells[1].Value = drp_audioTrack.Text; newTrack.Cells[2].Value = drp_audioEncoder.Text; newTrack.Cells[3].Value = drp_audioMix.Text; newTrack.Cells[4].Value = drp_audioSample.Text; newTrack.Cells[5].Value = drp_audioBitrate.Text; newTrack.Cells[6].Value = value.ToString(); audioList.Rows.Add(newTrack); // The Audio List has changed to raise the event. if (this.AudioListChanged != null) this.AudioListChanged(this, new EventArgs()); // Select the newly added track and select the control audioList.ClearSelection(); audioList.Rows[audioList.Rows.Count - 1].Selected = true; audioList.Select(); } /// /// The Remove Track button event handler /// /// /// The sender. /// /// /// The e. /// private void btn_RemoveAudioTrack_Click(object sender, EventArgs e) { RemoveTrack(); } #endregion #region Audio List Menu /// /// The Audio List Move Up menu item /// /// /// The sender. /// /// /// The e. /// private void audioList_moveup_Click(object sender, EventArgs e) { MoveTrack(true); } /// /// The audio list move down menu item /// /// /// The sender. /// /// /// The e. /// private void audioList_movedown_Click(object sender, EventArgs e) { MoveTrack(false); } /// /// The audio list remove menu item /// /// /// The sender. /// /// /// The e. /// private void audioList_remove_Click(object sender, EventArgs e) { RemoveTrack(); } #endregion #region Private Functions private void AutomaticTrackSelection() { // Handle Native Language and "Dub Foreign language audio" and "Use Foreign language audio and Subtitles" Options if (Properties.Settings.Default.NativeLanguage == "Any") { drp_audioTrack.SelectedIndex = 0; foreach (DataGridViewRow item in audioList.Rows) { if (this.drp_audioTrack.SelectedItem != null) { item.Cells[1].Value = this.drp_audioTrack.SelectedItem.ToString(); } } } else { int mode = Properties.Settings.Default.DubMode; switch (mode) { case 1: case 3: // Dub Foreign Language Audio // Select the prefered language audio, or the first track if it doesn't exist. int i = 0; foreach (object item in drp_audioTrack.Items) { if (item.ToString().Contains(Properties.Settings.Default.NativeLanguage)) { drp_audioTrack.SelectedIndex = i; break; } i++; } if (drp_audioTrack.SelectedItem != null) foreach (DataGridViewRow item in audioList.Rows) item.Cells[1].Value = drp_audioTrack.SelectedItem.ToString(); else { drp_audioTrack.SelectedIndex = 0; if (drp_audioTrack.SelectedItem != null) foreach (DataGridViewRow item in audioList.Rows) item.Cells[1].Value = drp_audioTrack.SelectedItem.ToString(); } break; case 2: default: // Select the first track which is hopefully the default and foreign track. drp_audioTrack.SelectedIndex = 0; if (drp_audioTrack.SelectedItem != null) foreach (DataGridViewRow item in audioList.Rows) item.Cells[1].Value = drp_audioTrack.SelectedItem.ToString(); break; } } } /// /// Add track for preset /// /// /// The item. /// private void AddTrackForPreset(DataGridViewRow item) { audioList.Rows.Add(item); if (this.AudioListChanged != null) this.AudioListChanged(this, new EventArgs()); } /// /// Clear the audio list /// private void ClearAudioList() { audioList.Rows.Clear(); if (this.AudioListChanged != null) this.AudioListChanged(this, new EventArgs()); } /// /// Get a new ID for the next audio track /// /// /// an int /// private int GetNewID() { return audioList.Rows.Count + 1; } /// /// Remove an audio track from the list /// private void RemoveTrack() { // Remove the Item and reselect the control if the following conditions are met. if (audioList.SelectedRows.Count != 0) { // The Audio List is about to change so raise the event. if (this.AudioListChanged != null) this.AudioListChanged(this, new EventArgs()); // Record the current selected index. int currentPosition = audioList.SelectedRows[0].Index; audioList.Rows.Remove(audioList.SelectedRows[0]); // Now reslect the correct item and give focus to the audio list. if (audioList.Rows.Count != 0) { audioList.ClearSelection(); if (currentPosition <= (audioList.Rows.Count - 1)) audioList.Rows[currentPosition].Selected = true; else if (currentPosition > (audioList.Rows.Count - 1)) audioList.Rows[audioList.Rows.Count - 1].Selected = true; audioList.Select(); } // Regenerate the ID numers ReGenerateListIDs(); } } /// /// Move an audio track up or down the audio list /// /// /// The up. /// private void MoveTrack(bool up) { if (audioList.SelectedRows.Count == 0) return; DataGridViewRow item = audioList.SelectedRows[0]; int index = item.Index; if (up) index--; else index++; if (index < audioList.Rows.Count || (audioList.Rows.Count > index && index >= 0)) { audioList.Rows.Remove(item); audioList.Rows.Insert(index, item); audioList.ClearSelection(); item.Selected = true; } } /// /// Regenerate all the audio track id's on the audio list /// private void ReGenerateListIDs() { int i = 1; foreach (DataGridViewRow item in audioList.Rows) { item.Cells[0].Value = i.ToString(); i++; } } /// /// Set the bitrate dropdown /// private void SetBitrate() { int max = 0; string defaultRate = "160"; // Remove defaults drp_audioBitrate.Items.Remove("Auto"); drp_audioBitrate.Items.Remove("192"); drp_audioBitrate.Items.Remove("224"); drp_audioBitrate.Items.Remove("256"); drp_audioBitrate.Items.Remove("320"); drp_audioBitrate.Items.Remove("384"); drp_audioBitrate.Items.Remove("448"); drp_audioBitrate.Items.Remove("640"); drp_audioBitrate.Items.Remove("768"); // Find Max and Defaults based on encoders switch (drp_audioEncoder.Text) { case "AAC (faac)": max = drp_audioMix.Text.Contains("6 Channel") ? 768 : 320; defaultRate = "160"; break; case "MP3 (lame)": max = 320; defaultRate = "160"; break; case "Vorbis (vorbis)": defaultRate = "160"; max = 384; break; case "AC3 (ffmpeg)": defaultRate = "640"; max = 640; break; case AC3Passthru: drp_audioBitrate.Items.Add("Auto"); defaultRate = "Auto"; drp_audioSample.SelectedItem = "Auto"; break; case DTSPassthru: drp_audioBitrate.Items.Add("Auto"); defaultRate = "Auto"; drp_audioSample.SelectedItem = "Auto"; break; } // Re-add appropiate options if (max > 160) { drp_audioBitrate.Items.Add("192"); drp_audioBitrate.Items.Add("224"); drp_audioBitrate.Items.Add("256"); drp_audioBitrate.Items.Add("320"); } if (max > 320) { drp_audioBitrate.Items.Add("384"); } if (max >= 640) { drp_audioBitrate.Items.Add("448"); drp_audioBitrate.Items.Add("640"); } if (max == 768) { drp_audioBitrate.Items.Add("768"); } // Set the default bit-rate drp_audioBitrate.SelectedItem = defaultRate; } /// /// Set the mixdown dropdown /// private void SetMixDown() { drp_audioMix.Items.Clear(); drp_audioMix.Items.Add("Mono"); drp_audioMix.Items.Add("Stereo"); drp_audioMix.Items.Add("Dolby Surround"); drp_audioMix.Items.Add("Dolby Pro Logic II"); drp_audioMix.Items.Add("6 Channel Discrete"); drp_audioMix.Items.Add(AC3Passthru); drp_audioMix.Items.Add(DTSPassthru); drp_audioMix.SelectedItem = "Dolby Pro Logic II"; switch (drp_audioEncoder.Text) { case "AAC (faac)": drp_audioMix.Items.Remove(AC3Passthru); drp_audioMix.Items.Remove(DTSPassthru); break; case "MP3 (lame)": drp_audioMix.Items.Remove("6 Channel Discrete"); drp_audioMix.Items.Remove(AC3Passthru); drp_audioMix.Items.Remove(DTSPassthru); break; case "Vorbis (vorbis)": drp_audioMix.Items.Remove(AC3Passthru); drp_audioMix.Items.Remove(DTSPassthru); break; case "AC3 (ffmpeg)": drp_audioMix.Items.Remove(AC3Passthru); drp_audioMix.Items.Remove(DTSPassthru); break; case "AC3 Passthru": drp_audioMix.SelectedItem = AC3Passthru; break; case "DTS Passthru": drp_audioMix.SelectedItem = DTSPassthru; break; } } #endregion } }