Progress on radio implementation
This commit is contained in:
parent
fbb65a039a
commit
32d3610b07
@ -364,7 +364,14 @@ namespace unison
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
using MemoryStream stream = new MemoryStream(data.ToArray());
|
using MemoryStream stream = new MemoryStream(data.ToArray());
|
||||||
_cover = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
try
|
||||||
|
{
|
||||||
|
_cover = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||||
|
}
|
||||||
|
catch (System.NotSupportedException e)
|
||||||
|
{
|
||||||
|
_cover = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UpdateCover();
|
UpdateCover();
|
||||||
}
|
}
|
||||||
|
@ -70,11 +70,12 @@ namespace unison
|
|||||||
SongTitle.Text = _mpd.GetCurrentSong().Title;
|
SongTitle.Text = _mpd.GetCurrentSong().Title;
|
||||||
else if (_mpd.GetCurrentSong().HasName && _mpd.GetCurrentSong().Name.Length > 0)
|
else if (_mpd.GetCurrentSong().HasName && _mpd.GetCurrentSong().Name.Length > 0)
|
||||||
SongTitle.Text = _mpd.GetCurrentSong().Name;
|
SongTitle.Text = _mpd.GetCurrentSong().Name;
|
||||||
else
|
else if (_mpd.GetCurrentSong().Path != null)
|
||||||
{
|
{
|
||||||
int start = _mpd.GetCurrentSong().Path.LastIndexOf("/") + 1;
|
int start = _mpd.GetCurrentSong().Path.LastIndexOf("/") + 1;
|
||||||
int end = _mpd.GetCurrentSong().Path.LastIndexOf(".");
|
int end = _mpd.GetCurrentSong().Path.LastIndexOf(".");
|
||||||
SongTitle.Text = _mpd.GetCurrentSong().Path.Substring(start, end - start);
|
if (start > 0 && end > 0 && end > start)
|
||||||
|
SongTitle.Text = _mpd.GetCurrentSong().Path.Substring(start, end - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
SongTitle.ToolTip = _mpd.GetCurrentSong().Path;
|
SongTitle.ToolTip = _mpd.GetCurrentSong().Path;
|
||||||
@ -216,7 +217,7 @@ namespace unison
|
|||||||
snapcast.LaunchOrExit();
|
snapcast.LaunchOrExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Radios_Clicked(object sender, RoutedEventArgs e)
|
public void Radios_Clicked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_radiosWin.Show();
|
_radiosWin.Show();
|
||||||
_radiosWin.Activate();
|
_radiosWin.Activate();
|
||||||
|
@ -3,20 +3,77 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:emoji="clr-namespace:Emoji.Wpf;assembly=Emoji.Wpf"
|
||||||
xmlns:local="clr-namespace:unison"
|
xmlns:local="clr-namespace:unison"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="Radios" Closing="Window_Closing" SizeToContent="WidthAndHeight">
|
Title="Radios" Closing="Window_Closing" SizeToContent="WidthAndHeight" ResizeMode="NoResize">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<StackPanel HorizontalAlignment="Left" Orientation="Vertical">
|
<StackPanel HorizontalAlignment="Left" Orientation="Vertical">
|
||||||
|
|
||||||
|
<GroupBox DockPanel.Dock="Top" Padding="0,4,0,0" Margin="5,0,5,0">
|
||||||
|
<GroupBox.Header>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock>
|
||||||
|
<emoji:EmojiInline Text="📻"/>
|
||||||
|
<Run Text="Search station"/>
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</GroupBox.Header>
|
||||||
|
<Grid VerticalAlignment="Top">
|
||||||
|
<StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
|
||||||
|
<StackPanel HorizontalAlignment="Stretch">
|
||||||
|
<TextBlock Text="Name" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,0,0,0" />
|
||||||
|
<TextBox x:Name="NameSearch" KeyDown="SearchHandler" Text="" TextWrapping="Wrap" HorizontalAlignment="Left" Width="200" Margin="5,6,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5,5,0,0">
|
<StackPanel HorizontalAlignment="Stretch" Margin="20,0,0,0">
|
||||||
<TextBox x:Name="SearchBar" Text="fip" TextWrapping="Wrap" HorizontalAlignment="Left" Width="200"/>
|
<TextBlock Text="Tags" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" />
|
||||||
<Button Content="Search" Click="Search_Clicked" Margin="5,0,0,0"/>
|
<TextBox x:Name="TagSearch" KeyDown="SearchHandler" Text="" TextWrapping="Wrap" HorizontalAlignment="Left" Width="300" Margin="0,6,0,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel HorizontalAlignment="Stretch" Margin="20,0,0,0">
|
||||||
|
<TextBlock Text="Country" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" />
|
||||||
|
<ComboBox x:Name="CountryList" SelectedIndex="0" KeyDown="SearchHandler" Width="240" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,2,0,0" ScrollViewer.CanContentScroll="False"/>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="5,7.5,0,0">
|
||||||
|
<Button Content="Search" Click="Search_Clicked"/>
|
||||||
|
<Button Content="Reset" Click="Reset_Clicked" Margin="10,0,0,0"/>
|
||||||
|
<TextBlock x:Name="SearchStatus" Text="" Margin="15,1,0,0" FontStyle="Italic" />
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<Grid Margin="5,10,5,5" MaxHeight="600" MinWidth="800" MaxWidth="800">
|
||||||
|
<Grid.Resources>
|
||||||
|
<DataTemplate x:Key="CountryTemplate">
|
||||||
|
<emoji:TextBlock TextAlignment="Center" Text="{Binding Country}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</Grid.Resources>
|
||||||
|
<DataGrid Name="RadioListGrid" CanUserAddRows="False" CanUserDeleteRows="False"
|
||||||
|
IsReadOnly="True" MouseDoubleClick="Row_DoubleClick" SelectionMode="Single" CanUserReorderColumns="False"
|
||||||
|
HeadersVisibility="Column" GridLinesVisibility="None" AutoGenerateColumns="False" CanUserResizeRows="False"
|
||||||
|
>
|
||||||
|
<DataGrid.Columns>
|
||||||
|
<DataGridTemplateColumn Header="🏳️" CellTemplate="{StaticResource CountryTemplate}" MinWidth="25" />
|
||||||
|
<DataGridTextColumn Header="Name" Binding="{Binding Name}" MinWidth="50"/>
|
||||||
|
<DataGridTextColumn Header="Codec" Binding="{Binding Codec}" MinWidth="47"/>
|
||||||
|
<DataGridTextColumn Header="Bitrate" Binding="{Binding Bitrate}" MinWidth="47"/>
|
||||||
|
<DataGridTextColumn Header="Tags" Binding="{Binding Tags}" MinWidth="50"/>
|
||||||
|
</DataGrid.Columns>
|
||||||
|
<DataGrid.CellStyle>
|
||||||
|
<Style TargetType="DataGridCell">
|
||||||
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
|
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
|
||||||
|
</Style>
|
||||||
|
</DataGrid.CellStyle>
|
||||||
|
</DataGrid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<ListView x:Name="lvDataBinding" SelectionChanged="SelectionChanged" Width="400" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5,10,5,5"/>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using RadioBrowser;
|
using RadioBrowser;
|
||||||
using RadioBrowser.Models;
|
using RadioBrowser.Models;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -9,86 +8,179 @@ using System;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
using System.Windows.Input;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace unison
|
namespace unison
|
||||||
{
|
{
|
||||||
public class StationView : StationInfo
|
public class CountryListItem
|
||||||
{
|
{
|
||||||
public StationView(string _name, Uri _url, int _bitrate, string _codec, string _country, Uri _favicon)
|
public uint Count { get; set; }
|
||||||
{
|
public string Name { get; set; }
|
||||||
Name = _name;
|
|
||||||
Url = _url;
|
|
||||||
Bitrate = _bitrate;
|
|
||||||
Codec = _codec;
|
|
||||||
CountryCode = _country;
|
|
||||||
Favicon = _favicon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{this.Name} - {this.Bitrate} - {this.Codec} - {this.CountryCode}";
|
if (Name == "")
|
||||||
|
return "None";
|
||||||
|
return $"{Name} ({Count})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StationListItem
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Codec { get; set; }
|
||||||
|
public string Tags { get; set; }
|
||||||
|
public Uri Url { get; set; }
|
||||||
|
|
||||||
|
private string _country;
|
||||||
|
public string Country
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_country.Length == 0)
|
||||||
|
return "🏴☠️";
|
||||||
|
return string.Concat(_country.ToUpper().Select(x => char.ConvertFromUtf32(x + 0x1F1A5))); // return emoji
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_country = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _bitrate;
|
||||||
|
public string Bitrate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_bitrate == "0")
|
||||||
|
return "—";
|
||||||
|
return _bitrate.ToString();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_bitrate = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class Radios : Window
|
public partial class Radios : Window
|
||||||
{
|
{
|
||||||
RadioBrowserClient _radioBrowser;
|
private RadioBrowserClient _radioBrowser;
|
||||||
List<StationView> _stations = new List<StationView>();
|
|
||||||
|
|
||||||
private MPDHandler _mpd;
|
private MPDHandler _mpd;
|
||||||
|
|
||||||
public Radios()
|
public Radios()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
_radioBrowser = new RadioBrowserClient();
|
_radioBrowser = new RadioBrowserClient();
|
||||||
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Search(string name)
|
public async void Initialize()
|
||||||
{
|
{
|
||||||
var searchByName = await _radioBrowser.Search.ByNameAsync(name);
|
List<NameAndCount> Countries = await _radioBrowser.Lists.GetCountriesAsync();
|
||||||
Debug.WriteLine(searchByName.FirstOrDefault()?.Name);
|
CountryList.Items.Add(new CountryListItem { Name = "", Count = 0 });
|
||||||
Debug.WriteLine("");
|
|
||||||
}
|
foreach (NameAndCount Country in Countries)
|
||||||
|
|
||||||
public async Task SearchAdvanced(string name)
|
|
||||||
{
|
|
||||||
Debug.Write(name);
|
|
||||||
|
|
||||||
_stations.Clear();
|
|
||||||
var advancedSearch = await _radioBrowser.Search.AdvancedAsync(new AdvancedSearchOptions
|
|
||||||
{
|
{
|
||||||
Name = name
|
CountryList.Items.Add(new CountryListItem
|
||||||
});
|
{
|
||||||
foreach (var station in advancedSearch)
|
Name = Country.Name,
|
||||||
_stations.Add(new StationView(station.Name, station.Url, station.Bitrate, station.Codec, station.CountryCode, station.Favicon));
|
Count = Country.Stationcount
|
||||||
lvDataBinding.ItemsSource = _stations;
|
});
|
||||||
ICollectionView view = CollectionViewSource.GetDefaultView(_stations);
|
}
|
||||||
view.Refresh();
|
|
||||||
|
|
||||||
Debug.WriteLine(_stations[0].Url.AbsoluteUri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private string CleanString(string str)
|
||||||
{
|
{
|
||||||
Debug.WriteLine("Selected: {0}", e.AddedItems[0]);
|
return str.Replace("\r\n", "").Replace("\n", "").Replace("\r", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SearchAdvanced(string name, string country, string tags)
|
||||||
|
{
|
||||||
|
SearchStatus.Text = "Loading stations...";
|
||||||
|
|
||||||
|
List<StationInfo> advancedSearch = await _radioBrowser.Search.AdvancedAsync(new AdvancedSearchOptions
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
Country = country,
|
||||||
|
TagList = tags
|
||||||
|
});
|
||||||
|
|
||||||
|
RadioListGrid.Items.Clear();
|
||||||
|
if (advancedSearch.Count > 0)
|
||||||
|
{
|
||||||
|
SearchStatus.Text = "";
|
||||||
|
foreach (StationInfo station in advancedSearch)
|
||||||
|
{
|
||||||
|
RadioListGrid.Items.Add(new StationListItem
|
||||||
|
{
|
||||||
|
Name = CleanString(station.Name),
|
||||||
|
Country = station.CountryCode,
|
||||||
|
Codec = station.Codec,
|
||||||
|
Bitrate = station.Bitrate.ToString(),
|
||||||
|
Url = station.Url,
|
||||||
|
Tags = string.Join(", ", station.Tags)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
FitToContent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SearchStatus.Text = "No stations found!";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FitToContent()
|
||||||
|
{
|
||||||
|
foreach (DataGridColumn column in RadioListGrid.Columns)
|
||||||
|
column.Width = new DataGridLength(1.0, DataGridLengthUnitType.SizeToCells);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Row_DoubleClick(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
DataGrid grid = sender as DataGrid;
|
||||||
|
StationListItem station;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
station = grid.Items[grid.SelectedIndex] as StationListItem;
|
||||||
|
}
|
||||||
|
catch (System.ArgumentOutOfRangeException)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Error: Invalid index.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (station.Url == null)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Error: Invalid station.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_mpd = (MPDHandler)Application.Current.Properties["mpd"];
|
_mpd = (MPDHandler)Application.Current.Properties["mpd"];
|
||||||
_mpd.ClearQueue();
|
_mpd.ClearQueue();
|
||||||
|
|
||||||
StationView station = (StationView)e.AddedItems[0];
|
|
||||||
_mpd.AddSong(station.Url.AbsoluteUri);
|
_mpd.AddSong(station.Url.AbsoluteUri);
|
||||||
_mpd.PlayCommand();
|
_mpd.PlayCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<StationView> GetStations()
|
|
||||||
{
|
|
||||||
return _stations;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Search_Clicked(object sender, RoutedEventArgs e)
|
private async void Search_Clicked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
await SearchAdvanced(SearchBar.Text);
|
CountryListItem a = (CountryListItem)CountryList.SelectedItem;
|
||||||
|
await SearchAdvanced(NameSearch.Text, a?.Name, TagSearch.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Reset_Clicked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
NameSearch.Text = "";
|
||||||
|
TagSearch.Text = "";
|
||||||
|
CountryList.SelectedIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SearchHandler(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key == Key.Return)
|
||||||
|
{
|
||||||
|
Search_Clicked(null, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Closing(object sender, CancelEventArgs e)
|
private void Window_Closing(object sender, CancelEventArgs e)
|
||||||
@ -104,4 +196,4 @@ namespace unison
|
|||||||
helper.EnsureHandle();
|
helper.EnsureHandle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user