// --------------------------------------------------------------------------------------------------------------------
//
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
//
//
// The Audio View Model
//
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrakeWPF.ViewModels
{
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel.Composition;
using System.Linq;
using Caliburn.Micro;
using HandBrake.ApplicationServices.Functions;
using HandBrake.ApplicationServices.Model;
using HandBrake.ApplicationServices.Model.Encoding;
using HandBrake.ApplicationServices.Parsing;
using HandBrake.ApplicationServices.Services.Interfaces;
using HandBrake.Interop.Model.Encoding;
using HandBrakeWPF.ViewModels.Interfaces;
///
/// The Audio View Model
///
[Export(typeof(IAudioViewModel))]
public class AudioViewModel : ViewModelBase, IAudioViewModel
{
///
/// Backing field for the source tracks list.
///
private IEnumerable sourceTracks;
#region Constructors and Destructors
///
/// Initializes a new instance of the class.
///
///
/// The window manager.
///
///
/// The user Setting Service.
///
public AudioViewModel(IWindowManager windowManager, IUserSettingService userSettingService)
{
this.Task = new EncodeTask();
this.SampleRates = new ObservableCollection { "Auto", "48", "44.1", "32", "24", "22.05" };
this.AudioBitrates = this.GetAppropiateBitrates(AudioEncoder.ffaac, Mixdown.DolbyProLogicII);
this.AudioEncoders = EnumHelper.GetEnumList();
this.AudioMixdowns = EnumHelper.GetEnumList();
this.SourceTracks = new List();
}
#endregion
#region Properties
///
/// Gets or sets AudioBitrates.
///
public IEnumerable AudioBitrates { get; set; }
///
/// Gets or sets AudioEncoders.
///
public IEnumerable AudioEncoders { get; set; }
///
/// Gets or sets AudioMixdowns.
///
public IEnumerable AudioMixdowns { get; set; }
///
/// Gets or sets SampleRates.
///
public IEnumerable SampleRates { get; set; }
///
/// Gets or sets SourceTracks.
///
public IEnumerable SourceTracks
{
get
{
return this.sourceTracks;
}
set
{
this.sourceTracks = value;
this.NotifyOfPropertyChange(() => this.SourceTracks);
}
}
///
/// Gets or sets the EncodeTask.
///
public EncodeTask Task { get; set; }
///
/// Gets a value indicating whether ShowPassthruOptions.
///
public bool ShowPassthruOptions
{
get
{
return this.UserSettingService.GetUserSetting(UserSettingConstants.ShowAdvancedAudioPassthruOpts);
}
}
#endregion
#region Public Methods
///
/// Add an Audio Track
///
public void Add()
{
// Add the first track if available.
this.Add(null);
}
///
/// Remove the Selected Track
///
///
/// The track.
///
public void Remove(AudioTrack track)
{
this.Task.AudioTracks.Remove(track);
}
///
/// Trigger a Notify Property Changed on the Task to force various UI elements to update.
///
public void RefreshTask()
{
this.NotifyOfPropertyChange(() => this.Task);
if (Task.OutputFormat == OutputFormat.Mp4)
{
foreach (AudioTrack track in this.Task.AudioTracks.Where(track => track.Encoder == AudioEncoder.ffflac || track.Encoder == AudioEncoder.Vorbis))
{
track.Encoder = AudioEncoder.ffaac;
}
}
}
#endregion
#region Implemented Interfaces
#region ITabInterface
///
/// Setup this tab for the specified preset.
///
///
/// The preset.
///
///
/// The task.
///
public void SetPreset(Preset preset, EncodeTask task)
{
this.Task = task;
if (preset != null && preset.Task != null)
{
this.AddTracksFromPreset(preset);
this.Task.AllowedPassthruOptions = new AllowedPassthru(preset.Task.AllowedPassthruOptions);
}
this.NotifyOfPropertyChange(() => this.Task);
this.Task.AllowedPassthruOptions.IsEnabled =
this.UserSettingService.GetUserSetting(UserSettingConstants.ShowAdvancedAudioPassthruOpts);
}
///
/// Set the Source Title
///
///
/// The title.
///
///
/// The preset.
///
///
/// The task.
///
public void SetSource(Title title, Preset preset, EncodeTask task)
{
this.SourceTracks = title.AudioTracks;
// Only reset the audio tracks if we have none, or if the task is null.
if (this.Task == null || this.Task.AudioTracks.Count == 0)
{
this.SetPreset(preset, task);
}
// If there are no source tracks, clear the list, otherwise try to Auto-Select the correct tracks
if (this.SourceTracks == null || !this.SourceTracks.Any())
{
this.Task.AudioTracks.Clear();
}
else
{
this.AutomaticTrackSelection();
}
// Force UI Updates
this.NotifyOfPropertyChange(() => this.Task);
}
#endregion
#endregion
#region Methods
///
/// Add the specified source track, or the first track in the SourceTracks collection if available.
///
///
/// The source track.
///
private void Add(Audio sourceTrack)
{
if (this.SourceTracks != null)
{
Audio track = sourceTrack ?? this.SourceTracks.FirstOrDefault();
if (track != null)
{
this.Task.AudioTracks.Add(new AudioTrack { ScannedTrack = track });
}
}
}
///
/// Add all source tracks that don't currently exist on the list.
///
private void AddAllRemaining()
{
foreach (Audio sourceTrack in this.SourceTracks)
{
bool found = this.Task.AudioTracks.Any(audioTrack => audioTrack.ScannedTrack == sourceTrack);
if (!found)
{
this.Add(sourceTrack);
}
}
}
///
/// Add the required tracks for the current preset
///
///
/// The preset.
///
private void AddTracksFromPreset(Preset preset)
{
// Clear out the old tracks
this.Task.AudioTracks.Clear();
// Get the preferred Language
IEnumerable preferredAudioTracks =
this.SourceTracks.Where(
item =>
item.Language.Contains(
this.UserSettingService.GetUserSetting(UserSettingConstants.NativeLanguage)));
Audio preferred = preferredAudioTracks.FirstOrDefault() ?? this.SourceTracks.FirstOrDefault();
// Add the preset audio tracks with the preferred language
foreach (AudioTrack track in preset.Task.AudioTracks)
{
this.Task.AudioTracks.Add(new AudioTrack(track) { ScannedTrack = preferred });
}
}
///
/// Attempt to automatically select the correct audio tracks based on the users settings.
///
private void AutomaticTrackSelection()
{
List trackList = new List();
if (!this.SourceTracks.Any())
{
return;
}
// Step 1: Fetch all the Preferred Language settings
if (this.UserSettingService.GetUserSetting(UserSettingConstants.NativeLanguage) == "Any")
{
// If we have Any as the preferred Language, just set the first track to all audio tracks.
trackList.Add(this.SourceTracks.FirstOrDefault());
}
else
{
// Otherwise, fetch the preferred language.
foreach (
Audio item in
this.SourceTracks.Where(
item =>
item.Language.Contains(
this.UserSettingService.GetUserSetting(UserSettingConstants.NativeLanguage))))
{
trackList.Add(item);
break;
}
}
// Step 2: Handle "All Remaining Tracks" and "All for Selected Languages" or use the default behaviour
int mode = this.UserSettingService.GetUserSetting(UserSettingConstants.DubModeAudio);
switch (mode)
{
default: // Default by setting all existing tracks to a preferred or first source track.
foreach (AudioTrack track in this.Task.AudioTracks)
{
track.ScannedTrack = trackList.FirstOrDefault() ?? this.SourceTracks.FirstOrDefault();
}
break;
case 1: // Adding all remaining audio tracks
this.AddAllRemaining();
break;
case 2: // Add Langauges tracks for the additional languages selected, in-order.
// Figure out the source tracks we want to add
trackList.Clear();
foreach (
string language in
this.UserSettingService.GetUserSetting(
UserSettingConstants.SelectedLanguages))
{
// TODO add support for "Add only 1 per language"
trackList.AddRange(this.SourceTracks.Where(source => source.Language.Trim() == language));
}
// Add them if they are not already added.
foreach (Audio sourceTrack in trackList)
{
bool found = this.Task.AudioTracks.Any(audioTrack => audioTrack.ScannedTrack == sourceTrack);
if (!found)
{
this.Add(sourceTrack);
}
}
break;
}
}
///
/// Get Appropiate Bitrates for the selected encoder and mixdown.
///
///
/// The encoder.
///
///
/// The mixdown.
///
///
/// A List of valid audio bitrates
///
private IEnumerable GetAppropiateBitrates(AudioEncoder encoder, Mixdown mixdown)
{
return new ObservableCollection { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 640, 768 };
}
#endregion
}
}