diff --git a/README.md b/README.md index bbafd0e..807f6fb 100644 --- a/README.md +++ b/README.md @@ -55,13 +55,25 @@ Table of contents ### Screenshots -![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvnet.png) +#### Main Window -![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvnetContextMenu.png) +![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/Main.png) -![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvConfEdit.png) +#### Context Menu -![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvInputEdit.png) +![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/Menu.png) + +#### Config Editor + +![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/ConfEditor.png) + +#### Input Editor + +![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/InputEditor.png) + +#### Command Palette + +![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/CommandPalette.png) ### Context Menu @@ -183,12 +195,15 @@ mpv.net bugs and requests: the config folder should be created (portable or appdata) - there was an issue causing keys not working after a modal window was shown - there was a crash when no script folder existed in the conf folder -- MediaInfo, youtube-dl and libmpv were updated +- MediaInfo and youtube-dl were updated - a new JavaScript example script was added to the wiki and the script descriptions were improved. [Scripting Page](https://github.com/stax76/mpv.net/wiki/Scripting). - greatly improved README.md file and github startpage - About dialog added - the input editor shows only a closing message if actually a change was made +- the input editor don't show menu separators any longer +- new Command Palette feature added +- the history feature had a bug causing files to be logged more than once ### 3.1 (2019-04-23) diff --git a/mpv.net/Command.cs b/mpv.net/Command.cs index e1b6d49..0b7f46a 100644 --- a/mpv.net/Command.cs +++ b/mpv.net/Command.cs @@ -89,6 +89,15 @@ namespace mpvnet })); } + public static void show_command_palette(string[] args) + { + MainForm.Instance.Invoke(new Action(() => { + var w = new CommandPaletteWindow(); + new WindowInteropHelper(w).Owner = MainForm.Instance.Handle; + w.ShowDialog(); + })); + } + public static void show_history(string[] args) { var fp = mp.MpvConfFolder + "history.txt"; diff --git a/mpv.net/MainForm.cs b/mpv.net/MainForm.cs index 3686263..bdafaeb 100644 --- a/mpv.net/MainForm.cs +++ b/mpv.net/MainForm.cs @@ -305,13 +305,13 @@ namespace mpvnet } } - foreach (string i in lines) + foreach (string line in lines) { - if (!i.Contains("#menu:")) continue; - string left = i.Substring(0, i.IndexOf("#menu:")).Trim(); + if (!line.Contains("#menu:")) continue; + string left = line.Substring(0, line.IndexOf("#menu:")).Trim(); if (left.StartsWith("#")) continue; string command = left.Substring(left.IndexOf(" ") + 1).Trim(); - string menu = i.Substring(i.IndexOf("#menu:") + "#menu:".Length).Trim(); + string menu = line.Substring(line.IndexOf("#menu:") + "#menu:".Length).Trim(); string input = left.Substring(0, left.IndexOf(" ")); if (input == "_") input = ""; if (menu.Contains(";")) input = menu.Substring(0, menu.IndexOf(";")).Trim(); @@ -393,6 +393,8 @@ namespace mpvnet protected override void WndProc(ref Message m) { + //Debug.WriteLine(m); + switch (m.Msg) { case 0x0201: // WM_LBUTTONDOWN diff --git a/mpv.net/Misc.cs b/mpv.net/Misc.cs index 1ca748a..8208e2f 100644 --- a/mpv.net/Misc.cs +++ b/mpv.net/Misc.cs @@ -163,15 +163,16 @@ namespace mpvnet } [Serializable] - public class InputItem : INotifyPropertyChanged + public class CommandItem : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; - public string Menu { get; set; } = ""; + + public string Path { get; set; } = ""; public string Command { get; set; } = ""; - public InputItem() { } + public CommandItem() { } - public InputItem(SerializationInfo info, StreamingContext context) { } + public CommandItem(SerializationInfo info, StreamingContext context) { } private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") { @@ -188,45 +189,44 @@ namespace mpvnet } } - private static ObservableCollection _InputItems; + private static ObservableCollection _Items; - public static ObservableCollection InputItems { + public static ObservableCollection Items { get { - if (_InputItems is null) + if (_Items is null) { - _InputItems = new ObservableCollection(); + _Items = new ObservableCollection(); if (File.Exists(mp.InputConfPath)) { foreach (string line in File.ReadAllLines(mp.InputConfPath)) { - string l = line.Trim(); - if (l.StartsWith("#")) continue; - if (!l.Contains(" ")) continue; - InputItem item = new InputItem(); - item.Input = l.Substring(0, l.IndexOf(" ")); - if (item.Input == "") continue; - l = l.Substring(l.IndexOf(" ") + 1); + string val = line.Trim(); + if (val.StartsWith("#")) continue; + if (!val.Contains(" ")) continue; + CommandItem item = new CommandItem(); + item.Input = val.Substring(0, val.IndexOf(" ")).Replace("_", ""); + val = val.Substring(val.IndexOf(" ") + 1); - if (l.Contains("#menu:")) + if (val.Contains("#menu:")) { - item.Menu = l.Substring(l.IndexOf("#menu:") + 6).Trim(); - l = l.Substring(0, l.IndexOf("#menu:")); + item.Path = val.Substring(val.IndexOf("#menu:") + 6).Trim(); + val = val.Substring(0, val.IndexOf("#menu:")); - if (item.Menu.Contains(";")) - item.Menu = item.Menu.Substring(item.Menu.IndexOf(";") + 1).Trim(); + if (item.Path.Contains(";")) + item.Path = item.Path.Substring(item.Path.IndexOf(";") + 1).Trim(); } - item.Command = l.Trim(); + item.Command = val.Trim(); if (item.Command == "") continue; if (item.Command.ToLower() == "ignore") item.Command = ""; - _InputItems.Add(item); + _Items.Add(item); } } } - return _InputItems; + return _Items; } } } diff --git a/mpv.net/Resources/inputConf.txt b/mpv.net/Resources/inputConf.txt index f41138a..6ef742c 100644 --- a/mpv.net/Resources/inputConf.txt +++ b/mpv.net/Resources/inputConf.txt @@ -138,11 +138,12 @@ Ctrl+i script-message mpv.net show-input-editor #menu: Settings > Show Input Editor Ctrl+f script-message mpv.net open-conf-folder #menu: Settings > Open Config Folder - h script-message mpv.net show-history #menu: Tools > Show History - l ab-loop #menu: Tools > Set/clear A-B loop points - L cycle-values loop-file "inf" "no" #menu: Tools > Toggle infinite file looping - Ctrl+h cycle-values hwdec "auto" "no" #menu: Tools > Cycle Hardware Decoding - _ script-message mpv.net execute-mpv-command #menu: Tools > Execute mpv command... + Ctrl+P script-message mpv.net show-command-palette #menu: Tools > Command Palette + h script-message mpv.net show-history #menu: Tools > Show History + l ab-loop #menu: Tools > Set/clear A-B loop points + L cycle-values loop-file "inf" "no" #menu: Tools > Toggle infinite file looping + Ctrl+h cycle-values hwdec "auto" "no" #menu: Tools > Cycle Hardware Decoding + _ script-message mpv.net execute-mpv-command #menu: Tools > Execute mpv command... _ script-message mpv.net shell-execute https://mpv.io/manual/stable/ #menu: Help > Show mpv manual _ script-message mpv.net shell-execute https://github.com/mpv-player/mpv/blob/master/etc/input.conf #menu: Help > Show mpv default keys diff --git a/mpv.net/Windows/AboutWindow.xaml b/mpv.net/Windows/AboutWindow.xaml index ed640ec..a426e30 100644 --- a/mpv.net/Windows/AboutWindow.xaml +++ b/mpv.net/Windows/AboutWindow.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="About mpv.net" Height="230" Width="420" FontSize="16" ShowInTaskbar="False" - WindowStartupLocation="CenterOwner" ResizeMode="NoResize"> + WindowStartupLocation="CenterOwner" ResizeMode="NoResize" PreviewKeyDown="Window_PreviewKeyDown"> mpv.net diff --git a/mpv.net/Windows/AboutWindow.xaml.cs b/mpv.net/Windows/AboutWindow.xaml.cs index bb3a264..a3d41e9 100644 --- a/mpv.net/Windows/AboutWindow.xaml.cs +++ b/mpv.net/Windows/AboutWindow.xaml.cs @@ -11,5 +11,10 @@ namespace mpvnet Version.Text = $"Version {System.Windows.Forms.Application.ProductVersion}"; Foreground = WPF.WPF.ThemeBrush; } + + private void Window_PreviewKeyDown(object sender, KeyEventArgs e) + { + Close(); + } } } \ No newline at end of file diff --git a/mpv.net/Windows/CommandPaletteWindow.xaml b/mpv.net/Windows/CommandPaletteWindow.xaml new file mode 100644 index 0000000..b518e02 --- /dev/null +++ b/mpv.net/Windows/CommandPaletteWindow.xaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mpv.net/Windows/CommandPaletteWindow.xaml.cs b/mpv.net/Windows/CommandPaletteWindow.xaml.cs new file mode 100644 index 0000000..3a1bcc2 --- /dev/null +++ b/mpv.net/Windows/CommandPaletteWindow.xaml.cs @@ -0,0 +1,109 @@ +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Interop; + +namespace mpvnet +{ + public partial class CommandPaletteWindow : Window + { + ICollectionView CollectionView; + + public CommandPaletteWindow() + { + InitializeComponent(); + CollectionViewSource collectionViewSource = new CollectionViewSource() { Source = CommandItem.Items }; + CollectionView = collectionViewSource.View; + var yourCostumFilter = new Predicate(item => Filter((CommandItem)item)); + CollectionView.Filter = yourCostumFilter; + ListView.ItemsSource = CollectionView; + } + + bool Filter(CommandItem item) + { + if (item.Command == "") return false; + string filter = FilterTextBox.Text.ToLower(); + if (filter == "") return true; + if (item.Command.ToLower().Contains(filter) || + item.Input.ToLower().Contains(filter) || + item.Path.ToLower().Contains(filter)) + return true; + return false; + } + + private void Window_Loaded(object sender, RoutedEventArgs e) + { + HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); + source.AddHook(new HwndSourceHook(WndProc)); + Keyboard.Focus(FilterTextBox); + SelectFirst(); + } + + void SelectFirst() + { + if (ListView.Items.Count > 0) + ListView.SelectedIndex = 0; + } + + private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + if (msg == 0x200 /*WM_MOUSEMOVE*/ && Mouse.LeftButton != MouseButtonState.Pressed) + handled = true; + return IntPtr.Zero; + } + + private void FilterTextBox_PreviewKeyDown(object sender, KeyEventArgs e) + { + switch (e.Key) + { + case Key.Up: + { + int index = ListView.SelectedIndex; + index -= 1; + if (index < 0) index = 0; + ListView.SelectedIndex = index; + ListView.ScrollIntoView(ListView.SelectedItem); + } + break; + case Key.Down: + { + int index = ListView.SelectedIndex; + index += 1; + if (index > ListView.Items.Count - 1) index = ListView.Items.Count - 1; + ListView.SelectedIndex = index; + ListView.ScrollIntoView(ListView.SelectedItem); + } + break; + case Key.Escape: + Close(); + break; + case Key.Enter: + Execute(); + break; + } + } + + void Execute() + { + if (ListView.SelectedItem != null) + { + CommandItem item = ListView.SelectedItem as CommandItem; + Close(); + mp.command_string(item.Command); + } + } + + private void ListView_MouseUp(object sender, MouseButtonEventArgs e) + { + Execute(); + } + + private void FilterTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) + { + CollectionView.Refresh(); + SelectFirst(); + } + } +} \ No newline at end of file diff --git a/mpv.net/Windows/ConfWindow.xaml b/mpv.net/Windows/ConfWindow.xaml index a542c8c..8c8d55c 100644 --- a/mpv.net/Windows/ConfWindow.xaml +++ b/mpv.net/Windows/ConfWindow.xaml @@ -10,11 +10,11 @@ - + - - + + @@ -24,9 +24,7 @@ - - - + diff --git a/mpv.net/Windows/InputWindow.xaml b/mpv.net/Windows/InputWindow.xaml index bf1c652..5ad37e5 100644 --- a/mpv.net/Windows/InputWindow.xaml +++ b/mpv.net/Windows/InputWindow.xaml @@ -27,7 +27,7 @@ - + diff --git a/mpv.net/Windows/InputWindow.xaml.cs b/mpv.net/Windows/InputWindow.xaml.cs index d4182b4..1a0f3d6 100644 --- a/mpv.net/Windows/InputWindow.xaml.cs +++ b/mpv.net/Windows/InputWindow.xaml.cs @@ -20,9 +20,9 @@ namespace mpvnet InitialInputConfContent = GetInputConfContent(); SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged; DataGrid.SelectionMode = DataGridSelectionMode.Single; - CollectionViewSource collectionViewSource = new CollectionViewSource() { Source = InputItem.InputItems }; + CollectionViewSource collectionViewSource = new CollectionViewSource() { Source = CommandItem.Items }; CollectionView = collectionViewSource.View; - var yourCostumFilter = new Predicate(item => Filter((InputItem)item)); + var yourCostumFilter = new Predicate(item => Filter((CommandItem)item)); CollectionView.Filter = yourCostumFilter; DataGrid.ItemsSource = CollectionView; } @@ -35,8 +35,9 @@ namespace mpvnet MessageBox.Show("Filtering works by searching in the Input, Menu and Command but it's possible to reduce the filter scope to either of Input, Menu or Command by prefixing as follows:\n\ni \ni: \n\nm \nm: \n\nc \nc: \n\nIf only one character is entered the search will be performed only in the input.", "Filtering", MessageBoxButton.OK, MessageBoxImage.Information); } - bool Filter(InputItem item) + bool Filter(CommandItem item) { + if (item.Command == "") return false; string searchText = SearchControl.SearchTextBox.Text.ToLower(); if (searchText == "") return true; @@ -51,11 +52,11 @@ namespace mpvnet return item.Input.ToLower().Contains(searchText); } else if (searchText.StartsWith("m ") || searchText.StartsWith("m:")) - return item.Menu.ToLower().Contains(searchText.Substring(2).Trim()); + return item.Path.ToLower().Contains(searchText.Substring(2).Trim()); else if (searchText.StartsWith("c ") || searchText.StartsWith("c:")) return item.Command.ToLower().Contains(searchText.Substring(2).Trim()); else if (item.Command.ToLower().Contains(searchText) || - item.Menu.ToLower().Contains(searchText) || + item.Path.ToLower().Contains(searchText) || item.Input.ToLower().Contains(searchText)) { return true; @@ -65,18 +66,18 @@ namespace mpvnet private void ButtonClick(object sender, RoutedEventArgs e) { - InputItem item = ((Button)e.Source).DataContext as InputItem; + CommandItem item = ((Button)e.Source).DataContext as CommandItem; if (item is null) return; LearnWindow w = new LearnWindow(); w.Owner = this; w.InputItem = item; w.ShowDialog(); - var items = new Dictionary(); + var items = new Dictionary(); - foreach (InputItem i in InputItem.InputItems) - if (items.ContainsKey(i.Input) && i.Input != "_") - MessageBox.Show($"Duplicate found:\n\n{i.Input}: {i.Menu}\n\n{items[i.Input].Input}: {items[i.Input].Menu}\n\nPlease note that you can chain multiple commands in the same line by using a semicolon as separator.", "Duplicate Found", MessageBoxButton.OK, MessageBoxImage.Warning); + foreach (CommandItem i in CommandItem.Items) + if (items.ContainsKey(i.Input) && i.Input != "") + MessageBox.Show($"Duplicate found:\n\n{i.Input}: {i.Path}\n\n{items[i.Input].Input}: {items[i.Input].Path}\n\nPlease note that you can chain multiple commands in the same line by using a semicolon as separator.", "Duplicate Found", MessageBoxButton.OK, MessageBoxImage.Warning); else items[i.Input] = i; } @@ -87,17 +88,18 @@ namespace mpvnet { string text = Properties.Resources.inputConfHeader + "\r\n"; - foreach (InputItem item in InputItem.InputItems) + foreach (CommandItem item in CommandItem.Items) { - string line = " " + item.Input.PadRight(10); + string input = item.Input == "" ? "_" : item.Input; + string line = " " + input.PadRight(10); if (item.Command.Trim() == "") line += " ignore"; else line += " " + item.Command.Trim(); - if (item.Menu.Trim() != "") - line = line.PadRight(40) + " #menu: " + item.Menu; + if (item.Path.Trim() != "") + line = line.PadRight(40) + " #menu: " + item.Path; text += line + "\r\n"; } @@ -117,7 +119,7 @@ namespace mpvnet DataGrid grid = (DataGrid)sender; if (e.Command == DataGrid.DeleteCommand) - if (MessageBox.Show($"Confirm to delete: {(grid.SelectedItem as InputItem).Input} ({(grid.SelectedItem as InputItem).Menu})", "Confirm Delete", MessageBoxButton.OKCancel, MessageBoxImage.Question) != MessageBoxResult.OK) + if (MessageBox.Show($"Confirm to delete: {(grid.SelectedItem as CommandItem).Input} ({(grid.SelectedItem as CommandItem).Path})", "Confirm Delete", MessageBoxButton.OKCancel, MessageBoxImage.Question) != MessageBoxResult.OK) e.Handled = true; } } diff --git a/mpv.net/Windows/LearnWindow.xaml.cs b/mpv.net/Windows/LearnWindow.xaml.cs index f122831..d8044b4 100644 --- a/mpv.net/Windows/LearnWindow.xaml.cs +++ b/mpv.net/Windows/LearnWindow.xaml.cs @@ -9,7 +9,7 @@ namespace mpvnet { public partial class LearnWindow : Window { - public InputItem InputItem { get; set; } + public CommandItem InputItem { get; set; } public string NewKey { get; set; } = ""; public LearnWindow() @@ -144,7 +144,7 @@ namespace mpvnet void SetKey(string key) { NewKey = key; - MenuLabel.Content = InputItem.Menu; + MenuLabel.Content = InputItem.Path; KeyLabel.Content = key; } diff --git a/mpv.net/mp.cs b/mpv.net/mp.cs index 46eb6de..cec8d1a 100644 --- a/mpv.net/mp.cs +++ b/mpv.net/mp.cs @@ -231,6 +231,7 @@ namespace mpvnet case mpv_event_id.MPV_EVENT_FILE_LOADED: FileLoaded?.Invoke(); LoadFolder(); + WriteHistory(mp.get_property_string("path")); break; case mpv_event_id.MPV_EVENT_TRACKS_CHANGED: TracksChanged?.Invoke(); @@ -322,10 +323,7 @@ namespace mpvnet VideoSizeChanged?.Invoke(); } - Task.Run(new Action(() => { - WriteHistory(mp.get_property_string("path")); - ReadMetaData(); - })); + Task.Run(new Action(() => ReadMetaData())); break; case mpv_event_id.MPV_EVENT_CHAPTER_CHANGE: ChapterChange?.Invoke(); diff --git a/mpv.net/mpv.net.csproj b/mpv.net/mpv.net.csproj index aeacfa6..ef52418 100644 --- a/mpv.net/mpv.net.csproj +++ b/mpv.net/mpv.net.csproj @@ -145,6 +145,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + Designer MSBuild:Compile @@ -186,6 +190,9 @@ + + CommandPaletteWindow.xaml + ConfWindow.xaml diff --git a/screenshots/CommandPalette.png b/screenshots/CommandPalette.png new file mode 100644 index 0000000..488f7f1 Binary files /dev/null and b/screenshots/CommandPalette.png differ diff --git a/screenshots/ConfEditor.png b/screenshots/ConfEditor.png new file mode 100644 index 0000000..7201957 Binary files /dev/null and b/screenshots/ConfEditor.png differ diff --git a/screenshots/InputEditor.png b/screenshots/InputEditor.png new file mode 100644 index 0000000..14d9255 Binary files /dev/null and b/screenshots/InputEditor.png differ diff --git a/screenshots/mpvnet.png b/screenshots/Main.png similarity index 100% rename from screenshots/mpvnet.png rename to screenshots/Main.png diff --git a/screenshots/mpvnetContextMenu.png b/screenshots/Menu.png similarity index 100% rename from screenshots/mpvnetContextMenu.png rename to screenshots/Menu.png diff --git a/screenshots/mpvConfEdit.png b/screenshots/mpvConfEdit.png deleted file mode 100644 index 6fb4491..0000000 Binary files a/screenshots/mpvConfEdit.png and /dev/null differ diff --git a/screenshots/mpvInputEdit.png b/screenshots/mpvInputEdit.png deleted file mode 100644 index df3cb60..0000000 Binary files a/screenshots/mpvInputEdit.png and /dev/null differ