diff options
author | sr55 <[email protected]> | 2016-03-21 00:07:04 +0000 |
---|---|---|
committer | sr55 <[email protected]> | 2016-03-21 00:07:04 +0000 |
commit | 9e9167bb63f14f176913cc42521d45639512c15a (patch) | |
tree | c62ab72125805ee252ac96fdb6c78154c5c9d1fc /win/CS | |
parent | 78827728072257daadc8acb00bb24af7779c4d63 (diff) |
WinGui: Add a Logging Service into the AppServices library. This does not depend on any 3rd party libraries and is off by default. It must be initialised by calling Enable() on the LogService class. Otherwise LogMessage does nothing.
Changed the Logging screen to a single panel in the WinGui. This will change back to separate Scan/Encode logs when we get libhb it's own processes.
Added Auto-Scroll to the log window.
Diffstat (limited to 'win/CS')
24 files changed, 774 insertions, 681 deletions
diff --git a/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj b/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj index c6fddcfb7..91342b059 100644 --- a/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj +++ b/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj @@ -181,7 +181,9 @@ <Compile Include="Interop\Model\VideoQualityLimits.cs" />
<Compile Include="Model\HBConfiguration.cs" />
<Compile Include="Model\VideoScaler.cs" />
- <Compile Include="Services\Logging\LogHelper.cs" />
+ <Compile Include="Services\Logging\EventArgs\LogEventArgs.cs" />
+ <Compile Include="Services\Logging\Interfaces\ILog.cs" />
+ <Compile Include="Services\Logging\LogService.cs" />
<Compile Include="Services\Logging\Model\LogLevel.cs" />
<Compile Include="Services\Logging\Model\LogMessage.cs" />
<Compile Include="Services\Logging\Model\LogMessageType.cs" />
diff --git a/win/CS/HandBrake.ApplicationServices/Interop/HandBrakeInstance.cs b/win/CS/HandBrake.ApplicationServices/Interop/HandBrakeInstance.cs index a862dc1e6..633c4e1fb 100644 --- a/win/CS/HandBrake.ApplicationServices/Interop/HandBrakeInstance.cs +++ b/win/CS/HandBrake.ApplicationServices/Interop/HandBrakeInstance.cs @@ -34,6 +34,7 @@ namespace HandBrake.ApplicationServices.Interop using HandBrake.ApplicationServices.Interop.Model.Encoding;
using HandBrake.ApplicationServices.Interop.Model.Preview;
using HandBrake.ApplicationServices.Services.Logging;
+ using HandBrake.ApplicationServices.Services.Logging.Interfaces;
using HandBrake.ApplicationServices.Services.Logging.Model;
using Newtonsoft.Json;
@@ -55,6 +56,8 @@ namespace HandBrake.ApplicationServices.Interop /// </summary>
private const double EncodePollIntervalMs = 250;
+ private readonly ILog log = LogService.GetLogger();
+
/// <summary>
/// The native handle to the HandBrake instance.
/// </summary>
@@ -502,7 +505,7 @@ namespace HandBrake.ApplicationServices.Interop {
IntPtr json = HBFunctions.hb_get_state_json(this.hbHandle);
string statusJson = Marshal.PtrToStringAnsi(json);
- LogHelper.LogMessage(new LogMessage(statusJson, LogMessageType.progressJson, LogLevel.debug));
+ this.log.LogMessage(statusJson, LogMessageType.Progress, LogLevel.Trace);
JsonState state = JsonConvert.DeserializeObject<JsonState>(statusJson);
if (state != null && state.State == NativeConstants.HB_STATE_SCANNING)
@@ -516,7 +519,7 @@ namespace HandBrake.ApplicationServices.Interop {
var jsonMsg = HBFunctions.hb_get_title_set_json(this.hbHandle);
string scanJson = InteropUtilities.ToStringFromUtf8Ptr(jsonMsg);
- LogHelper.LogMessage(new LogMessage(scanJson, LogMessageType.scanJson, LogLevel.debug));
+ this.log.LogMessage(scanJson, LogMessageType.Progress, LogLevel.Trace);
this.titles = JsonConvert.DeserializeObject<JsonScanObject>(scanJson);
this.featureTitle = this.titles.MainFeature;
@@ -541,7 +544,7 @@ namespace HandBrake.ApplicationServices.Interop IntPtr json = HBFunctions.hb_get_state_json(this.hbHandle);
string statusJson = Marshal.PtrToStringAnsi(json);
- LogHelper.LogMessage(new LogMessage(statusJson, LogMessageType.progressJson, LogLevel.debug));
+ this.log.LogMessage(statusJson, LogMessageType.Progress, LogLevel.Trace);
JsonState state = JsonConvert.DeserializeObject<JsonState>(statusJson);
diff --git a/win/CS/HandBrake.ApplicationServices/Interop/HandBrakePresetService.cs b/win/CS/HandBrake.ApplicationServices/Interop/HandBrakePresetService.cs index fcc6d61da..7e1f95d3e 100644 --- a/win/CS/HandBrake.ApplicationServices/Interop/HandBrakePresetService.cs +++ b/win/CS/HandBrake.ApplicationServices/Interop/HandBrakePresetService.cs @@ -18,6 +18,7 @@ namespace HandBrake.ApplicationServices.Interop using HandBrake.ApplicationServices.Interop.Helpers;
using HandBrake.ApplicationServices.Interop.Json.Presets;
using HandBrake.ApplicationServices.Services.Logging;
+ using HandBrake.ApplicationServices.Services.Logging.Interfaces;
using HandBrake.ApplicationServices.Services.Logging.Model;
using Newtonsoft.Json;
@@ -27,6 +28,8 @@ namespace HandBrake.ApplicationServices.Interop /// </summary>
public class HandBrakePresetService
{
+ private static readonly ILog log = LogService.GetLogger();
+
/// <summary>
/// The get built in presets.
/// Requires an hb_init to have been invoked.
@@ -39,7 +42,7 @@ namespace HandBrake.ApplicationServices.Interop IntPtr presets = HBFunctions.hb_presets_builtin_get_json();
string presetJson = Marshal.PtrToStringAnsi(presets);
- LogHelper.LogMessage(new LogMessage(presetJson, LogMessageType.progressJson, LogLevel.debug));
+ log.LogMessage(presetJson, LogMessageType.API, LogLevel.Debug);
IList<PresetCategory> presetList = JsonConvert.DeserializeObject<IList<PresetCategory>>(presetJson);
@@ -60,7 +63,7 @@ namespace HandBrake.ApplicationServices.Interop IntPtr presetStringPointer = HBFunctions.hb_presets_read_file_json(InteropUtilities.ToUtf8PtrFromString(filename));
string presetJson = Marshal.PtrToStringAnsi(presetStringPointer);
- LogHelper.LogMessage(new LogMessage(presetJson, LogMessageType.libhb, LogLevel.debug));
+ log.LogMessage(presetJson, LogMessageType.API, LogLevel.Debug);
PresetTransportContainer preset = JsonConvert.DeserializeObject<PresetTransportContainer>(presetJson);
diff --git a/win/CS/HandBrake.ApplicationServices/Interop/HandBrakeUtils.cs b/win/CS/HandBrake.ApplicationServices/Interop/HandBrakeUtils.cs index 3540bb368..ef98f3f86 100644 --- a/win/CS/HandBrake.ApplicationServices/Interop/HandBrakeUtils.cs +++ b/win/CS/HandBrake.ApplicationServices/Interop/HandBrakeUtils.cs @@ -11,7 +11,6 @@ namespace HandBrake.ApplicationServices.Interop {
using System;
using System.Collections.Generic;
- using System.Diagnostics;
using System.Runtime.InteropServices;
using HandBrake.ApplicationServices.Interop.EventArgs;
@@ -19,6 +18,7 @@ namespace HandBrake.ApplicationServices.Interop using HandBrake.ApplicationServices.Interop.Json.Anamorphic;
using HandBrake.ApplicationServices.Interop.Json.Shared;
using HandBrake.ApplicationServices.Services.Logging;
+ using HandBrake.ApplicationServices.Services.Logging.Interfaces;
using HandBrake.ApplicationServices.Services.Logging.Model;
using Newtonsoft.Json;
@@ -28,6 +28,8 @@ namespace HandBrake.ApplicationServices.Interop /// </summary>
public static class HandBrakeUtils
{
+ private static readonly ILog log = LogService.GetLogger();
+
/// <summary>
/// The callback for log messages from HandBrake.
/// </summary>
@@ -301,7 +303,7 @@ namespace HandBrake.ApplicationServices.Interop public static Geometry GetAnamorphicSize(AnamorphicGeometry anamorphicGeometry)
{
string encode = JsonConvert.SerializeObject(anamorphicGeometry, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
- LogHelper.LogMessage(new LogMessage(encode, LogMessageType.encodeJson, LogLevel.debug));
+ log.LogMessage(encode, LogMessageType.API, LogLevel.Debug);
IntPtr json = HBFunctions.hb_set_anamorphic_size_json(Marshal.StringToHGlobalAnsi(encode));
string result = Marshal.PtrToStringAnsi(json);
return JsonConvert.DeserializeObject<Geometry>(result);
@@ -317,10 +319,9 @@ namespace HandBrake.ApplicationServices.Interop {
if (MessageLogged != null)
{
+ log.LogMessage(message, LogMessageType.ScanOrEncode, LogLevel.Info);
MessageLogged(null, new MessageLoggedEventArgs(message));
}
-
- Debug.WriteLine(message);
}
/// <summary>
@@ -333,10 +334,9 @@ namespace HandBrake.ApplicationServices.Interop {
if (ErrorLogged != null)
{
+ log.LogMessage(message, LogMessageType.ScanOrEncode, LogLevel.Error);
ErrorLogged(null, new MessageLoggedEventArgs(message));
}
-
- Debug.WriteLine("ERROR: " + message);
}
}
}
diff --git a/win/CS/HandBrake.ApplicationServices/Services/Logging/EventArgs/LogEventArgs.cs b/win/CS/HandBrake.ApplicationServices/Services/Logging/EventArgs/LogEventArgs.cs new file mode 100644 index 000000000..b9691e4a3 --- /dev/null +++ b/win/CS/HandBrake.ApplicationServices/Services/Logging/EventArgs/LogEventArgs.cs @@ -0,0 +1,37 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="LogEventArgs.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Defines the LogEventArgs type. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.ApplicationServices.Services.Logging.EventArgs +{ + using System; + + using Model; + + /// <summary> + /// The Message Logged Event Args + /// </summary> + public class LogEventArgs : EventArgs + { + /// <summary> + /// Initializes a new instance of the <see cref="LogEventArgs"/> class. + /// </summary> + /// <param name="message"> + /// The message. + /// </param> + public LogEventArgs(LogMessage message) + { + this.Log = message; + } + + /// <summary> + /// Gets the Message. + /// </summary> + public LogMessage Log { get; private set; } + } +} diff --git a/win/CS/HandBrake.ApplicationServices/Services/Logging/Interfaces/ILog.cs b/win/CS/HandBrake.ApplicationServices/Services/Logging/Interfaces/ILog.cs new file mode 100644 index 000000000..dc0b3c08b --- /dev/null +++ b/win/CS/HandBrake.ApplicationServices/Services/Logging/Interfaces/ILog.cs @@ -0,0 +1,87 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="ILog.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Defines the ILog type. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.ApplicationServices.Services.Logging.Interfaces +{ + using System; + using System.Collections.Generic; + + using EventArgs; + + using Model; + + /// <summary> + /// The Log interface. + /// </summary> + public interface ILog + { + /// <summary> + /// The message logged. + /// </summary> + event EventHandler<LogEventArgs> MessageLogged; + + /// <summary> + /// The log reset event + /// </summary> + event EventHandler LogReset; + + /// <summary> + /// Gets the log messages. + /// </summary> + IEnumerable<LogMessage> LogMessages { get; } + + /// <summary> + /// Gets the activity log. + /// </summary> + string ActivityLog { get; } + + /// <summary> + /// The reset. + /// </summary> + void Reset(); + + /// <summary> + /// The enable. + /// </summary> + void Enable(); + + /// <summary> + /// Log a message. + /// </summary> + /// <param name="content"> + /// The content of the log message, + /// </param> + /// <param name="type"> + /// The Message Type. (i.e. where it came from) + /// </param> + /// <param name="level"> + /// The log level + /// </param> + void LogMessage(string content, LogMessageType type, LogLevel level); + + /// <summary> + /// Enable Logging to Disk + /// </summary> + /// <param name="logFile"> + /// The log file to write to. + /// </param> + /// <param name="deleteCurrentLogFirst"> + /// Delete the current log file if it exists. + /// </param> + void EnableLoggingToDisk(string logFile, bool deleteCurrentLogFirst); + + /// <summary> + /// The setup log header. + /// </summary> + /// <param name="header"> + /// The header. + /// </param> + void SetupLogHeader(string header); + } +}
\ No newline at end of file diff --git a/win/CS/HandBrake.ApplicationServices/Services/Logging/LogHelper.cs b/win/CS/HandBrake.ApplicationServices/Services/Logging/LogHelper.cs deleted file mode 100644 index 44ccc757c..000000000 --- a/win/CS/HandBrake.ApplicationServices/Services/Logging/LogHelper.cs +++ /dev/null @@ -1,53 +0,0 @@ -// --------------------------------------------------------------------------------------------------------------------
-// <copyright file="LogHelper.cs" company="HandBrake Project (http://handbrake.fr)">
-// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
-// </copyright>
-// <summary>
-// The log service.
-// For now, this is just a simple logging service but we could provide support for a formal logging library later.
-// Also, we can consider providing the UI layer with more functional logging. (i.e levels, time/date, highlighting etc)
-// The Interop Classes are not very OO friendly, so this is going to be a static class.
-// </summary>
-// --------------------------------------------------------------------------------------------------------------------
-
-namespace HandBrake.ApplicationServices.Services.Logging
-{
- using System.Diagnostics;
-
- using HandBrake.ApplicationServices.Services.Logging.Model;
-
- /// <summary>
- /// The log helper.
- /// </summary>
- public static class LogHelper
- {
- private static LogLevel currentLogLevel = LogLevel.debug; // TODO default to Info when this class is implimented.
-
- /// <summary>
- /// Log message.
- /// </summary>
- /// <param name="message">
- /// The message.
- /// </param>
- public static void LogMessage(LogMessage message)
- {
- if (message.LogLevel <= currentLogLevel)
- {
- //Debug.WriteLine(message.Content);
- }
-
- // TODO cache logging.
- }
-
- /// <summary>
- /// The set log level. Default: Info.
- /// </summary>
- /// <param name="level">
- /// The level.
- /// </param>
- public static void SetLogLevel(LogLevel level)
- {
- currentLogLevel = level;
- }
- }
-}
diff --git a/win/CS/HandBrake.ApplicationServices/Services/Logging/LogService.cs b/win/CS/HandBrake.ApplicationServices/Services/Logging/LogService.cs new file mode 100644 index 000000000..cd0d5a483 --- /dev/null +++ b/win/CS/HandBrake.ApplicationServices/Services/Logging/LogService.cs @@ -0,0 +1,361 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="LogService.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// The log service. +// For now, this is just a simple logging service but we could provide support for a formal logging library later. +// Also, we can consider providing the UI layer with more functional logging. (i.e levels, time/date, highlighting etc) +// The Interop Classes are not very OO friendly, so this is going to be a static class. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.ApplicationServices.Services.Logging +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.IO; + using System.Text; + + using HandBrake.ApplicationServices.Services.Logging.EventArgs; + using HandBrake.ApplicationServices.Services.Logging.Interfaces; + using HandBrake.ApplicationServices.Services.Logging.Model; + + /// <summary> + /// The log helper. + /// </summary> + public class LogService : ILog + { + // TODO List. + // Maybe make the event weak? + // Make this class Thread Safe. + private static ILog loggerInstance; + private readonly object lockObject = new object(); + private readonly object FileWriterLock = new object(); + private readonly StringBuilder logBuilder = new StringBuilder(); + + private LogLevel currentLogLevel = LogLevel.Error; + private bool isLoggingEnabled; + private List<LogMessage> logMessages = new List<LogMessage>(); + private long messageIndex; + private string diskLogPath; + private bool deleteLogFirst; + private bool isDiskLoggingEnabled; + private StreamWriter fileWriter; + private string logHeader; + + /// <summary> + /// Fires when a new QueueTask starts + /// </summary> + public event EventHandler<LogEventArgs> MessageLogged; + + /// <summary> + /// The log reset event + /// </summary> + public event EventHandler LogReset; + + /// <summary> + /// Gets the log messages. + /// </summary> + public IEnumerable<LogMessage> LogMessages + { + get + { + lock (this.lockObject) + { + return this.logMessages; + } + } + } + + /// <summary> + /// Gets the Activity Log as a string. + /// </summary> + public string ActivityLog + { + get + { + lock (this.lockObject) + { + return this.logBuilder.ToString(); + } + } + } + + /// <summary> + /// Log message. + /// </summary> + /// <param name="content"> + /// The content. + /// </param> + /// <param name="type"> + /// The type. + /// </param> + /// <param name="level"> + /// The level. + /// </param> + public void LogMessage(string content, LogMessageType type, LogLevel level) + { + if (!this.isLoggingEnabled) + { + return; + } + + if (level >= this.currentLogLevel) + { + return; + } + + LogMessage msg = new LogMessage(content, type, level, this.messageIndex); + lock (this.lockObject) + { + this.messageIndex = this.messageIndex + 1; + this.logMessages.Add(msg); + this.logBuilder.AppendLine(msg.Content); + this.LogMessageToDisk(msg); + + if (this.logMessages.Count > 50000) + { + this.messageIndex = this.messageIndex + 1; + msg = new LogMessage( + "Log Service Pausing. Too Many Log messages. This may indicate a problem with your encode.", + LogMessageType.Vital, + LogLevel.Error, + this.messageIndex); + this.logMessages.Add(msg); + this.logBuilder.AppendLine(msg.Content); + this.LogMessageToDisk(msg); + + this.Disable(); + } + } + + this.OnMessageLogged(msg); // Must be outside lock to be thread safe. + } + + /// <summary> + /// Gets an shared instance of the logger. Logging is enabled by default + /// You can turn it off by calling Disable() if you don't want it. + /// </summary> + /// <returns> + /// An instance of this logger. + /// </returns> + public static ILog GetLogger() + { + return loggerInstance ?? (loggerInstance = new LogService()); + } + + /// <summary> + /// The set log level. Default: Info. + /// </summary> + /// <param name="level"> + /// The level. + /// </param> + public void SetLogLevel(LogLevel level) + { + this.currentLogLevel = level; + } + + /// <summary> + /// The enable. + /// </summary> + public void Enable() + { + this.isLoggingEnabled = true; + } + + /// <summary> + /// Enable Logging to Disk + /// </summary> + /// <param name="logFile"> + /// The log file to write to. + /// </param> + /// <param name="deleteCurrentLogFirst"> + /// Delete the current log file if it exists. + /// </param> + public void EnableLoggingToDisk(string logFile, bool deleteCurrentLogFirst) + { + if (this.isDiskLoggingEnabled) + { + throw new Exception("Disk Logging already enabled!"); + } + + try + { + if (!Directory.Exists(Path.GetDirectoryName(logFile))) + { + throw new Exception("Log Directory does not exist. This service will not create it for you!"); + } + + if (deleteCurrentLogFirst && File.Exists(logFile)) + { + File.Delete(logFile); + } + + this.diskLogPath = logFile; + this.isDiskLoggingEnabled = true; + this.deleteLogFirst = deleteCurrentLogFirst; + + lock (this.FileWriterLock) + { + this.fileWriter = new StreamWriter(logFile) { AutoFlush = true }; + } + } + catch (Exception exc) + { + this.LogMessage("Failed to Initialise Disk Logging. " + Environment.NewLine + exc, LogMessageType.Vital, LogLevel.Error); + + if (this.fileWriter != null) + { + lock (this.FileWriterLock) + { + this.fileWriter.Flush(); + this.fileWriter.Close(); + this.fileWriter.Dispose(); + } + } + } + } + + /// <summary> + /// The setup log header. + /// </summary> + /// <param name="header"> + /// The header. + /// </param> + public void SetupLogHeader(string header) + { + this.logHeader = header; + this.LogMessage(header, LogMessageType.Vital, LogLevel.Info); + } + + /// <summary> + /// The disable. + /// </summary> + public void Disable() + { + this.isLoggingEnabled = false; + } + + /// <summary> + /// Clear the log messages collection. + /// </summary> + public void Reset() + { + lock (this.lockObject) + { + this.logMessages.Clear(); + this.logBuilder.Clear(); + this.messageIndex = 0; + + try + { + lock (this.FileWriterLock) + { + if (this.fileWriter != null) + { + this.fileWriter.Flush(); + this.fileWriter.Close(); + this.fileWriter.Dispose(); + } + + this.fileWriter = null; + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); + } + + if (this.fileWriter == null) + { + this.isDiskLoggingEnabled = false; + this.EnableLoggingToDisk(this.diskLogPath, this.deleteLogFirst); + } + + if (!string.IsNullOrEmpty(this.logHeader)) + { + this.SetupLogHeader(this.logHeader); + } + + this.OnLogReset(); + } + } + + /// <summary> + /// Helper method for logging content to disk + /// </summary> + /// <param name="msg"> + /// Log message to write. + /// </param> + private void LogMessageToDisk(LogMessage msg) + { + if (!this.isDiskLoggingEnabled) + { + return; + } + + try + { + lock (this.FileWriterLock) + { + if (this.fileWriter != null && this.fileWriter.BaseStream.CanWrite) + { + this.fileWriter.WriteLine(msg.Content); + } + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); // This exception doesn't warrent user interaction, but it should be logged + } + } + + /// <summary> + /// Called when a log message is created. + /// </summary> + /// <param name="msg"> + /// The Log Message + /// </param> + protected virtual void OnMessageLogged(LogMessage msg) + { + var onMessageLogged = this.MessageLogged; + if (onMessageLogged != null) + { + onMessageLogged.Invoke(this, new LogEventArgs(msg)); + } + } + + /// <summary> + /// Shutdown and Dispose of the File Writer. + /// </summary> + protected void ShutdownFileWriter() + { + try + { + lock (this.FileWriterLock) + { + if (this.fileWriter != null) + { + this.fileWriter.Flush(); + this.fileWriter.Close(); + this.fileWriter.Dispose(); + } + + this.fileWriter = null; + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); // This exception doesn't warrent user interaction, but it should be logged + } + } + + // Trigger the Event to notify any subscribers that the log has been reset. + protected virtual void OnLogReset() + { + this.LogReset?.Invoke(this, System.EventArgs.Empty); + } + } +} diff --git a/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogLevel.cs b/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogLevel.cs index c2e2b8f0a..a319ae385 100644 --- a/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogLevel.cs +++ b/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogLevel.cs @@ -17,21 +17,26 @@ namespace HandBrake.ApplicationServices.Services.Logging.Model /// <summary>
/// The info.
/// </summary>
- info,
+ Info,
/// <summary>
/// The warning.
/// </summary>
- warning,
+ Warning,
/// <summary>
/// The error.
/// </summary>
- error,
+ Error,
/// <summary>
/// The debug.
/// </summary>
- debug,
+ Debug,
+
+ /// <summary>
+ /// Trace Level Logging.
+ /// </summary>
+ Trace,
}
}
diff --git a/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogMessage.cs b/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogMessage.cs index 9179e2fa5..edf071ba1 100644 --- a/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogMessage.cs +++ b/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogMessage.cs @@ -10,7 +10,7 @@ namespace HandBrake.ApplicationServices.Services.Logging.Model
{
/// <summary>
- /// The json message.
+ /// An Immutable Log Entry.
/// </summary>
public class LogMessage
{
@@ -26,11 +26,15 @@ namespace HandBrake.ApplicationServices.Services.Logging.Model /// <param name="logLevel">
/// The log level.
/// </param>
- public LogMessage(string content, LogMessageType messageType, LogLevel logLevel)
+ /// <param name="messageIndex">
+ /// The message Index.
+ /// </param>
+ public LogMessage(string content, LogMessageType messageType, LogLevel logLevel, long messageIndex)
{
this.Content = content;
this.MessageType = messageType;
this.LogLevel = logLevel;
+ this.MessageIndex = messageIndex;
}
/// <summary>
@@ -48,5 +52,10 @@ namespace HandBrake.ApplicationServices.Services.Logging.Model /// Gets the log level.
/// </summary>
public LogLevel LogLevel { get; private set; }
+
+ /// <summary>
+ /// Gets the message index.
+ /// </summary>
+ public long MessageIndex { get; private set; }
}
}
diff --git a/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogMessageType.cs b/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogMessageType.cs index df0ce0fc3..47302a872 100644 --- a/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogMessageType.cs +++ b/win/CS/HandBrake.ApplicationServices/Services/Logging/Model/LogMessageType.cs @@ -14,10 +14,9 @@ namespace HandBrake.ApplicationServices.Services.Logging.Model /// </summary>
public enum LogMessageType
{
- scanJson,
- encodeJson,
- anamorphicJson,
- progressJson,
- libhb,
+ ScanOrEncode,
+ API,
+ Progress,
+ Vital,
}
}
diff --git a/win/CS/HandBrake.ApplicationServices/Utilities/LanguageUtilities.cs b/win/CS/HandBrake.ApplicationServices/Utilities/LanguageUtilities.cs index 1acc9cccc..12665c062 100644 --- a/win/CS/HandBrake.ApplicationServices/Utilities/LanguageUtilities.cs +++ b/win/CS/HandBrake.ApplicationServices/Utilities/LanguageUtilities.cs @@ -277,6 +277,15 @@ namespace HandBrake.ApplicationServices.Utilities return iso6392Codes;
}
+ /// <summary>
+ /// The get language names.
+ /// </summary>
+ /// <param name="languageCodes">
+ /// The language codes.
+ /// </param>
+ /// <returns>
+ /// The <see cref="List"/>.
+ /// </returns>
public static List<string> GetLanguageNames(IList<string> languageCodes)
{
// Translate to Iso Codes
diff --git a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj index 4b4dd7b81..c2dd50a54 100644 --- a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj +++ b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj @@ -157,6 +157,7 @@ <Compile Include="EventArgs\SettingChangedEventArgs.cs" />
<Compile Include="Exceptions\GeneralApplicationException.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
+ <Compile Include="Helpers\LogManager.cs" />
<Compile Include="Helpers\MP4Helper.cs" />
<Compile Include="Helpers\TimeSpanHelper.cs" />
<Compile Include="Helpers\Validate.cs" />
diff --git a/win/CS/HandBrakeWPF/Helpers/LogManager.cs b/win/CS/HandBrakeWPF/Helpers/LogManager.cs new file mode 100644 index 000000000..4e883f8ee --- /dev/null +++ b/win/CS/HandBrakeWPF/Helpers/LogManager.cs @@ -0,0 +1,49 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="LogManager.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// The log manager. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Helpers +{ + using System; + using System.IO; + + using HandBrake.ApplicationServices.Interop; + using HandBrake.ApplicationServices.Services.Logging; + using HandBrake.ApplicationServices.Services.Logging.Interfaces; + + using HandBrakeWPF.Utilities; + + /// <summary> + /// Tempory Class to Initialise the logging. + /// </summary> + public static class LogManager + { + /// <summary> + /// The init. + /// </summary> + public static void Init() + { + ILog log = LogService.GetLogger(); + string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs"; + string logFile = Path.Combine(logDir, string.Format("activity_log{0}.txt", GeneralUtilities.ProcessId)); + log.Enable(); + log.SetupLogHeader(GeneralUtilities.CreateLogHeader().ToString()); + log.EnableLoggingToDisk(logFile, true); + HandBrakeUtils.MessageLogged += HandBrakeUtils_MessageLogged; + HandBrakeUtils.ErrorLogged += HandBrakeUtils_ErrorLogged; + } + + private static void HandBrakeUtils_ErrorLogged(object sender, HandBrake.ApplicationServices.Interop.EventArgs.MessageLoggedEventArgs e) + { + } + + private static void HandBrakeUtils_MessageLogged(object sender, HandBrake.ApplicationServices.Interop.EventArgs.MessageLoggedEventArgs e) + { + } + } +}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Encode/EncodeBase.cs b/win/CS/HandBrakeWPF/Services/Encode/EncodeBase.cs index 9ae0398ee..801a8c9cc 100644 --- a/win/CS/HandBrakeWPF/Services/Encode/EncodeBase.cs +++ b/win/CS/HandBrakeWPF/Services/Encode/EncodeBase.cs @@ -13,11 +13,10 @@ namespace HandBrakeWPF.Services.Encode using System.Diagnostics; using System.Globalization; using System.IO; - using System.Text; using HandBrake.ApplicationServices.Model; - - using HandBrakeWPF.Utilities; + using HandBrake.ApplicationServices.Services.Logging; + using HandBrake.ApplicationServices.Services.Logging.Interfaces; using EncodeCompletedEventArgs = HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs; using EncodeCompletedStatus = HandBrakeWPF.Services.Encode.Interfaces.EncodeCompletedStatus; @@ -31,38 +30,11 @@ namespace HandBrakeWPF.Services.Encode /// </summary> public class EncodeBase { - #region Private Variables - - /// <summary> - /// A Lock for the filewriter - /// </summary> - private static readonly object FileWriterLock = new object(); - - /// <summary> - /// The Log File Header - /// </summary> - private readonly StringBuilder header; - - /// <summary> - /// The Log Buffer - /// </summary> - private StringBuilder logBuffer; - - /// <summary> - /// The Log file writer - /// </summary> - private StreamWriter fileWriter; - - #endregion - /// <summary> /// Initializes a new instance of the <see cref="EncodeBase"/> class. /// </summary> public EncodeBase() - { - this.logBuffer = new StringBuilder(); - this.header = GeneralUtilities.CreateLogHeader(); - this.LogIndex = 0; + { } #region Events @@ -91,39 +63,6 @@ namespace HandBrakeWPF.Services.Encode /// </summary> public bool IsEncoding { get; protected set; } - /// <summary> - /// Gets ActivityLog. - /// </summary> - public string ActivityLog - { - get - { - string noLog = "There is no log information to display." + Environment.NewLine + Environment.NewLine - + "This window will only display logging information after you have started an encode." + Environment.NewLine - + Environment.NewLine + "You can find previous log files in the log directory or by clicking the 'Open Log Directory' button above."; - - return string.IsNullOrEmpty(this.logBuffer.ToString()) - ? noLog - : this.header + this.logBuffer.ToString(); - } - } - - /// <summary> - /// Gets the log index. - /// </summary> - public int LogIndex { get; private set; } - - /// <summary> - /// Gets LogBuffer. - /// </summary> - public StringBuilder LogBuffer - { - get - { - return this.logBuffer; - } - } - #endregion #region Invoke Events @@ -156,8 +95,6 @@ namespace HandBrakeWPF.Services.Encode { handler(this, e); } - - this.LogIndex = 0; // Reset } /// <summary> @@ -186,6 +123,9 @@ namespace HandBrakeWPF.Services.Encode /// <param name="destination"> /// The Destination File Path /// </param> + /// <param name="isPreview"> + /// The is Preview. + /// </param> /// <param name="configuration"> /// The configuration. /// </param> @@ -193,15 +133,12 @@ namespace HandBrakeWPF.Services.Encode { try { - string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + - "\\HandBrake\\logs"; - - string tempLogFile = Path.Combine(logDir, isPreview ? $"preview_encode_log{GeneralUtilities.ProcessId}.txt" : string.Format("last_encode_log{0}.txt", GeneralUtilities.ProcessId)); - + string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs"; string encodeDestinationPath = Path.GetDirectoryName(destination); string destinationFile = Path.GetFileName(destination); - string encodeLogFile = destinationFile + " " + - DateTime.Now.ToString(CultureInfo.InvariantCulture).Replace("/", "-").Replace(":", "-") + ".txt"; + string encodeLogFile = destinationFile + " " + DateTime.Now.ToString(CultureInfo.InvariantCulture).Replace("/", "-").Replace(":", "-") + ".txt"; + ILog log = LogService.GetLogger(); + string logContent = log.ActivityLog; // Make sure the log directory exists. if (!Directory.Exists(logDir)) @@ -210,19 +147,18 @@ namespace HandBrakeWPF.Services.Encode } // Copy the Log to HandBrakes log folder in the users applciation data folder. - File.Copy(tempLogFile, Path.Combine(logDir, encodeLogFile)); + this.WriteFile(logContent, Path.Combine(logDir, encodeLogFile)); // Save a copy of the log file in the same location as the enocde. if (configuration.SaveLogWithVideo) { - File.Copy(tempLogFile, Path.Combine(encodeDestinationPath, encodeLogFile)); + this.WriteFile(logContent, Path.Combine(encodeDestinationPath, encodeLogFile)); } // Save a copy of the log file to a user specified location if (Directory.Exists(configuration.SaveLogCopyDirectory) && configuration.SaveLogToCopyDirectory) { - File.Copy( - tempLogFile, Path.Combine(configuration.SaveLogCopyDirectory, encodeLogFile)); + this.WriteFile(logContent, Path.Combine(configuration.SaveLogCopyDirectory, encodeLogFile)); } } catch (Exception exc) @@ -232,116 +168,26 @@ namespace HandBrakeWPF.Services.Encode } /// <summary> - /// Setup the logging. + /// The write file. /// </summary> - protected void SetupLogging(bool isPreviewEncode) - { - this.ShutdownFileWriter(); - string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs"; - string logFile = Path.Combine(logDir, isPreviewEncode ? $"preview_last_encode_log{GeneralUtilities.ProcessId}.txt" : $"last_encode_log{GeneralUtilities.ProcessId}.txt"); - - try - { - this.logBuffer = new StringBuilder(); - - this.logBuffer.AppendLine(); - - // Clear the current Encode Logs) - if (File.Exists(logFile)) - { - File.Delete(logFile); - } - - lock (FileWriterLock) - { - this.fileWriter = new StreamWriter(logFile) { AutoFlush = true }; - this.fileWriter.WriteLine(this.header); - this.fileWriter.WriteLine(); - } - } - catch (Exception) - { - if (this.fileWriter != null) - { - lock (FileWriterLock) - { - this.fileWriter.Flush(); - this.fileWriter.Close(); - this.fileWriter.Dispose(); - } - } - - throw; - } - } - - /// <summary> - /// The service log message. - /// </summary> - /// <param name="message"> - /// The message. + /// <param name="fileName"> + /// The file name. /// </param> - protected void ServiceLogMessage(string message) - { - this.ProcessLogMessage(string.Format("# {0}", message)); - } - - /// <summary> - /// Process an Incomming Log Message. - /// </summary> - /// <param name="message"> - /// The message. + /// <param name="content"> + /// The content. /// </param> - protected void ProcessLogMessage(string message) - { - if (!string.IsNullOrEmpty(message)) - { - try - { - this.LogIndex = this.LogIndex + 1; - - lock (this.LogBuffer) - { - this.LogBuffer.AppendLine(message); - } - - lock (FileWriterLock) - { - if (this.fileWriter != null && this.fileWriter.BaseStream.CanWrite) - { - this.fileWriter.WriteLine(message); - } - } - } - catch (Exception exc) - { - Debug.WriteLine(exc); // This exception doesn't warrent user interaction, but it should be logged - } - } - } - - /// <summary> - /// Shutdown and Dispose of the File Writer. - /// </summary> - protected void ShutdownFileWriter() + private void WriteFile(string fileName, string content) { try { - lock (FileWriterLock) + using (StreamWriter fileWriter = new StreamWriter(fileName) { AutoFlush = true }) { - if (this.fileWriter != null) - { - this.fileWriter.Flush(); - this.fileWriter.Close(); - this.fileWriter.Dispose(); - } - - this.fileWriter = null; + fileWriter.WriteLineAsync(content); } } catch (Exception exc) { - Debug.WriteLine(exc); // This exception doesn't warrent user interaction, but it should be logged + Debug.WriteLine(exc); } } diff --git a/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs b/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs index 691df1500..b9a5f0aff 100644 --- a/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs +++ b/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs @@ -65,16 +65,6 @@ namespace HandBrakeWPF.Services.Encode.Interfaces bool IsEncoding { get; } /// <summary> - /// Gets ActivityLog. - /// </summary> - string ActivityLog { get; } - - /// <summary> - /// Gets the log index. The current log row counter. - /// </summary> - int LogIndex { get; } - - /// <summary> /// Gets a value indicating whether is pasued. /// </summary> bool IsPasued { get; } diff --git a/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs b/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs index 4bf64e5e1..e8b920c57 100644 --- a/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs +++ b/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs @@ -16,6 +16,9 @@ namespace HandBrakeWPF.Services.Encode using HandBrake.ApplicationServices.Interop.EventArgs; using HandBrake.ApplicationServices.Interop.Interfaces; using HandBrake.ApplicationServices.Model; + using HandBrake.ApplicationServices.Services.Logging; + using HandBrake.ApplicationServices.Services.Logging.Interfaces; + using HandBrake.ApplicationServices.Services.Logging.Model; using HandBrakeWPF.Exceptions; using HandBrakeWPF.Services.Encode.Factories; @@ -30,7 +33,7 @@ namespace HandBrakeWPF.Services.Encode { #region Private Variables - private static readonly object LogLock = new object(); + private ILog log = LogService.GetLogger(); private IHandBrakeInstance instance; private DateTime startTime; private EncodeTask currentTask; @@ -70,8 +73,6 @@ namespace HandBrakeWPF.Services.Encode // Create a new HandBrake instance // Setup the HandBrake Instance - HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged; - HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged; this.instance = task.IsPreviewEncode ? HandBrakeInstanceManager.GetPreviewInstance(configuration.Verbosity) : HandBrakeInstanceManager.GetEncodeInstance(configuration.Verbosity); this.instance.EncodeCompleted += this.InstanceEncodeCompleted; @@ -79,11 +80,11 @@ namespace HandBrakeWPF.Services.Encode this.IsEncoding = true; this.isPreviewInstance = task.IsPreviewEncode; - this.SetupLogging(task.IsPreviewEncode); // Verify the Destination Path Exists, and if not, create it. this.VerifyEncodeDestinationPath(task); + this.log.Reset(); // Reset so we have a clean log for the start of the encode. this.ServiceLogMessage("Starting Encode ..."); // Get an EncodeJob object for the Interop Library @@ -97,7 +98,7 @@ namespace HandBrakeWPF.Services.Encode this.IsEncoding = false; this.ServiceLogMessage("Failed to start encoding ..." + Environment.NewLine + exc); - this.InvokeEncodeCompleted(new HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs(false, exc, "Unable to start encoding", task.Source)); + this.InvokeEncodeCompleted(new EventArgs.EncodeCompletedEventArgs(false, exc, "Unable to start encoding", task.Source)); } } @@ -150,40 +151,6 @@ namespace HandBrakeWPF.Services.Encode #region HandBrakeInstance Event Handlers. /// <summary> - /// Log a message - /// </summary> - /// <param name="sender"> - /// The sender. - /// </param> - /// <param name="e"> - /// The MessageLoggedEventArgs. - /// </param> - private void HandBrakeInstanceErrorLogged(object sender, MessageLoggedEventArgs e) - { - lock (LogLock) - { - this.ProcessLogMessage(e.Message); - } - } - - /// <summary> - /// Log a message - /// </summary> - /// <param name="sender"> - /// The sender. - /// </param> - /// <param name="e"> - /// The MessageLoggedEventArgs. - /// </param> - private void HandBrakeInstanceMessageLogged(object sender, MessageLoggedEventArgs e) - { - lock (LogLock) - { - this.ProcessLogMessage(e.Message); - } - } - - /// <summary> /// Encode Progress Event Handler /// </summary> /// <param name="sender"> @@ -194,7 +161,7 @@ namespace HandBrakeWPF.Services.Encode /// </param> private void InstanceEncodeProgress(object sender, EncodeProgressEventArgs e) { - HandBrakeWPF.Services.Encode.EventArgs.EncodeProgressEventArgs args = new HandBrakeWPF.Services.Encode.EventArgs.EncodeProgressEventArgs + EventArgs.EncodeProgressEventArgs args = new EventArgs.EncodeProgressEventArgs { AverageFrameRate = e.AverageFrameRate, CurrentFrameRate = e.CurrentFrameRate, @@ -221,22 +188,24 @@ namespace HandBrakeWPF.Services.Encode { this.IsEncoding = false; this.ServiceLogMessage("Encode Completed ..."); - - // Stop Logging. - HandBrakeUtils.MessageLogged -= this.HandBrakeInstanceMessageLogged; - HandBrakeUtils.ErrorLogged -= this.HandBrakeInstanceErrorLogged; - + // Handling Log Data this.ProcessLogs(this.currentTask.Destination, this.isPreviewInstance, this.currentConfiguration); - // Cleanup - this.ShutdownFileWriter(); - // Raise the Encode Completed EVent. this.InvokeEncodeCompleted( e.Error - ? new HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs(false, null, string.Empty, this.currentTask.Destination) - : new HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs(true, null, string.Empty, this.currentTask.Destination)); + ? new EventArgs.EncodeCompletedEventArgs(false, null, string.Empty, this.currentTask.Destination) + : new EventArgs.EncodeCompletedEventArgs(true, null, string.Empty, this.currentTask.Destination)); + } + + /// <summary> + /// Service Log Message. + /// </summary> + /// <param name="message">Log message content</param> + protected void ServiceLogMessage(string message) + { + this.log.LogMessage(string.Format("# {0}", message), LogMessageType.ScanOrEncode, LogLevel.Info); } #endregion } diff --git a/win/CS/HandBrakeWPF/Services/Scan/Interfaces/IScan.cs b/win/CS/HandBrakeWPF/Services/Scan/Interfaces/IScan.cs index 0af5f30ec..4336574aa 100644 --- a/win/CS/HandBrakeWPF/Services/Scan/Interfaces/IScan.cs +++ b/win/CS/HandBrakeWPF/Services/Scan/Interfaces/IScan.cs @@ -66,11 +66,6 @@ namespace HandBrakeWPF.Services.Scan.Interfaces bool IsScanning { get; } /// <summary> - /// Gets ActivityLog. - /// </summary> - string ActivityLog { get; } - - /// <summary> /// Scan a Source Path. /// Title 0: scan all /// </summary> diff --git a/win/CS/HandBrakeWPF/Services/Scan/LibScan.cs b/win/CS/HandBrakeWPF/Services/Scan/LibScan.cs index 3d9d475a1..d72593cff 100644 --- a/win/CS/HandBrakeWPF/Services/Scan/LibScan.cs +++ b/win/CS/HandBrakeWPF/Services/Scan/LibScan.cs @@ -12,19 +12,18 @@ namespace HandBrakeWPF.Services.Scan using System; using System.Collections.Generic; using System.Diagnostics; - using System.IO; - using System.Text; using System.Windows.Media.Imaging; using HandBrake.ApplicationServices.Interop; - using HandBrake.ApplicationServices.Interop.EventArgs; using HandBrake.ApplicationServices.Interop.HbLib; using HandBrake.ApplicationServices.Interop.Interfaces; using HandBrake.ApplicationServices.Interop.Json.Scan; using HandBrake.ApplicationServices.Interop.Model; using HandBrake.ApplicationServices.Interop.Model.Preview; using HandBrake.ApplicationServices.Model; - using HandBrake.ApplicationServices.Utilities; + using HandBrake.ApplicationServices.Services.Logging; + using HandBrake.ApplicationServices.Services.Logging.Interfaces; + using HandBrake.ApplicationServices.Services.Logging.Model; using HandBrakeWPF.Properties; using HandBrakeWPF.Services.Encode.Model; @@ -32,7 +31,6 @@ namespace HandBrakeWPF.Services.Scan using HandBrakeWPF.Services.Scan.EventArgs; using HandBrakeWPF.Services.Scan.Interfaces; using HandBrakeWPF.Services.Scan.Model; - using HandBrakeWPF.Utilities; using Chapter = HandBrakeWPF.Services.Scan.Model.Chapter; using ScanProgressEventArgs = HandBrake.ApplicationServices.Interop.EventArgs.ScanProgressEventArgs; @@ -46,54 +44,10 @@ namespace HandBrakeWPF.Services.Scan { #region Private Variables - /// <summary> - /// Lock for the log file - /// </summary> - static readonly object LogLock = new object(); - - /// <summary> - /// Log data from HandBrakeInstance - /// </summary> - private readonly StringBuilder logging; - - /// <summary> - /// The Log File Header - /// </summary> - private readonly StringBuilder header; - - /// <summary> - /// The Current source scan path. - /// </summary> + private readonly ILog log = LogService.GetLogger(); private string currentSourceScanPath; - - /// <summary> - /// The log dir. - /// </summary> - private static string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs"; - - /// <summary> - /// The dvd info path. - /// </summary> - private string dvdInfoPath = Path.Combine(logDir, string.Format("last_scan_log{0}.txt", GeneralUtilities.ProcessId)); - - /// <summary> - /// The scan log. - /// </summary> - private StreamWriter scanLog; - - /// <summary> - /// LibHB Instance - /// </summary> private IHandBrakeInstance instance; - - /// <summary> - /// The post scan operation. - /// </summary> private Action<bool, Source> postScanOperation; - - /// <summary> - /// Global to handle cancelled scans. - /// </summary> private bool isCancelled = false; #endregion @@ -103,8 +57,6 @@ namespace HandBrakeWPF.Services.Scan /// </summary> public LibScan() { - this.logging = new StringBuilder(); - this.header = GeneralUtilities.CreateLogHeader(); this.IsScanning = false; } @@ -134,21 +86,6 @@ namespace HandBrakeWPF.Services.Scan /// </summary> public bool IsScanning { get; private set; } - /// <summary> - /// Gets ActivityLog. - /// </summary> - public string ActivityLog - { - get - { - string noLog = "There is no log information to display." + Environment.NewLine + Environment.NewLine - + "This window will only display logging information after you have scanned a source." + Environment.NewLine - + Environment.NewLine + "You can find previous log files in the log directory or by clicking the 'Open Log Directory' button above."; - - return string.IsNullOrEmpty(this.logging.ToString()) ? noLog : this.header + this.logging.ToString(); - } - } - #endregion #region Public Methods @@ -176,12 +113,6 @@ namespace HandBrakeWPF.Services.Scan { try { - lock (LogLock) - { - this.scanLog.Close(); - this.scanLog.Dispose(); - this.scanLog = null; - } this.instance.Dispose(); } catch (Exception) @@ -193,33 +124,7 @@ namespace HandBrakeWPF.Services.Scan // Handle the post scan operation. this.postScanOperation = postAction; - // Clear down the logging - this.logging.Clear(); - - try - { - // Make we don't pick up a stale last_scan_log_xyz.txt (and that we have rights to the file) - if (File.Exists(this.dvdInfoPath)) - { - File.Delete(this.dvdInfoPath); - } - } - catch (Exception exc) - { - Debug.WriteLine(exc); - } - - if (!Directory.Exists(Path.GetDirectoryName(this.dvdInfoPath))) - { - Directory.CreateDirectory(Path.GetDirectoryName(this.dvdInfoPath)); - } - - // Create a new scan log. - this.scanLog = new StreamWriter(this.dvdInfoPath); - // Create a new HandBrake Instance. - HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged; - HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged; this.instance = HandBrakeInstanceManager.GetScanInstance(configuraiton.Verbosity); this.instance.ScanProgress += this.InstanceScanProgress; this.instance.ScanCompleted += this.InstanceScanCompleted; @@ -238,16 +143,6 @@ namespace HandBrakeWPF.Services.Scan this.ServiceLogMessage("Stopping Scan."); this.IsScanning = false; this.instance.StopScan(); - - lock (LogLock) - { - if (this.scanLog != null) - { - this.scanLog.Close(); - this.scanLog.Dispose(); - this.scanLog = null; - } - } } catch (Exception exc) { @@ -339,8 +234,6 @@ namespace HandBrakeWPF.Services.Scan { try { - this.logging.Clear(); - string source = sourcePath.ToString().EndsWith("\\") ? string.Format("\"{0}\\\\\"", sourcePath.ToString().TrimEnd('\\')) : "\"" + sourcePath + "\""; this.currentSourceScanPath = source; @@ -362,8 +255,7 @@ namespace HandBrakeWPF.Services.Scan this.ServiceLogMessage("Scan Failed ..." + Environment.NewLine + exc); this.Stop(); - if (this.ScanCompleted != null) - this.ScanCompleted(this, new ScanCompletedEventArgs(false, exc, "An Error has occured in ScanService.ScanSource()", null)); + this.ScanCompleted?.Invoke(this, new ScanCompletedEventArgs(false, exc, "An Error has occured in ScanService.ScanSource()", null)); } } @@ -385,22 +277,6 @@ namespace HandBrakeWPF.Services.Scan bool cancelled = this.isCancelled; this.isCancelled = false; - // Write the log file out before we start processing incase we crash. - try - { - if (this.scanLog != null) - { - this.scanLog.Flush(); - } - } - catch (Exception exc) - { - Debug.WriteLine(exc); - } - - HandBrakeUtils.MessageLogged -= this.HandBrakeInstanceMessageLogged; - HandBrakeUtils.ErrorLogged -= this.HandBrakeInstanceErrorLogged; - // TODO -> Might be a better place to fix this. string path = this.currentSourceScanPath; if (this.currentSourceScanPath.Contains("\"")) @@ -449,8 +325,8 @@ namespace HandBrakeWPF.Services.Scan { if (this.ScanStatusChanged != null) { - HandBrakeWPF.Services.Scan.EventArgs.ScanProgressEventArgs eventArgs = - new HandBrakeWPF.Services.Scan.EventArgs.ScanProgressEventArgs + EventArgs.ScanProgressEventArgs eventArgs = + new EventArgs.ScanProgressEventArgs { CurrentTitle = e.CurrentTitle, Titles = e.Titles, @@ -462,34 +338,6 @@ namespace HandBrakeWPF.Services.Scan } /// <summary> - /// Log a message - /// </summary> - /// <param name="sender"> - /// The sender. - /// </param> - /// <param name="e"> - /// The MessageLoggedEventArgs. - /// </param> - private void HandBrakeInstanceErrorLogged(object sender, MessageLoggedEventArgs e) - { - this.LogMessage(e.Message); - } - - /// <summary> - /// Log a message - /// </summary> - /// <param name="sender"> - /// The sender. - /// </param> - /// <param name="e"> - /// The MessageLoggedEventArgs. - /// </param> - private void HandBrakeInstanceMessageLogged(object sender, MessageLoggedEventArgs e) - { - this.LogMessage(e.Message); - } - - /// <summary> /// Convert Interop Title objects to App Services Title object /// </summary> /// <param name="titles"> @@ -587,25 +435,6 @@ namespace HandBrakeWPF.Services.Scan } /// <summary> - /// The log message. - /// </summary> - /// <param name="message"> - /// The message. - /// </param> - private void LogMessage(string message) - { - lock (LogLock) - { - if (this.scanLog != null) - { - this.scanLog.WriteLine(message); - } - - this.logging.AppendLine(message); - } - } - - /// <summary> /// The service log message. /// </summary> /// <param name="message"> @@ -613,7 +442,7 @@ namespace HandBrakeWPF.Services.Scan /// </param> protected void ServiceLogMessage(string message) { - this.LogMessage(string.Format("# {0}", message)); + this.log.LogMessage(string.Format("{0} # {1}{0}", Environment.NewLine, message), LogMessageType.ScanOrEncode, LogLevel.Info); } #endregion } diff --git a/win/CS/HandBrakeWPF/ViewModels/Interfaces/ILogViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/Interfaces/ILogViewModel.cs index 6c7a7a2c8..6aa1020d4 100644 --- a/win/CS/HandBrakeWPF/ViewModels/Interfaces/ILogViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/Interfaces/ILogViewModel.cs @@ -14,9 +14,5 @@ namespace HandBrakeWPF.ViewModels.Interfaces /// </summary>
public interface ILogViewModel
{
- /// <summary>
- /// Gets or sets the selected tab.
- /// </summary>
- int SelectedTab { get; set; }
}
}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/ViewModels/LogViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/LogViewModel.cs index f9a26c1ed..572d8a440 100644 --- a/win/CS/HandBrakeWPF/ViewModels/LogViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/LogViewModel.cs @@ -11,15 +11,18 @@ namespace HandBrakeWPF.ViewModels {
using System;
using System.Diagnostics;
+ using System.Text;
using System.Windows;
- using HandBrakeWPF.Services.Scan.EventArgs;
- using HandBrakeWPF.Services.Scan.Interfaces;
+ using Caliburn.Micro;
+
+ using HandBrake.ApplicationServices.Services.Logging;
+ using HandBrake.ApplicationServices.Services.Logging.EventArgs;
+ using HandBrake.ApplicationServices.Services.Logging.Model;
+
using HandBrakeWPF.ViewModels.Interfaces;
- using EncodeCompletedEventArgs = HandBrakeWPF.Services.Encode.EventArgs.EncodeCompletedEventArgs;
- using EncodeProgressEventArgs = HandBrakeWPF.Services.Encode.EventArgs.EncodeProgressEventArgs;
- using IEncode = HandBrakeWPF.Services.Encode.Interfaces.IEncode;
+ using ILog = HandBrake.ApplicationServices.Services.Logging.Interfaces.ILog;
/// <summary>
/// The Log View Model
@@ -28,83 +31,37 @@ namespace HandBrakeWPF.ViewModels {
#region Private Fields
- /// <summary>
- /// Backing field for the encodeService service
- /// </summary>
- private readonly IEncode encodeService;
-
- /// <summary>
- /// Backing field for the Scan Service
- /// </summary>
- private readonly IScan scanService;
-
- /// <summary>
- /// The selected tab.
- /// </summary>
- private int selectedTab;
-
- /// <summary>
- /// The encode log index.
- /// </summary>
- private int encodeLogIndex;
+ private readonly ILog logService;
+ private StringBuilder log = new StringBuilder();
+ private long lastReadIndex;
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="LogViewModel"/> class.
/// </summary>
- /// <param name="encodeService">
- /// The encode service.
- /// </param>
- /// <param name="scanService">
- /// The scan service.
- /// </param>
- public LogViewModel(IEncode encodeService, IScan scanService)
+ public LogViewModel()
{
- this.encodeService = encodeService;
- this.scanService = scanService;
+ this.logService = LogService.GetLogger();
this.Title = "Log Viewer";
- this.encodeLogIndex = 0;
- }
-
- /// <summary>
- /// Gets or sets the selected tab.
- /// </summary>
- public int SelectedTab
- {
- get
- {
- return this.selectedTab;
- }
- set
- {
- this.selectedTab = value;
- this.NotifyOfPropertyChange(() => this.SelectedTab);
- }
}
/// <summary>
/// Gets Log.
/// </summary>
- public string ScanLog
+ public string ActivityLog
{
get
{
- return this.scanService.ActivityLog;
+ return this.log.ToString();
}
}
/// <summary>
- /// Gets the encodelog.
+ /// The log message received.
/// </summary>
- public string EncodeLog
- {
- get
- {
- return this.encodeService.ActivityLog;
- }
- }
-
+ public event EventHandler<LogEventArgs> LogMessageReceived;
+
/// <summary>
/// Open the Log file directory
/// </summary>
@@ -121,7 +78,7 @@ namespace HandBrakeWPF.ViewModels /// </summary>
public void CopyLog()
{
- Clipboard.SetDataObject(this.SelectedTab == 1 ? this.ScanLog : this.EncodeLog, true);
+ Clipboard.SetDataObject(this.ActivityLog, true);
}
/// <summary>
@@ -129,49 +86,26 @@ namespace HandBrakeWPF.ViewModels /// </summary>
protected override void OnActivate()
{
- this.scanService.ScanCompleted += ScanServiceScanCompleted;
- this.encodeService.EncodeCompleted += EncodeServiceEncodeCompleted;
- this.encodeService.EncodeStatusChanged += this.EncodeServiceEncodeStatusChanged;
- this.scanService.ScanStatusChanged += this.ScanServiceScanStatusChanged;
- this.scanService.ScanStarted += this.scanService_ScanStared;
- this.encodeService.EncodeStarted += this.encodeService_EncodeStarted;
- base.OnActivate();
-
- this.NotifyOfPropertyChange(() => this.ScanLog);
- this.NotifyOfPropertyChange(() => this.EncodeLog);
- }
-
- /// <summary>
- /// Scan Status has changed, update log window.
- /// </summary>
- /// <param name="sender">
- /// The sender.
- /// </param>
- /// <param name="e">
- /// The e.
- /// </param>
- private void ScanServiceScanStatusChanged(object sender, ScanProgressEventArgs e)
- {
- this.NotifyOfPropertyChange(() => this.ScanLog);
- }
+ this.logService.MessageLogged += this.LogService_MessageLogged;
+ this.logService.LogReset += LogService_LogReset;
- /// <summary>
- /// Encode Status has changed, update log window
- /// </summary>
- /// <param name="sender">
- /// The sender.
- /// </param>
- /// <param name="e">
- /// The e.
- /// </param>
- private void EncodeServiceEncodeStatusChanged(object sender, EncodeProgressEventArgs e)
- {
- if (encodeLogIndex != this.encodeService.LogIndex || this.encodeService.LogIndex == -1)
+ // Refresh the Log Display
+ this.log.Clear();
+ foreach (LogMessage logMessage in this.logService.LogMessages)
{
- this.NotifyOfPropertyChange(() => this.EncodeLog);
+ this.log.AppendLine(logMessage.Content);
+ this.lastReadIndex = logMessage.MessageIndex;
+
+ if (this.lastReadIndex > logMessage.MessageIndex)
+ {
+ throw new Exception("Log Message Index Error");
+ }
}
- encodeLogIndex = this.encodeService.LogIndex;
+ this.OnLogMessageReceived(null);
+ this.NotifyOfPropertyChange("ActivityLog");
+
+ base.OnActivate();
}
/// <summary>
@@ -182,18 +116,14 @@ namespace HandBrakeWPF.ViewModels /// </param>
protected override void OnDeactivate(bool close)
{
- this.scanService.ScanCompleted -= ScanServiceScanCompleted;
- this.encodeService.EncodeCompleted -= EncodeServiceEncodeCompleted;
- this.encodeService.EncodeStatusChanged -= this.EncodeServiceEncodeStatusChanged;
- this.scanService.ScanStatusChanged -= this.ScanServiceScanStatusChanged;
- this.scanService.ScanStarted -= this.scanService_ScanStared;
- this.encodeService.EncodeStarted -= this.encodeService_EncodeStarted;
+ this.logService.MessageLogged -= this.LogService_MessageLogged;
+ this.logService.LogReset -= this.LogService_LogReset;
base.OnDeactivate(close);
}
/// <summary>
- /// Scan Completed Event Handler.
+ /// The log service_ log reset.
/// </summary>
/// <param name="sender">
/// The sender.
@@ -201,27 +131,28 @@ namespace HandBrakeWPF.ViewModels /// <param name="e">
/// The e.
/// </param>
- private void ScanServiceScanCompleted(object sender, ScanCompletedEventArgs e)
+ private void LogService_LogReset(object sender, EventArgs e)
{
- this.NotifyOfPropertyChange(() => this.ScanLog);
- }
+ this.log.Clear();
+ this.lastReadIndex = 0;
- /// <summary>
- /// Encode Completed Event Handler.
- /// </summary>
- /// <param name="sender">
- /// The sender.
- /// </param>
- /// <param name="e">
- /// The e.
- /// </param>
- private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e)
- {
- this.NotifyOfPropertyChange(() => this.EncodeLog);
+ foreach (LogMessage logMessage in this.logService.LogMessages)
+ {
+ this.log.AppendLine(logMessage.Content);
+ this.lastReadIndex = logMessage.MessageIndex;
+
+ if (this.lastReadIndex > logMessage.MessageIndex)
+ {
+ throw new Exception("Log Message Index Error");
+ }
+ }
+
+ this.NotifyOfPropertyChange("ActivityLog");
+ this.OnLogMessageReceived(null);
}
/// <summary>
- /// The encode service encode started.
+ /// The log service_ message logged.
/// </summary>
/// <param name="sender">
/// The sender.
@@ -229,24 +160,34 @@ namespace HandBrakeWPF.ViewModels /// <param name="e">
/// The e.
/// </param>
- private void encodeService_EncodeStarted(object sender, EventArgs e)
+ private void LogService_MessageLogged(object sender, LogEventArgs e)
{
- this.encodeLogIndex = -1; // Reset the log index.
- this.SelectedTab = 0;
+ if (this.lastReadIndex < e.Log.MessageIndex)
+ {
+ Execute.OnUIThreadAsync(
+ () =>
+ {
+ this.lastReadIndex = e.Log.MessageIndex;
+ this.log.AppendLine(e.Log.Content);
+ this.OnLogMessageReceived(e);
+ this.NotifyOfPropertyChange("ActivityLog");
+ });
+ }
}
/// <summary>
- /// The scan service scan stared.
+ /// Trigger a faster / smoother way of updating the log window.
/// </summary>
- /// <param name="sender">
- /// The sender.
- /// </param>
/// <param name="e">
/// The e.
/// </param>
- private void scanService_ScanStared(object sender, EventArgs e)
+ protected virtual void OnLogMessageReceived(LogEventArgs e)
{
- this.SelectedTab = 1;
+ var onLogMessageReceived = this.LogMessageReceived;
+ if (onLogMessageReceived != null)
+ {
+ onLogMessageReceived.Invoke(this, e);
+ }
}
}
}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs index 0886768e7..3f9bc7201 100644 --- a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs @@ -23,6 +23,8 @@ namespace HandBrakeWPF.ViewModels using Caliburn.Micro;
using HandBrake.ApplicationServices.Interop;
+ using HandBrake.ApplicationServices.Interop.HbLib;
+ using HandBrake.ApplicationServices.Services.Logging;
using HandBrake.ApplicationServices.Utilities;
using HandBrakeWPF.Commands;
@@ -56,6 +58,8 @@ namespace HandBrakeWPF.ViewModels using Action = System.Action;
using Execute = Caliburn.Micro.Execute;
+ using ILog = HandBrake.ApplicationServices.Services.Logging.Interfaces.ILog;
+ using LogManager = HandBrakeWPF.Helpers.LogManager;
/// <summary>
/// HandBrakes Main Window
@@ -226,6 +230,7 @@ namespace HandBrakeWPF.ViewModels // Setup Commands
this.QueueCommand = new QueueCommands(this.QueueViewModel);
+ LogManager.Init();
HandBrakeInstanceManager.Init();
}
@@ -1277,14 +1282,11 @@ namespace HandBrakeWPF.ViewModels if (window != null)
{
- ILogViewModel logvm = (ILogViewModel)window.DataContext;
- logvm.SelectedTab = this.IsEncoding ? 0 : 1;
window.Activate();
}
else
{
ILogViewModel logvm = IoC.Get<ILogViewModel>();
- logvm.SelectedTab = this.IsEncoding ? 0 : 1;
this.windowManager.ShowWindow(logvm);
}
}
diff --git a/win/CS/HandBrakeWPF/Views/LogView.xaml b/win/CS/HandBrakeWPF/Views/LogView.xaml index 64ca9da2d..878fd430a 100644 --- a/win/CS/HandBrakeWPF/Views/LogView.xaml +++ b/win/CS/HandBrakeWPF/Views/LogView.xaml @@ -38,51 +38,8 @@ </ToolBar>
+ <TextBox Grid.Row="2" ScrollViewer.VerticalScrollBarVisibility="Visible" TextWrapping="Wrap" x:Name="logText" />
- <TabControl Grid.Row="2" SelectedIndex="{Binding SelectedTab}" Margin="0,3,0,0">
- <TabItem>
- <TabItem.Header>
- <TextBlock Text="{x:Static Properties:ResourcesUI.LogView_EncodeLog}" Padding="4">
- <TextBlock.Style>
- <Style TargetType="TextBlock">
- <Style.Triggers>
- <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="True">
- <Setter Property="FontWeight" Value="Bold"/>
- </DataTrigger>
- </Style.Triggers>
- </Style>
- </TextBlock.Style>
- </TextBlock>
- </TabItem.Header>
-
- <TextBox
- AcceptsReturn="True"
- IsReadOnly="True"
- ScrollViewer.VerticalScrollBarVisibility="Visible"
- Text="{Binding EncodeLog, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
- TextWrapping="Wrap" />
- </TabItem>
-
- <TabItem>
- <TabItem.Header>
- <TextBlock Text="{x:Static Properties:ResourcesUI.LogView_ScanLog}" Padding="4">
- <TextBlock.Style>
- <Style TargetType="TextBlock">
- <Style.Triggers>
- <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="True">
- <Setter Property="FontWeight" Value="Bold"/>
- </DataTrigger>
- </Style.Triggers>
- </Style>
- </TextBlock.Style>
- </TextBlock>
- </TabItem.Header>
- <TextBox AcceptsReturn="True" IsReadOnly="True" ScrollViewer.VerticalScrollBarVisibility="Visible"
- Text="{Binding ScanLog, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
- TextWrapping="Wrap" />
- </TabItem>
-
- </TabControl>
</Grid>
</Grid>
diff --git a/win/CS/HandBrakeWPF/Views/LogView.xaml.cs b/win/CS/HandBrakeWPF/Views/LogView.xaml.cs index d0bdaf0ee..af07ae509 100644 --- a/win/CS/HandBrakeWPF/Views/LogView.xaml.cs +++ b/win/CS/HandBrakeWPF/Views/LogView.xaml.cs @@ -9,9 +9,13 @@ namespace HandBrakeWPF.Views
{
+ using System;
+ using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
+ using HandBrakeWPF.ViewModels;
+
/// <summary>
/// Interaction logic for LogView.xaml
/// </summary>
@@ -22,7 +26,59 @@ namespace HandBrakeWPF.Views /// </summary>
public LogView()
{
- InitializeComponent();
+ this.InitializeComponent();
+ this.DataContextChanged += this.LogView_DataContextChanged;
+ }
+
+ /// <summary>
+ /// The log view_ data context changed.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The e.
+ /// </param>
+ private void LogView_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ LogViewModel vm = e.NewValue as LogViewModel;
+ if (vm != null)
+ {
+ this.logText.AppendText(vm.ActivityLog);
+ vm.LogMessageReceived += this.Vm_LogMessageReceived;
+ }
+ }
+
+ /// <summary>
+ /// The vm_ log message received.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The e.
+ /// </param>
+ private void Vm_LogMessageReceived(object sender, HandBrake.ApplicationServices.Services.Logging.EventArgs.LogEventArgs e)
+ {
+ if (e == null)
+ {
+ LogViewModel vm = this.DataContext as LogViewModel;
+ if (vm != null)
+ {
+ this.logText.Clear();
+ this.logText.AppendText(vm.ActivityLog);
+ }
+ else
+ {
+ Debug.WriteLine("Failed to Reset Log correctly.");
+ }
+ }
+ else
+ {
+ // This works better than Data Binding because of the scroll.
+ this.logText.AppendText(Environment.NewLine + e.Log.Content);
+ this.logText.ScrollToEnd();
+ }
}
/// <summary>
|