// --------------------------------------------------------------------------------------------------------------------
//
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
//
//
// The Subtitles View Model
//
// --------------------------------------------------------------------------------------------------------------------
using System.IO;
namespace HandBrakeWPF.ViewModels
{
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using Caliburn.Micro;
using HandBrake.ApplicationServices.Model;
using HandBrake.ApplicationServices.Model.Encoding;
using HandBrake.ApplicationServices.Parsing;
using HandBrake.ApplicationServices.Services.Interfaces;
using HandBrake.ApplicationServices.Utilities;
using HandBrakeWPF.ViewModels.Interfaces;
using Ookii.Dialogs.Wpf;
///
/// The Subtitles View Model
///
[Export(typeof(ISubtitlesViewModel))]
public class SubtitlesViewModel : ViewModelBase, ISubtitlesViewModel
{
#region Constants and Fields
///
/// Backing field for the source subtitle tracks.
///
private IList sourceTracks;
///
/// The Foreign Audio Search Track
///
private readonly Subtitle ForeignAudioSearchTrack;
#endregion
#region Constructors and Destructors
///
/// Initializes a new instance of the class.
///
///
/// The window manager.
///
///
/// The user Setting Service.
///
public SubtitlesViewModel(IWindowManager windowManager, IUserSettingService userSettingService)
{
this.Task = new EncodeTask();
this.Langauges = LanguageUtilities.MapLanguages().Keys;
this.CharacterCodes = CharCodesUtilities.GetCharacterCodes();
this.ForeignAudioSearchTrack = new Subtitle { SubtitleType = SubtitleType.ForeignAudioSearch, Language = "Foreign Audio Search (Bitmap)" };
this.SourceTracks = new List { this.ForeignAudioSearchTrack };
}
#endregion
#region Properties
///
/// Gets or sets CharacterCodes.
///
public IEnumerable CharacterCodes { get; set; }
///
/// Gets or sets Langauges.
///
public IEnumerable Langauges { get; set; }
///
/// Gets or sets SourceTracks.
///
public IList SourceTracks
{
get
{
return this.sourceTracks;
}
set
{
this.sourceTracks = value;
this.NotifyOfPropertyChange(() => this.SourceTracks);
}
}
///
/// Gets or sets Task.
///
public EncodeTask Task { get; set; }
#endregion
#region Public Methods
///
/// Add a new Track
///
public void Add()
{
this.Add(null);
}
///
/// Automatic Subtitle Selection based on user preferences.
///
public void AutomaticSubtitleSelection()
{
this.Task.SubtitleTracks.Clear();
// New DUB Settings
int mode = this.UserSettingService.GetUserSetting(UserSettingConstants.DubModeSubtitle);
switch (mode)
{
case 1: // Adding all remaining subtitle tracks
this.AddAllRemaining();
break;
case 2: // Adding only the first or preferred first subtitle track.
this.Add();
break;
case 3: // Selected Languages Only
this.AddAllRemainingForSelectedLanguages();
break;
case 4: // Prefered Only
this.AddForPreferredLanaguages(true);
break;
case 5: // Prefered Only All
this.AddForPreferredLanaguages(false);
break;
}
// Add all closed captions if enabled.
this.AddAllClosedCaptions();
}
///
/// Import an SRT File.
///
public void Import()
{
VistaOpenFileDialog dialog = new VistaOpenFileDialog
{
Filter = "SRT files (*.srt)|*.srt",
CheckFileExists = true,
Multiselect = true
};
dialog.ShowDialog();
foreach (var srtFile in dialog.FileNames)
{
SubtitleTrack track = new SubtitleTrack
{
SrtFileName = Path.GetFileNameWithoutExtension(srtFile),
SrtOffset = 0,
SrtCharCode = "UTF-8",
SrtLang = "English",
SubtitleType = SubtitleType.SRT,
SrtPath = srtFile
};
this.Task.SubtitleTracks.Add(track);
}
}
///
/// Remove a Track
///
///
/// The track.
///
public void Remove(SubtitleTrack track)
{
this.Task.SubtitleTracks.Remove(track);
}
///
/// Select the default subtitle track.
///
///
/// The subtitle.
///
public void SelectDefaultTrack(SubtitleTrack subtitle)
{
foreach (SubtitleTrack track in this.Task.SubtitleTracks)
{
if (track == subtitle)
{
continue; // Skip the track the user selected.
}
track.Default = false;
}
this.NotifyOfPropertyChange(() => this.Task);
}
///
/// Select the burned in track.
///
///
/// The subtitle.
///
public void SelectBurnedInTrack(SubtitleTrack subtitle)
{
foreach (SubtitleTrack track in this.Task.SubtitleTracks)
{
if (track == subtitle)
{
continue; // Skip the track the user selected.
}
track.Burned = false;
}
this.NotifyOfPropertyChange(() => this.Task);
}
#endregion
#region Implemented Interfaces
#region ITabInterface
///
/// Setup this tab for the specified preset.
///
///
/// The preset.
///
///
/// The task.
///
public void SetPreset(Preset preset, EncodeTask task)
{
// Note, We don't support Subtitles in presets yet.
this.Task = task;
this.NotifyOfPropertyChange(() => this.Task);
}
///
/// Update all the UI controls based on the encode task passed in.
///
///
/// The task.
///
public void UpdateTask(EncodeTask task)
{
this.Task = task;
this.NotifyOfPropertyChange(() => this.Task.SubtitleTracks);
this.NotifyOfPropertyChange(() => this.Task);
}
///
/// Setup this window for a new source
///
///
/// The title.
///
///
/// The preset.
///
///
/// The task.
///
public void SetSource(Title title, Preset preset, EncodeTask task)
{
this.SourceTracks.Clear();
this.SourceTracks.Add(ForeignAudioSearchTrack);
foreach (Subtitle subtitle in title.Subtitles)
{
this.SourceTracks.Add(subtitle);
}
this.Task = task;
this.NotifyOfPropertyChange(() => this.Task);
this.AutomaticSubtitleSelection();
}
#endregion
#endregion
#region Methods
///
/// Add a subtitle track.
/// The Source track is set based on the following order. If null, it will skip to the next option.
/// 1. Passed in Subitle param
/// 2. First preferred Subtitle from source
/// 3. First subtitle from source.
/// Will not add a subtitle if the source has none.
///
///
/// The subtitle. Use null to add preferred, or first from source (based on user preference)
///
private void Add(Subtitle subtitle)
{
string preferred =
this.UserSettingService.GetUserSetting(UserSettingConstants.NativeLanguageForSubtitles);
Subtitle source = subtitle ??
((this.SourceTracks != null)
? (this.SourceTracks.FirstOrDefault(l => l.Language == preferred) ??
this.SourceTracks.FirstOrDefault(s => s.SubtitleType != SubtitleType.ForeignAudioSearch))
: null);
if (source == null)
{
source = ForeignAudioSearchTrack;
}
SubtitleTrack track = new SubtitleTrack
{
SubtitleType = SubtitleType.VobSub,
SourceTrack = source,
};
this.Task.SubtitleTracks.Add(track);
}
///
/// Add all closed captions not already on the list.
///
private void AddAllClosedCaptions()
{
if (this.UserSettingService.GetUserSetting(UserSettingConstants.UseClosedCaption))
{
foreach (
Subtitle subtitle in this.SourceTitlesSubset(null).Where(s => s.SubtitleType == SubtitleType.CC))
{
this.Add(subtitle);
}
}
}
///
/// Add all the remaining subtitle tracks.
///
private void AddAllRemaining()
{
foreach (Subtitle subtitle in this.SourceTitlesSubset(null))
{
this.Add(subtitle);
}
}
///
/// Add all remaining tracks for the users preferred and selected languages
///
private void AddAllRemainingForSelectedLanguages()
{
// Get a list of subtitle tracks that match the users lanaguages
StringCollection userSelectedLanguages =
this.UserSettingService.GetUserSetting(UserSettingConstants.SelectedLanguages);
userSelectedLanguages.Add(
this.UserSettingService.GetUserSetting(UserSettingConstants.NativeLanguageForSubtitles));
List availableTracks =
this.SourceTracks.Where(subtitle => userSelectedLanguages.Contains(subtitle.Language)).ToList();
foreach (Subtitle subtitle in this.SourceTitlesSubset(availableTracks))
{
this.Add(subtitle);
}
}
///
/// Add all tracks for the preferred languages settings.
///
///
/// The first only.
///
private void AddForPreferredLanaguages(bool firstOnly)
{
string preferred =
this.UserSettingService.GetUserSetting(UserSettingConstants.NativeLanguageForSubtitles);
foreach (Subtitle subtitle in this.SourceTitlesSubset(null))
{
if (subtitle.Language == preferred)
{
this.Add(subtitle);
if (firstOnly)
{
break;
}
}
}
}
///
/// Gets a list of Source subtitle tracks that are not currently used.
///
///
/// The subtitles. (Optional). If null, works on the full source subtitle collection
///
///
/// An IEnumerable collection of subtitles
///
private IEnumerable SourceTitlesSubset(IEnumerable subtitles)
{
return subtitles != null
? subtitles.Where(
subtitle => !this.Task.SubtitleTracks.Any(track => track.SourceTrack == subtitle)).ToList()
: this.SourceTracks.Where(
subtitle => !this.Task.SubtitleTracks.Any(track => track.SourceTrack == subtitle)).ToList();
}
#endregion
}
}