Refactored to only having one executor per platform

This commit is contained in:
watsonb8 2019-07-05 11:37:44 -04:00
parent 0cb0546741
commit a01d399a1f
18 changed files with 226 additions and 170 deletions

View File

@ -1,94 +1,52 @@
<Project
Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<ProduceAssemblyReference>true</ProduceAssemblyReference>
</PropertyGroup>
<PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<PackageReference
Include="Xamarin.Forms"
Version="3.6.0.264807"/>
<PackageReference
Include="Xamarin.Essentials"
Version="1.0.1"/>
<PackageReference
Include="Xamarin.Forms.DataGrid"
Version="3.1.0"/>
<PackageReference
Include="taglib-sharp-netstandard2.0"
Version="2.1.0"/>
<PackageReference
Include="LibVLCSharp.Forms"
Version="3.0.0"/>
<PackageReference
Include="VideoLAN.LibVLC.Mac"
Version="3.1.3"/>
<PackageReference
Include="Grpc"
Version="1.21.0"/>
<PackageReference
Include="Grpc.Tools"
Version="1.21.0"
PrivateAssests="All"/>
<PackageReference
Include="Google.Protobuf"
Version="3.8.0"/>
<PackageReference Include="Xamarin.Forms" Version="3.6.0.264807" />
<PackageReference Include="Xamarin.Essentials" Version="1.0.1" />
<PackageReference Include="Xamarin.Forms.DataGrid" Version="3.1.0" />
<PackageReference Include="taglib-sharp-netstandard2.0" Version="2.1.0" />
<PackageReference Include="LibVLCSharp.Forms" Version="3.0.0" />
<PackageReference Include="VideoLAN.LibVLC.Mac" Version="3.1.3" />
<PackageReference Include="Grpc" Version="1.21.0" />
<PackageReference Include="Grpc.Tools" Version="1.21.0" PrivateAssests="All" />
<PackageReference Include="Google.Protobuf" Version="3.8.0" />
</ItemGroup>
<ItemGroup>
<Folder
Include="Frontend\"/>
<Folder
Include="Backend\"/>
<Folder
Include="Frontend\Components\"/>
<Folder
Include="Frontend\Views\"/>
<Folder
Include="Frontend\Views\Songs\"/>
<Folder
Include="Frontend\Views\MainView\"/>
<Folder
Include="Frontend\Behaviors\"/>
<Folder
Include="Frontend\Components\NavigationMenu\"/>
<Folder
Include="Frontend\Views\Albums\"/>
<Folder
Include="Frontend\Views\Artists\"/>
<Folder
Include="Frontend\Views\Stations\"/>
<Folder
Include="Backend\Utils\"/>
<Folder
Include="Backend\Models\"/>
<Folder
Include="Backend\Services\"/>
<Folder
Include="Frontend\Views\Party\"/>
<Folder
Include="Frontend\Components\HostSelector\"/>
<Folder
Include="Frontend\Components\MemberList\"/>
<Folder
Include="Frontend\Components\Queue\"/>
<Folder Include="Frontend\" />
<Folder Include="Backend\" />
<Folder Include="Frontend\Components\" />
<Folder Include="Frontend\Views\" />
<Folder Include="Frontend\Views\Songs\" />
<Folder Include="Frontend\Views\MainView\" />
<Folder Include="Frontend\Behaviors\" />
<Folder Include="Frontend\Components\NavigationMenu\" />
<Folder Include="Frontend\Views\Albums\" />
<Folder Include="Frontend\Views\Artists\" />
<Folder Include="Frontend\Views\Stations\" />
<Folder Include="Backend\Utils\" />
<Folder Include="Backend\Models\" />
<Folder Include="Backend\Services\" />
<Folder Include="Frontend\Views\Party\" />
<Folder Include="Frontend\Components\HostSelector\" />
<Folder Include="Frontend\Components\MemberList\" />
<Folder Include="Frontend\Components\Queue\" />
<Folder Include="Frontend\Views\Profile\" />
</ItemGroup>
<ItemGroup>
<Compile
Update="Frontend\Components\MusicPlayer\Player.xaml.cs">
<Compile Update="Frontend\Components\MusicPlayer\Player.xaml.cs">
<DependentUpon>Player.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<Protobuf
Include="Backend\Proto\PartyService\party.proto"/>
<Protobuf
Include="Backend\Proto\PlaybackService\playback.proto"/>
<Protobuf
Include="Backend\Proto\general.proto"/>
<Protobuf Include="Backend\Proto\general.proto" />
<Protobuf Include="Backend\Proto\party.proto" />
<Protobuf Include="Backend\Proto\playback.proto" />
</ItemGroup>
</Project>

