diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/PluginInterface.cs b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/PluginInterface.cs new file mode 100644 index 0000000..097cced --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/PluginInterface.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; +using System.Linq; +using System.Windows; +using Unosquare.FFmpegMediaElement; + +namespace QuickLook.Plugin.VideoViewer +{ + public class PluginInterface : IViewer + { + private ViewerPanel _vp; + + public int Priority => int.MaxValue; + + public bool CanHandle(string path) + { + if (Directory.Exists(path)) + return false; + + var formats = new[] + { + ".3g2", ".3gp", ".3gp2", ".3gpp", ".amv", ".asf", ".asf", ".avi", ".flv", ".m2ts", ".m4v", ".mkv", + ".mov", ".mp4", ".mp4v", ".mpeg", ".mpg", ".ogv", ".qt", ".vob", ".webm", ".wmv" + }; + + if (formats.Contains(Path.GetExtension(path).ToLower())) + return true; + + return false; + } + + public void Prepare(string path, ContextObject context) + { + using (var element = new MediaElement {Source = new Uri(path)}) + { + context.SetPreferredSizeFit(new Size(element.NaturalVideoWidth, element.NaturalVideoHeight), 0.6); + } + } + + public void View(string path, ContextObject context) + { + _vp = new ViewerPanel(); + + context.ViewerContent = _vp; + + _vp.LoadAndPlay(path); + + context.Title = $"{Path.GetFileName(path)} ({TimeSpan.FromSeconds(_vp.mediaElement.NaturalDuration).ToString(@"hh\:mm\:ss")}, {_vp.mediaElement.NaturalVideoWidth} × {_vp.mediaElement.NaturalVideoHeight} )"; + context.IsBusy = false; + } + + public void Dispose() + { + _vp?.Dispose(); + } + } +} diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/AssemblyInfo.cs b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c9740cb --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("QuickLook.Plugin.VideoViewer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("QuickLook.Plugin.VideoViewer")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly:ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Resources.Designer.cs b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Resources.Designer.cs new file mode 100644 index 0000000..a726e9e --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Resources.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace QuickLook.Plugin.VideoViewer.Properties { + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if ((resourceMan == null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("QuickLook.Plugin.VideoViewer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Resources.resx b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Settings.Designer.cs b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Settings.Designer.cs new file mode 100644 index 0000000..56d8efc --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace QuickLook.Plugin.VideoViewer.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Settings.settings b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/QuickLook.Plugin.VideoViewer.csproj b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/QuickLook.Plugin.VideoViewer.csproj new file mode 100644 index 0000000..393fd2d --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/QuickLook.Plugin.VideoViewer.csproj @@ -0,0 +1,98 @@ + + + + + Debug + AnyCPU + {1B746D92-49A5-4A37-9D75-DCC490393290} + library + QuickLook.Plugin.VideoViewer + QuickLook.Plugin.VideoViewer + v4.5.2 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + true + full + false + ..\..\Build\Debug\Plugins\QuickLook.Plugin.VideoViewer\ + DEBUG;TRACE + prompt + 4 + x86 + false + + + pdbonly + true + ..\..\Build\Release\Plugins\QuickLook.Plugin.VideoViewer\ + TRACE + prompt + 4 + x86 + false + + + + + + + + + + + + 4.0 + + + References\Unosquare.FFmpegMediaElement.dll + + + + + + + + MSBuild:Compile + Designer + + + + ViewerPanel.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + {8b4a9ce5-67b5-4a94-81cb-3771f688fdeb} + QuickLook + False + + + + \ No newline at end of file diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/References/Unosquare.FFmpegMediaElement.dll b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/References/Unosquare.FFmpegMediaElement.dll new file mode 100644 index 0000000..e1c1e78 Binary files /dev/null and b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/References/Unosquare.FFmpegMediaElement.dll differ diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/References/Unosquare.FFmpegMediaElement.xml b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/References/Unosquare.FFmpegMediaElement.xml new file mode 100644 index 0000000..a4ff5d1 --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/References/Unosquare.FFmpegMediaElement.xml @@ -0,0 +1,2552 @@ + + + + Unosquare.FFmpegMediaElement + + + + + Defines various constants used across all classes + + + + + Represents a multimedia source with its corresponding control methods. + + + + + Provides audio data samples in PCM, 16-bit format. + This class is used to keep track of the samples and matching frames times + It also ensures samples are not repeated and are unique in a discrete timeline + + + + + Initializes a new instance of the class. + + The media. + + + + Clears the buffer and frame times + + + + + Provides the next small buffer that the audio device requests. + the buffer to fill is a non-null reference to the buffer that needs to be filled + The return value represents how many bytes were written to buffer. + + + + + Gets a value indicating whether the wall clock is in the first time segment. + + + true if this instance is in first time segment; otherwise, false. + + + + + Gets a value indicating whether the wall clock is in the last time segment. + + + true if this instance is in last time segment; otherwise, false. + + + + + Gets a value indicating whether frame bound should be checked. + Typically, if the realtime clock is in the first time segment, we don't check for bounds + + + true if [check frame bounds]; otherwise, false. + + + + + Waits for the frame extractor to be ready for playback. + Returns true if successful, false if it timed out. + + + + + Gets the estimated duration in number of seconds. + This is not necessarily the real, precise duration in all media streams but it tends to be extremely close. + + + The duration. + + + + + Gets the start time of the leading media stream. + + + The start time. + + + + + Gets the end time of the leading media stream. + + + The end time. + + + + + Determines if the input is a live stream. + + + + + Gets the current position in number of seconds. + Use the Seek method to move to a different position within the input. + + + The position. + + + + + Queries if a leading frame for the given position is immediately available. + + The position. + + + + + Gets or sets the volume of the current session. + Valid ranges are anything from 0 to 1 + + + The volume. + + + + + Gets or sets the video playback speed ratio. + By default the speed ratio is 1.0M + Note: Audio will not be rendered when the speed ratio is not exactly 1.0M + + + The speed ratio. + + + + + Gets a value indicating whether we have reached the end of stream. + This does not necessarily means the media has reached an end. It simply means that all + data within the media has been read (not necessarily that it all has been rendered). + + + true if this we are at end of stream; otherwise, false. + + + + + Gets a value indicating whether the real-time clock is on the last media frame. + + + true if this instance has media ended; otherwise, false. + + + + + Gets a value indicating whether the media is playing. + + + true if the media is playing; otherwise, false. + + + + + Sets the Volume to 0 + + + + + Starts or resumes media playback + + + + + Pauses media playback + + + + + Rewinds and pauses media playback + + + + + Seeks to the specified target second. + + The target second. + + + + Multicast event for property change notifications. + + + + + Checks if a property already matches a desired value. Sets the property and + notifies listeners only when necessary. + + Type of the property. + Reference to a property with both getter and setter. + Desired value for the property. + Name of the property used to notify listeners. This + value is optional and can be provided automatically when invoked from compilers that + support CallerMemberName. + True if the value was changed, false if the existing value matched the + desired value. + + + + Notifies listeners that a property value has changed. + + Name of the property used to notify listeners. This + value is optional and can be provided automatically when invoked from compilers + that support . + + + + Initializes a new instance of the class. + + The file path. + The error callback. + + + + Initializes a new instance of the class. + + The file path. + The error callback. + The referer. Leave null or emtpy to skip setting it. + The user agent. Leave null or empty in order to skip setting a User Agent + errorCallback cannot be null + or + filePath cannot be null or empty + + errorCallback cannot be null + or + filePath cannot be null or empty + + + + + Internals the seek input. + + The render time. + + + + Extracts the media frames continuously. + + + + + Renders the video image. This method is called on a Dispatcher timer. + It is responsible for rendering the decoded video image continuously. + It also avoids rendering the same image again. + + The sender. + The instance containing the event data. + + + + Renders the audio buffer. This is the implementation of IAudioDataProvider.RenderAudioBufferMethod + It basically gets the decoded PCM bytes from the audio buffer provider. This method is called by the audio device itself. + + The buffer to fill. + The bytes written. + + + + + Initializes the internal transcoder -- This create the input, processing, and output blocks that make + up the video and audio decoding stream. + + The file path. + Name of the input format. Leave null or empty to detect automatically + The referer. Leave null or empty to skip setting it + The user agent. Leave null or empty to skip setting it. + + Could not find stream info + or + Media must contain at least a video or and audio stream + Could not open file + or + Could not find stream info + or + Media must contain a video stream + or + Media must contain an audio stream + or + Unsupported codec + or + Could not initialize the output conversion context + or + Could not create output codec context from input + or + Could not open codec + + + + Initializes the audio. + + + Unsupported audio codec + or + Could not create audio output codec context from input + or + Could not open codec + + Could not load media file + + + + Pulls the next-available frame. This does not queue the frame in either the video or audio queue. + Please keep in mind that you will need to manually call the Release() method the returned object + are done with it. If working with Media Caches, the cache will automatically release the frame + + + Error while decoding frame + + + + Releases all managed and unmanaged resources + + + + + Represents a control that contains audio and/or video. + In contrast with System.Windows.Controls.MediaElement, this version uses + the FFmpeg library to perform reading and decoding of media streams. + + + + + Defines constants for Property Names that are used to + either register dependency properties or notify property changes. + + + + + + Called when [source property changed]. + + The dependency object. + The instance containing the event data. + + + + Gets/Sets the Source on this MediaElement. + The Source property is the Uri of the media to be played. + Note: Currently, this does not support the pack protocol (pack://) + + + + + DependencyProperty for Stretch property. + + + + + Called when [stretch property changed]. + + The dependency object. + The instance containing the event data. + + + + Gets/Sets the Stretch on this MediaElement. + The Stretch property determines how large the MediaElement will be drawn. + + + + + DependencyProperty for StretchDirection property. + + + + + Called when [stretch direction property changed]. + + The dependency object. + The instance containing the event data. + + + + Gets/Sets the stretch direction of the Viewbox, which determines the restrictions on + scaling that are applied to the content inside the Viewbox.  For instance, this property + can be used to prevent the content from being smaller than its native size or larger than + its native size. + + + + +     The DependencyProperty for the MediaElement.Volume property. + + + + + Gets/Sets the Volume property on the MediaElement. + Note: Valid values are from 0 to 1 + + + + +     The DependencyProperty for the MediaElement.Balance property. + + + + + Gets/Sets the Balance property on the MediaElement. + Note: Balance changes are not yet supported. Value will always be 0; + + + + + The DependencyProperty for the MediaElement.ScrubbingEnabled property. + + + + + Gets/Sets the ScrubbingEnabled property on the MediaElement. + Note: Frame scrubbing is always enabled. The real effect of this property is + that when it is set to true, setting values on the Position property occurs synchronously. + Wehn it is set to false, setting values on the Position property occurs asyncrhonously + + + + + The DependencyProperty for the MediaElement.UnloadedBehavior property. + + + + + Specifies how the underlying media should behave when the given + MediaElement is unloaded, the default behavior is to Close the + media. + + + + + The DependencyProperty for the MediaElement.LoadedBehavior property. + + + + + Specifies the behavior that the media element should have when it + is loaded. The default behavior is that it is under manual control + (i.e. the caller should call methods such as Play in order to play + the media). If a source is set, then the default behavior changes to + to be playing the media. If a source is set and a loaded behavior is + also set, then the loaded behavior takes control. + + + + + The DependencyProperty for the MediaElement.IsMuted property. + + + + + Gets/Sets the IsMuted property on the MediaElement. + Note: Muting Sets the Volume to 0; Unmuting set the volume to what + it originally was before muting. + + + + +     The DependencyProperty for the MediaElement.Position property. + + + + + Callback when the seek position timer ticks. + + The sender. + The instance containing the event data. + + + + Gets/Sets the Position property on the MediaElement. + + + + +     The DependencyProperty for the MediaElement.SpeedRatio property. + + + + + Gets/Sets the SpeedRatio property on the MediaElement. + + + + + Dependency property for the user agent property + + + + + Gets or sets the user agent. Property takes effect only upon loading + live streams such as m3u8 files. + + + The user agent. + + + + + Dependency property for the Referer property + + + + + Gets or sets the referer. Property takes effect only upon loading + live streams such as m3u8 files. + + + The user agent. + + + + + Returns whether the given media has audio. + Only valid after the MediaOpened event has fired. + + + + + Returns whether the given media has video. Only valid after the + MediaOpened event has fired. + + + + + Gets the video codec. + Only valid after the MediaOpened event has fired. + + + + + Gets the video bitrate. + Only valid after the MediaOpened event has fired. + + + + + Returns the natural width of the media in the video. + Only valid after the MediaOpened event has fired. + + + + + Returns the natural height of the media in the video. + Only valid after the MediaOpened event has fired. + + + + + Gets the video frame rate. + Only valid after the MediaOpened event has fired. + + + + + Gets the length of the video frame. + Only valid after the MediaOpened event has fired. + + + + + Gets the audio codec. + Only valid after the MediaOpened event has fired. + + + + + Gets the audio bitrate. + Only valid after the MediaOpened event has fired. + + + + + Gets the audio channels count. + Only valid after the MediaOpened event has fired. + + + + + Gets the audio output bits per sample. + Only valid after the MediaOpened event has fired. + This value will always have to be 16 + + + + + Gets the audio sample rate. + Only valid after the MediaOpened event has fired. + + + + + Gets the audio output sample rate. + Only valid after the MediaOpened event has fired. + + + + + Gets the audio bytes per sample. + Only valid after the MediaOpened event has fired. + + + + + Gets the Media's natural duration + Only valid after the MediaOpened event has fired. + + + + + Returns whether the given media can be paused. + This is only valid after the MediaOpened event has fired. + Note: This property is computed based on wether the stream is detected to be a live stream. + + + + + Gets a value indicating whether the media is playing. + + + + + Gets a value indicating whether the media has reached its end. + + + true if this instance has media ended; otherwise, false. + + + + + Handles the PropertyChanged event of the underlying media. + + The source of the event. + The instance containing the event data. + + + + Called when a media error occurs. + + The sender. + The ex. + + + + Opens the media. + + The source URI. + The referer. Optional -- Leave null or empty if you do not wish to set it. + The user agent. Optional -- Leave null or empty if you do not wish to set it. + + + + Closes the media. + + if set to true [update properties]. + + + + Updates the media properties. + + + + + Defines constants that contain Routed event names + + + + + MediaFailedEvent is a routed event. + + + + + Raised when the media fails to load or a fatal error has occurred which prevents playback. + + + + + MediaErrorEvent is a routed event. + + + + + Raised when a problem with the media is found + + + + + MediaOpened is a routed event. + + + + + Raised when the media is opened + + + + + MediaEnded is a routed event + + + + + Raised when the corresponding media ends. + + + + + Gets or sets the horizontal alignment characteristics applied to this element when it is composed within a parent element, such as a panel or items control. + + + + + Gets the current frame being displayed + + Clone of the current frame + + + + Provides access to the paths where FFmpeg binaries are extracted to + + + + + Initializes the class. + + + + + Gets the path to where the FFmpeg binaries are stored + + + + + Gets the full path to ffmpeg.exe + + + + + Gets the full path to ffprobe.exe + + + + + Gets the full path to ffplay.exe + + + + + Initializes the class. + + + + + Initializes a new instance of the class. + + + + + Initializes the seek position timer. + + + + + Multicast event for property change notifications. + + + + + Checks if a property already matches a desired value. Sets the property and + notifies listeners only when necessary. + + Type of the property. + Reference to a property with both getter and setter. + Desired value for the property. + Name of the property used to notify listeners. This + value is optional and can be provided automatically when invoked from compilers that + support CallerMemberName. + True if the value was changed, false if the existing value matched the + desired value. + + + + Notifies listeners that a property value has changed. + + Name of the property used to notify listeners. This + value is optional and can be provided automatically when invoked from compilers + that support . + + + + Gets or sets the base URI of the current application context. + + + + + Dumps the state into a string dictionary. + Optionally, it prints the output to the debugging console + + + + + Begins playback if not already playing + + + + + Pauses media playback. + + + + + Stops media playback. + + + + + Closes the media source and releases its resources + + + + + Provides methods and constants for miscellaneous operations + + + + + Miscellaneous native methods + + + + + Extracts the FFmpeg Dlls. + + The resource prefix. + + + + + Registers FFmpeg library and initializes its components. + + + + + + Determines if we are currently in Design Time + + + true if this instance is in design time; otherwise, false. + + + + + Converts a Timestamp to seconds. + + The ts. + The stream time base. + + + + + Converts seconds to a timestamp value. + + The seconds. + The stream time base. + + + + + Gets the FFmpeg error mesage based on the error code + + The code. + + + + + Represents a set of ordered media frames of a given type + + + + + Gets the capacity in number frames. + + + + + Gets the current amount of frames. + + + + + Gets the index of the middle frame. + + + + + Gets the PTS in seconds of the first frame + + + + + Gets the PTS in seconds of the last frame + + + + + Gets the PTS in seconds of the middle frame + + + + + Gets the best effort resentation time (PTS) of the first frame. + + + + + Gets the end time. Last Frame Time + Last Frame Duration + + + + + Gets the total duration from the first frame start time to + the last frame start time + its duration. + + + + + Gets a value indicating whether this cache is full. + + + + + Gets a value indicating whether this cache is empty. + + + + + Gets the type of frames this cache is holding. + + + + + Gets the frame right at the middle of the collection + + + + + Gets the first frame. + + + + + Gets the last frame. + + + + + Initializes a new instance of the class. + This copies all properties from an existing cache excluding frames of course. + + The other cache. + + + + Initializes a new instance of the class. + + The frame rate. + The type. + + + + Recomputes the properties. + + + + + Throws the invalid frame type exception. + + Type of the frame. + + + + + Replaces the internally-held frames with the specified new frames. + + The new frames. + Buffer does not support the capacity of new elements + + + + Adds the specified frame at the right location. + This method ensures the collection stays ordered + + The frame. + Buffer is already at capacity. + + + + Removes the first frame and releases it. + + + + + Removes the last frame and releases it. + + + + + Clears all the frames and releases them. + + + + + Highly optimized frame search function combining guess, binary and finally, linear search + + The render time. + + + + + Gets the frame at the given index. + + The index. + + + + + Gets a frame at the given render time. + + The render time. + + + + + Gets a maximum of frameCount frames at the given starting renderTime + + The render time. + The frame count. + + + + + Gets a maximum duration of frames at the given starting renderTime + + The render time. + The duration. + + + + + Gets the index of the frame. Returns -1 for not found. + + The frame. + + + + + Gets the index of the frame. + Returns -1 if not found. + + The render time. + + + + + Enumerates the different media frame types + + + + + Represents a video or audio frame. + + + + + Gets or sets the flags. + + + + + For video frames, gets or sets the type of the picture. + + + + + Gets the frame's best effort PTS in seconds + + + + + For video frames, gets the pointer to the decoded picture buffer + + + + + For video frames, gets the length of the decoded picture buffer + + + + + For video frames, gets the coded picture number. + + + + + Gets the duration in seconds of the frame. + + + + + Gets the frame's best effort PTS + + + + + Gets the type of frame + + + + + Gets the stream index this frame belongs to + + + + + For audio frames, holds the bytes array with the decoded waveform + + + + + For video frames, A pointer to the decodes picture + + + + + For video frames, A Pointer to the decoded picture buffer + + + + + Synchronized lock for frame disposal + + + + + Initializes a new instance of the class. + All properties need to be set immediately after instantiation + + + + + Enumerates the flags of a decoded frame + + + + + Enumerates the picture types for video frames + + + + + Represents an event that occurs when the underlying media stream fails to load or + corrupt packets are found within the stream. + + + + + Gets the error exception. + + + + + Enumerates Media Playback error codes + + + + + Represents an error that occurs during media playback or during a seek operation. + + + + + A high precision timer designed to keep track of + media playback. Control methods mimic media playback + control methods such as Play Pause, Stop and Seek + + + + + Initializes a new instance of the class. + + + + + Gets a value indicating whether the timer is running. If the timer is stopped or paused, + then this property will return false. + + + + + Stops the timer and makes the elapsed time effectively 0 + + + + + Starts or resumes the timer + + + + + Pauses the timer + + + + + Sets the Position to the specified value. + If the timer is running, it will be paused after this method call. + + The ts. + + + + Sets the Position to the specified value. + If the timer is running, it will be paused after this method call. + + The seconds. + + + + Sets the Position to the specified value. + If the timer is running, it will be paused after this method call. + + The ticks. + + + + Gets or sets the speed ratio at which the timer runs. + + + + + Gets or Sets the position in ticks. + + + + + Gets or Sets the position in the elapsed seconds + + + + + Gets or Sets the TimeSpan representing the total elapsed milliseconds. + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized resource of type System.Drawing.Bitmap. + + + + + An interface that defines a callback method providing audio data + + + + + When called in its implementation, this method fills the buffer with audio data and sets the amount of bytes written + + The buffer to fill. + The bytes written. + True if the audio device should request more samples. False if the audio device needs to be shutdown + + + + Represents a calss that renders audio data to speakers + via callbacks + + + + + A thread-safe callback provider + + + + + Initializes a new instance of the class. + + + + + Initializes the specified provider. + + The provider. + The sample rate. + The channels. + The bits per sample. + + Wave device already started + + + + Stops the underlying audio device + + Wave device not started + + + + Plays the underlying audio device + + Wave device not started + + + + Pauses the underlying audio device + + Wave device not started + + + + Gets a value indicating whether this instance has initialized. + + + true if this instance has initialized; otherwise, false. + + + + + Gets or sets the volume (amplitude) of the data samples. + Valid range is from 0.0 to 1.0 + + + + + Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + + + + + Microsoft ADPCM + See http://icculus.org/SDL_sound/downloads/external_documentation/wavecomp.htm + + + + + Empty constructor needed for marshalling from a pointer + + + + + Samples per block + + + + + Number of coefficients + + + + + Coefficients + + + + + Microsoft ADPCM + + Sample Rate + Channels + + + + Serializes this wave format + + Binary writer + + + + String Description of this WaveFormat + + + + + NativeDirectSoundOut using DirectSound COM interop. + Contact author: Alexandre Mutel - alexandre_mutel at yahoo.fr + Modified by: Graham "Gee" Plumb + + + + + Playback Stopped + + + + + Gets the DirectSound output devices in the system + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + (40ms seems to work under Vista). + + The latency. + Selected device + + + + Releases unmanaged resources and performs other cleanup operations before the + is reclaimed by garbage collection. + + + + + Begin playback + + + + + Stop playback + + + + + Pause Playback + + + + + Gets the current position in bytes from the wave output device. + (n.b. this is not the same thing as the position within your reader + stream) + + Position in bytes + + + + Gets the current position from the wave output device. + + + + + Initialise playback + + The waveprovider to be played + + + + Current playback state + + + + + + The volume 1.0 is full scale + + + + + + Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + + + + + Determines whether the SecondaryBuffer is lost. + + + true if [is buffer lost]; otherwise, false. + + + + + Convert ms to bytes size according to WaveFormat + + The ms + number of byttes + + + + Processes the samples in a separate thread. + + + + + Stop playback + + + + + Feeds the SecondaryBuffer with the WaveStream + + number of bytes to feed + + + + IDirectSound interface + + + + + IDirectSoundBuffer interface + + + + + IDirectSoundNotify interface + + + + + Instanciate DirectSound from the DLL + + The GUID. + The direct sound. + The p unk outer. + + + + DirectSound default playback device GUID + + + + + DirectSound default capture device GUID + + + + + DirectSound default device for voice playback + + + + + DirectSound default device for voice capture + + + + + The DSEnumCallback function is an application-defined callback function that enumerates the DirectSound drivers. + The system calls this function in response to the application's call to the DirectSoundEnumerate or DirectSoundCaptureEnumerate function. + + Address of the GUID that identifies the device being enumerated, or NULL for the primary device. This value can be passed to the DirectSoundCreate8 or DirectSoundCaptureCreate8 function to create a device object for that driver. + Address of a null-terminated string that provides a textual description of the DirectSound device. + Address of a null-terminated string that specifies the module name of the DirectSound driver corresponding to this device. + Address of application-defined data. This is the pointer passed to DirectSoundEnumerate or DirectSoundCaptureEnumerate as the lpContext parameter. + Returns TRUE to continue enumerating drivers, or FALSE to stop. + + + + The DirectSoundEnumerate function enumerates the DirectSound drivers installed in the system. + + callback function + User context + + + + Gets the HANDLE of the desktop window. + + HANDLE of the Desktop window + + + + Class for enumerating DirectSound devices + + + + + The device identifier + + + + + Device description + + + + + Device module name + + + + + GSM 610 + + + + + Creates a GSM 610 WaveFormat + For now hardcoded to 13kbps + + + + + Samples per block + + + + + Writes this structure to a BinaryWriter + + + + + Represents the interface to a device that can play a WaveFile + + + + + Begin playback + + + + + Stop playback + + + + + Pause Playback + + + + + Initialise playback + + The waveprovider to be played + + + + Current playback state + + + + + The volume 1.0 is full scale + + + + + Indicates that playback has gone into a stopped state due to + reaching the end of the input stream or an error has been encountered during playback + + + + + Interface for IWavePlayers that can report position + + + + + Position (in terms of bytes played - does not necessarily) + + Position in bytes + + + + Gets a instance indicating the format the hardware is using. + + + + + Generic interface for all WaveProviders. + + + + + Gets the WaveFormat of this WaveProvider. + + The wave format. + + + + Fill the specified buffer with wave data. + + The buffer to fill of wave data. + Offset into buffer + The number of bytes to read + the number of bytes written to the buffer. + + + + Playback State + + + + + Stopped + + + + + Playing + + + + + Paused + + + + + Stopped Event Args + + + + + Initializes a new instance of StoppedEventArgs + + An exception to report (null if no exception) + + + + An exception. Will be null if the playback or record operation stopped + + + + + Helper class allowing us to modify the volume of a 16 bit stream without converting to IEEE float + + + + + Constructs a new VolumeWaveProvider16 + + Source provider, must be 16 bit PCM + + + + Gets or sets volume. + 1.0 is full scale, 0.0 is silence, anything over 1.0 will amplify but potentially clip + + + + + WaveFormat of this WaveProvider + + + + + Read bytes from this WaveProvider + + Buffer to read into + Offset within buffer to read to + Bytes desired + Bytes read + + + + Represents a Wave file format + + + + format type + + + number of channels + + + sample rate + + + for buffer estimation + + + block size of data + + + number of bits per sample of mono data + + + number of following bytes + + + + Creates a new PCM 44.1Khz stereo 16 bit format + + + + + Creates a new 16 bit wave format with the specified sample + rate and channel count + + Sample Rate + Number of channels + + + + Gets the size of a wave buffer equivalent to the latency in milliseconds. + + The milliseconds. + + + + + Creates a WaveFormat with custom members + + The encoding + Sample Rate + Number of channels + Average Bytes Per Second + Block Align + Bits Per Sample + + + + + Creates an A-law wave format + + Sample Rate + Number of Channels + Wave Format + + + + Creates a Mu-law wave format + + Sample Rate + Number of Channels + Wave Format + + + + Creates a new PCM format with the specified sample rate, bit depth and channels + + + + + Creates a new 32 bit IEEE floating point wave format + + sample rate + number of channels + + + + Helper function to retrieve a WaveFormat structure from a pointer + + WaveFormat structure + + + + + Helper function to marshal WaveFormat to an IntPtr + + WaveFormat + IntPtr to WaveFormat structure (needs to be freed by callee) + + + + Reads in a WaveFormat (with extra data) from a fmt chunk (chunk identifier and + length should already have been read) + + Binary reader + Format chunk length + A WaveFormatExtraData + + + + Reads a new WaveFormat object from a stream + + A binary reader that wraps the stream + + + + Reports this WaveFormat as a string + + String describing the wave format + + + + Compares with another WaveFormat object + + Object to compare to + True if the objects are the same + + + + Provides a Hashcode for this WaveFormat + + A hashcode + + + + Returns the encoding type used + + + + + Writes this WaveFormat object to a stream + + the output stream + + + + Returns the number of channels (1=mono,2=stereo etc) + + + + + Returns the sample rate (samples per second) + + + + + Returns the average number of bytes used per second + + + + + Returns the block alignment + + + + + Returns the number of bits per sample (usually 16 or 32, sometimes 24 or 8) + Can be 0 for some codecs + + + + + Returns the number of extra bytes used by this waveformat. Often 0, + except for compressed formats which store extra data after the WAVEFORMATEX header + + + + + Summary description for WaveFormatEncoding. + + + + WAVE_FORMAT_UNKNOWN, Microsoft Corporation + + + WAVE_FORMAT_PCM Microsoft Corporation + + + WAVE_FORMAT_ADPCM Microsoft Corporation + + + WAVE_FORMAT_IEEE_FLOAT Microsoft Corporation + + + WAVE_FORMAT_VSELP Compaq Computer Corp. + + + WAVE_FORMAT_IBM_CVSD IBM Corporation + + + WAVE_FORMAT_ALAW Microsoft Corporation + + + WAVE_FORMAT_MULAW Microsoft Corporation + + + WAVE_FORMAT_DTS Microsoft Corporation + + + WAVE_FORMAT_DRM Microsoft Corporation + + + WAVE_FORMAT_WMAVOICE9 + + + WAVE_FORMAT_OKI_ADPCM OKI + + + WAVE_FORMAT_DVI_ADPCM Intel Corporation + + + WAVE_FORMAT_IMA_ADPCM Intel Corporation + + + WAVE_FORMAT_MEDIASPACE_ADPCM Videologic + + + WAVE_FORMAT_SIERRA_ADPCM Sierra Semiconductor Corp + + + WAVE_FORMAT_G723_ADPCM Antex Electronics Corporation + + + WAVE_FORMAT_DIGISTD DSP Solutions, Inc. + + + WAVE_FORMAT_DIGIFIX DSP Solutions, Inc. + + + WAVE_FORMAT_DIALOGIC_OKI_ADPCM Dialogic Corporation + + + WAVE_FORMAT_MEDIAVISION_ADPCM Media Vision, Inc. + + + WAVE_FORMAT_CU_CODEC Hewlett-Packard Company + + + WAVE_FORMAT_YAMAHA_ADPCM Yamaha Corporation of America + + + WAVE_FORMAT_SONARC Speech Compression + + + WAVE_FORMAT_DSPGROUP_TRUESPEECH DSP Group, Inc + + + WAVE_FORMAT_ECHOSC1 Echo Speech Corporation + + + WAVE_FORMAT_AUDIOFILE_AF36, Virtual Music, Inc. + + + WAVE_FORMAT_APTX Audio Processing Technology + + + WAVE_FORMAT_AUDIOFILE_AF10, Virtual Music, Inc. + + + WAVE_FORMAT_PROSODY_1612, Aculab plc + + + WAVE_FORMAT_LRC, Merging Technologies S.A. + + + WAVE_FORMAT_DOLBY_AC2, Dolby Laboratories + + + WAVE_FORMAT_GSM610, Microsoft Corporation + + + WAVE_FORMAT_MSNAUDIO, Microsoft Corporation + + + WAVE_FORMAT_ANTEX_ADPCME, Antex Electronics Corporation + + + WAVE_FORMAT_CONTROL_RES_VQLPC, Control Resources Limited + + + WAVE_FORMAT_DIGIREAL, DSP Solutions, Inc. + + + WAVE_FORMAT_DIGIADPCM, DSP Solutions, Inc. + + + WAVE_FORMAT_CONTROL_RES_CR10, Control Resources Limited + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WAVE_FORMAT_MPEG, Microsoft Corporation + + + + + + + + + WAVE_FORMAT_MPEGLAYER3, ISO/MPEG Layer3 Format Tag + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WAVE_FORMAT_GSM + + + WAVE_FORMAT_G729 + + + WAVE_FORMAT_G723 + + + WAVE_FORMAT_ACELP + + + + WAVE_FORMAT_RAW_AAC1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Windows Media Audio, WAVE_FORMAT_WMAUDIO2, Microsoft Corporation + + + + + Windows Media Audio Professional WAVE_FORMAT_WMAUDIO3, Microsoft Corporation + + + + + Windows Media Audio Lossless, WAVE_FORMAT_WMAUDIO_LOSSLESS + + + + + Windows Media Audio Professional over SPDIF WAVE_FORMAT_WMASPDIF (0x0164) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Advanced Audio Coding (AAC) audio in Audio Data Transport Stream (ADTS) format. + The format block is a WAVEFORMATEX structure with wFormatTag equal to WAVE_FORMAT_MPEG_ADTS_AAC. + + + The WAVEFORMATEX structure specifies the core AAC-LC sample rate and number of channels, + prior to applying spectral band replication (SBR) or parametric stereo (PS) tools, if present. + No additional data is required after the WAVEFORMATEX structure. + + http://msdn.microsoft.com/en-us/library/dd317599%28VS.85%29.aspx + + + + Source wmCodec.h + + + + MPEG-4 audio transport stream with a synchronization layer (LOAS) and a multiplex layer (LATM). + The format block is a WAVEFORMATEX structure with wFormatTag equal to WAVE_FORMAT_MPEG_LOAS. + + + The WAVEFORMATEX structure specifies the core AAC-LC sample rate and number of channels, + prior to applying spectral SBR or PS tools, if present. + No additional data is required after the WAVEFORMATEX structure. + + http://msdn.microsoft.com/en-us/library/dd317599%28VS.85%29.aspx + + + NOKIA_MPEG_ADTS_AAC + Source wmCodec.h + + + NOKIA_MPEG_RAW_AAC + Source wmCodec.h + + + VODAFONE_MPEG_ADTS_AAC + Source wmCodec.h + + + VODAFONE_MPEG_RAW_AAC + Source wmCodec.h + + + + High-Efficiency Advanced Audio Coding (HE-AAC) stream. + The format block is an HEAACWAVEFORMAT structure. + + http://msdn.microsoft.com/en-us/library/dd317599%28VS.85%29.aspx + + + WAVE_FORMAT_DVM + + + WAVE_FORMAT_VORBIS1 "Og" Original stream compatible + + + WAVE_FORMAT_VORBIS2 "Pg" Have independent header + + + WAVE_FORMAT_VORBIS3 "Qg" Have no codebook header + + + WAVE_FORMAT_VORBIS1P "og" Original stream compatible + + + WAVE_FORMAT_VORBIS2P "pg" Have independent headere + + + WAVE_FORMAT_VORBIS3P "qg" Have no codebook header + + + WAVE_FORMAT_EXTENSIBLE + + + + + + + WaveFormatExtensible + http://www.microsoft.com/whdc/device/audio/multichaud.mspx + + + + + Parameterless constructor for marshalling + + + + + Creates a new WaveFormatExtensible for PCM or IEEE + + + + + WaveFormatExtensible for PCM or floating point can be awkward to work with + This creates a regular WaveFormat structure representing the same audio format + Returns the WaveFormat unchanged for non PCM or IEEE float + + + + + + SubFormat (may be one of AudioMediaSubtypes) + + + + + Serialize + + + + + + String representation + + + + + This class used for marshalling from unmanaged code + + + + + Allows the extra data to be read + + + + + parameterless constructor for marshalling + + + + + Reads this structure from a BinaryReader + + + + + Writes this structure to a BinaryWriter + + + + diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml new file mode 100644 index 0000000..553d68f --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs new file mode 100644 index 0000000..a52803b --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace QuickLook.Plugin.VideoViewer +{ + /// + /// Interaction logic for UserControl1.xaml + /// + public partial class ViewerPanel : UserControl, IDisposable + { + public ViewerPanel() + { + InitializeComponent(); + } + + public void LoadAndPlay(string path) + { + mediaElement.Source = new Uri(path); + mediaElement.Play(); + } + + ~ViewerPanel() + { + GC.SuppressFinalize(this); + Dispose(); + } + + public void Dispose() + { + mediaElement?.Dispose(); + } + } +} diff --git a/QuickLook.sln b/QuickLook.sln index 21f414e..9385615 100644 --- a/QuickLook.sln +++ b/QuickLook.sln @@ -22,6 +22,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuickLook.Plugin.TextViewer EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuickLook.Plugin.OfficeViewer", "QuickLook.Plugin\QuickLook.Plugin.OfficeViewer\QuickLook.Plugin.OfficeViewer.csproj", "{E37675EA-D957-4495-8655-2609BF86756C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuickLook.Plugin.VideoViewer", "QuickLook.Plugin\QuickLook.Plugin.VideoViewer\QuickLook.Plugin.VideoViewer.csproj", "{1B746D92-49A5-4A37-9D75-DCC490393290}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 @@ -56,6 +58,10 @@ Global {E37675EA-D957-4495-8655-2609BF86756C}.Debug|x86.Build.0 = Debug|Any CPU {E37675EA-D957-4495-8655-2609BF86756C}.Release|x86.ActiveCfg = Release|Any CPU {E37675EA-D957-4495-8655-2609BF86756C}.Release|x86.Build.0 = Release|Any CPU + {1B746D92-49A5-4A37-9D75-DCC490393290}.Debug|x86.ActiveCfg = Debug|Any CPU + {1B746D92-49A5-4A37-9D75-DCC490393290}.Debug|x86.Build.0 = Debug|Any CPU + {1B746D92-49A5-4A37-9D75-DCC490393290}.Release|x86.ActiveCfg = Release|Any CPU + {1B746D92-49A5-4A37-9D75-DCC490393290}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -66,5 +72,6 @@ Global {A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D} = {06EFDBE0-6408-4B37-BCF2-0CF9EBEA2E93} {AE041682-E3A1-44F6-8BB4-916A98D89FBE} = {06EFDBE0-6408-4B37-BCF2-0CF9EBEA2E93} {E37675EA-D957-4495-8655-2609BF86756C} = {06EFDBE0-6408-4B37-BCF2-0CF9EBEA2E93} + {1B746D92-49A5-4A37-9D75-DCC490393290} = {06EFDBE0-6408-4B37-BCF2-0CF9EBEA2E93} EndGlobalSection EndGlobal