Skip to content

Commit

Permalink
Add project files.
Browse files Browse the repository at this point in the history
  • Loading branch information
chaojian-zhang committed Aug 13, 2020
1 parent 152fab7 commit 8b74add
Show file tree
Hide file tree
Showing 17 changed files with 842 additions and 0 deletions.
25 changes: 25 additions & 0 deletions VideoTagPlayer.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30204.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VideoTagPlayer", "VideoTagPlayer\VideoTagPlayer.csproj", "{E73F3C78-6E45-40B9-B6C7-3A01530ABEB0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E73F3C78-6E45-40B9-B6C7-3A01530ABEB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E73F3C78-6E45-40B9-B6C7-3A01530ABEB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E73F3C78-6E45-40B9-B6C7-3A01530ABEB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E73F3C78-6E45-40B9-B6C7-3A01530ABEB0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C6534F7A-544D-475C-857A-574CAD45E28D}
EndGlobalSection
EndGlobal
21 changes: 21 additions & 0 deletions VideoTagPlayer/AddNoteWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Window x:Class="VideoTagPlayer.AddNoteWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:VideoTagPlayer"
mc:Ignorable="d"
Title="AddNoteWindow" Height="450" Width="800"
DataContext="{Binding RelativeSource={RelativeSource self}}">
<DockPanel LastChildFill="True">
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
<Label Content="Time: "/>
<Label Content="{Binding Location}"/>
</StackPanel>
<DockPanel DockPanel.Dock="Bottom">
<Button Content="Remove" Click="RemoveButton_Click"/>
<Button Content="Finish" Click="FinishButton_Click"/>
</DockPanel>
<TextBox AcceptsReturn="True" AcceptsTab="True" Text="{Binding TagContent}"></TextBox>
</DockPanel>
</Window>
77 changes: 77 additions & 0 deletions VideoTagPlayer/AddNoteWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
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.Shapes;
using VideoTagPlayer.Models;

namespace VideoTagPlayer
{
/// <summary>
/// Interaction logic for AddNoteWindow.xaml
/// </summary>
public partial class AddNoteWindow : Window, INotifyPropertyChanged
{
#region Properties
public AddNoteWindow(VideoNote note, TimeSpan location)
{
Note = note;
Location = location;
InitializeComponent();
}
public AddNoteWindow(VideoNote note, NoteTag tag)
{
Note = note;
Location = tag.Location;
TagContent = tag.Content;
InitializeComponent();
}
private VideoNote Note;
#endregion

#region View Properties
private TimeSpan _Location;
public TimeSpan Location { get => _Location; set => SetField(ref _Location, value); }
private string _TagContent;
public string TagContent { get => _TagContent; set => SetField(ref _TagContent, value); }
#endregion

#region Data Binding
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected bool SetField<type>(ref type field, type value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<type>.Default.Equals(field, value)) return false;
field = value;
NotifyPropertyChanged(propertyName);
return true;
}

#endregion

#region Events
private void RemoveButton_Click(object sender, RoutedEventArgs e)
{
var tag = Note.GetNoteAt(Location);
if(tag != null)
Note.RemoveNote(tag);
}
private void FinishButton_Click(object sender, RoutedEventArgs e)
{
Note.AddNoteAt(Location, TagContent);
this.Close();
}
#endregion
}
}
6 changes: 6 additions & 0 deletions VideoTagPlayer/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
9 changes: 9 additions & 0 deletions VideoTagPlayer/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Application x:Class="VideoTagPlayer.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VideoTagPlayer"
StartupUri="MainWindow.xaml">
<Application.Resources>

