From 7569b18d51170f3b421b5b77df02b5b0a0e2dda0 Mon Sep 17 00:00:00 2001 From: sr55 Date: Sun, 26 May 2013 16:28:07 +0000 Subject: [PATCH] Merging Trunk to OpenCL git-svn-id: svn://svn.handbrake.fr/HandBrake/branches/opencl@5518 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- libhb/common.h | 6 +- libhb/vfr.c | 61 +++---- libhb/work.c | 10 +- .../ASUserSettingConstants.cs | 25 --- .../EventArgs/EncodeCompletedEventArgs.cs | 14 +- .../Model/EncodeTask.cs | 3 + .../Model/PresetPictureSettingsMode.cs | 6 +- .../Services/Encode.cs | 24 +-- .../Services/LibEncode.cs | 24 +-- .../Services/QueueProcessor.cs | 99 +++-------- .../Utilities/PlistUtility.cs | 2 + win/CS/HandBrake.Server/Program.cs | 4 - .../AttachedProperties/DriveMenu.cs | 127 ++++++++++++++ win/CS/HandBrakeWPF/Constants.cs | 15 ++ win/CS/HandBrakeWPF/HandBrakeWPF.csproj | 6 +- win/CS/HandBrakeWPF/Helpers/AutoNameHelper.cs | 4 +- win/CS/HandBrakeWPF/Helpers/CliCheckHelper.cs | 5 +- win/CS/HandBrakeWPF/Model/SourceMenuItem.cs | 5 + .../Properties/Resources.Designer.cs | 31 +++- win/CS/HandBrakeWPF/Properties/Resources.resx | 16 +- .../Services/DriveDetectService.cs | 97 ----------- .../Interfaces/IDriveDetectService.cs | 32 ---- .../Interfaces/INotificationService.cs | 14 +- .../Interfaces/IPrePostActionService.cs | 18 ++ .../Services/PrePostActionService.cs | 159 ++++++++++++++++++ .../Startup/CastleBootstrapper.cs | 2 +- win/CS/HandBrakeWPF/UserSettingConstants.cs | 25 +++ .../ViewModels/AddPresetViewModel.cs | 17 +- .../Interfaces/IAddPresetViewModel.cs | 6 +- .../Interfaces/IQueueSelectionViewModel.cs | 6 +- .../HandBrakeWPF/ViewModels/MainViewModel.cs | 118 ++++++++----- .../ViewModels/OptionsViewModel.cs | 26 +-- .../ViewModels/PictureSettingsViewModel.cs | 109 ++++++------ .../ViewModels/QueueSelectionViewModel.cs | 48 +++++- .../HandBrakeWPF/ViewModels/QueueViewModel.cs | 95 +++++------ .../HandBrakeWPF/ViewModels/VideoViewModel.cs | 2 +- win/CS/HandBrakeWPF/Views/AddPresetView.xaml | 2 +- win/CS/HandBrakeWPF/Views/AudioView.xaml | 11 +- win/CS/HandBrakeWPF/Views/MainView.xaml | 7 +- .../Views/QueueSelectionView.xaml | 22 ++- win/CS/HandBrakeWPF/Views/QueueView.xaml | 83 ++++++--- win/CS/HandBrakeWPF/Views/SubtitlesView.xaml | 23 ++- win/CS/HandBrakeWPF/Views/VideoView.xaml | 4 +- 43 files changed, 848 insertions(+), 565 deletions(-) create mode 100644 win/CS/HandBrakeWPF/AttachedProperties/DriveMenu.cs delete mode 100644 win/CS/HandBrakeWPF/Services/DriveDetectService.cs delete mode 100644 win/CS/HandBrakeWPF/Services/Interfaces/IDriveDetectService.cs create mode 100644 win/CS/HandBrakeWPF/Services/Interfaces/IPrePostActionService.cs create mode 100644 win/CS/HandBrakeWPF/Services/PrePostActionService.cs diff --git a/libhb/common.h b/libhb/common.h index 6048922b6..caa706bfb 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -371,8 +371,6 @@ struct hb_job_s int vcodec; float vquality; int vbitrate; - int pfr_vrate; - int pfr_vrate_base; int vrate; int vrate_base; int cfr; @@ -1039,8 +1037,8 @@ typedef struct hb_filter_init_s int crop[4]; int vrate_base; int vrate; - int pfr_vrate_base; - int pfr_vrate; + int title_rate_base; + int title_rate; int cfr; #ifdef USE_OPENCL int use_dxva; diff --git a/libhb/vfr.c b/libhb/vfr.c index 844beef80..c2156f72d 100644 --- a/libhb/vfr.c +++ b/libhb/vfr.c @@ -301,20 +301,21 @@ static void adjust_frame_rate( hb_filter_private_t *pv, hb_buffer_t **buf_out ) } } -static int hb_vfr_init( hb_filter_object_t * filter, - hb_filter_init_t * init ) +static int hb_vfr_init(hb_filter_object_t *filter, hb_filter_init_t *init) { - filter->private_data = calloc( 1, sizeof(struct hb_filter_private_s) ); - hb_filter_private_t * pv = filter->private_data; - - build_gamma_lut( pv ); - pv->cfr = init->cfr; - pv->input_vrate = pv->vrate = init->vrate; - pv->input_vrate_base = pv->vrate_base = init->vrate_base; - if( filter->settings ) + filter->private_data = calloc(1, sizeof(struct hb_filter_private_s)); + hb_filter_private_t *pv = filter->private_data; + build_gamma_lut(pv); + + pv->cfr = init->cfr; + pv->vrate = init->vrate; + pv->vrate_base = init->vrate_base; + pv->input_vrate = init->title_rate; + pv->input_vrate_base = init->title_rate_base; + if (filter->settings != NULL) { - sscanf( filter->settings, "%d:%d:%d", - &pv->cfr, &pv->vrate, &pv->vrate_base ); + sscanf(filter->settings, "%d:%d:%d", + &pv->cfr, &pv->vrate, &pv->vrate_base); } pv->job = init->job; @@ -336,36 +337,18 @@ static int hb_vfr_init( hb_filter_object_t * filter, pv->lost_time[0] = 0; pv->lost_time[1] = 0; pv->lost_time[2] = 0; pv->lost_time[3] = 0; pv->frame_metric = 1000; // Force first frame - if ( pv->cfr == 0 ) + if (!pv->cfr) { /* Ensure we're using "Same as source" FPS */ - pv->vrate_base = init->vrate_base; - pv->vrate = init->vrate; - } - else if ( pv->cfr == 2 ) - { - // For PFR, we want the framerate based on the source's actual - // framerate, unless it's higher than the specified peak framerate. - double source_fps = (double)init->vrate / init->vrate_base; - double peak_fps = (double)pv->vrate / pv->vrate_base; - if ( source_fps > peak_fps ) - { - // peak framerate is lower than source framerate. so signal - // that the nominal framerate will be changed. - init->vrate = pv->vrate; - init->vrate_base = pv->vrate_base; - } - init->pfr_vrate = pv->vrate; - init->pfr_vrate_base = pv->vrate_base; - } - else - { - // Constant framerate. Signal the framerate we are using. - init->vrate = pv->vrate; - init->vrate_base = pv->vrate_base; + pv->vrate_base = pv->input_vrate_base; + pv->vrate = pv->input_vrate; } - init->cfr = pv->cfr; - pv->frame_rate = (double)pv->vrate_base * 90000. / pv->vrate; + pv->frame_rate = (double)pv->vrate_base * 90000. / pv->vrate; + init->cfr = pv->cfr; + init->vrate = pv->vrate; + init->vrate_base = pv->vrate_base; + init->title_rate = pv->input_vrate; + init->title_rate_base = pv->input_vrate_base; return 0; } diff --git a/libhb/work.c b/libhb/work.c index de6978c4c..d44206e1d 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -259,7 +259,7 @@ void hb_display_job_info( hb_job_t * job ) { hb_log( " + frame rate: %.3f fps -> peak rate limited to %.3f fps", (float) title->rate / (float) title->rate_base, - (float) job->pfr_vrate / (float) job->pfr_vrate_base ); + (float) job->vrate / (float) job->vrate_base ); } // Filters can modify dimensions. So show them first. @@ -718,8 +718,8 @@ static void do_job( hb_job_t * job ) memcpy(init.crop, job->crop, sizeof(int[4])); init.vrate_base = job->vrate_base; init.vrate = job->vrate; - init.pfr_vrate_base = job->pfr_vrate_base; - init.pfr_vrate = job->pfr_vrate; + init.title_rate_base = title->rate_base; + init.title_rate = title->rate; init.cfr = 0; for( i = 0; i < hb_list_count( job->list_filter ); ) { @@ -741,8 +741,8 @@ static void do_job( hb_job_t * job ) memcpy(job->crop, init.crop, sizeof(int[4])); job->vrate_base = init.vrate_base; job->vrate = init.vrate; - job->pfr_vrate_base = init.pfr_vrate_base; - job->pfr_vrate = init.pfr_vrate; + title->rate_base = init.title_rate_base; + title->rate = init.title_rate; job->cfr = init.cfr; } diff --git a/win/CS/HandBrake.ApplicationServices/ASUserSettingConstants.cs b/win/CS/HandBrake.ApplicationServices/ASUserSettingConstants.cs index 7e3ee4583..78f5b18ab 100644 --- a/win/CS/HandBrake.ApplicationServices/ASUserSettingConstants.cs +++ b/win/CS/HandBrake.ApplicationServices/ASUserSettingConstants.cs @@ -19,21 +19,11 @@ namespace HandBrake.ApplicationServices /// public const string Verbosity = "Verbosity"; - /// - /// When Complete Action - /// - public const string WhenCompleteAction = "WhenCompleteAction"; - /// /// Process Priority /// public const string ProcessPriority = "ProcessPriority"; - /// - /// Prevent Sleep - /// - public const string PreventSleep = "PreventSleep"; - /// /// Save Log Directory /// @@ -59,21 +49,6 @@ namespace HandBrake.ApplicationServices /// public const string DisableLibDvdNav = "DisableLibDvdNav"; - /// - /// Send file enabled. - /// - public const string SendFile = "SendFile"; - - /// - /// Send file to application path - /// - public const string SendFileTo = "SendFileTo"; - - /// - /// Send file to arguments - /// - public const string SendFileToArgs = "SendFileToArgs"; - /// /// Min Title Scan Duration /// diff --git a/win/CS/HandBrake.ApplicationServices/EventArgs/EncodeCompletedEventArgs.cs b/win/CS/HandBrake.ApplicationServices/EventArgs/EncodeCompletedEventArgs.cs index 44a66cac7..2bbb7ab97 100644 --- a/win/CS/HandBrake.ApplicationServices/EventArgs/EncodeCompletedEventArgs.cs +++ b/win/CS/HandBrake.ApplicationServices/EventArgs/EncodeCompletedEventArgs.cs @@ -12,6 +12,8 @@ namespace HandBrake.ApplicationServices.EventArgs using System; using System.Runtime.Serialization; + using HandBrake.ApplicationServices.Model; + /// /// Encode Progress Event Args /// @@ -30,13 +32,23 @@ namespace HandBrake.ApplicationServices.EventArgs /// /// The error information. /// - public EncodeCompletedEventArgs(bool sucessful, Exception exception, string errorInformation) + /// + /// The filename. + /// + public EncodeCompletedEventArgs(bool sucessful, Exception exception, string errorInformation, string filename) { this.Successful = sucessful; this.Exception = exception; this.ErrorInformation = errorInformation; + this.FileName = filename; } + /// + /// Gets or sets the file name. + /// + [DataMember] + public string FileName { get; set; } + /// /// Gets or sets a value indicating whether Successful. /// diff --git a/win/CS/HandBrake.ApplicationServices/Model/EncodeTask.cs b/win/CS/HandBrake.ApplicationServices/Model/EncodeTask.cs index 36d416c9d..c5499497b 100644 --- a/win/CS/HandBrake.ApplicationServices/Model/EncodeTask.cs +++ b/win/CS/HandBrake.ApplicationServices/Model/EncodeTask.cs @@ -133,9 +133,12 @@ namespace HandBrake.ApplicationServices.Model this.H264Level = task.H264Level; this.FastDecode = task.FastDecode; this.ExtraAdvancedArguments = task.ExtraAdvancedArguments; + this.PreviewStartAt = task.PreviewStartAt; this.PreviewDuration = task.PreviewDuration; + + this.ShowAdvancedTab = task.ShowAdvancedTab; } #region Source diff --git a/win/CS/HandBrake.ApplicationServices/Model/PresetPictureSettingsMode.cs b/win/CS/HandBrake.ApplicationServices/Model/PresetPictureSettingsMode.cs index e670ccb7e..d6a84a617 100644 --- a/win/CS/HandBrake.ApplicationServices/Model/PresetPictureSettingsMode.cs +++ b/win/CS/HandBrake.ApplicationServices/Model/PresetPictureSettingsMode.cs @@ -18,9 +18,11 @@ namespace HandBrake.ApplicationServices.Model { [Display(Name = "None")] None = 0, - [Display(Name = "Custom")] + [Display(Name = "Custom (Keep AR)")] Custom = 1, - [Display(Name = "Source Maximum")] + [Display(Name = "Current Source Max Size (Keep AR)")] SourceMaximum = 2, + [Display(Name = "No Limit (Keep AR)")] + NoLimit = 3, } } \ No newline at end of file diff --git a/win/CS/HandBrake.ApplicationServices/Services/Encode.cs b/win/CS/HandBrake.ApplicationServices/Services/Encode.cs index b4f572521..4779d353e 100644 --- a/win/CS/HandBrake.ApplicationServices/Services/Encode.cs +++ b/win/CS/HandBrake.ApplicationServices/Services/Encode.cs @@ -14,9 +14,8 @@ namespace HandBrake.ApplicationServices.Services using System.IO; using System.Windows.Forms; - using Caliburn.Micro; - using HandBrake.ApplicationServices.EventArgs; + using HandBrake.ApplicationServices.Exceptions; using HandBrake.ApplicationServices.Model; using HandBrake.ApplicationServices.Services.Base; using HandBrake.ApplicationServices.Services.Interfaces; @@ -95,11 +94,10 @@ namespace HandBrake.ApplicationServices.Services { if (this.IsEncoding) { - throw new Exception("HandBrake is already encodeing."); + throw new GeneralApplicationException("HandBrake is already encodeing.", "Please try again in a minute", null); } this.IsEncoding = true; - this.currentTask = encodeQueueTask; if (enableLogging) @@ -115,11 +113,6 @@ namespace HandBrake.ApplicationServices.Services } } - if (this.userSettingService.GetUserSetting(ASUserSettingConstants.PreventSleep)) - { - Win32.PreventSleep(); - } - // Make sure the path exists, attempt to create it if it doesn't this.VerifyEncodeDestinationPath(currentTask); @@ -200,9 +193,10 @@ namespace HandBrake.ApplicationServices.Services catch (Exception exc) { encodeQueueTask.Status = QueueItemStatus.Error; + this.IsEncoding = false; this.InvokeEncodeCompleted( new EncodeCompletedEventArgs( - false, null, "An Error occured when trying to encode this source. ")); + false, exc, "An Error occured when trying to encode this source. ", this.currentTask.Task.Destination)); throw; } } @@ -261,17 +255,9 @@ namespace HandBrake.ApplicationServices.Services // This exception doesn't warrent user interaction, but it should be logged (TODO) } - Execute.OnUIThread(() => - { - if (this.userSettingService.GetUserSetting(ASUserSettingConstants.PreventSleep)) - { - Win32.AllowSleep(); - } - }); - this.currentTask.Status = QueueItemStatus.Completed; this.IsEncoding = false; - this.InvokeEncodeCompleted(new EncodeCompletedEventArgs(true, null, string.Empty)); + this.InvokeEncodeCompleted(new EncodeCompletedEventArgs(true, null, string.Empty, this.currentTask.Task.Destination)); } /// diff --git a/win/CS/HandBrake.ApplicationServices/Services/LibEncode.cs b/win/CS/HandBrake.ApplicationServices/Services/LibEncode.cs index 33453dad8..f7247f6cf 100644 --- a/win/CS/HandBrake.ApplicationServices/Services/LibEncode.cs +++ b/win/CS/HandBrake.ApplicationServices/Services/LibEncode.cs @@ -11,7 +11,6 @@ namespace HandBrake.ApplicationServices.Services { using System; using System.Diagnostics; - using System.Globalization; using HandBrake.ApplicationServices.Model; using HandBrake.ApplicationServices.Services.Base; @@ -57,6 +56,11 @@ namespace HandBrake.ApplicationServices.Services /// private bool loggingEnabled; + /// + /// The Current Task + /// + private QueueTask currentTask; + #endregion /// @@ -95,6 +99,7 @@ namespace HandBrake.ApplicationServices.Services { this.startTime = DateTime.Now; this.loggingEnabled = enableLogging; + this.currentTask = job; try { @@ -123,12 +128,6 @@ namespace HandBrake.ApplicationServices.Services } } - // Prvent the system from sleeping if the user asks - if (this.userSettingService.GetUserSetting(ASUserSettingConstants.PreventSleep) ) - { - Win32.PreventSleep(); - } - // Verify the Destination Path Exists, and if not, create it. this.VerifyEncodeDestinationPath(job); @@ -163,7 +162,7 @@ namespace HandBrake.ApplicationServices.Services } catch (Exception exc) { - this.InvokeEncodeCompleted(new EncodeCompletedEventArgs(false, exc, "An Error has occured.")); + this.InvokeEncodeCompleted(new EncodeCompletedEventArgs(false, exc, "An Error has occured.", this.currentTask.Task.Destination)); } } @@ -271,13 +270,8 @@ namespace HandBrake.ApplicationServices.Services this.InvokeEncodeCompleted( e.Error - ? new EncodeCompletedEventArgs(false, null, string.Empty) - : new EncodeCompletedEventArgs(true, null, string.Empty)); - - if (this.userSettingService.GetUserSetting(ASUserSettingConstants.PreventSleep)) - { - Win32.AllowSleep(); - } + ? new EncodeCompletedEventArgs(false, null, string.Empty, this.currentTask.Task.Destination) + : new EncodeCompletedEventArgs(true, null, string.Empty, this.currentTask.Task.Destination)); this.ShutdownFileWriter(); } diff --git a/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs b/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs index a442dc5ce..a8cb55f58 100644 --- a/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs +++ b/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs @@ -12,10 +12,8 @@ namespace HandBrake.ApplicationServices.Services using System; using System.Collections.Generic; using System.ComponentModel; - using System.Diagnostics; using System.IO; using System.Linq; - using System.Windows.Forms; using System.Xml.Serialization; using Caliburn.Micro; @@ -53,6 +51,11 @@ namespace HandBrake.ApplicationServices.Services /// private string queueFile; + /// + /// The is paused. + /// + private bool isPaused; + #endregion #region Constructors and Destructors @@ -238,15 +241,15 @@ namespace HandBrake.ApplicationServices.Services { Execute.OnUIThread( () => + { + List deleteList = + this.queue.Where(task => task.Status == QueueItemStatus.Completed).ToList(); + foreach (QueueTask item in deleteList) { - List deleteList = - this.queue.Where(task => task.Status == QueueItemStatus.Completed).ToList(); - foreach (QueueTask item in deleteList) - { - this.queue.Remove(item); - } - this.InvokeQueueChanged(EventArgs.Empty); - }); + this.queue.Remove(item); + } + this.InvokeQueueChanged(EventArgs.Empty); + }); } /// @@ -381,8 +384,8 @@ namespace HandBrake.ApplicationServices.Services catch (Exception exc) { throw new GeneralApplicationException( - "Unable to restore queue file.", - "The file may be corrupted or from an older incompatible version of HandBrake", + "Unable to restore queue file.", + "The file may be corrupted or from an older incompatible version of HandBrake", exc); } @@ -421,6 +424,7 @@ namespace HandBrake.ApplicationServices.Services { this.InvokeQueuePaused(EventArgs.Empty); this.IsProcessing = false; + this.isPaused = true; } /// @@ -434,9 +438,16 @@ namespace HandBrake.ApplicationServices.Services throw new Exception("Already Processing the Queue"); } - this.IsProcessing = true; + this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; this.EncodeService.EncodeCompleted += this.EncodeServiceEncodeCompleted; - this.ProcessNextJob(); + + if (!this.EncodeService.IsEncoding) + { + this.ProcessNextJob(); + } + + this.IsProcessing = true; + this.isPaused = false; } #endregion @@ -471,12 +482,6 @@ namespace HandBrake.ApplicationServices.Services // Handling Log Data this.EncodeService.ProcessLogs(this.LastProcessedJob.Task.Destination); - // Post-Processing - if (e.Successful) - { - this.SendToApplication(this.LastProcessedJob.Task.Destination); - } - // Move onto the next job. if (this.IsProcessing) { @@ -490,35 +495,6 @@ namespace HandBrake.ApplicationServices.Services } } - /// - /// Perform an action after an encode. e.g a shutdown, standby, restart etc. - /// - private void Finish() - { - // Do something whent he encode ends. - switch (this.userSettingService.GetUserSetting(ASUserSettingConstants.WhenCompleteAction)) - { - case "Shutdown": - Process.Start("Shutdown", "-s -t 60"); - break; - case "Log off": - Win32.ExitWindowsEx(0, 0); - break; - case "Suspend": - Application.SetSuspendState(PowerState.Suspend, true, true); - break; - case "Hibernate": - Application.SetSuspendState(PowerState.Hibernate, true, true); - break; - case "Lock System": - Win32.LockWorkStation(); - break; - case "Quit HandBrake": - Application.Exit(); - break; - } - } - /// /// Invoke the JobProcessingStarted event /// @@ -608,31 +584,6 @@ namespace HandBrake.ApplicationServices.Services // Fire the event to tell connected services. this.InvokeQueueCompleted(EventArgs.Empty); - - // Run the After encode completeion work - this.Finish(); - } - } - - /// - /// Send a file to a 3rd party application after encoding has completed. - /// - /// - /// The file path - /// - private void SendToApplication(string file) - { - if (this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFile) && - !string.IsNullOrEmpty(this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFileTo))) - { - string args = string.Format( - "{0} \"{1}\"", - this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFileToArgs), - file); - var vlc = - new ProcessStartInfo( - this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFileTo), args); - Process.Start(vlc); } } diff --git a/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs b/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs index 2a11914b8..81bff63bb 100644 --- a/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs +++ b/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs @@ -281,6 +281,8 @@ namespace HandBrake.ApplicationServices.Utilities tune = tune == "none" ? "fastdecode" : tune + ",fastdecode"; } AddEncodeElement(xmlWriter, "x264Tune", "string", tune); + AddEncodeElement(xmlWriter, "x264UseAdvancedOptions", "integer", parsed.ShowAdvancedTab ? "1" : "0"); + int videoQualityType = 0; if (parsed.VideoBitrate != null) videoQualityType = 1; diff --git a/win/CS/HandBrake.Server/Program.cs b/win/CS/HandBrake.Server/Program.cs index b6fc92736..d5c21ac0c 100644 --- a/win/CS/HandBrake.Server/Program.cs +++ b/win/CS/HandBrake.Server/Program.cs @@ -1,6 +1,5 @@ namespace HandBrake.Server { - using System; using System.Linq; using HandBrake.ApplicationServices.Services; @@ -21,9 +20,6 @@ { if (args.Count() != 1) { - //Console.WriteLine("Invalid Arguments"); - //Console.ReadLine(); - IServerService server = new ServerService(); server.Start("8001"); } diff --git a/win/CS/HandBrakeWPF/AttachedProperties/DriveMenu.cs b/win/CS/HandBrakeWPF/AttachedProperties/DriveMenu.cs new file mode 100644 index 000000000..1149b579e --- /dev/null +++ b/win/CS/HandBrakeWPF/AttachedProperties/DriveMenu.cs @@ -0,0 +1,127 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// +// The drive menu. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.AttachedProperties +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Windows; + using System.Windows.Controls; + using System.Windows.Media.Imaging; + + using HandBrake.ApplicationServices.Utilities; + + using HandBrakeWPF.Commands; + using HandBrakeWPF.Model; + using HandBrakeWPF.ViewModels; + + /// + /// The drive menu. + /// + public class DriveMenu + { + /// + /// The show available drives property. + /// + public static readonly DependencyProperty ShowAvailableDrivesProperty = DependencyProperty.RegisterAttached( + "ShowAvailableDrives", + typeof(Boolean), + typeof(DriveMenu), + new PropertyMetadata(false, OnShowAvailableDrivesChanged)); + + /// + /// The get show available drives. + /// + /// + /// The element. + /// + /// + /// The . + /// + public static Boolean GetShowAvailableDrives(MenuItem element) + { + bool result; + return bool.TryParse(element.GetValue(ShowAvailableDrivesProperty).ToString(), out result) && result; + } + + /// + /// The set show available drives. + /// + /// + /// The element. + /// + /// + /// The value. + /// + public static void SetShowAvailableDrives(MenuItem element, Boolean value) + { + element.SetValue(ShowAvailableDrivesProperty, value); + } + + /// + /// The on show available drives changed. + /// + /// + /// The d. + /// + /// + /// The e. + /// + private static void OnShowAvailableDrivesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + Menu menu = d as Menu; + if (menu != null) + { + menu.PreviewMouseDown -= MenuMouseDown; + menu.PreviewMouseDown += MenuMouseDown; + } + } + + /// + /// The menu_ mouse down. + /// + /// + /// The sender. + /// + /// + /// The e. + /// + private static void MenuMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) + { + Menu menu = sender as Menu; + if (menu != null) + { + MainViewModel mvm = menu.DataContext as MainViewModel; + if (mvm != null) + { + List remove = mvm.SourceMenu.Where(s => s.IsDrive).ToList(); + foreach (var item in remove) + { + mvm.SourceMenu.Remove(item); + } + + foreach (SourceMenuItem menuItem in from item in GeneralUtilities.GetDrives() + let driveInformation = item + select new SourceMenuItem + { + Image = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/HandBrake;component/Views/Images/disc_small.png")), Width = 16, Height = 16 }, + Text = string.Format("{0} ({1})", item.RootDirectory, item.VolumeLabel), + Command = new SourceMenuCommand(() => mvm.ProcessDrive(driveInformation)), + Tag = item, + IsDrive = true + }) + { + mvm.SourceMenu.Add(menuItem); + } + } + } + } + } +} diff --git a/win/CS/HandBrakeWPF/Constants.cs b/win/CS/HandBrakeWPF/Constants.cs index 862f08011..1d279427a 100644 --- a/win/CS/HandBrakeWPF/Constants.cs +++ b/win/CS/HandBrakeWPF/Constants.cs @@ -23,5 +23,20 @@ namespace HandBrakeWPF /// The appcast 32. /// public const string Appcast32 = "http://handbrake.fr/appcast.i386.xml"; + + /// + /// The any. + /// + public const string Any = "(Any)"; + + /// + /// The chapters. + /// + public const string Chapters = "{chapters}"; + + /// + /// The title. + /// + public const string Title = "{title}"; } } diff --git a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj index d7c81d861..bc8018c08 100644 --- a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj +++ b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj @@ -123,6 +123,7 @@ MSBuild:Compile Designer + @@ -157,18 +158,18 @@ - - + + @@ -310,6 +311,7 @@ PublicResXFileCodeGenerator Resources.Designer.cs + Designer diff --git a/win/CS/HandBrakeWPF/Helpers/AutoNameHelper.cs b/win/CS/HandBrakeWPF/Helpers/AutoNameHelper.cs index 5c4e83cb1..2298eb4ab 100644 --- a/win/CS/HandBrakeWPF/Helpers/AutoNameHelper.cs +++ b/win/CS/HandBrakeWPF/Helpers/AutoNameHelper.cs @@ -79,8 +79,8 @@ namespace HandBrakeWPF.Helpers { destinationFilename = userSettingService.GetUserSetting(UserSettingConstants.AutoNameFormat); destinationFilename = destinationFilename.Replace("{source}", sourceName) - .Replace("{title}", dvdTitle) - .Replace("{chapters}", combinedChapterTag) + .Replace(Constants.Title, dvdTitle) + .Replace(Constants.Chapters, combinedChapterTag) .Replace("{date}", DateTime.Now.Date.ToShortDateString().Replace('/', '-')); } else diff --git a/win/CS/HandBrakeWPF/Helpers/CliCheckHelper.cs b/win/CS/HandBrakeWPF/Helpers/CliCheckHelper.cs index 2e69eacec..0060b1d15 100644 --- a/win/CS/HandBrakeWPF/Helpers/CliCheckHelper.cs +++ b/win/CS/HandBrakeWPF/Helpers/CliCheckHelper.cs @@ -14,6 +14,7 @@ namespace HandBrakeWPF.Helpers using System.IO; using System.Security.Cryptography; using System.Text.RegularExpressions; + using System.Windows.Forms; using Caliburn.Micro; @@ -43,7 +44,7 @@ namespace HandBrakeWPF.Helpers // Get the SHA1 Hash of HandBrakeCLI byte[] hash; - using (Stream stream = File.OpenRead("HandBrakeCLI.exe")) + using (Stream stream = File.OpenRead(Path.Combine(Application.StartupPath, "HandBrakeCLI.exe"))) { hash = SHA1.Create().ComputeHash(stream); } @@ -58,7 +59,7 @@ namespace HandBrakeWPF.Helpers // It's not the same, so start the CLI to get it's version data. Process cliProcess = new Process(); - ProcessStartInfo handBrakeCli = new ProcessStartInfo("HandBrakeCLI.exe", " -u -v0") + ProcessStartInfo handBrakeCli = new ProcessStartInfo(Path.Combine(Application.StartupPath, "HandBrakeCLI.exe"), " -u -v0") { UseShellExecute = false, RedirectStandardError = true, diff --git a/win/CS/HandBrakeWPF/Model/SourceMenuItem.cs b/win/CS/HandBrakeWPF/Model/SourceMenuItem.cs index b0c4a9766..f0b809849 100644 --- a/win/CS/HandBrakeWPF/Model/SourceMenuItem.cs +++ b/win/CS/HandBrakeWPF/Model/SourceMenuItem.cs @@ -46,6 +46,11 @@ namespace HandBrakeWPF.Model /// public ObservableCollection Children { get; set; } + /// + /// Gets or sets a value indicating whether is drive. + /// + public bool IsDrive { get; set; } + /// /// Gets or sets the tag. /// diff --git a/win/CS/HandBrakeWPF/Properties/Resources.Designer.cs b/win/CS/HandBrakeWPF/Properties/Resources.Designer.cs index 7db59a4d0..bef7d7030 100644 --- a/win/CS/HandBrakeWPF/Properties/Resources.Designer.cs +++ b/win/CS/HandBrakeWPF/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.296 +// Runtime Version:4.0.30319.18047 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -80,13 +80,13 @@ namespace HandBrakeWPF.Properties { } /// - /// Looks up a localized string similar to You can optionally store a maximum resolution for encodes that use this preset. There are 3 modes: + /// Looks up a localized string similar to You can optionally store a maximum resolution for encodes that use this preset. There are 4 modes: /// - ///None: There is no maximum resolution for encodes using this preset. They will always use the source resolution minus any cropping that may be applied. + ///None: There is no maximum resolution for encodes using this preset. When the preset is loaded, the current width, height and aspect ratio that you currently have set will be reloaded. /// - ///Custom: You can optionally set a Maximum width and height. When doing this an encode will be less than or equal to these values. + ///Custom: You can optionally set a Maximum width and Height. When doing this an encode will be less than or equal to these values. Keep Aspect Ratio will be automatically turned on. /// - ///Source Maximum: Similar to custom, but the resolution of your current source is used as the Max width and Height values in [rest of string was truncated]";. + ///Source Maximum: Similar to custom, but [rest of string was truncated]";. /// public static string AddPreset_PictureSizeMode { get { @@ -337,6 +337,9 @@ namespace HandBrakeWPF.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// public static System.Drawing.Bitmap logo64 { get { object obj = ResourceManager.GetObject("logo64", resourceCulture); @@ -344,6 +347,24 @@ namespace HandBrakeWPF.Properties { } } + /// + /// Looks up a localized string similar to WARNING: You do not have automatic file naming turned on. Please enable this in options.. + /// + public static string QueueSelection_AutoNameWarning { + get { + return ResourceManager.GetString("QueueSelection_AutoNameWarning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to WARNING: You do not currently have automatic audio and subtitle track selection setup. You can setup the default track selection behaviour in options.. + /// + public static string QueueSelection_AutoTrackSelectionWarning { + get { + return ResourceManager.GetString("QueueSelection_AutoTrackSelectionWarning", resourceCulture); + } + } + /// /// Looks up a localized string similar to Warning: RF 0 is Lossless!. /// diff --git a/win/CS/HandBrakeWPF/Properties/Resources.resx b/win/CS/HandBrakeWPF/Properties/Resources.resx index fed5d3923..180d0abc5 100644 --- a/win/CS/HandBrakeWPF/Properties/Resources.resx +++ b/win/CS/HandBrakeWPF/Properties/Resources.resx @@ -292,13 +292,15 @@ So small increases in value will result in progressively larger increases in the Suggested values are: 18 to 20 for Standard Definition and 20 to 23 for High Definition. - You can optionally store a maximum resolution for encodes that use this preset. There are 3 modes: + You can optionally store a maximum resolution for encodes that use this preset. There are 4 modes: -None: There is no maximum resolution for encodes using this preset. They will always use the source resolution minus any cropping that may be applied. +None: There is no maximum resolution for encodes using this preset. When the preset is loaded, the current width, height and aspect ratio that you currently have set will be reloaded. -Custom: You can optionally set a Maximum width and height. When doing this an encode will be less than or equal to these values. +Custom: You can optionally set a Maximum width and Height. When doing this an encode will be less than or equal to these values. Keep Aspect Ratio will be automatically turned on. -Source Maximum: Similar to custom, but the resolution of your current source is used as the Max width and Height values instead. +Source Maximum: Similar to custom, but the resolution of your current source is used as the Max width and Height values instead. Keep Aspect Ratio will be automatically turned on. + +No Limit: Always use the full source resolution for all sources keeping aspect ratio. This is the default behaviour. The options passed to the x264 encoder. @@ -329,4 +331,10 @@ To enable this tab, check the "Use Advanced Tab instead" option on the Video Tab If you do not use this tab, it can be hidden from: Tools Menu > Options > Advanced. + + WARNING: You do not have automatic file naming turned on. Please enable this in options. + + + WARNING: You do not currently have automatic audio and subtitle track selection setup. You can setup the default track selection behaviour in options. + \ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/DriveDetectService.cs b/win/CS/HandBrakeWPF/Services/DriveDetectService.cs deleted file mode 100644 index 3a4ef5113..000000000 --- a/win/CS/HandBrakeWPF/Services/DriveDetectService.cs +++ /dev/null @@ -1,97 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. -// -// -// Drive Detection Helper. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace HandBrakeWPF.Services -{ - using System; - using System.Management; - using System.Threading; - - using HandBrakeWPF.Services.Interfaces; - - /// - /// Drive Detection Helper. - /// - public class DriveDetectService : IDriveDetectService - { - /// - /// The watcher. - /// - private ManagementEventWatcher watcher; - - /// - /// The detection action. - /// - private Action detectionAction; - - /// - /// The start detection. - /// - /// - /// The detection Action. - /// - public void StartDetection(Action action) - { - ThreadPool.QueueUserWorkItem( - delegate - { - this.detectionAction = action; - - var options = new ConnectionOptions { EnablePrivileges = true }; - var scope = new ManagementScope(@"root\CIMV2", options); - - try - { - var query = new WqlEventQuery - { - EventClassName = "__InstanceModificationEvent", - WithinInterval = TimeSpan.FromSeconds(1), - Condition = @"TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 5" // DriveType - 5: CDROM - }; - - this.watcher = new ManagementEventWatcher(scope, query); - this.watcher.EventArrived += this.WatcherEventArrived; - this.watcher.Start(); - } - catch (Exception e) - { - Console.WriteLine(e.Message); - } - }); - } - - /// - /// The close. - /// - public void Close() - { - if (watcher != null) - { - this.watcher.Stop(); - } - } - - /// - /// The watcher_ event arrived. - /// - /// - /// The sender. - /// - /// - /// The EventArrivedEventArgs. - /// - private void WatcherEventArrived(object sender, EventArrivedEventArgs e) - { - if (this.detectionAction != null) - { - this.detectionAction(); - } - } - } -} diff --git a/win/CS/HandBrakeWPF/Services/Interfaces/IDriveDetectService.cs b/win/CS/HandBrakeWPF/Services/Interfaces/IDriveDetectService.cs deleted file mode 100644 index 16ef42a4f..000000000 --- a/win/CS/HandBrakeWPF/Services/Interfaces/IDriveDetectService.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. -// -// -// Defines the IDriveDetectService type. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace HandBrakeWPF.Services.Interfaces -{ - using System; - - /// - /// The DriveDetectService interface. - /// - public interface IDriveDetectService - { - /// - /// The start detection. - /// - /// - /// The detection Action. - /// - void StartDetection(Action action); - - /// - /// Stop the watcher. Must be done before the app shuts down. - /// - void Close(); - } -} \ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Interfaces/INotificationService.cs b/win/CS/HandBrakeWPF/Services/Interfaces/INotificationService.cs index d955bb55c..8a20c274e 100644 --- a/win/CS/HandBrakeWPF/Services/Interfaces/INotificationService.cs +++ b/win/CS/HandBrakeWPF/Services/Interfaces/INotificationService.cs @@ -1,5 +1,17 @@ -namespace HandBrakeWPF.Services.Interfaces +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// +// Defines the INotificationService type. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Interfaces { + /// + /// The NotificationService interface. + /// public interface INotificationService { } diff --git a/win/CS/HandBrakeWPF/Services/Interfaces/IPrePostActionService.cs b/win/CS/HandBrakeWPF/Services/Interfaces/IPrePostActionService.cs new file mode 100644 index 000000000..fcd164a69 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Interfaces/IPrePostActionService.cs @@ -0,0 +1,18 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// +// Defines the IPrePostActionService type. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Interfaces +{ + /// + /// The WhenDoneService interface. + /// + public interface IPrePostActionService + { + } +} diff --git a/win/CS/HandBrakeWPF/Services/PrePostActionService.cs b/win/CS/HandBrakeWPF/Services/PrePostActionService.cs new file mode 100644 index 000000000..ce4eee423 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/PrePostActionService.cs @@ -0,0 +1,159 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// +// Defines the WhenDoneService type. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services +{ + using System.Diagnostics; + using System.Windows.Forms; + + using Caliburn.Micro; + + using HandBrake.ApplicationServices.Services.Interfaces; + using HandBrake.ApplicationServices.Utilities; + + using HandBrakeWPF.Services.Interfaces; + + using Application = System.Windows.Application; + + /// + /// The when done service. + /// + public class PrePostActionService : IPrePostActionService + { + /// + /// The queue processor. + /// + private readonly IQueueProcessor queueProcessor; + + /// + /// The user setting service. + /// + private readonly IUserSettingService userSettingService; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The queue processor. + /// + /// + /// The user Setting Service. + /// + public PrePostActionService(IQueueProcessor queueProcessor, IUserSettingService userSettingService) + { + this.queueProcessor = queueProcessor; + this.userSettingService = userSettingService; + + this.queueProcessor.QueueCompleted += QueueProcessorQueueCompleted; + this.queueProcessor.EncodeService.EncodeCompleted += EncodeService_EncodeCompleted; + this.queueProcessor.EncodeService.EncodeStarted += EncodeService_EncodeStarted; + } + + /// + /// The encode service_ encode started. + /// + /// + /// The sender. + /// + /// + /// The e. + /// + private void EncodeService_EncodeStarted(object sender, System.EventArgs e) + { + if (this.userSettingService.GetUserSetting(UserSettingConstants.PreventSleep)) + { + Win32.PreventSleep(); + } + } + + /// + /// The encode service_ encode completed. + /// + /// + /// The sender. + /// + /// + /// The EncodeCompletedEventArgs. + /// + private void EncodeService_EncodeCompleted(object sender, HandBrake.ApplicationServices.EventArgs.EncodeCompletedEventArgs e) + { + // Send the file to the users requested applicaiton + if (e.Successful) + { + this.SendToApplication(e.FileName); + } + + // Allow the system to sleep again. + Execute.OnUIThread(() => + { + if (this.userSettingService.GetUserSetting(UserSettingConstants.PreventSleep)) + { + Win32.AllowSleep(); + } + }); + } + + /// + /// The queue processor queue completed event handler. + /// + /// + /// The sender. + /// + /// + /// The e. + /// + private void QueueProcessorQueueCompleted(object sender, System.EventArgs e) + { + // Do something whent he encode ends. + switch (this.userSettingService.GetUserSetting(UserSettingConstants.WhenCompleteAction)) + { + case "Shutdown": + Process.Start("Shutdown", "-s -t 60"); + break; + case "Log off": + Win32.ExitWindowsEx(0, 0); + break; + case "Suspend": + System.Windows.Forms.Application.SetSuspendState(PowerState.Suspend, true, true); + break; + case "Hibernate": + System.Windows.Forms.Application.SetSuspendState(PowerState.Hibernate, true, true); + break; + case "Lock System": + Win32.LockWorkStation(); + break; + case "Quit HandBrake": + Execute.OnUIThread(() => Application.Current.Shutdown()); + break; + } + } + + /// + /// Send a file to a 3rd party application after encoding has completed. + /// + /// + /// The file path + /// + private void SendToApplication(string file) + { + if (this.userSettingService.GetUserSetting(UserSettingConstants.SendFile) && + !string.IsNullOrEmpty(this.userSettingService.GetUserSetting(UserSettingConstants.SendFileTo))) + { + string args = string.Format( + "{0} \"{1}\"", + this.userSettingService.GetUserSetting(UserSettingConstants.SendFileToArgs), + file); + var vlc = + new ProcessStartInfo( + this.userSettingService.GetUserSetting(UserSettingConstants.SendFileTo), args); + Process.Start(vlc); + } + } + } +} diff --git a/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs b/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs index 6f3428de3..87a92824a 100644 --- a/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs +++ b/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs @@ -57,10 +57,10 @@ namespace HandBrakeWPF.Startup // Services this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); - this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); + this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); // Commands this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); diff --git a/win/CS/HandBrakeWPF/UserSettingConstants.cs b/win/CS/HandBrakeWPF/UserSettingConstants.cs index 1f4c02fce..b70d88654 100644 --- a/win/CS/HandBrakeWPF/UserSettingConstants.cs +++ b/win/CS/HandBrakeWPF/UserSettingConstants.cs @@ -200,6 +200,31 @@ namespace HandBrakeWPF /// Disable LibHb Features /// public const string DisableLibHbFeatures = "DisableLibHbFeatures"; + + /// + /// When Complete Action + /// + public const string WhenCompleteAction = "WhenCompleteAction"; + + /// + /// Send file enabled. + /// + public const string SendFile = "SendFile"; + + /// + /// Send file to application path + /// + public const string SendFileTo = "SendFileTo"; + + /// + /// Send file to arguments + /// + public const string SendFileToArgs = "SendFileToArgs"; + + /// + /// Prevent Sleep + /// + public const string PreventSleep = "PreventSleep"; #endregion } diff --git a/win/CS/HandBrakeWPF/ViewModels/AddPresetViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/AddPresetViewModel.cs index f4f496fcb..488f58d74 100644 --- a/win/CS/HandBrakeWPF/ViewModels/AddPresetViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/AddPresetViewModel.cs @@ -13,6 +13,7 @@ namespace HandBrakeWPF.ViewModels using System.Windows; using HandBrake.ApplicationServices.Model; + using HandBrake.ApplicationServices.Parsing; using HandBrake.ApplicationServices.Services; using HandBrake.ApplicationServices.Services.Interfaces; using HandBrake.ApplicationServices.Utilities; @@ -25,8 +26,6 @@ namespace HandBrakeWPF.ViewModels /// public class AddPresetViewModel : ViewModelBase, IAddPresetViewModel { - /* TODO this window is up for redesign. Quite a few nippy edge cases that can cause odd behaviour with importing presets. */ - /// /// Backing field for the Preset Service /// @@ -47,6 +46,11 @@ namespace HandBrakeWPF.ViewModels /// private bool showCustomInputs; + /// + /// The source. + /// + private Title selectedTitle; + /// /// Initializes a new instance of the class. /// @@ -123,9 +127,10 @@ namespace HandBrakeWPF.ViewModels /// /// The Encode Task. /// - public void Setup(EncodeTask task) + public void Setup(EncodeTask task, Title title) { this.Preset.Task = new EncodeTask(task); + this.selectedTitle = title; } /// @@ -148,7 +153,7 @@ namespace HandBrakeWPF.ViewModels } } - if (this.SelectedPictureSettingMode == PresetPictureSettingsMode.SourceMaximum && (this.Preset.Task.Width == null || this.Preset.Task.Width == 0)) + if (this.SelectedPictureSettingMode == PresetPictureSettingsMode.SourceMaximum && this.selectedTitle == null) { this.errorService.ShowMessageBox("You must first scan a source to use the 'Source Maximum' Option.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; @@ -174,8 +179,8 @@ namespace HandBrakeWPF.ViewModels if (this.SelectedPictureSettingMode == PresetPictureSettingsMode.SourceMaximum) { - this.Preset.Task.MaxWidth = this.Preset.Task.Width; - this.Preset.Task.MaxHeight = this.Preset.Task.Height; + this.Preset.Task.MaxWidth = selectedTitle.Resolution.Width; + this.Preset.Task.MaxHeight = selectedTitle.Resolution.Height; } // Add the Preset diff --git a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IAddPresetViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IAddPresetViewModel.cs index 1d5342e01..ac0ec160f 100644 --- a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IAddPresetViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IAddPresetViewModel.cs @@ -10,6 +10,7 @@ namespace HandBrakeWPF.ViewModels.Interfaces { using HandBrake.ApplicationServices.Model; + using HandBrake.ApplicationServices.Parsing; /// /// The Add Preset View Model @@ -22,6 +23,9 @@ namespace HandBrakeWPF.ViewModels.Interfaces /// /// The Encode Task. /// - void Setup(EncodeTask task); + /// + /// The title. + /// + void Setup(EncodeTask task, Title title); } } diff --git a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IQueueSelectionViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IQueueSelectionViewModel.cs index 36a64846a..c9c0e38bd 100644 --- a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IQueueSelectionViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IQueueSelectionViewModel.cs @@ -9,6 +9,7 @@ namespace HandBrakeWPF.ViewModels.Interfaces { + using System; using System.Collections.Generic; using System.ComponentModel; @@ -35,6 +36,9 @@ namespace HandBrakeWPF.ViewModels.Interfaces /// /// The source Name. /// - void Setup(Source scannedSource, string sourceName); + /// + /// The add To Queue action + /// + void Setup(Source scannedSource, string sourceName, Action> addAction); } } diff --git a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs index b36da2e65..4a23d3ecf 100644 --- a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs @@ -11,6 +11,7 @@ namespace HandBrakeWPF.ViewModels { using System; using System.Collections.Generic; + using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; @@ -74,11 +75,6 @@ namespace HandBrakeWPF.ViewModels /// private readonly IUpdateService updateService; - /// - /// The drive detect service. - /// - private readonly IDriveDetectService driveDetectService; - /// /// Backing field for the user setting service. /// @@ -177,7 +173,7 @@ namespace HandBrakeWPF.ViewModels /// /// The Source Menu Backing Field /// - private IEnumerable sourceMenu; + private BindingList sourceMenu; /// /// The last percentage complete value. @@ -210,15 +206,17 @@ namespace HandBrakeWPF.ViewModels /// /// The update Service. /// - /// - /// The drive Detect Service. - /// /// /// The notification Service. - /// *** Leave in Constructor. *** TODO find out why? + /// *** Leave in Constructor. *** + /// + /// + /// The when Done Service. + /// *** Leave in Constructor. *** /// public MainViewModel(IUserSettingService userSettingService, IScanServiceWrapper scanService, IEncodeServiceWrapper encodeService, IPresetService presetService, - IErrorService errorService, IShellViewModel shellViewModel, IUpdateService updateService, IDriveDetectService driveDetectService, INotificationService notificationService) + IErrorService errorService, IShellViewModel shellViewModel, IUpdateService updateService, INotificationService notificationService, + IPrePostActionService whenDoneService) { this.scanService = scanService; this.encodeService = encodeService; @@ -226,7 +224,6 @@ namespace HandBrakeWPF.ViewModels this.errorService = errorService; this.shellViewModel = shellViewModel; this.updateService = updateService; - this.driveDetectService = driveDetectService; this.userSettingService = userSettingService; this.queueProcessor = IoC.Get(); @@ -353,7 +350,7 @@ namespace HandBrakeWPF.ViewModels /// /// Gets or sets the source menu. /// - public IEnumerable SourceMenu + public BindingList SourceMenu { get { @@ -739,7 +736,10 @@ namespace HandBrakeWPF.ViewModels if (this.UserSettingService.GetUserSetting(UserSettingConstants.AutoNaming)) { - this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName); + if (this.userSettingService.GetUserSetting(UserSettingConstants.AutoNameFormat) != null ) + { + this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName); + } } this.NotifyOfPropertyChange(() => this.CurrentTask); @@ -790,7 +790,16 @@ namespace HandBrakeWPF.ViewModels if (this.UserSettingService.GetUserSetting(UserSettingConstants.AutoNaming) && this.ScannedSource.ScanPath != null) { - this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName); + if (this.SelectedPointToPoint == PointToPointMode.Chapters && this.userSettingService.GetUserSetting(UserSettingConstants.AutoNameFormat) != null && + this.userSettingService.GetUserSetting(UserSettingConstants.AutoNameFormat).Contains(Constants.Chapters)) + { + this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName); + } + } + + if (this.SelectedStartPoint > this.SelectedEndPoint) + { + this.SelectedEndPoint = this.SelectedStartPoint; } } } @@ -810,10 +819,16 @@ namespace HandBrakeWPF.ViewModels this.NotifyOfPropertyChange(() => this.SelectedEndPoint); this.Duration = this.DurationCalculation(); - if (this.UserSettingService.GetUserSetting(UserSettingConstants.AutoNaming) && this.ScannedSource.ScanPath != null) + if (this.SelectedPointToPoint == PointToPointMode.Chapters && this.userSettingService.GetUserSetting(UserSettingConstants.AutoNameFormat) != null && + this.userSettingService.GetUserSetting(UserSettingConstants.AutoNameFormat).Contains(Constants.Chapters)) { this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName); } + + if (this.SelectedStartPoint > this.SelectedEndPoint && this.SelectedPointToPoint == PointToPointMode.Chapters) + { + this.SelectedStartPoint = this.SelectedEndPoint; + } } } @@ -842,7 +857,7 @@ namespace HandBrakeWPF.ViewModels this.SelectedStartPoint = 1; this.SelectedEndPoint = selectedTitle.Chapters.Last().ChapterNumber; - } + } else if (value == PointToPointMode.Seconds) { if (this.selectedTitle == null) @@ -938,7 +953,8 @@ namespace HandBrakeWPF.ViewModels // Setup the presets. if (this.presetService.CheckIfPresetsAreOutOfDate()) if (!this.userSettingService.GetUserSetting(UserSettingConstants.PresetNotification)) - this.errorService.ShowMessageBox("HandBrake has determined your built-in presets are out of date... These presets will now be updated.", + this.errorService.ShowMessageBox("HandBrake has determined your built-in presets are out of date... These presets will now be updated." + Environment.NewLine + + "Your custom presets have not been updated so you may have to re-create these by deleting and re-adding them.", "Preset Update", MessageBoxButton.OK, MessageBoxImage.Information); // Queue Recovery @@ -947,9 +963,7 @@ namespace HandBrakeWPF.ViewModels this.SelectedPreset = this.presetService.DefaultPreset; // Populate the Source menu with drives. - this.SourceMenu = this.GenerateSourceMenu(); - - this.driveDetectService.StartDetection(this.DriveTrayChanged); + this.SourceMenu = new BindingList(this.GenerateSourceMenu()); // Log Cleaning if (userSettingService.GetUserSetting(UserSettingConstants.ClearOldLogs)) @@ -965,8 +979,6 @@ namespace HandBrakeWPF.ViewModels public void Shutdown() { // Shutdown Service - this.driveDetectService.Close(); - this.scanService.Shutdown(); this.encodeService.Shutdown(); @@ -1154,7 +1166,14 @@ namespace HandBrakeWPF.ViewModels Window window = Application.Current.Windows.Cast().FirstOrDefault(x => x.GetType() == typeof(QueueSelectionViewModel)); IQueueSelectionViewModel viewModel = IoC.Get(); - viewModel.Setup(this.ScannedSource, this.SourceName); + viewModel.Setup(this.ScannedSource, this.SourceName, (tasks) => + { + foreach (SelectionTitle title in tasks) + { + this.SelectedTitle = title.Title; + this.AddToQueue(); + } + }); if (window != null) { @@ -1435,7 +1454,7 @@ namespace HandBrakeWPF.ViewModels public void PresetAdd() { IAddPresetViewModel presetViewModel = IoC.Get(); - presetViewModel.Setup(this.CurrentTask); + presetViewModel.Setup(this.CurrentTask, this.SelectedTitle); this.WindowManager.ShowWindow(presetViewModel); } @@ -1843,7 +1862,7 @@ namespace HandBrakeWPF.ViewModels } else { - this.SourceLabel = "Scan Failed... See Activity Log for details."; this.StatusLabel = "Scan Failed... See Activity Log for details."; + this.SourceLabel = "Scan Failed... See Activity Log for details."; this.StatusLabel = "Scan Failed... See Activity Log for details."; } }); } @@ -1887,7 +1906,7 @@ namespace HandBrakeWPF.ViewModels Execute.OnUIThread( () => { - if (this.IsEncoding) + if (this.queueProcessor.EncodeService.IsEncoding) { this.ProgramStatusLabel = string.Format( @@ -1906,6 +1925,16 @@ namespace HandBrakeWPF.ViewModels lastEncodePercentage = percent; } + else + { + this.ProgramStatusLabel = "Queue Finished"; + this.IsEncoding = false; + + if (this.windowsSeven.IsWindowsSeven) + { + this.windowsSeven.SetTaskBarProgressToNoProgress(); + } + } }); } @@ -1978,7 +2007,7 @@ namespace HandBrakeWPF.ViewModels /// /// The item. /// - private void ProcessDrive(object item) + public void ProcessDrive(object item) { if (item != null) { @@ -1992,7 +2021,7 @@ namespace HandBrakeWPF.ViewModels /// /// The System.Collections.Generic.IEnumerable`1[T -> HandBrakeWPF.Model.SourceMenuItem]. /// - private IEnumerable GenerateSourceMenu() + private IList GenerateSourceMenu() { List menuItems = new List(); @@ -2000,13 +2029,15 @@ namespace HandBrakeWPF.ViewModels { Image = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/HandBrake;component/Views/Images/folder.png")), Width = 16, Height = 16 }, Text = "Open Folder", - Command = new SourceMenuCommand(this.FolderScan) + Command = new SourceMenuCommand(this.FolderScan), + IsDrive = false }; SourceMenuItem fileScan = new SourceMenuItem { Image = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/HandBrake;component/Views/Images/Movies.png")), Width = 16, Height = 16 }, Text = "Open File", - Command = new SourceMenuCommand(this.FileScan) + Command = new SourceMenuCommand(this.FileScan), + IsDrive = false }; SourceMenuItem titleSpecific = new SourceMenuItem { Text = "Title Specific Scan" }; @@ -2014,13 +2045,15 @@ namespace HandBrakeWPF.ViewModels { Image = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/HandBrake;component/Views/Images/folder.png")), Width = 16, Height = 16 }, Text = "Open Folder", - Command = new SourceMenuCommand(this.FolderScanTitleSpecific) + Command = new SourceMenuCommand(this.FolderScanTitleSpecific), + IsDrive = false }; SourceMenuItem fileScanTitle = new SourceMenuItem { Image = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/HandBrake;component/Views/Images/Movies.png")), Width = 16, Height = 16 }, Text = "Open File", - Command = new SourceMenuCommand(this.FileScanTitleSpecific) + Command = new SourceMenuCommand(this.FileScanTitleSpecific), + IsDrive = false }; titleSpecific.Children.Add(folderScanTitle); titleSpecific.Children.Add(fileScanTitle); @@ -2039,20 +2072,13 @@ namespace HandBrakeWPF.ViewModels Image = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/HandBrake;component/Views/Images/disc_small.png")), Width = 16, Height = 16 }, Text = string.Format("{0} ({1})", item.RootDirectory, item.VolumeLabel), Command = new SourceMenuCommand(() => this.ProcessDrive(driveInformation)), - Tag = item + Tag = item, + IsDrive = true }); return menuItems; } - /// - /// The drive tray changed. - /// - private void DriveTrayChanged() - { - Caliburn.Micro.Execute.OnUIThread(() => this.SourceMenu = this.GenerateSourceMenu()); - } - /// /// Allows the main window to respond to setting changes. /// @@ -2082,10 +2108,10 @@ namespace HandBrakeWPF.ViewModels /// private void CurrentTask_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { - if (e.PropertyName == UserSettingConstants.ShowAdvancedTab) - { - this.NotifyOfPropertyChange(() => this.ShowAdvancedTab); - } + if (e.PropertyName == UserSettingConstants.ShowAdvancedTab) + { + this.NotifyOfPropertyChange(() => this.ShowAdvancedTab); + } } #endregion diff --git a/win/CS/HandBrakeWPF/ViewModels/OptionsViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/OptionsViewModel.cs index 8156aa806..4ed8e208e 100644 --- a/win/CS/HandBrakeWPF/ViewModels/OptionsViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/OptionsViewModel.cs @@ -19,6 +19,8 @@ namespace HandBrakeWPF.ViewModels using System.Linq; using System.Windows; + using Caliburn.Micro; + using HandBrake.ApplicationServices; using HandBrake.ApplicationServices.Services.Interfaces; using HandBrake.ApplicationServices.Utilities; @@ -1487,10 +1489,10 @@ namespace HandBrakeWPF.ViewModels this.GrowlAfterEncode = userSettingService.GetUserSetting(UserSettingConstants.GrowlEncode); this.GrowlAfterQueue = userSettingService.GetUserSetting(UserSettingConstants.GrowlQueue); - this.SendFileAfterEncode = this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFile); - this.SendFileTo = Path.GetFileNameWithoutExtension(this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFileTo)) ?? string.Empty; - this.SendFileToPath = this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFileTo) ?? string.Empty; - this.Arguments = this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFileToArgs) ?? string.Empty; + this.SendFileAfterEncode = this.userSettingService.GetUserSetting(UserSettingConstants.SendFile); + this.SendFileTo = Path.GetFileNameWithoutExtension(this.userSettingService.GetUserSetting(UserSettingConstants.SendFileTo)) ?? string.Empty; + this.SendFileToPath = this.userSettingService.GetUserSetting(UserSettingConstants.SendFileTo) ?? string.Empty; + this.Arguments = this.userSettingService.GetUserSetting(UserSettingConstants.SendFileToArgs) ?? string.Empty; // ############################# // Output Settings @@ -1554,7 +1556,7 @@ namespace HandBrakeWPF.ViewModels this.preferredLanguages.Add(item); // In the available languages should be no "Any" and no selected language. - if ((item != "(Any)") && (!this.userSettingService.GetUserSetting(UserSettingConstants.SelectedLanguages).Contains(item))) + if ((item != Constants.Any) && (!this.userSettingService.GetUserSetting(UserSettingConstants.SelectedLanguages).Contains(item))) { this.availableLanguages.Add(item); } @@ -1597,7 +1599,7 @@ namespace HandBrakeWPF.ViewModels this.priorityLevelOptions.Add("Low"); this.SelectedPriority = userSettingService.GetUserSetting(ASUserSettingConstants.ProcessPriority); - this.PreventSleep = userSettingService.GetUserSetting(ASUserSettingConstants.PreventSleep); + this.PreventSleep = userSettingService.GetUserSetting(UserSettingConstants.PreventSleep); // Log Verbosity Level this.logVerbosityOptions.Clear(); @@ -1820,12 +1822,12 @@ namespace HandBrakeWPF.ViewModels /* General */ this.userSettingService.SetUserSetting(UserSettingConstants.UpdateStatus, this.CheckForUpdates); this.userSettingService.SetUserSetting(UserSettingConstants.DaysBetweenUpdateCheck, this.CheckForUpdatesFrequency); - this.userSettingService.SetUserSetting(ASUserSettingConstants.WhenCompleteAction, this.WhenDone); + this.userSettingService.SetUserSetting(UserSettingConstants.WhenCompleteAction, this.WhenDone); this.userSettingService.SetUserSetting(UserSettingConstants.GrowlQueue, this.GrowlAfterQueue); this.userSettingService.SetUserSetting(UserSettingConstants.GrowlEncode, this.GrowlAfterEncode); - this.userSettingService.SetUserSetting(ASUserSettingConstants.SendFileTo, this.SendFileToPath); - this.userSettingService.SetUserSetting(ASUserSettingConstants.SendFile, this.SendFileAfterEncode); - this.userSettingService.SetUserSetting(ASUserSettingConstants.SendFileToArgs, this.Arguments); + this.userSettingService.SetUserSetting(UserSettingConstants.SendFileTo, this.SendFileToPath); + this.userSettingService.SetUserSetting(UserSettingConstants.SendFile, this.SendFileAfterEncode); + this.userSettingService.SetUserSetting(UserSettingConstants.SendFileToArgs, this.Arguments); /* Output Files */ this.userSettingService.SetUserSetting(UserSettingConstants.AutoNaming, this.AutomaticallyNameFiles); @@ -1852,7 +1854,7 @@ namespace HandBrakeWPF.ViewModels /* System and Logging */ userSettingService.SetUserSetting(ASUserSettingConstants.ProcessPriority, this.SelectedPriority); - userSettingService.SetUserSetting(ASUserSettingConstants.PreventSleep, this.PreventSleep); + userSettingService.SetUserSetting(UserSettingConstants.PreventSleep, this.PreventSleep); userSettingService.SetUserSetting(ASUserSettingConstants.Verbosity, this.SelectedVerbosity); userSettingService.SetUserSetting(ASUserSettingConstants.SaveLogWithVideo, this.CopyLogToEncodeDirectory); userSettingService.SetUserSetting(ASUserSettingConstants.SaveLogToCopyDirectory, this.CopyLogToSepcficedLocation); @@ -1935,7 +1937,7 @@ namespace HandBrakeWPF.ViewModels this.UpdateMessage = info.WasSuccessful ? "Update Downloaded" : "Update Failed. You can try downloading the update from http://handbrake.fr"; Process.Start(Path.Combine(Path.GetTempPath(), "handbrake-setup.exe")); - Application.Current.Shutdown(); + Execute.OnUIThread(() => Application.Current.Shutdown()); } /// diff --git a/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs index 1a6c90538..268418692 100644 --- a/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs @@ -601,59 +601,71 @@ namespace HandBrakeWPF.ViewModels { this.Task = task; - // TODO: These all need to be handled correctly. + // Anamorphic Mode this.SelectedAnamorphicMode = preset.Task.Anamorphic; - // Set the limits on the UI Controls. - this.MaxWidth = preset.Task.MaxWidth ?? this.sourceResolution.Width; - this.MaxHeight = preset.Task.MaxHeight ?? this.sourceResolution.Height; - this.Task.MaxWidth = preset.Task.MaxWidth; - this.Task.MaxHeight = preset.Task.MaxHeight; - - // Setup the Width - if (preset.Task.MaxWidth.HasValue) + // Modulus + if (preset.Task.Modulus.HasValue) { - if (this.Width > preset.Task.MaxWidth) - { - // Limit the Width to the Max Width - this.Width = preset.Task.MaxWidth.Value; - } - else - { - // Figure out the best width based on the preset and source - this.Width = preset.Task.Width ?? this.GetModulusValue(this.getRes((this.sourceResolution.Width - this.CropLeft - this.CropRight), preset.Task.MaxWidth.Value)); - } + this.SelectedModulus = preset.Task.Modulus; } - else + + // Set the Maintain Aspect ratio. + this.MaintainAspectRatio = preset.Task.Anamorphic == Anamorphic.None && preset.Task.KeepDisplayAspect; + + // Handle built-in presets. + if (preset.IsBuildIn) { - this.Width = preset.Task.Width ?? this.GetModulusValue((this.sourceResolution.Width - this.CropLeft - this.CropRight)); + preset.PictureSettingsMode = PresetPictureSettingsMode.Custom; } - // Set the Maintain Aspect ratio. This will calculate Height for us now. - this.MaintainAspectRatio = preset.Task.Anamorphic == Anamorphic.None || preset.Task.KeepDisplayAspect; - - // Set Height, but only if necessary. - if (preset.Task.MaxHeight.HasValue) + // Setup the Picture Sizes + switch (preset.PictureSettingsMode) { - if (this.Height > preset.Task.MaxHeight) - { - // Limit the Height to the Max Height of the preset. Setting this will recalculate the width. - this.Height = preset.Task.MaxHeight.Value; - } - else - { - // Only calculate height if Maintain Aspect ratio is off. - if (!this.MaintainAspectRatio) + default: + case PresetPictureSettingsMode.Custom: + case PresetPictureSettingsMode.SourceMaximum: + this.MaintainAspectRatio = true; + + // Set the width, then check the height doesn't breach the max height and correct if necessary. + int width = this.GetModulusValue(this.getRes((this.sourceResolution.Width - this.CropLeft - this.CropRight), preset.Task.MaxWidth)); + this.Width = width; + + // If we have a max height, make sure we havn't breached it. + int height = this.GetModulusValue(this.getRes((this.sourceResolution.Height - this.CropTop - this.CropBottom), preset.Task.MaxHeight)); + if (preset.Task.MaxHeight.HasValue && this.Height > preset.Task.MaxHeight.Value) { - this.Height = preset.Task.Height ?? - this.getRes( - (this.sourceResolution.Height - this.CropTop - this.CropBottom), - preset.Task.MaxHeight.Value); + this.Height = height; } - } + + this.MaxWidth = width; + this.MaxHeight = height; + break; + case PresetPictureSettingsMode.NoLimit: + this.MaintainAspectRatio = true; + this.Width = this.GetModulusValue(this.sourceResolution.Width - this.CropLeft - this.CropRight); + + this.MaxWidth = this.sourceResolution.Width; + this.MaxHeight = this.sourceResolution.Height; + break; + case PresetPictureSettingsMode.None: + + if (preset.Task.Width.HasValue) + { + this.Width = this.GetModulusValue(preset.Task.Width.Value - this.CropLeft - this.CropRight); + } + + if (!this.MaintainAspectRatio && preset.Task.Height.HasValue) + { + this.Height = this.GetModulusValue(preset.Task.Height.Value - this.CropTop - this.CropBottom); + } + + this.MaxWidth = this.sourceResolution.Width; + this.MaxHeight = this.sourceResolution.Height; + break; } - // Anamorphic + // Custom Anamorphic if (preset.Task.Anamorphic == Anamorphic.Custom) { this.DisplayWidth = preset.Task.DisplayWidth != null ? int.Parse(preset.Task.DisplayWidth.ToString()) : 0; @@ -661,12 +673,6 @@ namespace HandBrakeWPF.ViewModels this.ParHeight = preset.Task.PixelAspectY; } - // Modulus - if (preset.Task.Modulus.HasValue) - { - this.SelectedModulus = preset.Task.Modulus; - } - // Cropping if (preset.Task.HasCropping) { @@ -765,15 +771,14 @@ namespace HandBrakeWPF.ViewModels } // Set the Width, and Maintain Aspect ratio. That should calc the Height for us. - this.Width = this.MaxWidth; - this.MaintainAspectRatio = true; + this.Width = preset.Task.Width ?? this.MaxWidth; // If our height is too large, let it downscale the width for us by setting the height to the lower value. if (this.Height > this.MaxHeight) { this.Height = this.MaxHeight; } - + if (this.SelectedAnamorphicMode == Anamorphic.Custom) { this.AnamorphicAdjust(); // Refresh the values @@ -1145,9 +1150,9 @@ namespace HandBrakeWPF.ViewModels /// /// An Int /// - private int getRes(int value, int max) + private int getRes(int value, int? max) { - return value > max ? max : value; + return max.HasValue ? (value > max.Value ? max.Value : value) : value; } #endregion diff --git a/win/CS/HandBrakeWPF/ViewModels/QueueSelectionViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/QueueSelectionViewModel.cs index c5b6072cc..3cbe56feb 100644 --- a/win/CS/HandBrakeWPF/ViewModels/QueueSelectionViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/QueueSelectionViewModel.cs @@ -40,6 +40,11 @@ namespace HandBrakeWPF.ViewModels /// private bool orderedByTitle; + /// + /// The add to queue. + /// + private Action> addToQueue; + /// /// Initializes a new instance of the class. /// @@ -98,6 +103,36 @@ namespace HandBrakeWPF.ViewModels } } + /// + /// Gets a value indicating whether is auto naming enabled. + /// + public bool IsAutoNamingEnabled + { + get + { + return this.UserSettingService.GetUserSetting(UserSettingConstants.AutoNaming); + } + } + + /// + /// Gets a value indicating whether is automatic track selection enabled. + /// + public bool IsAutomaticTrackSelectionEnabled + { + get + { + // TODO decide what is the minimal requirement to hide the warning message. + if (this.UserSettingService.GetUserSetting(UserSettingConstants.NativeLanguage) != Constants.Any || + this.UserSettingService.GetUserSetting(UserSettingConstants.NativeLanguageForSubtitles) != + Constants.Any) + { + return true; + } + + return false; + } + } + /// /// The order by title. /// @@ -147,6 +182,7 @@ namespace HandBrakeWPF.ViewModels /// public void Add() { + this.addToQueue(this.TitleList.Where(c => c.IsSelected)); this.Close(); } @@ -176,23 +212,29 @@ namespace HandBrakeWPF.ViewModels /// /// The src Name. /// - public void Setup(Source scannedSource, string srcName) + /// + /// The add Action. + /// + public void Setup(Source scannedSource, string srcName, Action> addAction) { this.TitleList.Clear(); + this.addToQueue = addAction; if (scannedSource != null) { - IEnumerable titles = orderedByTitle ? scannedSource.Titles : scannedSource.Titles.OrderByDescending(o => o.Duration).ToList(); foreach (Title item in titles) { - SelectionTitle title = new SelectionTitle(item, srcName); + SelectionTitle title = new SelectionTitle(item, srcName) { IsSelected = true }; TitleList.Add(title); } } + + this.NotifyOfPropertyChange(() => this.IsAutoNamingEnabled); + this.NotifyOfPropertyChange(() => this.IsAutomaticTrackSelectionEnabled); } } } diff --git a/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs index 3b5bf33e8..3465fe273 100644 --- a/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs @@ -10,13 +10,11 @@ namespace HandBrakeWPF.ViewModels { using System; - using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows; using Caliburn.Micro; - using HandBrake.ApplicationServices; using HandBrake.ApplicationServices.EventArgs; using HandBrake.ApplicationServices.Model; using HandBrake.ApplicationServices.Services.Interfaces; @@ -31,13 +29,6 @@ namespace HandBrakeWPF.ViewModels /// </summary> public class QueueViewModel : ViewModelBase, IQueueViewModel { - /* - - * TODO FIX THE DRAP/DROP ADORNER! - */ - - - #region Constants and Fields /// <summary> @@ -82,9 +73,6 @@ namespace HandBrakeWPF.ViewModels /// <summary> /// Initializes a new instance of the <see cref="QueueViewModel"/> class. /// </summary> - /// <param name="windowManager"> - /// The window manager. - /// </param> /// <param name="userSettingService"> /// The user Setting Service. /// </param> @@ -94,7 +82,7 @@ namespace HandBrakeWPF.ViewModels /// <param name="errorService"> /// The Error Service /// </param> - public QueueViewModel(IWindowManager windowManager, IUserSettingService userSettingService, IQueueProcessor queueProcessor, IErrorService errorService) + public QueueViewModel(IUserSettingService userSettingService, IQueueProcessor queueProcessor, IErrorService errorService) { this.userSettingService = userSettingService; this.queueProcessor = queueProcessor; @@ -199,7 +187,7 @@ namespace HandBrakeWPF.ViewModels public void WhenDone(string action) { this.WhenDoneAction = action; - this.userSettingService.SetUserSetting(ASUserSettingConstants.WhenCompleteAction, action); + this.userSettingService.SetUserSetting(UserSettingConstants.WhenCompleteAction, action); } /// <summary> @@ -249,6 +237,13 @@ namespace HandBrakeWPF.ViewModels public void PauseEncode() { this.queueProcessor.Pause(); + + this.JobStatus = "Queue Paused"; + this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); + this.IsEncoding = false; + + MessageBox.Show("The Queue has been pasued. The currently running job will run to completion and no further jobs will start.", "Queue", + MessageBoxButton.OK, MessageBoxImage.Information); } /// <summary> @@ -305,6 +300,10 @@ namespace HandBrakeWPF.ViewModels return; } + this.JobStatus = "Queue Started"; + this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); + this.IsEncoding = true; + this.queueProcessor.Start(); } @@ -374,13 +373,15 @@ namespace HandBrakeWPF.ViewModels { this.Load(); - this.WhenDoneAction = this.userSettingService.GetUserSetting<string>(ASUserSettingConstants.WhenCompleteAction); + this.WhenDoneAction = this.userSettingService.GetUserSetting<string>(UserSettingConstants.WhenCompleteAction); - this.queueProcessor.JobProcessingStarted += this.queueProcessor_JobProcessingStarted; this.queueProcessor.QueueCompleted += this.queueProcessor_QueueCompleted; - this.queueProcessor.QueuePaused += this.queueProcessor_QueuePaused; this.queueProcessor.QueueChanged += this.QueueManager_QueueChanged; this.queueProcessor.EncodeService.EncodeStatusChanged += this.EncodeService_EncodeStatusChanged; + this.queueProcessor.EncodeService.EncodeCompleted += EncodeService_EncodeCompleted; + + this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); + this.JobStatus = "Queue Ready"; base.OnActivate(); } @@ -393,11 +394,10 @@ namespace HandBrakeWPF.ViewModels /// </param> protected override void OnDeactivate(bool close) { - this.queueProcessor.JobProcessingStarted -= this.queueProcessor_JobProcessingStarted; this.queueProcessor.QueueCompleted -= this.queueProcessor_QueueCompleted; - this.queueProcessor.QueuePaused -= this.queueProcessor_QueuePaused; this.queueProcessor.QueueChanged -= this.QueueManager_QueueChanged; this.queueProcessor.EncodeService.EncodeStatusChanged -= this.EncodeService_EncodeStatusChanged; + this.queueProcessor.EncodeService.EncodeCompleted -= EncodeService_EncodeCompleted; base.OnDeactivate(close); } @@ -416,20 +416,16 @@ namespace HandBrakeWPF.ViewModels { Caliburn.Micro.Execute.OnUIThread(() => { - if (this.IsEncoding) - { - this.JobStatus = - string.Format( - "Encoding: Pass {0} of {1}, {2:00.00}%, FPS: {3:000.0}, Avg FPS: {4:000.0}, Time Remaining: {5}, Elapsed: {6:hh\\:mm\\:ss}", - e.Task, - e.TaskCount, - e.PercentComplete, - e.CurrentFrameRate, - e.AverageFrameRate, - e.EstimatedTimeLeft, - e.ElapsedTime); - } - + this.JobStatus = + string.Format( + "Encoding: Pass {0} of {1}, {2:00.00}%, FPS: {3:000.0}, Avg FPS: {4:000.0}, Time Remaining: {5}, Elapsed: {6:hh\\:mm\\:ss}", + e.Task, + e.TaskCount, + e.PercentComplete, + e.CurrentFrameRate, + e.AverageFrameRate, + e.EstimatedTimeLeft, + e.ElapsedTime); }); } @@ -445,23 +441,11 @@ namespace HandBrakeWPF.ViewModels private void QueueManager_QueueChanged(object sender, EventArgs e) { this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); - } - /// <summary> - /// Handle teh Job Processing Started Event - /// </summary> - /// <param name="sender"> - /// The sender. - /// </param> - /// <param name="e"> - /// The QueueProgressEventArgs. - /// </param> - private void queueProcessor_JobProcessingStarted( - object sender, QueueProgressEventArgs e) - { - this.JobStatus = "Queue Started"; - this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); - this.IsEncoding = true; + if (!queueProcessor.IsProcessing) + { + this.JobStatus = "Queue Not Running"; + } } /// <summary> @@ -481,19 +465,20 @@ namespace HandBrakeWPF.ViewModels } /// <summary> - /// Handle the Queue Paused Event + /// The encode service_ encode completed. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> - /// The EventArgs. + /// The e. /// </param> - private void queueProcessor_QueuePaused(object sender, EventArgs e) + private void EncodeService_EncodeCompleted(object sender, EncodeCompletedEventArgs e) { - this.JobStatus = "Queue Paused"; - this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); - this.IsEncoding = false; + if (!this.queueProcessor.IsProcessing) + { + this.JobStatus = "Last Queued Job Finished"; + } } #endregion diff --git a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs index 514b45d5d..e5a8d6159 100644 --- a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs @@ -292,7 +292,7 @@ namespace HandBrakeWPF.ViewModels { get { - return 51.Equals(this.RF); + return 0.0.Equals(this.DisplayRF); } } diff --git a/win/CS/HandBrakeWPF/Views/AddPresetView.xaml b/win/CS/HandBrakeWPF/Views/AddPresetView.xaml index 3e7a3fd7b..b49b439a6 100644 --- a/win/CS/HandBrakeWPF/Views/AddPresetView.xaml +++ b/win/CS/HandBrakeWPF/Views/AddPresetView.xaml @@ -88,7 +88,7 @@ Grid.Column="0" Style="{StaticResource LongToolTipHolder}" ToolTip="{x:Static Properties:Resources.AddPreset_PictureSizeMode}" - Text="Picture Size:" /> + Text="Max Picture Size:" /> <ComboBox Grid.Row="2" Grid.Column="1" Width="125" diff --git a/win/CS/HandBrakeWPF/Views/AudioView.xaml b/win/CS/HandBrakeWPF/Views/AudioView.xaml index c63346642..1a1042e4d 100644 --- a/win/CS/HandBrakeWPF/Views/AudioView.xaml +++ b/win/CS/HandBrakeWPF/Views/AudioView.xaml @@ -40,12 +40,19 @@ <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> - <Button Grid.Column="0" - Width="75" + + <StackPanel Orientation="Horizontal" Grid.Row="0"> + <Button MinWidth="65" Margin="0,0,10,0" cal:Message.Attach="[Event Click] = [Action Add]" Content="Add Track" /> + <Button MinWidth="65" + Margin="0,0,10,0" + cal:Message.Attach="[Event Click] = [Action Clear]" + Content="Clear" /> + </StackPanel> + <StackPanel Grid.Column="2" Orientation="Horizontal" Visibility="{Binding ShowPassthruOptions, diff --git a/win/CS/HandBrakeWPF/Views/MainView.xaml b/win/CS/HandBrakeWPF/Views/MainView.xaml index 2ffd46574..70ee6c63c 100644 --- a/win/CS/HandBrakeWPF/Views/MainView.xaml +++ b/win/CS/HandBrakeWPF/Views/MainView.xaml @@ -5,7 +5,8 @@ xmlns:Converters="clr-namespace:HandBrakeWPF.Converters" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:Micro="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro" - AllowDrop="True" + xmlns:attachedProperties="clr-namespace:HandBrakeWPF.AttachedProperties" + AllowDrop="True" Background="#FFF0F0F0" FontSize="11" Micro:Message.Attach="[Event Loaded] = [Action Load]" @@ -146,7 +147,7 @@ ToolBar.OverflowMode="Never" ToolBarTray.IsLocked="True" > - <Menu Background="Transparent"> + <Menu Background="Transparent" attachedProperties:DriveMenu.ShowAvailableDrives="true"> <MenuItem ItemsSource="{Binding SourceMenu}"> <MenuItem.Header> <StackPanel Orientation="Horizontal"> @@ -270,7 +271,7 @@ </StackPanel> </MenuItem.Header> <MenuItem Header="Add All" Micro:Message.Attach="[Event Click] = [Action AddAllToQueue]" /> - <!--<MenuItem Header="Add Selection" Micro:Message.Attach="[Event Click] = [Action AddSelectionToQueue]" />--> + <MenuItem Header="Add Selection" Micro:Message.Attach="[Event Click] = [Action AddSelectionToQueue]" /> </MenuItem> </Menu> diff --git a/win/CS/HandBrakeWPF/Views/QueueSelectionView.xaml b/win/CS/HandBrakeWPF/Views/QueueSelectionView.xaml index b46b07ff5..5e645dc7b 100644 --- a/win/CS/HandBrakeWPF/Views/QueueSelectionView.xaml +++ b/win/CS/HandBrakeWPF/Views/QueueSelectionView.xaml @@ -4,6 +4,8 @@ xmlns:cal="http://www.caliburnproject.org" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:Conveters="clr-namespace:HandBrakeWPF.Converters" + xmlns:Properties="clr-namespace:HandBrakeWPF.Properties" Title="{Binding Title}" Width="450" MaxHeight="450" @@ -18,6 +20,8 @@ <Setter Property="ToolTipService.ShowDuration" Value="20000" /> <Setter Property="Margin" Value="0,2,0,2" /> </Style> + + <Conveters:BooleanToVisibilityConverter x:Key="boolToVisConverter" /> </Window.Resources> <Grid HorizontalAlignment="Stretch" @@ -33,17 +37,18 @@ <!-- Header --> <StackPanel Grid.Row="0" - Height="30" + Height="36" Margin="0,0,0,10" Background="White" Orientation="Horizontal"> - <Image Width="24" - Height="24" + <Image Width="32" + Height="32" Margin="10,0,5,0" VerticalAlignment="Center" Source="Images/AddToQueue_small.png" /> <StackPanel VerticalAlignment="Center" Orientation="Vertical"> - <TextBlock FontWeight="Bold" Text="Queue Multiple Items" /> + <TextBlock FontWeight="Bold" Text="Add to Queue" /> + <TextBlock Text="*** Experimental ***" /> </StackPanel> </StackPanel> @@ -70,7 +75,7 @@ <ListBox.ContextMenu> <ContextMenu> <MenuItem Header="Select All" cal:Message.Attach="[Event Click] = [Action SelectAll]" /> - <MenuItem Header="Select All" cal:Message.Attach="[Event Click] = [Action UnSelectAll]" /> + <MenuItem Header="Deselect All" cal:Message.Attach="[Event Click] = [Action UnSelectAll]" /> <Separator /> <MenuItem Header="Order by Title" IsChecked="{Binding OrderedByTitle}" cal:Message.Attach="[Event Click] = [Action OrderByTitle]" /> <MenuItem Header="Order by Duration" IsChecked="{Binding OrderedByDuration}" cal:Message.Attach="[Event Click] = [Action OrderByDuration]" /> @@ -109,7 +114,12 @@ <!-- Checlist --> <StackPanel Orientation="Vertical" Grid.Row="3" Margin="10,10,10,0"> - <TextBlock Text="Checklist " /> + <TextBlock Text="{x:Static Properties:Resources.QueueSelection_AutoTrackSelectionWarning}" + TextWrapping="Wrap" Visibility="{Binding IsAutomaticTrackSelectionEnabled, Converter={StaticResource boolToVisConverter}, ConverterParameter=true}" + Margin="0,0,0,10"/> + + <TextBlock Text="{x:Static Properties:Resources.QueueSelection_AutoNameWarning}" + TextWrapping="Wrap" Visibility="{Binding IsAutoNamingEnabled, Converter={StaticResource boolToVisConverter}, ConverterParameter=true}"/> </StackPanel> <!-- Controls --> diff --git a/win/CS/HandBrakeWPF/Views/QueueView.xaml b/win/CS/HandBrakeWPF/Views/QueueView.xaml index 394eb35e4..d3df53451 100644 --- a/win/CS/HandBrakeWPF/Views/QueueView.xaml +++ b/win/CS/HandBrakeWPF/Views/QueueView.xaml @@ -10,11 +10,10 @@ xmlns:YourNamespace="clr-namespace:HandBrakeWPF.AttachedProperties" xmlns:Audio="clr-namespace:HandBrakeWPF.Converters.Audio" xmlns:Subtitles="clr-namespace:HandBrakeWPF.Converters.Subtitles" Title="{Binding Title}" - Width="600" - Height="400" - MinWidth="600" - MinHeight="400" - MaxWidth="600" + Width="700" + Height="500" + MinWidth="200" + MinHeight="200" Background="#FFF0F0F0" WindowStartupLocation="CenterScreen" TextOptions.TextFormattingMode="Display" @@ -27,6 +26,12 @@ <Converters:QueueStatusToVisibilityConverter x:Key="queueStatusVisConverter" /> <Audio:AudioQueueDisplayConverter x:Key="audioTrackDisplayConverter" /> <Subtitles:SubtitlesQueueDisplayConverter x:Key="subtitleTrackDisplayConverter" /> + + + <Style x:Key="LongToolTipHolder" TargetType="FrameworkElement"> + <Setter Property="ToolTipService.ShowDuration" Value="10000" /> + </Style> + </Window.Resources> <Grid> @@ -115,7 +120,7 @@ YourNamespace:MenuItemExtensions.GroupName="whenDone" /> <MenuItem x:Name="lock" cal:Message.Attach="[Event Click] = [Action WhenDone(lock.Header)]" - Header="Lock system" + Header="Lock System" IsCheckable="True" YourNamespace:MenuItemExtensions.GroupName="whenDone" /> <MenuItem x:Name="logoff" @@ -137,7 +142,7 @@ <TextBlock Text="{Binding JobsPending}" /> <TextBlock Text="{Binding JobStatus}" /> </StackPanel> - + <ListBox Grid.Row="2" Margin="10,0,10,10" Background="LightGray" @@ -164,28 +169,50 @@ <Setter Property="Margin" Value="0,0,0,1" /> <Setter Property="ToolTip"> <Setter.Value> - <StackPanel Grid.Column="1" - Margin="0,5,0,5" - HorizontalAlignment="Stretch"> - <StackPanel Orientation="Horizontal"> - <TextBlock FontWeight="Bold" Text="Video" /> - <TextBlock Text=": " /> - <TextBlock Text="{Binding Task.VideoEncoder, Converter={StaticResource enumComboConverter}}" /> - <TextBlock Margin="10,0,0,0" FontWeight="Bold" Text="Audio: " /> - <TextBlock Text="{Binding Task.AudioTracks, Converter={StaticResource audioTrackDisplayConverter}}" /> - </StackPanel> - - <StackPanel Orientation="Horizontal"> - <TextBlock FontWeight="Bold" Text="Subtitles: " /> - <TextBlock Text="{Binding Task.SubtitleTracks, Converter={StaticResource subtitleTrackDisplayConverter}}" /> - </StackPanel> - - <StackPanel Orientation="Horizontal"> - <TextBlock FontWeight="Bold" Text="Advanced: " /> - <TextBlock Text="{Binding Task.AdvancedEncoderOptions}" /> - </StackPanel> + <Grid MaxWidth="650" Margin="0,5,0,5" Style="{StaticResource LongToolTipHolder}"> + <Grid.Resources> + <Style TargetType="TextBlock"> + <Setter Property="Margin" Value="0,5,0,5" /> + </Style> + </Grid.Resources> + + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + + <Grid.ColumnDefinitions> + <ColumnDefinition Width="90" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + + <TextBlock FontWeight="Bold" Text="Source:" VerticalAlignment="Top" Grid.Row="0" Grid.Column="0" /> + <TextBlock Text="{Binding Task.Source}" TextWrapping="Wrap" Grid.Row="0" Grid.Column="1" /> + + <TextBlock FontWeight="Bold" Text="Destination:" VerticalAlignment="Top" Grid.Row="1" Grid.Column="0" /> + <TextBlock Text="{Binding Task.Destination}" TextWrapping="Wrap" Grid.Row="1" Grid.Column="1" /> + + <TextBlock FontWeight="Bold" Text="Video:" Grid.Row="2" Grid.Column="0" /> + <TextBlock Text="{Binding Task.VideoEncoder, Converter={StaticResource enumComboConverter}}" + Grid.Row="2" Grid.Column="1" /> + + <TextBlock FontWeight="Bold" Text="Audio: " Grid.Row="3" Grid.Column="0"/> + <TextBlock Text="{Binding Task.AudioTracks, Converter={StaticResource audioTrackDisplayConverter}}" + Grid.Row="3" Grid.Column="1"/> + + <TextBlock FontWeight="Bold" VerticalAlignment="Top" Text="Subtitles: " Grid.Row="4" Grid.Column="0" /> + <TextBlock Text="{Binding Task.SubtitleTracks, Converter={StaticResource subtitleTrackDisplayConverter}}" + Grid.Row="4" Grid.Column="1" /> + + + <TextBlock FontWeight="Bold" VerticalAlignment="Top" Grid.Row="5" Grid.Column="0" Text="Advanced: " /> + <TextBlock Text="{Binding Task.AdvancedEncoderOptions}" Grid.Row="5" Grid.Column="1" /> + </Grid> - </StackPanel> </Setter.Value> </Setter> </Style> diff --git a/win/CS/HandBrakeWPF/Views/SubtitlesView.xaml b/win/CS/HandBrakeWPF/Views/SubtitlesView.xaml index a99989189..48c2e68b0 100644 --- a/win/CS/HandBrakeWPF/Views/SubtitlesView.xaml +++ b/win/CS/HandBrakeWPF/Views/SubtitlesView.xaml @@ -28,23 +28,22 @@ FontWeight="Bold" Text="Subtitles" /> - <Grid Grid.Row="1" Margin="10,5,10,0"> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="Auto" /> - <ColumnDefinition Width="Auto" /> - <ColumnDefinition Width="Auto" /> - </Grid.ColumnDefinitions> + <StackPanel Grid.Row="1" Margin="10,5,10,0" Orientation="Horizontal"> <Button Name="AddTrack" - Grid.Column="0" - Width="75" + MinWidth="75" Margin="0,0,10,0" cal:Message.Attach="[Event Click] = [Action Add]" Content="Add" /> - <Button Grid.Column="2" - Width="85" + <Button MinWidth="75" cal:Message.Attach="[Event Click] = [Action Import]" - Content="Import SRT" /> - </Grid> + Content="Import SRT" + Margin="0,0,10,0"/> + <Button MinWidth="65" + Grid.Column="3" + Margin="0,0,10,0" + cal:Message.Attach="[Event Click] = [Action Clear]" + Content="Clear" /> + </StackPanel> <ListBox Grid.Row="2" Margin="10,10,10,10" diff --git a/win/CS/HandBrakeWPF/Views/VideoView.xaml b/win/CS/HandBrakeWPF/Views/VideoView.xaml index 9e098596a..58fedf7bb 100644 --- a/win/CS/HandBrakeWPF/Views/VideoView.xaml +++ b/win/CS/HandBrakeWPF/Views/VideoView.xaml @@ -89,8 +89,8 @@ <StackPanel Orientation="Horizontal" Margin="0,0,0,10" > <RadioButton Content="Constant Quality:" IsChecked="{Binding IsConstantQuantity}" Margin="0,0,10,0"/> - <TextBlock Text="{Binding DisplayRF}" Width="25" /> - <TextBlock Text="{Binding Rfqp}" FontWeight="Bold" /> + <TextBlock Text="{Binding DisplayRF}" MinWidth="30" /> + <TextBlock Text="{Binding Rfqp}" FontWeight="Bold" Margin="5,0,0,0" /> <TextBlock Text="{x:Static Properties:Resources.Video_LosslessWarning}" Visibility="{Binding IsLossless, Converter={StaticResource boolToVisConverter}}" Margin="10,0,0,0" ToolTip="{x:Static Properties:Resources.Video_LosslessWarningTooltip}" FontWeight="Bold" /> -- 2.40.0