2 This file is part of the HandBrake source code.
\r
3 Homepage: <http://handbrake.fr>.
\r
4 It may be used under the terms of the GNU General Public License. */
\r
6 namespace Handbrake.Controls
\r
9 using System.Collections.Generic;
\r
12 using System.Windows.Forms;
\r
15 using HandBrake.ApplicationServices.Model;
\r
16 using HandBrake.ApplicationServices.Model.Encoding;
\r
21 /// The Subtitles Tab
\r
23 public partial class Subtitles : UserControl
\r
25 #region Priavate Variables and Collections
\r
28 /// Map of languages to language codes
\r
30 private readonly IDictionary<string, string> langMap = new Dictionary<string, string>();
\r
33 /// A List of SRT Files
\r
35 private readonly IDictionary<string, string> srtFiles = new Dictionary<string, string>();
\r
38 /// The Subtitle List
\r
40 private readonly List<SubtitleTrack> subList = new List<SubtitleTrack>();
\r
45 /// Initializes a new instance of the <see cref="Subtitles"/> class.
\r
49 InitializeComponent();
\r
51 langMap = Main.MapLanguages();
\r
52 foreach (string key in langMap.Keys)
\r
53 srt_lang.Items.Add(key);
\r
55 srt_charcode.SelectedIndex = 28;
\r
56 srt_lang.SelectedIndex = 40;
\r
59 #region Public Methods
\r
61 /// Gets the CLI Query for this panel
\r
63 /// <returns>A CliQuery string</returns>
\r
64 public string GetCliQuery
\r
68 string query = string.Empty;
\r
69 if (lv_subList.Items.Count != 0) // If we have subtitle tracks
\r
72 string subtitleTracks = String.Empty;
\r
73 string subtitleForced = String.Empty;
\r
74 string subtitleBurn = String.Empty;
\r
75 string subtitleDefault = String.Empty;
\r
78 string srtFile = String.Empty;
\r
79 string srtCodeset = String.Empty;
\r
80 string srtOffset = String.Empty;
\r
81 string srtLang = String.Empty;
\r
82 string srtDefault = String.Empty;
\r
86 foreach (SubtitleTrack item in subList)
\r
90 if (item.IsSrtSubtitle) // We have an SRT file
\r
92 srtCount++; // SRT track id.
\r
94 srtLang += srtLang == string.Empty ? langMap[item.SrtLang] : "," + langMap[item.SrtLang];
\r
95 srtCodeset += srtCodeset == string.Empty ? item.SrtCharCode : "," + item.SrtCharCode;
\r
98 srtDefault = srtCount.ToString();
\r
100 itemToAdd = item.SrtPath;
\r
101 srtFile += srtFile == string.Empty ? itemToAdd : "," + itemToAdd;
\r
103 itemToAdd = item.SrtOffset.ToString();
\r
104 srtOffset += srtOffset == string.Empty ? itemToAdd : "," + itemToAdd;
\r
106 else // We have Bitmap or CC
\r
110 // Find --subtitle <string>
\r
111 if (item.Track.Contains("Foreign Audio Search"))
\r
112 itemToAdd = "scan";
\r
115 string[] tempSub = item.Track.Split(' ');
\r
116 itemToAdd = tempSub[0];
\r
119 subtitleTracks += subtitleTracks == string.Empty ? itemToAdd : "," + itemToAdd;
\r
121 // Find --subtitle-forced
\r
123 subtitleForced += subtitleForced == string.Empty ? subCount.ToString() : "," + subCount;
\r
125 // Find --subtitle-burn
\r
127 subtitleBurn = subCount.ToString();
\r
129 // Find --subtitle-default
\r
131 subtitleDefault = subCount.ToString();
\r
135 // Build The CLI Subtitles Query
\r
136 if (subtitleTracks != string.Empty)
\r
138 query += " --subtitle " + subtitleTracks;
\r
140 if (subtitleForced != string.Empty)
\r
141 query += " --subtitle-forced=" + subtitleForced;
\r
142 if (subtitleBurn != string.Empty)
\r
143 query += " --subtitle-burn=" + subtitleBurn;
\r
144 if (subtitleDefault != string.Empty)
\r
145 query += " --subtitle-default=" + subtitleDefault;
\r
148 if (srtFile != string.Empty) // SRTs
\r
150 query += " --srt-file " + "\"" + srtFile + "\"";
\r
152 if (srtCodeset != string.Empty)
\r
153 query += " --srt-codeset " + srtCodeset;
\r
154 if (srtOffset != string.Empty)
\r
155 query += " --srt-offset " + srtOffset;
\r
156 if (srtLang != string.Empty)
\r
157 query += " --srt-lang " + srtLang;
\r
158 if (srtDefault != string.Empty)
\r
159 query += " --srt-default=" + srtDefault;
\r
167 /// Checks of the current settings will require the m4v file extension
\r
169 /// <returns>True if Yes</returns>
\r
170 public bool RequiresM4V()
\r
172 return this.subList.Any(track => track.SubtitleType != SubtitleType.VobSub);
\r
176 /// Automatically setup the subtitle tracks.
\r
177 /// This handles the automatic setup of subitles which the user can control from the program options
\r
179 /// <param name="subs">List of Subtitles</param>
\r
180 public void SetSubtitleTrackAuto(object[] subs)
\r
182 drp_subtitleTracks.Items.Clear();
\r
183 drp_subtitleTracks.Items.Add("Foreign Audio Search (Bitmap)");
\r
184 drp_subtitleTracks.Items.AddRange(subs);
\r
185 drp_subtitleTracks.SelectedIndex = 0;
\r
188 this.AutomaticSubtitleSelection();
\r
192 /// Automatic Subtitle Selection based on user preferences.
\r
194 public void AutomaticSubtitleSelection()
\r
196 // Handle Native Language and "Dub Foreign language audio" and "Use Foreign language audio and Subtitles" Options
\r
197 if (Properties.Settings.Default.NativeLanguage != "Any")
\r
199 if (Properties.Settings.Default.DubMode != 1) // We need to add a subtitle track if this is false.
\r
201 foreach (object item in drp_subtitleTracks.Items)
\r
203 if (item.ToString().Contains(Properties.Settings.Default.NativeLanguage))
\r
205 drp_subtitleTracks.SelectedItem = item;
\r
206 BtnAddSubTrackClick(this, new EventArgs());
\r
210 if (drp_subtitleTracks.SelectedIndex == 0 && Properties.Settings.Default.useClosedCaption)
\r
212 foreach (object item in drp_subtitleTracks.Items)
\r
214 if (item.ToString().Contains("Closed"))
\r
216 drp_subtitleTracks.SelectedItem = item;
\r
217 BtnAddSubTrackClick(this, new EventArgs());
\r
226 /// Clear the Subtitle List
\r
228 public void Clear()
\r
230 lv_subList.Items.Clear();
\r
235 #region Primary Controls
\r
238 /// Add a Subtitle track.
\r
240 /// <param name="sender">
\r
243 /// <param name="e">
\r
246 private void BtnAddSubTrackClick(object sender, EventArgs e)
\r
249 string forcedVal = check_forced.CheckState == CheckState.Checked ? "Yes" : "No";
\r
250 string defaultSub = check_default.CheckState == CheckState.Checked ? "Yes" : "No";
\r
251 string burnedVal = check_burned.CheckState == CheckState.Checked &&
\r
252 (drp_subtitleTracks.Text.Contains("(VOBSUB)") || drp_subtitleTracks.Text.Contains("(SSA)"))
\r
255 string srtCode = "-", srtLangVal = "-", srtPath = "-", srtFile = "-";
\r
256 int srtOffsetMs = 0;
\r
258 if (drp_subtitleTracks.SelectedItem.ToString().Contains(".srt"))
\r
260 srtFiles.TryGetValue(drp_subtitleTracks.SelectedItem.ToString(), out srtPath);
\r
261 srtFile = drp_subtitleTracks.SelectedItem.ToString();
\r
262 srtLangVal = srt_lang.SelectedItem.ToString();
\r
263 srtCode = srt_charcode.SelectedItem.ToString();
\r
264 srtOffsetMs = (int)srt_offset.Value;
\r
265 if (defaultSub == "Yes") this.SetDefaultToOffForAllSRTTracks();
\r
269 if (defaultSub == "Yes") this.SetDefaultToOffForAllTracks();
\r
270 if (burnedVal == "Yes") this.SetBurnedToOffForAllTracks();
\r
273 string trackName = (drp_subtitleTracks.SelectedItem.ToString().Contains(".srt"))
\r
274 ? srtLangVal + " (" + srtFile + ")"
\r
275 : drp_subtitleTracks.SelectedItem.ToString();
\r
277 SubtitleTrack track = new SubtitleTrack
\r
280 Forced = check_forced.Checked,
\r
281 Burned = check_burned.Checked,
\r
282 Default = check_default.Checked,
\r
283 SrtLang = srtLangVal,
\r
284 SrtCharCode = srtCode,
\r
285 SrtOffset = srtOffsetMs,
\r
287 SrtFileName = srtFile
\r
290 lv_subList.Items.Add(track.ListView);
\r
291 subList.Add(track);
\r
295 /// Import an SRT Subtitle Track
\r
297 /// <param name="sender">
\r
300 /// <param name="e">
\r
303 private void BtnSrtAddClick(object sender, EventArgs e)
\r
305 if (openFileDialog.ShowDialog() != DialogResult.OK)
\r
308 if (srtFiles.ContainsKey(Path.GetFileName(openFileDialog.FileName)))
\r
311 "A Subtitle track with the same name has already been imported.",
\r
313 MessageBoxButtons.OK,
\r
314 MessageBoxIcon.Warning);
\r
318 drp_subtitleTracks.Items.Add(Path.GetFileName(openFileDialog.FileName));
\r
319 drp_subtitleTracks.SelectedItem = Path.GetFileName(openFileDialog.FileName);
\r
320 srtFiles.Add(Path.GetFileName(openFileDialog.FileName), openFileDialog.FileName);
\r
324 /// Remove a subtitle track
\r
326 /// <param name="sender">
\r
329 /// <param name="e">
\r
332 private void BtnRemoveSubTrackClick(object sender, EventArgs e)
\r
334 this.RemoveSelectedTrack();
\r
338 /// The Subtitle List selected index has changed
\r
340 /// <param name="sender">
\r
343 /// <param name="e">
\r
346 private void LbSubListSelectedIndexChanged(object sender, EventArgs e)
\r
348 // Set the dropdown controls based on the selected item in the List.
\r
349 if (lv_subList.Items.Count != 0 && lv_subList.SelectedIndices.Count != 0)
\r
351 SubtitleTrack track = subList[lv_subList.SelectedIndices[0]];
\r
354 if (lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[0].Text.ToLower().Contains(".srt"))
\r
357 foreach (var item in drp_subtitleTracks.Items)
\r
359 if (item.ToString() == track.SrtFileName)
\r
360 drp_subtitleTracks.SelectedIndex = c;
\r
363 srt_lang.SelectedItem = track.SrtLang;
\r
364 srt_offset.Value = track.SrtOffset;
\r
365 srt_charcode.SelectedItem = track.SrtCharCode;
\r
366 check_default.CheckState = track.Default ? CheckState.Checked : CheckState.Unchecked;
\r
367 SubGroupBox.Text = "Selected Track: " + track.Track;
\r
369 else // We have Bitmap/CC
\r
371 foreach (var item in drp_subtitleTracks.Items)
\r
373 if (item.ToString() == track.Track)
\r
374 drp_subtitleTracks.SelectedIndex = c;
\r
377 check_forced.CheckState = track.Forced ? CheckState.Checked : CheckState.Unchecked;
\r
378 check_burned.CheckState = track.Burned ? CheckState.Checked : CheckState.Unchecked;
\r
379 check_default.CheckState = track.Default ? CheckState.Checked : CheckState.Unchecked;
\r
380 SubGroupBox.Text = "Selected Track: " +
\r
381 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[0].Text;
\r
385 SubGroupBox.Text = "Selected Track: None (Click \"Add\" to add another track to the list)";
\r
390 #region Subtitle Controls
\r
393 /// Handle the Subtitle track dropdown changed event
\r
395 /// <param name="sender">
\r
398 /// <param name="e">
\r
401 private void DrpSubtitleTracksSelectedIndexChanged(object sender, EventArgs e)
\r
403 if (drp_subtitleTracks.SelectedItem.ToString().Contains(".srt"))
\r
405 check_forced.Enabled = false;
\r
406 check_burned.Enabled = false;
\r
407 srt_lang.Enabled = true;
\r
408 srt_charcode.Enabled = true;
\r
409 srt_offset.Enabled = true;
\r
413 check_forced.Enabled = true;
\r
414 check_burned.Enabled = true;
\r
415 srt_lang.Enabled = false;
\r
416 srt_charcode.Enabled = false;
\r
417 srt_offset.Enabled = false;
\r
419 // Update an item in the list if required.
\r
420 if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;
\r
422 if (drp_subtitleTracks.SelectedItem.ToString().Contains(".srt"))
\r
424 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[0].Text = srt_lang.SelectedItem + "(" +
\r
425 drp_subtitleTracks.SelectedItem + ")";
\r
426 lv_subList.Select();
\r
429 srtFiles.TryGetValue(drp_subtitleTracks.SelectedItem.ToString(), out srtPath);
\r
430 subList[lv_subList.SelectedIndices[0]].SrtPath = srtPath;
\r
434 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[0].Text =
\r
435 drp_subtitleTracks.SelectedItem.ToString();
\r
436 lv_subList.Select();
\r
439 subList[lv_subList.SelectedIndices[0]].Track = drp_subtitleTracks.SelectedItem.ToString();
\r
443 /// Foreced Subtitles checkbox changed
\r
445 /// <param name="sender">
\r
448 /// <param name="e">
\r
451 private void CheckForcedCheckedChanged(object sender, EventArgs e)
\r
453 if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;
\r
455 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[1].Text = check_forced.Checked ? "Yes" : "No";
\r
456 lv_subList.Select();
\r
458 subList[lv_subList.SelectedIndices[0]].Forced = check_forced.Checked;
\r
459 // Update SubList List<SubtitleInfo>
\r
463 /// Burned in subtitles checkbox changed
\r
465 /// <param name="sender">
\r
468 /// <param name="e">
\r
471 private void CheckBurnedCheckedChanged(object sender, EventArgs e)
\r
473 if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;
\r
475 if (check_burned.Checked) // Make sure we only have 1 burned track
\r
476 this.SetBurnedToOffForAllTracks();
\r
478 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[2].Text = check_burned.Checked ? "Yes" : "No";
\r
479 lv_subList.Select();
\r
481 subList[lv_subList.SelectedIndices[0]].Burned = check_burned.Checked;
\r
482 // Update SubList List<SubtitleInfo>
\r
486 /// Default Subitle track check changed
\r
488 /// <param name="sender">
\r
491 /// <param name="e">
\r
494 private void CheckDefaultCheckedChanged(object sender, EventArgs e)
\r
496 if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;
\r
498 if (check_default.Checked) // Make sure we only have 1 default track
\r
499 if (lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[0].Text.Contains(".srt"))
\r
500 this.SetDefaultToOffForAllSRTTracks();
\r
502 this.SetDefaultToOffForAllTracks();
\r
504 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[3].Text = check_default.Checked ? "Yes" : "No";
\r
505 lv_subList.Select();
\r
507 subList[lv_subList.SelectedIndices[0]].Default = check_default.Checked;
\r
508 // Update SubList List<SubtitleInfo>
\r
512 /// Srt Offset Numeric Control Changed
\r
514 /// <param name="sender">
\r
517 /// <param name="e">
\r
520 private void SrtOffsetValueChanged(object sender, EventArgs e)
\r
522 // Update an item in the list if required.
\r
523 if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0)
\r
526 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[6].Text = srt_offset.Value.ToString();
\r
527 lv_subList.Select();
\r
529 subList[lv_subList.SelectedIndices[0]].SrtOffset = (int)srt_offset.Value;
\r
530 // Update SubList List<SubtitleInfo>
\r
534 /// The SRT Charcode changed
\r
536 /// <param name="sender">
\r
539 /// <param name="e">
\r
542 private void SrtCharcodeSelectedIndexChanged(object sender, EventArgs e)
\r
544 if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;
\r
546 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[5].Text = srt_charcode.SelectedItem.ToString();
\r
547 lv_subList.Select();
\r
549 subList[lv_subList.SelectedIndices[0]].SrtCharCode = srt_charcode.SelectedItem.ToString();
\r
550 // Update SubList List<SubtitleInfo>
\r
554 /// The Srt Language code changed
\r
556 /// <param name="sender">
\r
559 /// <param name="e">
\r
562 private void SrtLangSelectedIndexChanged(object sender, EventArgs e)
\r
564 if (lv_subList.Items.Count == 0 || lv_subList.SelectedIndices.Count == 0) return;
\r
566 lv_subList.Items[lv_subList.SelectedIndices[0]].SubItems[4].Text = srt_lang.SelectedItem.ToString();
\r
567 lv_subList.Select();
\r
569 subList[lv_subList.SelectedIndices[0]].SrtLang = srt_lang.SelectedItem.ToString();
\r
570 // Update SubList List<SubtitleInfo>
\r
575 #region Right Click Menu
\r
578 /// Move an item in the subtitle list up
\r
580 /// <param name="sender">
\r
583 /// <param name="e">
\r
586 private void MnuMoveupClick(object sender, EventArgs e)
\r
588 if (lv_subList.SelectedIndices.Count != 0)
\r
590 ListViewItem item = lv_subList.SelectedItems[0];
\r
591 int index = item.Index;
\r
594 if (lv_subList.Items.Count > index && index >= 0)
\r
596 lv_subList.Items.Remove(item);
\r
597 lv_subList.Items.Insert(index, item);
\r
598 item.Selected = true;
\r
599 lv_subList.Focus();
\r
605 /// Move an item in the subtitle list down
\r
607 /// <param name="sender">
\r
610 /// <param name="e">
\r
613 private void MnuMovedownClick(object sender, EventArgs e)
\r
615 if (lv_subList.SelectedIndices.Count != 0)
\r
617 ListViewItem item = lv_subList.SelectedItems[0];
\r
618 int index = item.Index;
\r
621 if (index < lv_subList.Items.Count)
\r
623 lv_subList.Items.Remove(item);
\r
624 lv_subList.Items.Insert(index, item);
\r
625 item.Selected = true;
\r
626 lv_subList.Focus();
\r
632 /// Remove a selected subtitle track.
\r
634 /// <param name="sender">
\r
637 /// <param name="e">
\r
640 private void MnuRemoveClick(object sender, EventArgs e)
\r
642 this.RemoveSelectedTrack();
\r
649 /// Set all Non SRT tracks to Default = NO
\r
651 private void SetDefaultToOffForAllTracks()
\r
654 foreach (ListViewItem item in lv_subList.Items)
\r
656 if (subList[c].SrtPath == "-")
\r
658 if (item.SubItems[3].Text == "Yes")
\r
660 item.SubItems[3].Text = "No";
\r
661 subList[c].Default = false;
\r
669 /// Set all subtitle tracks so that they have no default.
\r
671 private void SetDefaultToOffForAllSRTTracks()
\r
674 foreach (ListViewItem item in lv_subList.Items)
\r
676 if (!subList[c].IsSrtSubtitle)
\r
678 if (item.SubItems[3].Text == "Yes")
\r
680 item.SubItems[3].Text = "No";
\r
681 subList[c].Default = false;
\r
689 /// Set all tracks to Burned = No
\r
691 private void SetBurnedToOffForAllTracks()
\r
694 foreach (ListViewItem item in lv_subList.Items)
\r
696 if (item.SubItems[2].Text == "Yes")
\r
698 item.SubItems[2].Text = "No";
\r
699 subList[c].Burned = false;
\r
706 /// Remove a selected track
\r
708 private void RemoveSelectedTrack()
\r
710 // Remove the Item and reselect the control if the following conditions are met.
\r
711 if (lv_subList.SelectedItems.Count != 0)
\r
713 // Record the current selected index.
\r
714 int currentPosition = lv_subList.SelectedIndices[0];
\r
715 int selectedInd = lv_subList.SelectedIndices[0];
\r
717 lv_subList.Items.RemoveAt(selectedInd);
\r
718 subList.RemoveAt(selectedInd);
\r
720 // Now reslect the correct item and give focus to the list.
\r
721 if (lv_subList.Items.Count != 0)
\r
723 if (currentPosition <= (lv_subList.Items.Count - 1))
\r
724 lv_subList.Items[currentPosition].Selected = true;
\r
725 else if (currentPosition > (lv_subList.Items.Count - 1))
\r
726 lv_subList.Items[lv_subList.Items.Count - 1].Selected = true;
\r
728 lv_subList.Select();
\r