Got WPF version work
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<Application x:Class="TV_Player.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:TV_Player"
|
||||
>
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -0,0 +1,22 @@
|
||||
using DirectShowLib.BDA;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Windows;
|
||||
using TV_Player.ViewModels;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
private TVPlayerViewModel _tvPlayer;
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
_tvPlayer = new TVPlayerViewModel();
|
||||
|
||||
base.OnStartup(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Windows;
|
||||
|
||||
[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)
|
||||
)]
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
public class EnumToBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return value.Equals(parameter);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return value.Equals(true) ? parameter : Binding.DoNothing;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<UserControl x:Class="TV_Player.GroupButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="100" d:DesignWidth="200">
|
||||
<Viewbox Grid.Row="1">
|
||||
<Grid x:Name="ButtonBorder" Height="70" Width="150" >
|
||||
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="0.4*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Rectangle RadiusX="15" RadiusY="15" x:Name="Border" StrokeThickness="3" Stroke="Yellow" Stretch="Fill" Grid.RowSpan="2" Fill="#FF1F1E1E"/>
|
||||
|
||||
<TextBlock x:Name="groupName" Text="Group name" FontSize="15" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<TextBlock Grid.Row="1" FontSize="10" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" LineStackingStrategy="BlockLineHeight" LineHeight="10">
|
||||
<Run x:Name="programsFound"/>
|
||||
<Run>Programs</Run>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for GroupButton.xaml
|
||||
/// </summary>
|
||||
public partial class GroupButton : UserControl
|
||||
{
|
||||
public GroupButton(string groupName,int programsFound)
|
||||
{
|
||||
InitializeComponent();
|
||||
this.groupName.Text = groupName;
|
||||
this.programsFound.Text = programsFound.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Window x:Class="TV_Player.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:TV_Player"
|
||||
mc:Ignorable="d"
|
||||
Title="TV" Height="450" Width="800">
|
||||
<Window.DataContext>
|
||||
<local:MainViewModel/>
|
||||
</Window.DataContext>
|
||||
<Grid>
|
||||
<Grid.Background>
|
||||
<ImageBrush ImageSource="Assets/bkground.jpg" />
|
||||
</Grid.Background>
|
||||
<ContentControl Name="ControlContainer" Content="{Binding Control}" />
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<UserControl x:Class="TV_Player.ProgramsGroupGrid"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:TV_Player"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid x:Name="groupsGrid">
|
||||
<ScrollViewer>
|
||||
<ListBox ItemsSource="{Binding Programs}"
|
||||
SelectionMode="Single"
|
||||
SelectedItem="{Binding SelectedItem}"
|
||||
SelectionChanged="ListBox_SelectionChanged">
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ProgramsGroupGrid.xaml
|
||||
/// </summary>
|
||||
public partial class ProgramsGroupGrid : UserControl
|
||||
{
|
||||
public ProgramsGroupGrid()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (DataContext is ProgramsGroupViewModel viewModel)
|
||||
{
|
||||
viewModel.ItemSelectedCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<UserControl x:Class="TV_Player.ProgramsList"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid x:Name="groupsGrid">
|
||||
<ScrollViewer>
|
||||
<ListBox ItemsSource="{Binding Programs}"
|
||||
SelectionMode="Single"
|
||||
SelectedItem="{Binding SelectedItem}"
|
||||
SelectionChanged="ListBox_SelectionChanged">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel>
|
||||
<Image Source="{Binding Logo}" Width="50" Height="50"/>
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ProgramsGroupGrid.xaml
|
||||
/// </summary>
|
||||
public partial class ProgramsList : UserControl
|
||||
{
|
||||
public ProgramsList()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (DataContext is ProgramsListViewModel viewModel)
|
||||
{
|
||||
viewModel.ItemSelectedCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<RootNamespace>TV_Player</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Assets\bkGround.jpg" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||
<PackageReference Include="LibVLCSharp" Version="3.8.2" />
|
||||
<PackageReference Include="LibVLCSharp.WPF" Version="3.8.2" />
|
||||
<PackageReference Include="System.Reactive" Version="6.0.0" />
|
||||
<PackageReference Include="WPFMediaKitCore" Version="0.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Resource Include="Assets\bkground.jpg">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="VideoPlayer.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="ProgramsList.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,31 @@
|
||||
<UserControl x:Class="TV_Player.VideoPlayer"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vlc="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
>
|
||||
|
||||
<Grid>
|
||||
<Grid x:Name="videoPlayer">
|
||||
<vlc:VideoView x:Name="VideoView" Panel.ZIndex="1">
|
||||
<StackPanel Panel.ZIndex="2" Opacity="0.9"
|
||||
IsHitTestVisible="True"
|
||||
HorizontalAlignment="Stretch" MouseLeftButtonDown="MyUserControl_MouseDown"
|
||||
TouchDown="MyUserControl_TouchDown" >
|
||||
<Grid x:Name="overlayPanel" Visibility="Collapsed" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0" Content="Pause" HorizontalAlignment="Stretch" Click="PauseButton_Click" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</vlc:VideoView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,114 @@
|
||||
using LibVLCSharp.Shared;
|
||||
using LibVLCSharp.WPF;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ProgramsGroupGrid.xaml
|
||||
/// </summary>
|
||||
public partial class VideoPlayer : UserControl
|
||||
{
|
||||
private readonly DirectoryInfo vlcLibDirectory;
|
||||
|
||||
public static readonly DependencyProperty SourceUrlProperty =
|
||||
DependencyProperty.Register(
|
||||
"SourceUrl", // Name of the property
|
||||
typeof(string), // Type of the property
|
||||
typeof(VideoPlayer), // Type of the owner class
|
||||
new PropertyMetadata(string.Empty) // Default value
|
||||
);
|
||||
|
||||
LibVLC _libVLC;
|
||||
MediaPlayer _mediaPlayer;
|
||||
|
||||
public string SourceUrl
|
||||
{
|
||||
get { return (string)GetValue(SourceUrlProperty); }
|
||||
set { SetValue(SourceUrlProperty, value);}
|
||||
}
|
||||
public VideoPlayer()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_libVLC = new LibVLC(enableDebugLogs: true);
|
||||
_mediaPlayer = new MediaPlayer(_libVLC);
|
||||
|
||||
VideoView.Loaded += (sender, e) =>
|
||||
{
|
||||
VideoView.MediaPlayer = _mediaPlayer;
|
||||
VideoView.MouseLeftButtonDown += VideoView_MouseLeftButtonDown;
|
||||
VideoView.MediaPlayer.EnableMouseInput = false;
|
||||
VideoView.PreviewMouseLeftButtonDown += VideoView_MouseLeftButtonDown;
|
||||
AutoPlay();
|
||||
};
|
||||
Unloaded += VideoPlayer_Unloaded;
|
||||
|
||||
}
|
||||
|
||||
private void VideoView_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
ToggleOverlay();
|
||||
}
|
||||
|
||||
private void VideoPlayer_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
VideoView.Dispose();
|
||||
}
|
||||
|
||||
|
||||
void PauseButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (VideoView.MediaPlayer.IsPlaying)
|
||||
{
|
||||
VideoView.MediaPlayer.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
private void AutoPlay()
|
||||
{
|
||||
if (!VideoView.MediaPlayer.IsPlaying)
|
||||
{
|
||||
|
||||
using (var media = new Media(_libVLC, new Uri(SourceUrl)))
|
||||
VideoView.MediaPlayer.Play(media);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void MyUserControl_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
ToggleOverlay();
|
||||
}
|
||||
|
||||
private void MyUserControl_TouchDown(object sender, TouchEventArgs e)
|
||||
{
|
||||
ToggleOverlay();
|
||||
}
|
||||
|
||||
private void ToggleOverlay()
|
||||
{
|
||||
if (overlayPanel.Visibility == Visibility.Visible)
|
||||
{
|
||||
HideOverlay();
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowOverlay()
|
||||
{
|
||||
overlayPanel.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
public void HideOverlay()
|
||||
{
|
||||
overlayPanel.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace TV_Player
|
||||
{
|
||||
public class GroupInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Count { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace TV_Player
|
||||
{
|
||||
public class M3UInfo
|
||||
{
|
||||
public string CUID { get; set; }
|
||||
public string Number { get; set; }
|
||||
public string TvgID { get; set; }
|
||||
public string TvgName { get; set; }
|
||||
public string GroupTitle { get; set; }
|
||||
public string Logo { get; set; }
|
||||
public string Name{ get; set; }
|
||||
public string Url { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
public static class M3UParser
|
||||
{
|
||||
public static async Task<List<M3UInfo>> DownloadM3UFromWebAsync(string url)
|
||||
{
|
||||
List<M3UInfo> playlistItems = new List<M3UInfo>();
|
||||
|
||||
using (var client = new HttpClient())
|
||||
using (var request = new HttpRequestMessage())
|
||||
{
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/text"));
|
||||
request.Method = HttpMethod.Get;
|
||||
request.RequestUri = new Uri(url);
|
||||
var response = await client.GetAsync(url);
|
||||
response.EnsureSuccessStatusCode();
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// Parse M3U content
|
||||
playlistItems = ParseM3UFromString(responseBody);
|
||||
}
|
||||
return playlistItems;
|
||||
}
|
||||
|
||||
static string[] SplitStringBeforeSeparator(string input, string separator)
|
||||
{
|
||||
string[] parts = input.Split(separator);
|
||||
|
||||
// Reconstruct the string until the separator is reached
|
||||
int separatorIndex = input.IndexOf(separator);
|
||||
if (separatorIndex != -1)
|
||||
{
|
||||
parts[0] = input.Substring(0, separatorIndex + 1);
|
||||
for (int i = 1; i < parts.Length; i++)
|
||||
{
|
||||
parts[i] = separator + parts[i];
|
||||
}
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
static List<M3UInfo> ParseM3UFromString(string content)
|
||||
{
|
||||
List<M3UInfo> playlistItems = new List<M3UInfo>();
|
||||
|
||||
try
|
||||
{
|
||||
var m3u = SplitStringBeforeSeparator(content, "#EXT");
|
||||
|
||||
foreach (var line in m3u)
|
||||
{
|
||||
if (line.StartsWith("#EXTINF:"))
|
||||
{
|
||||
if (TryParseM3ULine(line, out var m3uInfo))
|
||||
{
|
||||
playlistItems.Add(m3uInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error reading M3U file: " + ex.Message);
|
||||
}
|
||||
|
||||
return playlistItems;
|
||||
}
|
||||
|
||||
|
||||
static bool TryParseM3ULine(string m3uLine, out M3UInfo? info)
|
||||
{
|
||||
info = null;
|
||||
string pattern = @"#EXTINF:\d+ CUID=""(?<CUID>.*?)"" number=""(?<Number>.*?)"" tvg-id=""(?<TvgID>.*?)"" tvg-name=""(?<TvgName>.*?)"".*?tvg-logo=""(?<Logo>.*?)"" group-title=""(?<GroupTitle>.*?)""[^,]*,(?<Name>.*)[^\r](?<URL>.*)$";
|
||||
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
|
||||
|
||||
Match match = regex.Match(m3uLine);
|
||||
if (match.Success)
|
||||
{
|
||||
info = new M3UInfo
|
||||
{
|
||||
CUID = match.Groups["CUID"].Value,
|
||||
Number = match.Groups["Number"].Value,
|
||||
TvgID = match.Groups["TvgID"].Value,
|
||||
TvgName = match.Groups["TvgName"].Value,
|
||||
GroupTitle = match.Groups["GroupTitle"].Value,
|
||||
Logo = match.Groups["Logo"].Value,
|
||||
Name = match.Groups["Name"].Value,
|
||||
Url = match.Groups["URL"].Value
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
public class MainViewModel : ObservableViewModelBase
|
||||
{
|
||||
private ContentControl _control;
|
||||
public ContentControl Control
|
||||
{
|
||||
get => _control;
|
||||
set => SetProperty(ref _control, value);
|
||||
}
|
||||
|
||||
public MainViewModel()
|
||||
{
|
||||
var vm = new ProgramsGroupViewModel();
|
||||
|
||||
var control = new ProgramsGroupGrid();
|
||||
control.DataContext = vm;
|
||||
Control = control;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
public abstract class ObservableViewModelBase : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected void RaisePropertyChanged(string propertyName)
|
||||
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
|
||||
/// <summary>
|
||||
/// Set a property and raise a property changed event if it has changed
|
||||
/// </summary>
|
||||
protected bool SetProperty<T>(ref T property, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(property, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
property = value;
|
||||
RaisePropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
|
||||
public class PlayerViewModel: ObservableViewModelBase
|
||||
{
|
||||
|
||||
private readonly M3UInfo _currentProgram;
|
||||
|
||||
private string _urlSource;
|
||||
public string URLSource
|
||||
{
|
||||
get => _urlSource;
|
||||
set => SetProperty(ref _urlSource, value);
|
||||
}
|
||||
|
||||
public GroupInfo SelectedItem { get; set; }
|
||||
public ICommand PlayCommand { get; }
|
||||
|
||||
public PlayerViewModel(M3UInfo selectedProgram)
|
||||
{
|
||||
_currentProgram = selectedProgram;
|
||||
//PlayM3U8(_currentProgram.Url);
|
||||
//_libVLC = new LibVLC();
|
||||
//_mediaPlayer = new MediaPlayer(new Media(_libVLC, new Uri(_currentProgram.Url)));
|
||||
//_mediaPlayer.Play();
|
||||
//PlayCommand = new Command(OnPlayButtonClicked);
|
||||
}
|
||||
|
||||
private void OnPlayButtonClicked()
|
||||
{
|
||||
PlayM3U8(_currentProgram.Url);
|
||||
}
|
||||
|
||||
private void PlayM3U8(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
URLSource = _currentProgram.Url;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Handle exceptions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Reactive.Subjects;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
public class ProgramsData
|
||||
{
|
||||
private static ProgramsData _instance;
|
||||
public static ProgramsData Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
_instance ??= new ProgramsData();
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly ReplaySubject<List<M3UInfo>> programsSubject = new ReplaySubject<List<M3UInfo>>();
|
||||
private readonly ReplaySubject<List<GroupInfo>> groupsSubject = new ReplaySubject<List<GroupInfo>>();
|
||||
public IObservable<List<M3UInfo>> AllPrograms => programsSubject;
|
||||
public IObservable<List<GroupInfo>> GroupsInformation => groupsSubject;
|
||||
|
||||
private ProgramsData()
|
||||
{
|
||||
_=Initialize();
|
||||
}
|
||||
private async Task Initialize()
|
||||
{
|
||||
string m3uLink = "http://pl.da-tv.vip/a71e77fa/835b3216/tv.m3u";
|
||||
var programs = await M3UParser.DownloadM3UFromWebAsync(m3uLink);
|
||||
|
||||
programsSubject.OnNext(programs);
|
||||
|
||||
var groupping = programs.GroupBy(item => item.GroupTitle)
|
||||
.Select(group => new GroupInfo() { Name = group.Key, Count = group.Count() })
|
||||
.ToList();
|
||||
groupsSubject.OnNext(groupping);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System.Windows.Input;
|
||||
using TV_Player.ViewModels;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
public class ProgramsGroupViewModel : ObservableViewModelBase
|
||||
{
|
||||
private List<GroupInfo> _programs;
|
||||
public List<GroupInfo> Programs
|
||||
{
|
||||
get => _programs;
|
||||
set => SetProperty(ref _programs, value);
|
||||
}
|
||||
|
||||
public GroupInfo SelectedItem { get; set; }
|
||||
public ICommand ItemSelectedCommand { get; }
|
||||
|
||||
public ProgramsGroupViewModel()
|
||||
{
|
||||
ItemSelectedCommand = new RelayCommand(OnItemSelected);
|
||||
ProgramsData.Instance.GroupsInformation.Subscribe(x=>Programs = x);
|
||||
}
|
||||
|
||||
private void OnItemSelected()
|
||||
{
|
||||
//var navigation = (INavigation)Application.Current.MainPage.Navigation;
|
||||
|
||||
var programListViewModel = new ProgramsListViewModel(SelectedItem);
|
||||
var conrtrol = new ProgramsList();
|
||||
TVPlayerViewModel.Instance.SetPageContext(conrtrol, programListViewModel);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System.Windows.Input;
|
||||
using TV_Player.ViewModels;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
public class ProgramsListViewModel : ObservableViewModelBase
|
||||
{
|
||||
private List<M3UInfo> _programs;
|
||||
public List<M3UInfo> Programs
|
||||
{
|
||||
get => _programs;
|
||||
set => SetProperty(ref _programs, value);
|
||||
}
|
||||
|
||||
public M3UInfo SelectedItem { get; set; }
|
||||
public ICommand ItemSelectedCommand { get; }
|
||||
|
||||
public ProgramsListViewModel(GroupInfo groupInfo)
|
||||
{
|
||||
ItemSelectedCommand = new RelayCommand(OnItemSelected);
|
||||
ProgramsData.Instance.AllPrograms.Subscribe(x=>Programs = x.Where(p=>p.GroupTitle== groupInfo.Name).ToList());
|
||||
}
|
||||
|
||||
private void OnItemSelected()
|
||||
{
|
||||
|
||||
var playerViewModel = new PlayerViewModel(SelectedItem);
|
||||
var conrtrol = new VideoPlayer();
|
||||
conrtrol.SourceUrl = SelectedItem.Url;
|
||||
TVPlayerViewModel.Instance.SetPageContext(conrtrol, playerViewModel);
|
||||
//var navigation = (INavigation)Application.Current.MainPage.Navigation;
|
||||
|
||||
//var playerViewModel = new PlayerViewModel(SelectedItem);
|
||||
|
||||
//// Create a new SecondPage and set its BindingContext to the ViewModel
|
||||
//var playerPage = new PlayerPage
|
||||
//{
|
||||
// BindingContext = playerViewModel
|
||||
//};
|
||||
//// Navigate to the OtherPage
|
||||
//navigation.PushAsync(playerPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace TV_Player.ViewModels
|
||||
{
|
||||
//public class RelayCommand : ICommand
|
||||
//{
|
||||
// private readonly Action _execute;
|
||||
// private readonly Func<bool> _canExecute;
|
||||
|
||||
// public event EventHandler CanExecuteChanged;
|
||||
|
||||
// public RelayCommand(Action execute, Func<bool> canExecute = null)
|
||||
// {
|
||||
// _execute = execute ?? throw new ArgumentNullException(nameof(execute));
|
||||
// _canExecute = canExecute;
|
||||
// }
|
||||
|
||||
// public bool CanExecute(object parameter)
|
||||
// {
|
||||
// return _canExecute == null || _canExecute();
|
||||
// }
|
||||
|
||||
// public void Execute(object parameter)
|
||||
// {
|
||||
// _execute();
|
||||
// }
|
||||
|
||||
// public void RaiseCanExecuteChanged()
|
||||
// {
|
||||
// CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace TV_Player.ViewModels
|
||||
{
|
||||
public class TVPlayerViewModel
|
||||
{
|
||||
private readonly MainViewModel _mainViewModel;
|
||||
|
||||
private static TVPlayerViewModel _instance;
|
||||
public static TVPlayerViewModel Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if(_instance==null)
|
||||
_instance = new TVPlayerViewModel();
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public TVPlayerViewModel()
|
||||
{
|
||||
_mainViewModel = new MainViewModel();
|
||||
var mainWindow=new MainWindow();
|
||||
mainWindow.DataContext = _mainViewModel;
|
||||
|
||||
mainWindow.Show();
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
public void SetPageContext(ContentControl control, object viewModel)
|
||||
{
|
||||
control.DataContext = viewModel;
|
||||
_mainViewModel.Control = control;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user