</Application.Resources>
</Application>
17 changes: 17 additions & 0 deletions VideoTagPlayer/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace VideoTagPlayer
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
18 changes: 18 additions & 0 deletions VideoTagPlayer/CustomCommands.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace VideoTagPlayer
{
public static class CustomCommands
{
#region UI Commands
public static readonly RoutedUICommand OpenFile = new RoutedUICommand("Open file", "OpenFile", typeof(CustomCommands));
public static readonly RoutedUICommand PlayPause = new RoutedUICommand("Play or pause", "PlayPause", typeof(CustomCommands));
public static readonly RoutedUICommand AddNote = new RoutedUICommand("Add note at current time", "AddNote", typeof(CustomCommands));
#endregion
}
}
38 changes: 38 additions & 0 deletions VideoTagPlayer/MainWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<Window x:Class="VideoTagPlayer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:VideoTagPlayer"
xmlns:wpf="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
mc:Ignorable="d"
Title="Video Tag Player" Height="450" Width="800"
Closing="Window_Closing"
DataContext="{Binding RelativeSource={RelativeSource self}}">
<Window.CommandBindings>
<CommandBinding Command="Open" CanExecute="OpenFileCommand_CanExecute" Executed="OpenFileCommand_Executed"/>
<CommandBinding Command="local:CustomCommands.PlayPause" CanExecute="PlayPauseCommand_CanExecute" Executed="PlayPauseCommand_Executed"/>
<CommandBinding Command="local:CustomCommands.AddNote" CanExecute="AddNoteCommand_CanExecute" Executed="AddNoteCommand_Executed"/>
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Key="F1" Command="Open"/>
<KeyBinding Key="Space" Command="local:CustomCommands.PlayPause"/>
<KeyBinding Key="F2" Command="local:CustomCommands.AddNote"/>
</Window.InputBindings>
<Grid>
<wpf:VideoView x:Name="VideoView" Loaded="VideoView_Loaded">
<Grid>
<TextBlock x:Name="IntroTextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFAAAAAA" Visibility="Visible">
F1 to Open File<LineBreak/>
Space to Play/Pause<LineBreak/>
F2 to Add Note at Current Location<LineBreak/>
Tags are automatically saved.
</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Bottom">
<Label Content="{Binding CurrentTime}"/>
<Button x:Name="OpenTagButton" Content="Open Tag" Visibility="Collapsed" Click="OpenTagButton_Click"/>
</StackPanel>
</Grid>
</wpf:VideoView>
</Grid>
</Window>
147 changes: 147 additions & 0 deletions VideoTagPlayer/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using LibVLCSharp.Shared;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
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.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VideoTagPlayer.Models;
using MediaPlayer = LibVLCSharp.Shared.MediaPlayer;

namespace VideoTagPlayer
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
#region Components
LibVLC _LibVLC;
MediaPlayer _MediaPlayer;
#endregion

#region Construction
public MainWindow()
{
InitializeComponent();
}
#endregion

#region Properties
public VideoNote Note { get; set; }
#endregion

#region View Properties
private TimeSpan _CurrentTime;
public TimeSpan CurrentTime { get => _CurrentTime; set => SetField(ref _CurrentTime, value); }
private NoteTag Tag { get; set; }
#endregion

#region Events
private void VideoView_Loaded(object sender, RoutedEventArgs e)
{
Core.Initialize();

// Initialize components
_LibVLC = new LibVLC();
_MediaPlayer = new MediaPlayer(_LibVLC);

// Setup media player
VideoView.MediaPlayer = _MediaPlayer;
_MediaPlayer.TimeChanged += _MediaPlayer_TimeChanged;
}

private void _MediaPlayer_TimeChanged(object sender, MediaPlayerTimeChangedEventArgs e)
{
CurrentTime = TimeSpan.FromSeconds(_MediaPlayer.Time / 1000);
if(Note != null && Note.GetNoteAt(CurrentTime) != null)
{
Tag = Note.GetNoteAt(CurrentTime);
Dispatcher.Invoke(() => OpenTagButton.Visibility = Visibility.Visible);
}
else
{
Dispatcher.Invoke(() => OpenTagButton.Visibility = Visibility.Collapsed);
}
}
private void Window_Closing(object sender, CancelEventArgs e)
{
if(Note!=null)
Note.Save();
}
private void OpenTagButton_Click(object sender, RoutedEventArgs e)
{
AddNoteWindow noteWindow = new AddNoteWindow(Note, Tag);
noteWindow.Owner = this;
noteWindow.Show();
}
#endregion

#region Commands
private void OpenFileCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
=> e.CanExecute = true;
private void OpenFileCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
if(dialog.ShowDialog() == true)
{
// Initialize note
Note = new VideoNote(dialog.FileName);
// Start play
IntroTextBlock.Visibility = Visibility.Collapsed;
_MediaPlayer.Play(new Media(_LibVLC, new Uri(dialog.FileName)));
}
}
private void PlayPauseCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
=> e.CanExecute = true;

private void PlayPauseCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
if (_MediaPlayer.IsPlaying)
_MediaPlayer.Pause();
else if(_MediaPlayer.WillPlay)
_MediaPlayer.Play();
}

private void AddNoteCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
=> e.CanExecute = true;
private void AddNoteCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
if(_MediaPlayer.WillPlay)
{
_MediaPlayer.Pause();

AddNoteWindow noteWindow = new AddNoteWindow(Note, TimeSpan.FromSeconds(_MediaPlayer.Time / 1000));
noteWindow.Owner = this;
noteWindow.Show();
noteWindow.Closed += (o, v) => { _MediaPlayer.Play(); };
}
}
#endregion

#region Data Binding
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected bool SetField<type>(ref type field, type value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<type>.Default.Equals(field, value)) return false;
field = value;
NotifyPropertyChanged(propertyName);
return true;
}
#endregion
}
}
Loading

0 comments on commit 8b74add

Please sign in to comment.