PlazaSharp/WinPlaza/MainWindow.xaml.cs

154 lines
5.2 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Media.Imaging;
using libplaza;
using ManagedBass;
namespace WinPlaza {
public partial class MainWindow : Window {
static readonly object BufferLock=new object();
private int BuffCh;
private int BufferReqs;
string LastArtwork="";
Nightwave plaza=new Nightwave();
Timer tRefresh;
Timer tAudio;
bool AudioInit=false;
public MainWindow() {
InitializeComponent();
tRefresh = new Timer(300) { AutoReset = true };
tRefresh.Elapsed += evtRefresh;
tRefresh.Start();
if(!Bass.Init())
sbStatus.Text = "Unable to initialise audio subsystem";
else
AudioInit = true;
if(!AudioInit)
return;
tAudio = new Timer(50);
tAudio.Elapsed += evtAud;
Bass.NetPlaylist = 1;
Bass.NetPreBuffer = 0;
}
private void evtAud(object sender, ElapsedEventArgs e) =>
_ = Dispatcher.BeginInvoke(new dgtNoParam(dgtAud));
~MainWindow() {
if(AudioInit)
_ = Bass.Free();
}
private void _Status(string s) => sbStatus.Text = s;
private void SetStatus(string msg) => Dispatcher.BeginInvoke(new dgtStr(_Status), msg);
private void _Title(string s) => Title = s;
private void SetTitle(string msg) => Dispatcher.BeginInvoke(new dgtStr(_Title), msg);
private void LoadUri(string uri) => Task.Factory.StartNew(() => {
int r;
lock(BufferLock)
r = ++BufferReqs;
tAudio.Stop();
_ = Bass.StreamFree(BuffCh);
SetStatus("Connecting stream..");
int stream = Bass.CreateStream(uri, 0, BassFlags.StreamDownloadBlocks | BassFlags.StreamStatus | BassFlags.AutoFree, StatusProc, new IntPtr(r));
lock(BufferLock) {
if(r != BufferReqs) {
if(stream != 0)
_ = Bass.StreamFree(stream);
}
BuffCh = stream;
}
if(BuffCh == 0)
SetStatus("Unable to connect to stream");
else
tAudio.Start();
});
private void StatusProc(IntPtr buf, int len, IntPtr usr) {
if(buf != IntPtr.Zero && len == 0 && usr.ToInt32() == BufferReqs)
SetStatus(Marshal.PtrToStringAnsi(buf));
}
private void EndSync(int hdl, int ch, int dat, IntPtr usr) {
SetStatus("Idle..");
SetTitle("Nightwave.Net");
}
private void MetaSync(int hdl, int ch, int dat, IntPtr usr) => Dispatcher.BeginInvoke(new dgtBool(dgtRefresh), true);
private void evtRefresh(object sender, ElapsedEventArgs e) =>
_ = Dispatcher.BeginInvoke(new dgtBool(dgtRefresh), false);
private delegate void dgtNoParam();
private delegate void dgtBool(bool b);
private delegate void dgtStr(string s);
private async void dgtRefresh(bool Force = false) {
Nightwave.Status s=await plaza.Broadcast(Force);
slDuration.Value = s.CalculatedElapsed;
sbListeners.Text = $"{s.Listeners} listeners";
lbLikeCt.Content = s.Likes;
lbDislikeCt.Content = s.Dislikes;
lbElapsed.Content = $"{(s.CalculatedElapsed / 60).ToString("D")}:{(s.CalculatedElapsed % 60).ToString("D2")}";
if(LastArtwork != s.ArtworkUri) {
lbArtist.Content = s.Artist;
lbTitle.Content = s.Title;
lbAlbum.Content = s.Album;
if(btPlayPause.IsChecked == true)
SetTitle($"▶ {s.Title} - {s.Artist}");
slDuration.Maximum = s.Duration;
lbTime.Content = $"{(s.Duration / 60).ToString("D")}:{(s.Duration % 60).ToString("D2")}";
art.Source = new BitmapImage(new Uri(s.ArtworkUri));
LastArtwork = s.ArtworkUri;
}
}
private void dgtAud() {
long progress = Bass.StreamGetFilePosition(BuffCh, FileStreamPosition.Buffer)
* 100 / Bass.StreamGetFilePosition(BuffCh, FileStreamPosition.End);
if(progress > 75 || Bass.StreamGetFilePosition(BuffCh, FileStreamPosition.Connected) == 0) {
tAudio.Stop();
sbStatus.Text = "Playing";
SetTitle($"▶ {lbTitle.Content} - {lbArtist.Content}");
/*
IntPtr icy = Bass.ChannelGetTags(BuffCh, TagType.ICY);
if(icy == IntPtr.Zero)
icy = Bass.ChannelGetTags(BuffCh, TagType.HTTP);
if(icy != IntPtr.Zero) {
foreach(string tag in Extensions.ExtractMultiStringAnsi(icy)) {
string icymeta = string.Empty;
if(tag.StartsWith("icy-name:"))
icymeta += $"ICY Name: {tag.Substring(9)}";
if(tag.StartsWith("icy-url:"))
icymeta += $"ICY Url: {tag.Substring(8)}";
//IcyMeta = icymeta;
}
}*/
_ = Bass.ChannelSetSync(BuffCh, SyncFlags.MetadataReceived, 0, MetaSync);
_ = Bass.ChannelSetSync(BuffCh, SyncFlags.OggChange, 0, MetaSync);
_ = Bass.ChannelSetSync(BuffCh, SyncFlags.End, 0, EndSync);
_ = Bass.ChannelPlay(BuffCh);
} else
sbStatus.Text = $"Buffering... {progress}%";
}
private void PlazaLoad() => LoadUri("https://radio.plaza.one/ogg");
private void PlazaStop() {
lock(BufferLock) {
_ = Bass.StreamFree(BufferReqs);
_ = Bass.StreamFree(BuffCh);
_ = Bass.ChannelStop(BufferReqs);
_ = Bass.ChannelStop(BuffCh);
tAudio.Stop();
SetStatus("Idle..");
SetTitle("Nightwave.Net");
}
}
private void BtPlayPause_Click(object sender, RoutedEventArgs e) {
if(!AudioInit)
return;
if(btPlayPause.IsChecked == true)
_ = Dispatcher.BeginInvoke(new dgtNoParam(PlazaLoad));
else
_ = Dispatcher.BeginInvoke(new dgtNoParam(PlazaStop));
}
}
}