View File

@ -6,22 +6,47 @@ namespace Aurora.Backend.Executors
{
public abstract class BaseExecutor
{
public BaseExecutor()
protected BaseExecutor()
{
}
public ExecutorType ExecutorType { get; protected set; }
public Type ExecutorType { get; protected set; }
public static BaseExecutor CreateExecutor<T>(ExecutorType executorType) where T : BaseExecutor
public static BaseExecutor CreateExecutor<T>()
{
MethodInfo method = typeof(T).GetMethod("Create");
if (method == null)
BaseExecutor executor = null;
if (typeof(T) == typeof(HostExecutor))
{
throw new InvalidOperationException("Executor must include a 'create' method.");
executor = new HostExecutor();
executor.ExecutorType = typeof(HostExecutor);
}
else if (typeof(T) == typeof(ClientExecutor))
{
executor = new ClientExecutor();
executor.ExecutorType = typeof(ClientExecutor);
}
else
{
throw new InvalidOperationException("Cannot create an executor of type: " + nameof(T));
}
return method.Invoke(null, new object[] { executorType }) as BaseExecutor;
return executor;
}
public abstract void Initialize();
public abstract void Run();
public abstract void Close();
public abstract void GetMembers();
public abstract void GetQueue();
public abstract void AddToQueue();
public abstract void RemoveFromQueue();
}
public enum ExecutorType

View File

@ -1,51 +0,0 @@
using System;
using Aurora.Backend.Server.Party;
using Aurora.Backend.Client.Party;
namespace Aurora.Backend.Executors
{
public abstract class BasePartyExecutor : BaseExecutor
{
public BasePartyExecutor()
{
}
public static BasePartyExecutor Create(ExecutorType type)
{
BasePartyExecutor executor = null;
switch (type)
{
case ExecutorType.Client:
{
executor = new ClientPartyExecutor();
executor.ExecutorType = type;
break;
}
case ExecutorType.Server:
{
executor = new HostPartyExecutor();
executor.ExecutorType = type;
break;
}
}
return executor;
}
public abstract void Initialize();
public abstract void Run();
public abstract void Close();
public abstract void GetMembers();
public abstract void GetQueue();
public abstract void AddToQueue();
public abstract void RemoveFromQueue();
}
}

View File

@ -1,11 +1,11 @@
using System;
using Aurora.Backend.Executors;
namespace Aurora.Backend.Client.Party
namespace Aurora.Backend.Executors
{
public class ClientPartyExecutor : BasePartyExecutor
public class ClientExecutor : BaseExecutor
{
public ClientPartyExecutor()
public ClientExecutor()
{
}

View File

@ -3,20 +3,25 @@ using System.Threading.Tasks;
using Aurora.Backend.Executors;
using Aurora.Backend.Services;
using Aurora.Backend.Proto;
using Aurora.Backend.RemoteImpl;
namespace Aurora.Backend.Server.Party
namespace Aurora.Backend.Executors
{
public class HostPartyExecutor : BasePartyExecutor
public class HostExecutor : BaseExecutor
{
PartyServiceImpl _partyServiceImpl;
public HostPartyExecutor()
RemotePartyServiceImpl _remoteServiceImpl;
RemotePlaybackServiceImpl _remotePlaybackImpl;
public HostExecutor()
{
_partyServiceImpl = new PartyServiceImpl();
_remoteServiceImpl = new RemotePartyServiceImpl();
}
public override void Initialize()
{
ServerService.Instance.RegisterService(PartyService.BindService(_partyServiceImpl));
//Register grpc RemoteService with singleton server service
ServerService.Instance.RegisterService(RemotePartyService.BindService(_remoteServiceImpl));
ServerService.Instance.RegisterService(RemotePlaybackService.BindService(_remotePlaybackImpl));
}
public override async void Close()

View File

@ -2,8 +2,9 @@ syntax = "proto3";
package Aurora.Backend.Proto;
// PartyServic definition
service PartyService{
import "Backend/Proto/general.proto";
service RemotePartyService {
//Party Service
rpc JoinParty(JoinPartyRequest) returns (JoinPartyResponse);
rpc LeaveParty(LeavePartyRequest) returns (LeavePartyResponse);

View File

@ -4,7 +4,7 @@ package Aurora.Backend.Proto;
import "Backend/Proto/general.proto";
service PlaybackService {
service RemotePlaybackService {
//Playback Service
rpc GetPartyStream(Empty) returns (stream Chunk) {};
}

View File

@ -4,16 +4,16 @@ using System.Collections.Generic;
using Aurora.Backend.Proto;
using Aurora.Backend.Models;
namespace Aurora.Backend.Server.Party
namespace Aurora.Backend.RemoteImpl
{
class PartyServiceImpl : PartyService.PartyServiceBase
public class RemotePartyServiceImpl : RemotePartyService.RemotePartyServiceBase
{
/// <summary>
/// Dictionary of party members. Key -> ClientId
/// </summary>
private Dictionary<string, PartyMember> _partyMembers;
public PartyServiceImpl()
public RemotePartyServiceImpl()
{
_partyMembers = new Dictionary<string, PartyMember>();
}

View File

@ -0,0 +1,32 @@
using System;
using System.Threading.Tasks;
using System.IO;
using Aurora.Backend.Proto;
using Aurora.Backend.Models;
namespace Aurora.Backend.RemoteImpl
{
public class RemotePlaybackServiceImpl : RemotePlaybackService.RemotePlaybackServiceBase
{
public override async Task GetPartyStream(Empty empty,
Grpc.Core.IServerStreamWriter<Chunk> responseStream,
Grpc.Core.ServerCallContext context)
{
throw new NotImplementedException("Working on it");
// //Send stream
// string cwd = Directory.GetCurrentDirectory();
// using (FileStream fs = System.IO.File.OpenRead(Path.Combine(cwd, request.FileName)))
// {
// Console.WriteLine("Begin sending file");
// byte[] buffer = new byte[2048]; // read in chunks of 2KB
// int bytesRead;
// while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
// {
// Google.Protobuf.ByteString bufferByteString = Google.Protobuf.ByteString.CopyFrom(buffer);
// await responseStream.WriteAsync(new Chunk { Content = bufferByteString });
// }
// Console.WriteLine("Done sending file");
// };
}
}
}

View File

@ -1,10 +0,0 @@
using System;
using Aurora.Backend.Proto;
namespace Aurora.Backend.Server
{
class PlaybackServiceImpl : PlaybackService.PlaybackServiceBase
{
}
}

View File

@ -7,7 +7,8 @@ namespace Aurora.Backend.Services
{
public class ServerService : BaseService<ServerService>
{
private const int Port = 50051;
private string _hostname = "127.0.0.1";
private int _port = 50001;
private Grpc.Core.Server _server;
/// <summary>
@ -15,12 +16,16 @@ namespace Aurora.Backend.Services
/// </summary>
public ServerService()
{
}
public void Initialize(string hostname, int port)
{
this._port = port;
this._hostname = hostname;
_server = new Grpc.Core.Server
{
Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
Ports = { new ServerPort(_hostname, _port, ServerCredentials.Insecure) }
};
Start();
}
/// <summary>
@ -28,8 +33,16 @@ namespace Aurora.Backend.Services
/// </summary>
public void Start()
{
try
{
Console.WriteLine(string.Format("Starting gRPC server at hostname: {0}, port: {1}", _hostname, _port));
_server.Start();
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Error starting gRPC server: {0}", ex.Message));
}
}
/// <summary>
/// Shutdown server async.
@ -45,7 +58,7 @@ namespace Aurora.Backend.Services
await Stop();
_server = new Grpc.Core.Server
{
Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
Ports = { new ServerPort("localhost", _port, ServerCredentials.Insecure) }
};
}

View File

@ -0,0 +1,36 @@
using System;
using Xamarin.Forms;
namespace Aurora.Backend.Services
{
public class SettingsService : BaseService<SettingsService>
{
private string _usernameKey = "Username";
public SettingsService()
{
}
public string Username
{
get
{
if (!Application.Current.Properties.ContainsKey(_usernameKey))
{
return "";
}
Application.Current.Properties.TryGetValue(_usernameKey, out object val);
return val as string;
}
set
{
if (Application.Current.Properties.ContainsKey(_usernameKey))
{
Application.Current.Properties.Remove(_usernameKey);
}
Application.Current.Properties.Add(_usernameKey, value);
}
}
}
}

View File

@ -110,7 +110,7 @@ namespace Aurora.Frontend.Components.HostSelector
{
string newVal = newValue as string;
HostSelector instance = bindable as HostSelector;
if (instance.HostnameEntry.Text != newValue)
if (instance.HostnameEntry.Text != newVal)
{
instance.HostnameEntry.Text = newVal;
}

View File

@ -8,6 +8,7 @@ using Aurora.Frontend.Views.Artists;
using Aurora.Frontend.Views.Songs;
using Aurora.Frontend.Views.Stations;
using Aurora.Frontend.Views.Party;
using Aurora.Frontend.Views.Profile;
namespace Aurora.Frontend.Views.MainView
{
@ -32,7 +33,7 @@ namespace Aurora.Frontend.Views.MainView
_pages = new ObservableCollection<NavigationItem>(new[]
{
new NavigationItem { Id = 4, Title = "Party", Group="Social", TargetType = typeof(PartyView)},
new NavigationItem { Id = 5, Title = "Profile", Group="Social", TargetType = typeof(ArtistsView)},
new NavigationItem { Id = 5, Title = "Profile", Group="Social", TargetType = typeof(ProfileView)},
new NavigationItem { Id = 0, Title = "Songs", Group="Library", TargetType = typeof(SongsView) },
new NavigationItem { Id = 1, Title = "Artists", Group="Library", TargetType = typeof(ArtistsView)},
new NavigationItem { Id = 2, Title = "Albums", Group="Library", TargetType = typeof(AlbumsView)},

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.ObjectModel;
using Aurora.Backend.Executors;
using Aurora.Frontend.Components.HostSelector;
using Aurora.Backend.Services;
using Xamarin.Forms;
namespace Aurora.Frontend.Views.Party
@ -19,7 +20,7 @@ namespace Aurora.Frontend.Views.Party
private PartyState _state;
private BasePartyExecutor _executor;
private BaseExecutor _executor;
private string _hostname;
@ -91,7 +92,9 @@ namespace Aurora.Frontend.Views.Party
#region Commands
private void OnJoinExecute()
{
_executor = BaseExecutor.CreateExecutor<BasePartyExecutor>(ExecutorType.Client) as BasePartyExecutor;
_executor = BaseExecutor.CreateExecutor<ClientExecutor>();
Int32.TryParse(this.Port, out int intPort);
_executor.Initialize();
State(PartyState.Connecting);
}
@ -102,7 +105,19 @@ namespace Aurora.Frontend.Views.Party
private void OnHostExecute()
{
_executor = BaseExecutor.CreateExecutor<BasePartyExecutor>(ExecutorType.Server) as BasePartyExecutor;
Int32.TryParse(this.Port, out int intPort);
//Init gRPC server
ServerService.Instance.Initialize(this.Hostname, intPort);
//Instantiate and initialize all executors
_executor = BaseExecutor.CreateExecutor<HostExecutor>();
_executor.Initialize();
//start gRPC server
ServerService.Instance.Start();
//Change state
State(PartyState.Connecting);
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Aurora.Frontend.Views.Profile.ProfileView">
<ContentView.Content>
<Label Text="This is a profile"/>
</ContentView.Content>
</ContentView>

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace Aurora.Frontend.Views.Profile
{
public partial class ProfileView : ContentView
{
public ProfileView()
{
InitializeComponent();
BindingContext = new ProfileViewModel();
}
}
}

View File

@ -0,0 +1,10 @@
using System;
namespace Aurora.Frontend.Views.Profile
{
public class ProfileViewModel
{
public ProfileViewModel()
{
}
}
}