diff --git a/ClipForge.slnx b/ClipForge.slnx new file mode 100644 index 0000000..59f6575 --- /dev/null +++ b/ClipForge.slnx @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/ClipForge/App.xaml b/ClipForge/App.xaml new file mode 100644 index 0000000..b3f8d56 --- /dev/null +++ b/ClipForge/App.xaml @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/ClipForge/App.xaml.cs b/ClipForge/App.xaml.cs new file mode 100644 index 0000000..a58166f --- /dev/null +++ b/ClipForge/App.xaml.cs @@ -0,0 +1,46 @@ +using Microsoft.UI.Dispatching; +using Microsoft.UI.Xaml; +using WinRT.Interop; + +namespace ClipForge +{ + public partial class App : Application + { + public MainWindow? MainWindow { get; private set; } + public static DispatcherQueue? MainQueue { get; private set; } + public TrayIconService? TrayIcon { get; private set; } + + public App() + { + this.InitializeComponent(); + } + + protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) + { + MainQueue = DispatcherQueue.GetForCurrentThread(); + MainWindow = new MainWindow(); + MainWindow.Activate(); + + var hwnd = WindowNative.GetWindowHandle(MainWindow); + TrayIcon = new TrayIconService(); + TrayIcon.Initialize( + hwnd, + showWindow: () => + { + MainQueue?.TryEnqueue(() => + { + MainWindow?.AppWindow.Show(); + MainWindow?.Activate(); + }); + }, + exitApp: () => + { + MainQueue?.TryEnqueue(() => + { + TrayIcon?.Dispose(); + Microsoft.UI.Xaml.Application.Current.Exit(); + }); + }); + } + } +} \ No newline at end of file diff --git a/ClipForge/Assets/BadgeLogo.scale-100.png b/ClipForge/Assets/BadgeLogo.scale-100.png new file mode 100644 index 0000000..3a4492c Binary files /dev/null and b/ClipForge/Assets/BadgeLogo.scale-100.png differ diff --git a/ClipForge/Assets/BadgeLogo.scale-125.png b/ClipForge/Assets/BadgeLogo.scale-125.png new file mode 100644 index 0000000..78a796b Binary files /dev/null and b/ClipForge/Assets/BadgeLogo.scale-125.png differ diff --git a/ClipForge/Assets/BadgeLogo.scale-150.png b/ClipForge/Assets/BadgeLogo.scale-150.png new file mode 100644 index 0000000..d98dfa6 Binary files /dev/null and b/ClipForge/Assets/BadgeLogo.scale-150.png differ diff --git a/ClipForge/Assets/BadgeLogo.scale-200.png b/ClipForge/Assets/BadgeLogo.scale-200.png new file mode 100644 index 0000000..b7d9a76 Binary files /dev/null and b/ClipForge/Assets/BadgeLogo.scale-200.png differ diff --git a/ClipForge/Assets/BadgeLogo.scale-400.png b/ClipForge/Assets/BadgeLogo.scale-400.png new file mode 100644 index 0000000..0c8f92c Binary files /dev/null and b/ClipForge/Assets/BadgeLogo.scale-400.png differ diff --git a/ClipForge/Assets/LargeTile.scale-100.png b/ClipForge/Assets/LargeTile.scale-100.png new file mode 100644 index 0000000..1a9bd42 Binary files /dev/null and b/ClipForge/Assets/LargeTile.scale-100.png differ diff --git a/ClipForge/Assets/LargeTile.scale-125.png b/ClipForge/Assets/LargeTile.scale-125.png new file mode 100644 index 0000000..d520b68 Binary files /dev/null and b/ClipForge/Assets/LargeTile.scale-125.png differ diff --git a/ClipForge/Assets/LargeTile.scale-150.png b/ClipForge/Assets/LargeTile.scale-150.png new file mode 100644 index 0000000..fc25b0d Binary files /dev/null and b/ClipForge/Assets/LargeTile.scale-150.png differ diff --git a/ClipForge/Assets/LargeTile.scale-200.png b/ClipForge/Assets/LargeTile.scale-200.png new file mode 100644 index 0000000..007db29 Binary files /dev/null and b/ClipForge/Assets/LargeTile.scale-200.png differ diff --git a/ClipForge/Assets/LargeTile.scale-400.png b/ClipForge/Assets/LargeTile.scale-400.png new file mode 100644 index 0000000..9802e7d Binary files /dev/null and b/ClipForge/Assets/LargeTile.scale-400.png differ diff --git a/ClipForge/Assets/SmallTile.scale-100.png b/ClipForge/Assets/SmallTile.scale-100.png new file mode 100644 index 0000000..09ab901 Binary files /dev/null and b/ClipForge/Assets/SmallTile.scale-100.png differ diff --git a/ClipForge/Assets/SmallTile.scale-125.png b/ClipForge/Assets/SmallTile.scale-125.png new file mode 100644 index 0000000..8d254f5 Binary files /dev/null and b/ClipForge/Assets/SmallTile.scale-125.png differ diff --git a/ClipForge/Assets/SmallTile.scale-150.png b/ClipForge/Assets/SmallTile.scale-150.png new file mode 100644 index 0000000..d73d12a Binary files /dev/null and b/ClipForge/Assets/SmallTile.scale-150.png differ diff --git a/ClipForge/Assets/SmallTile.scale-200.png b/ClipForge/Assets/SmallTile.scale-200.png new file mode 100644 index 0000000..4fa45c9 Binary files /dev/null and b/ClipForge/Assets/SmallTile.scale-200.png differ diff --git a/ClipForge/Assets/SmallTile.scale-400.png b/ClipForge/Assets/SmallTile.scale-400.png new file mode 100644 index 0000000..3c6f165 Binary files /dev/null and b/ClipForge/Assets/SmallTile.scale-400.png differ diff --git a/ClipForge/Assets/SplashScreen.png b/ClipForge/Assets/SplashScreen.png new file mode 100644 index 0000000..c2a9d70 Binary files /dev/null and b/ClipForge/Assets/SplashScreen.png differ diff --git a/ClipForge/Assets/SplashScreen.scale-100.png b/ClipForge/Assets/SplashScreen.scale-100.png new file mode 100644 index 0000000..707aad7 Binary files /dev/null and b/ClipForge/Assets/SplashScreen.scale-100.png differ diff --git a/ClipForge/Assets/SplashScreen.scale-125.png b/ClipForge/Assets/SplashScreen.scale-125.png new file mode 100644 index 0000000..4f995a4 Binary files /dev/null and b/ClipForge/Assets/SplashScreen.scale-125.png differ diff --git a/ClipForge/Assets/SplashScreen.scale-150.png b/ClipForge/Assets/SplashScreen.scale-150.png new file mode 100644 index 0000000..aedd244 Binary files /dev/null and b/ClipForge/Assets/SplashScreen.scale-150.png differ diff --git a/ClipForge/Assets/SplashScreen.scale-200.png b/ClipForge/Assets/SplashScreen.scale-200.png new file mode 100644 index 0000000..9facdc8 Binary files /dev/null and b/ClipForge/Assets/SplashScreen.scale-200.png differ diff --git a/ClipForge/Assets/SplashScreen.scale-400.png b/ClipForge/Assets/SplashScreen.scale-400.png new file mode 100644 index 0000000..aa4db3c Binary files /dev/null and b/ClipForge/Assets/SplashScreen.scale-400.png differ diff --git a/ClipForge/Assets/Square150x150Logo.png b/ClipForge/Assets/Square150x150Logo.png new file mode 100644 index 0000000..6fe14b5 Binary files /dev/null and b/ClipForge/Assets/Square150x150Logo.png differ diff --git a/ClipForge/Assets/Square150x150Logo.scale-100.png b/ClipForge/Assets/Square150x150Logo.scale-100.png new file mode 100644 index 0000000..6010720 Binary files /dev/null and b/ClipForge/Assets/Square150x150Logo.scale-100.png differ diff --git a/ClipForge/Assets/Square150x150Logo.scale-125.png b/ClipForge/Assets/Square150x150Logo.scale-125.png new file mode 100644 index 0000000..9ecae74 Binary files /dev/null and b/ClipForge/Assets/Square150x150Logo.scale-125.png differ diff --git a/ClipForge/Assets/Square150x150Logo.scale-150.png b/ClipForge/Assets/Square150x150Logo.scale-150.png new file mode 100644 index 0000000..6bf0971 Binary files /dev/null and b/ClipForge/Assets/Square150x150Logo.scale-150.png differ diff --git a/ClipForge/Assets/Square150x150Logo.scale-200.png b/ClipForge/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 0000000..c079976 Binary files /dev/null and b/ClipForge/Assets/Square150x150Logo.scale-200.png differ diff --git a/ClipForge/Assets/Square150x150Logo.scale-400.png b/ClipForge/Assets/Square150x150Logo.scale-400.png new file mode 100644 index 0000000..93eb0d4 Binary files /dev/null and b/ClipForge/Assets/Square150x150Logo.scale-400.png differ diff --git a/ClipForge/Assets/Square310x310Logo.png b/ClipForge/Assets/Square310x310Logo.png new file mode 100644 index 0000000..e7790f2 Binary files /dev/null and b/ClipForge/Assets/Square310x310Logo.png differ diff --git a/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png b/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png new file mode 100644 index 0000000..d4c2919 Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png differ diff --git a/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png b/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png new file mode 100644 index 0000000..d3addbf Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png differ diff --git a/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png b/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png new file mode 100644 index 0000000..1c9405e Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png differ diff --git a/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png b/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png new file mode 100644 index 0000000..ad6e73f Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png differ diff --git a/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png b/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png new file mode 100644 index 0000000..2dfe5dc Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png differ diff --git a/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-16.png b/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-16.png new file mode 100644 index 0000000..d4c2919 Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-16.png differ diff --git a/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-24.png b/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-24.png new file mode 100644 index 0000000..d3addbf Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-24.png differ diff --git a/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-256.png b/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-256.png new file mode 100644 index 0000000..1c9405e Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-256.png differ diff --git a/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-32.png b/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-32.png new file mode 100644 index 0000000..ad6e73f Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-32.png differ diff --git a/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-48.png b/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-48.png new file mode 100644 index 0000000..2dfe5dc Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.altform-unplated_targetsize-48.png differ diff --git a/ClipForge/Assets/Square44x44Logo.png b/ClipForge/Assets/Square44x44Logo.png new file mode 100644 index 0000000..842c94a Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.png differ diff --git a/ClipForge/Assets/Square44x44Logo.scale-100.png b/ClipForge/Assets/Square44x44Logo.scale-100.png new file mode 100644 index 0000000..7f261c9 Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.scale-100.png differ diff --git a/ClipForge/Assets/Square44x44Logo.scale-125.png b/ClipForge/Assets/Square44x44Logo.scale-125.png new file mode 100644 index 0000000..226e2be Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.scale-125.png differ diff --git a/ClipForge/Assets/Square44x44Logo.scale-150.png b/ClipForge/Assets/Square44x44Logo.scale-150.png new file mode 100644 index 0000000..41ed872 Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.scale-150.png differ diff --git a/ClipForge/Assets/Square44x44Logo.scale-200.png b/ClipForge/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 0000000..c2f22df Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.scale-200.png differ diff --git a/ClipForge/Assets/Square44x44Logo.scale-400.png b/ClipForge/Assets/Square44x44Logo.scale-400.png new file mode 100644 index 0000000..353547a Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.scale-400.png differ diff --git a/ClipForge/Assets/Square44x44Logo.targetsize-16.png b/ClipForge/Assets/Square44x44Logo.targetsize-16.png new file mode 100644 index 0000000..f4a0270 Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.targetsize-16.png differ diff --git a/ClipForge/Assets/Square44x44Logo.targetsize-24.png b/ClipForge/Assets/Square44x44Logo.targetsize-24.png new file mode 100644 index 0000000..17e4837 Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.targetsize-24.png differ diff --git a/ClipForge/Assets/Square44x44Logo.targetsize-256.png b/ClipForge/Assets/Square44x44Logo.targetsize-256.png new file mode 100644 index 0000000..9780fa4 Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.targetsize-256.png differ diff --git a/ClipForge/Assets/Square44x44Logo.targetsize-32.png b/ClipForge/Assets/Square44x44Logo.targetsize-32.png new file mode 100644 index 0000000..a61fde5 Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.targetsize-32.png differ diff --git a/ClipForge/Assets/Square44x44Logo.targetsize-48.png b/ClipForge/Assets/Square44x44Logo.targetsize-48.png new file mode 100644 index 0000000..c9c46dd Binary files /dev/null and b/ClipForge/Assets/Square44x44Logo.targetsize-48.png differ diff --git a/ClipForge/Assets/StoreLogo.backup.png b/ClipForge/Assets/StoreLogo.backup.png new file mode 100644 index 0000000..4ee6d9f Binary files /dev/null and b/ClipForge/Assets/StoreLogo.backup.png differ diff --git a/ClipForge/Assets/StoreLogo.scale-100.png b/ClipForge/Assets/StoreLogo.scale-100.png new file mode 100644 index 0000000..08aeadf Binary files /dev/null and b/ClipForge/Assets/StoreLogo.scale-100.png differ diff --git a/ClipForge/Assets/StoreLogo.scale-125.png b/ClipForge/Assets/StoreLogo.scale-125.png new file mode 100644 index 0000000..d4f19b4 Binary files /dev/null and b/ClipForge/Assets/StoreLogo.scale-125.png differ diff --git a/ClipForge/Assets/StoreLogo.scale-150.png b/ClipForge/Assets/StoreLogo.scale-150.png new file mode 100644 index 0000000..2d05846 Binary files /dev/null and b/ClipForge/Assets/StoreLogo.scale-150.png differ diff --git a/ClipForge/Assets/StoreLogo.scale-200.png b/ClipForge/Assets/StoreLogo.scale-200.png new file mode 100644 index 0000000..65eece9 Binary files /dev/null and b/ClipForge/Assets/StoreLogo.scale-200.png differ diff --git a/ClipForge/Assets/StoreLogo.scale-400.png b/ClipForge/Assets/StoreLogo.scale-400.png new file mode 100644 index 0000000..6b587d4 Binary files /dev/null and b/ClipForge/Assets/StoreLogo.scale-400.png differ diff --git a/ClipForge/Assets/Wide310x150Logo.png b/ClipForge/Assets/Wide310x150Logo.png new file mode 100644 index 0000000..3817bc3 Binary files /dev/null and b/ClipForge/Assets/Wide310x150Logo.png differ diff --git a/ClipForge/Assets/Wide310x150Logo.scale-100.png b/ClipForge/Assets/Wide310x150Logo.scale-100.png new file mode 100644 index 0000000..552d04e Binary files /dev/null and b/ClipForge/Assets/Wide310x150Logo.scale-100.png differ diff --git a/ClipForge/Assets/Wide310x150Logo.scale-125.png b/ClipForge/Assets/Wide310x150Logo.scale-125.png new file mode 100644 index 0000000..2a39f95 Binary files /dev/null and b/ClipForge/Assets/Wide310x150Logo.scale-125.png differ diff --git a/ClipForge/Assets/Wide310x150Logo.scale-150.png b/ClipForge/Assets/Wide310x150Logo.scale-150.png new file mode 100644 index 0000000..c272211 Binary files /dev/null and b/ClipForge/Assets/Wide310x150Logo.scale-150.png differ diff --git a/ClipForge/Assets/Wide310x150Logo.scale-200.png b/ClipForge/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000..707aad7 Binary files /dev/null and b/ClipForge/Assets/Wide310x150Logo.scale-200.png differ diff --git a/ClipForge/Assets/Wide310x150Logo.scale-400.png b/ClipForge/Assets/Wide310x150Logo.scale-400.png new file mode 100644 index 0000000..9facdc8 Binary files /dev/null and b/ClipForge/Assets/Wide310x150Logo.scale-400.png differ diff --git a/ClipForge/ClipFile.cs b/ClipForge/ClipFile.cs new file mode 100644 index 0000000..2b8420a --- /dev/null +++ b/ClipForge/ClipFile.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; + +namespace ClipForge +{ + public class ClipFile : System.ComponentModel.INotifyPropertyChanged + { + public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged; + + private string _thumbnailPath = ""; + + public string Path { get; set; } = ""; + public string Title { get; set; } = ""; + public string Duration { get; set; } = ""; + public string FileSize { get; set; } = ""; + public DateTime CreatedAt { get; set; } + public string CreatedAtDisplay => CreatedAt.ToString("MMM d, yyyy h:mm tt"); + + public string ThumbnailPath + { + get => _thumbnailPath; + set + { + _thumbnailPath = value; + PropertyChanged?.Invoke(this, + new System.ComponentModel.PropertyChangedEventArgs( + nameof(ThumbnailPath))); + } + } + + public bool HasThumbnail => File.Exists(_thumbnailPath); + + public static ClipFile FromPath(string path) + { + var info = new FileInfo(path); + var thumbPath = System.IO.Path.ChangeExtension(path, ".thumb.png"); + return new ClipFile + { + Path = path, + Title = System.IO.Path.GetFileNameWithoutExtension(path), + FileSize = FormatFileSize(info.Length), + CreatedAt = info.CreationTime, + Duration = "0:30", + ThumbnailPath = thumbPath + }; + } + + private static string FormatFileSize(long bytes) + { + if (bytes >= 1_073_741_824) + return $"{bytes / 1_073_741_824.0:F1} GB"; + if (bytes >= 1_048_576) + return $"{bytes / 1_048_576.0:F0} MB"; + return $"{bytes / 1024.0:F0} KB"; + } + } +} \ No newline at end of file diff --git a/ClipForge/ClipForge.csproj b/ClipForge/ClipForge.csproj new file mode 100644 index 0000000..af21841 --- /dev/null +++ b/ClipForge/ClipForge.csproj @@ -0,0 +1,52 @@ + + + WinExe + net8.0-windows10.0.19041.0 + 10.0.17763.0 + ClipForge + app.manifest + clipforge.ico + x86;x64;ARM64 + win-x86;win-x64;win-arm64 + true + true + enable + disable + True + True + True + 4A55954F2A73A9D620442C7DFBFC7C95A71D8D24 + SHA256 + True + C:\Users\Blade\Desktop\Clipforge Packaged\V1\ + False + True + Auto + x64 + J:\Projects\ClipForge\ClipForge\bin\x64\Release\net8.0-windows10.0.19041.0 + 0 + + + + + PreserveNewest + + + PreserveNewest + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ClipForge/ClipLibraryService.cs b/ClipForge/ClipLibraryService.cs new file mode 100644 index 0000000..f269a35 --- /dev/null +++ b/ClipForge/ClipLibraryService.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.ObjectModel; +using System.IO; + +namespace ClipForge +{ + public class ClipLibraryService + { + private FileSystemWatcher? _watcher; + public ObservableCollection Clips { get; } = new(); + + public string ClipsDirectory { get; } = Path.Combine( + Environment.GetFolderPath( + Environment.SpecialFolder.MyVideos), "ClipForge"); + + public void Initialize() + { + // Create directory if it doesn't exist + if (!Directory.Exists(ClipsDirectory)) + Directory.CreateDirectory(ClipsDirectory); + + // Load existing clips + LoadExistingClips(); + + // Watch for new clips being saved + _watcher = new FileSystemWatcher(ClipsDirectory, "*.mp4") + { + EnableRaisingEvents = true, + NotifyFilter = NotifyFilters.FileName + }; + + _watcher.Created += OnClipCreated; + _watcher.Deleted += OnClipDeleted; + } + + private void LoadExistingClips() + { + Clips.Clear(); + var files = Directory.GetFiles(ClipsDirectory, "*.mp4"); + + // Sort newest first + Array.Sort(files, (a, b) => + File.GetCreationTime(b).CompareTo(File.GetCreationTime(a))); + + foreach (var file in files) + Clips.Add(ClipFile.FromPath(file)); + } + + private void OnClipCreated(object sender, FileSystemEventArgs e) + { + // Must update UI on main thread + App.MainQueue?.TryEnqueue(() => + { + Clips.Insert(0, ClipFile.FromPath(e.FullPath)); + }); + } + + private void OnClipDeleted(object sender, FileSystemEventArgs e) + { + App.MainQueue?.TryEnqueue(() => + { + for (int i = Clips.Count - 1; i >= 0; i--) + { + if (Clips[i].Path == e.FullPath) + { + Clips.RemoveAt(i); + break; + } + } + }); + } + + public void DeleteClip(ClipFile clip) + { + if (File.Exists(clip.Path)) + File.Delete(clip.Path); + } + + public void OpenInExplorer(ClipFile clip) + { + System.Diagnostics.Process.Start("explorer.exe", + $"/select,\"{clip.Path}\""); + } + } +} \ No newline at end of file diff --git a/ClipForge/Direct3D11Helper.cs b/ClipForge/Direct3D11Helper.cs new file mode 100644 index 0000000..a9445ed --- /dev/null +++ b/ClipForge/Direct3D11Helper.cs @@ -0,0 +1,71 @@ +using System; +using System.Runtime.InteropServices; +using Windows.Graphics.DirectX.Direct3D11; +using SharpDX.Direct3D11; +using SharpDX.DXGI; + +namespace ClipForge +{ + public static class Direct3D11Helper + { + [ComImport] + [Guid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComVisible(true)] + interface IDirect3DDxgiInterfaceAccess + { + IntPtr GetInterface([In] ref Guid iid); + } + + [DllImport("d3d11.dll", EntryPoint = "D3D11CreateDevice", + SetLastError = true, + CharSet = CharSet.Unicode, + ExactSpelling = true, + CallingConvention = CallingConvention.StdCall)] + private static extern int D3D11CreateDevice( + IntPtr pAdapter, + uint driverType, + IntPtr software, + uint flags, + IntPtr pFeatureLevels, + uint featureLevels, + uint sdkVersion, + out IntPtr ppDevice, + out uint pFeatureLevel, + out IntPtr ppImmediateContext); + + public static IDirect3DDevice CreateDevice() + { + // Create a SharpDX D3D11 device + var d3dDevice = new SharpDX.Direct3D11.Device( + SharpDX.Direct3D.DriverType.Hardware, + DeviceCreationFlags.BgraSupport); + + // Get the DXGI device interface from it + var dxgiDevice = d3dDevice.QueryInterface(); + + // Create a WinRT IDirect3DDevice from the DXGI device + var result = CreateDirect3DDeviceFromDXGIDevice(dxgiDevice.NativePointer); + + var winrtDevice = (IDirect3DDevice)Marshal.GetObjectForIUnknown(result); + Marshal.Release(result); + return winrtDevice; + } + + [DllImport("d3d11.dll", + EntryPoint = "CreateDirect3D11DeviceFromDXGIDevice", + SetLastError = true, + CharSet = CharSet.Unicode, + ExactSpelling = true, + CallingConvention = CallingConvention.StdCall)] + private static extern int CreateDirect3D11DeviceFromDXGIDevice( + IntPtr dxgiDevice, + out IntPtr graphicsDevice); + + private static IntPtr CreateDirect3DDeviceFromDXGIDevice(IntPtr dxgiDevice) + { + CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice, out IntPtr graphicsDevice); + return graphicsDevice; + } + } +} \ No newline at end of file diff --git a/ClipForge/EncoderService.cs b/ClipForge/EncoderService.cs new file mode 100644 index 0000000..854d743 --- /dev/null +++ b/ClipForge/EncoderService.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using Windows.Graphics.Capture; +using Windows.Graphics.DirectX.Direct3D11; + +namespace ClipForge +{ + public class EncoderService + { + private string _ffmpegPath; + + public EncoderService() + { + // FFmpeg binary will sit next to our app executable + _ffmpegPath = Path.Combine( + AppContext.BaseDirectory, "ffmpeg.exe"); + } + + public async Task SaveClipAsync( + List frames, + string outputPath) + { + if (frames == null || frames.Count == 0) return; + + // Create the output directory if it doesn't exist + var directory = Path.GetDirectoryName(outputPath); + if (!Directory.Exists(directory)) + Directory.CreateDirectory(directory!); + + // For now we'll save a placeholder file confirming + // the frame count — full encoding comes next session + await File.WriteAllTextAsync(outputPath, + $"Clip captured: {frames.Count} frames at {DateTime.Now}"); + } + } +} \ No newline at end of file diff --git a/ClipForge/GlobalHotkeyService.cs b/ClipForge/GlobalHotkeyService.cs new file mode 100644 index 0000000..d786b51 --- /dev/null +++ b/ClipForge/GlobalHotkeyService.cs @@ -0,0 +1,49 @@ +using System; +using System.Runtime.InteropServices; +using Microsoft.UI.Xaml; + +namespace ClipForge +{ + public class GlobalHotkeyService + { + // These two lines talk directly to Windows to register/unregister hotkeys + [DllImport("user32.dll")] + private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); + + [DllImport("user32.dll")] + private static extern bool UnregisterHotKey(IntPtr hWnd, int id); + + // This is the ID we'll use to identify our clip hotkey + private const int HOTKEY_CLIP = 1; + + // Alt key modifier + private const uint MOD_ALT = 0x0001; + + // F9 key + private const uint VK_F9 = 0x78; + + // This is the "event" that fires when the hotkey is pressed + public event Action? ClipRequested; + + private IntPtr _hwnd; + + public void Initialize(IntPtr hwnd) + { + _hwnd = hwnd; + RegisterHotKey(_hwnd, HOTKEY_CLIP, MOD_ALT, VK_F9); + } + + public void ProcessHotkey(int id) + { + if (id == HOTKEY_CLIP) + { + ClipRequested?.Invoke(); + } + } + + public void Cleanup() + { + UnregisterHotKey(_hwnd, HOTKEY_CLIP); + } + } +} \ No newline at end of file diff --git a/ClipForge/MainWindow.xaml b/ClipForge/MainWindow.xaml new file mode 100644 index 0000000..3e3959c --- /dev/null +++ b/ClipForge/MainWindow.xaml @@ -0,0 +1,433 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +