diff --git a/WinPlaza/MainWindow.xaml b/WinPlaza/MainWindow.xaml
index d0ec138..e157e9a 100644
--- a/WinPlaza/MainWindow.xaml
+++ b/WinPlaza/MainWindow.xaml
@@ -5,71 +5,74 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WinPlaza"
mc:Ignorable="d"
- Title="Nightwave.Net" Height="200" Width="480" Background="#FFF0F0F0" ResizeMode="CanMinimize" Deactivated="Window_Deactivated" Activated="Window_Activated" UseLayoutRounding="True" Closing="Window_Closing">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ Title="Nightwave.Net" Height="206" Width="480" Background="#FFF0F0F0" ResizeMode="CanMinimize" Deactivated="Window_Deactivated" Activated="Window_Activated" UseLayoutRounding="True" Closing="Window_Closing">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WinPlaza/MainWindow.xaml.cs b/WinPlaza/MainWindow.xaml.cs
index 344314f..eb265b4 100644
--- a/WinPlaza/MainWindow.xaml.cs
+++ b/WinPlaza/MainWindow.xaml.cs
@@ -6,6 +6,7 @@ using System.Windows;
using System.Windows.Media.Imaging;
using libplaza;
using ManagedBass;
+using Meziantou.Framework.Win32;
namespace WinPlaza {
public partial class MainWindow : Window {
@@ -20,6 +21,7 @@ namespace WinPlaza {
private Timer tRefresh;
private Timer tAudio;
private Timer tGfx;
+ private Timer tLogon;
private bool AudioInit=false;
#endregion
#region Delegates
@@ -38,6 +40,18 @@ namespace WinPlaza {
Dispatcher.BeginInvoke(new dgtStr(_Status), msg);
private void SetTitle(string msg) =>
Dispatcher.BeginInvoke(new dgtStr(_Title), msg);
+ private async void dgtFirstLogin() {
+ Credential c=CredentialManager.ReadCredential("Nightwave.NET");
+ if(c is null)
+ return;
+ if(await plaza.Login(c.UserName, c.Password)!=true)
+ return;
+ btLogin.IsEnabled = false;
+ btLogin.Visibility = Visibility.Hidden;
+ imLogin.IsEnabled = false;
+ imLogin.Visibility = Visibility.Hidden;
+ SetStatus($"Logged in as {await plaza.GetUser()}");
+ }
private async void dgtRefresh(bool Force = false) {
Nightwave.Status s=await plaza.Broadcast(Force);
slDuration.Value = s.CalculatedElapsed;
@@ -46,11 +60,13 @@ namespace WinPlaza {
lbDislikeCt.Content = s.Dislikes;
lbElapsed.Content = $"{(s.CalculatedElapsed / 60).ToString("D")}:{(s.CalculatedElapsed % 60).ToString("D2")}";
if(LastArtwork != s.ArtworkUri||Force) {
+ if(tGfx.Enabled)
+ SetStatus("Playing");
lbArtist.Content = s.Artist;
lbTitle.Content = s.Title;
lbAlbum.Content = s.Album;
if(btPlayPause.IsChecked == true)
- SetTitle($"▶ {s.Title} - {s.Artist}");
+ SetTitle($"{s.Title} - {s.Artist}");
slDuration.Maximum = s.Duration;
lbTime.Content = $"{(s.Duration / 60).ToString("D")}:{(s.Duration % 60).ToString("D2")}";
if(LastArtwork != s.ArtworkUri)
@@ -65,7 +81,7 @@ namespace WinPlaza {
tAudio.Stop();
//tbPlayPause.ImageSource = (BitmapImage)FindResource("tbPlaying");
SetStatus("Playing");
- SetTitle($"▶ {lbTitle.Content} - {lbArtist.Content}");
+ SetTitle($"{lbTitle.Content} - {lbArtist.Content}");
tGfx.Start();
_ = Bass.ChannelSetSync(BuffCh, SyncFlags.MetadataReceived, 0, MetaSync);
_ = Bass.ChannelSetSync(BuffCh, SyncFlags.OggChange, 0, MetaSync);
@@ -105,7 +121,6 @@ namespace WinPlaza {
_ = Bass.ChannelStop(BufferReqs);
_ = Bass.ChannelStop(BuffCh);
tAudio.Stop();
- //tbPlayPause.ImageSource = (BitmapImage)FindResource("tbStopped");
SetStatus("Idle..");
SetTitle("Nightwave.Net");
}
@@ -123,11 +138,13 @@ namespace WinPlaza {
SetStatus(Marshal.PtrToStringAnsi(buf));
}
private void EvtRefresh(object sender, ElapsedEventArgs e) =>
- _ = Dispatcher.BeginInvoke(new dgtBool(dgtRefresh), false);
+ Dispatcher.BeginInvoke(new dgtBool(dgtRefresh), false);
+ private async void EvtLogon(object sender, ElapsedEventArgs e) =>
+ await Dispatcher.BeginInvoke(new dgtNoParam(dgtFirstLogin));
private void EvtAudio(object sender, ElapsedEventArgs e) =>
_ = Dispatcher.BeginInvoke(new dgtNoParam(dgtAud));
- private void EvtRender(object sender, ElapsedEventArgs e) =>
- Dispatcher.BeginInvoke(new dgtNoParam(Leveller));
+ private async void EvtRender(object sender, ElapsedEventArgs e) =>
+ await Dispatcher.BeginInvoke(new dgtNoParam(Leveller));
private void BtPlayPause_Click(object sender, RoutedEventArgs e) {
if(!AudioInit)
return;
@@ -153,12 +170,52 @@ namespace WinPlaza {
sbVol.Value += e.Delta / 25;
e.Handled = true;
}
- private void SbVol_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) =>
+ private void SbVol_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) {
+ if(MuteVol >= 0)
+ sbMute.IsChecked = false;
Bass.GlobalStreamVolume = (int)sbVol.Value * 100;
+ }
+ private async void BtLogin_Click(object sender, RoutedEventArgs e) {
+ CredentialResult _c=CredentialManager.PromptForCredentials(messageText:"Please log into your Nightwave Plaza account", captionText:"Log into plaza.one");
+ if(_c is null)
+ return;
+ CredentialManager.WriteCredential("Nightwave.NET", _c.UserName, _c.Password, CredentialPersistence.Enterprise);
+ Credential c=CredentialManager.ReadCredential("Nightwave.NET");
+ if(c is null)
+ throw new Exception("what the fuck");
+ Console.WriteLine($"did login work? {await plaza.Login(c.UserName, c.Password)}");
+ Console.WriteLine($"can validate? {await plaza.CheckSession()}");
+#if DEBUG
+ Console.WriteLine($"token is {plaza.GetAuthorizationToken()}");
+#endif
+ btLogin.IsEnabled = false;
+ btLogin.Visibility = Visibility.Hidden;
+ imLogin.IsEnabled = false;
+ imLogin.Visibility = Visibility.Hidden;
+ }
+ private async void BtLike_Click(object sender, RoutedEventArgs e) {
+ if(await plaza.CastVote(Nightwave.Vote.Like))
+ SetStatus("Song liked!");
+ else
+ SetStatus("Something went weird while liking");
+ _ = Dispatcher.BeginInvoke(new dgtBool(dgtRefresh), true);
+ }
+ private async void BtDislike_Click(object sender, RoutedEventArgs e) {
+ if(await plaza.CastVote(Nightwave.Vote.Dislike))
+ SetStatus("Song disliked!");
+ else
+ SetStatus("Something went weird while disliking");
+ _ = Dispatcher.BeginInvoke(new dgtBool(dgtRefresh), true);
+ }
+ private void SbOnTop_Click(object sender, RoutedEventArgs e) {
+ Topmost = sbOnTop.IsChecked == true;
+ if(tGfx.Enabled)
+ tGfx.Interval = 1000.0 / 60.0;
+ }
private void TbPlayPause_Click(object sender, EventArgs e) =>
btPlayPause.IsChecked = !btPlayPause.IsChecked;
private void TbMute_Click(object sender, EventArgs e) =>
- SbMute_Click(sender, new RoutedEventArgs());
+ sbMute.IsChecked = !sbMute.IsChecked;
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
tRefresh.Stop();
if(AudioInit) {
@@ -168,7 +225,7 @@ namespace WinPlaza {
}
}
private void Window_Deactivated(object sender, EventArgs e) {
- if(tGfx.Enabled)
+ if(tGfx.Enabled && !Topmost)
tGfx.Interval = 1000.0 / 25.0;
}
private void Window_Activated(object sender, EventArgs e) {
@@ -182,6 +239,9 @@ namespace WinPlaza {
tRefresh = new Timer(300) { AutoReset = true };
tRefresh.Elapsed += EvtRefresh;
tRefresh.Start();
+ tLogon = new Timer(1000) { AutoReset = false };
+ tLogon.Elapsed += EvtLogon;
+ tLogon.Start();
if(!Bass.Init())
sbStatus.Text = "Unable to initialise audio subsystem";
else
@@ -195,6 +255,7 @@ namespace WinPlaza {
Bass.NetPlaylist = 1;
Bass.NetPreBuffer = 0;
}
+
~MainWindow() {
if(AudioInit)
_ = Bass.Free();
@@ -202,5 +263,6 @@ namespace WinPlaza {
private void _Status(string s) => sbStatus.Text = s;
private void _Title(string s) => Title = s;
#endregion
+
}
}
diff --git a/WinPlaza/SNSigningKey.snk b/WinPlaza/SNSigningKey.snk
new file mode 100644
index 0000000..84a38fb
Binary files /dev/null and b/WinPlaza/SNSigningKey.snk differ
diff --git a/WinPlaza/WinPlaza.csproj b/WinPlaza/WinPlaza.csproj
index ad3f147..01471ab 100644
--- a/WinPlaza/WinPlaza.csproj
+++ b/WinPlaza/WinPlaza.csproj
@@ -31,7 +31,7 @@
true
index.html
false
- 1
+ 2
1.4.0.%2a
false
true
@@ -73,7 +73,7 @@
true
- false
+ true
WinPlaza.App
@@ -81,6 +81,12 @@
app.manifest
+
+ false
+
+
+ SNSigningKey.snk
+
..\packages\ManagedBass.2.0.4\lib\net45\ManagedBass.dll
@@ -88,6 +94,9 @@
..\packages\ManagedBass.Opus.2.0.0\lib\netstandard1.4\ManagedBass.Opus.dll
+
+ ..\packages\Meziantou.Framework.Win32.CredentialManager.1.3.4\lib\net461\Meziantou.Framework.Win32.CredentialManager.dll
+
..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll
@@ -140,6 +149,7 @@
SettingsSingleFileGenerator
Settings.Designer.cs
+
diff --git a/WinPlaza/packages.config b/WinPlaza/packages.config
index 9c116c3..b59557a 100644
--- a/WinPlaza/packages.config
+++ b/WinPlaza/packages.config
@@ -2,5 +2,6 @@
+
\ No newline at end of file
diff --git a/libplaza/Main.cs b/libplaza/Main.cs
index c3b1c0d..85d93bc 100644
--- a/libplaza/Main.cs
+++ b/libplaza/Main.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
@@ -27,12 +28,35 @@ namespace libplaza {
[JsonProperty]
public PlazaPlayback playback;
}
+ public class PlazaUser {
+ public int id;
+ public string username;
+ public string email;
+ public int role;
+ public string created_at;
+ }
+ public class PlazaVote {
+ public string status;
+ public int[] ratings;
+ }
+ public class PlazaLogonResult {
+ public string status;
+ public string username;
+ public string email;
+ public string token;
+ }
internal class PlazaInMaintenanceException : Exception { }
internal class PlazaUnavailableException : Exception { }
public class Nightwave {
public int MinRefreshTime=10;
private long tsLastRefresh=0;
private static HttpClient _hcl=new HttpClient();
+ public enum Vote {
+ Dislike=-1,
+ Neutral,
+ Like,
+ Favourite
+ }
public enum BroadcastStatus {
OffAir,
OnAir
@@ -55,6 +79,7 @@ namespace libplaza {
public BroadcastStatus Broadcasting=BroadcastStatus.OffAir;
public Nightwave() {
_hcl.BaseAddress = new Uri(PlazaApi.ApiBase);
+ _hcl.Timeout = TimeSpan.FromSeconds(2);
_hcl.DefaultRequestHeaders.Accept.Clear();
_hcl.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
@@ -77,7 +102,6 @@ namespace libplaza {
tsLastRefresh = DateTimeOffset.Now.ToUnixTimeSeconds();
return _bc;
}
-
public async void Update() {
try {
Status _=await GetNightwaveAsync();
@@ -117,5 +141,56 @@ namespace libplaza {
status.CalculatedElapsed = (int)(DateTimeOffset.Now.ToUnixTimeSeconds() - status.ServerTimeOffset - j.playback.updated) + j.playback.position;
return status;
}
+ public async Task CastVote(Vote v) {
+ if(!await CheckSession())
+ return false;
+ HttpResponseMessage _r=await _hcl.PostAsync("/vote", new FormUrlEncodedContent(new[] {
+ new KeyValuePair("rate", ((int)v).ToString())}));
+ if(!_r.IsSuccessStatusCode)
+ return false;
+ PlazaVote r=JsonConvert.DeserializeObject(await _r.Content.ReadAsStringAsync());
+ if(r.status != "success")
+ return false;
+ return true;
+ }
+ public async Task CheckSession(string str) {
+ _=_hcl.DefaultRequestHeaders.Remove("X-Access-Token");
+ _hcl.DefaultRequestHeaders.Add("X-Access-Token", str);
+ return await CheckSession();
+ }
+ public async Task CheckSession() {
+ if(await GetUser() != null)
+ return true;
+ return false;
+ }
+ public async Task GetUser() {
+ HttpResponseMessage _r=await _hcl.GetAsync("/user");
+ if(!_r.IsSuccessStatusCode)
+ return null;
+ PlazaUser r=JsonConvert.DeserializeObject(await _r.Content.ReadAsStringAsync());
+ if(r.id <= 0)
+ return null;
+ return r.username;
+ }
+ public async Task Login(string u, string p) => await Login(Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{u}:{p}")));
+ public async Task Login(string str) {
+ _hcl.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", str);
+ HttpResponseMessage _r=await _hcl.PostAsync("/user/login", null);
+ if(!_r.IsSuccessStatusCode)
+ return false;
+ PlazaLogonResult r=JsonConvert.DeserializeObject(await _r.Content.ReadAsStringAsync());
+ if(r.status != "success")
+ return false;
+ _hcl.DefaultRequestHeaders.Add("X-Access-Token", r.token);
+ _=_hcl.DefaultRequestHeaders.Remove("Authorization");
+ return true;
+ }
+#if DEBUG
+ public string GetAuthorizationToken() {
+ IEnumerator h=_hcl.DefaultRequestHeaders.GetValues("X-Access-Token").GetEnumerator();
+ _ = h.MoveNext();
+ return h.Current;
+ }
+#endif
}
}