using System; using System.Threading.Tasks; using System.Net; using System.Net.Sockets; using Grpc.Core; using Xamarin.Forms; using Aurora.Services.EventManager; using Aurora.Services.Library; using Aurora.Services.Settings; using Aurora.Services; using Aurora.Proto.Party; using Aurora.Models.Media; using Aurora.Services.Controllers; using Aurora.Utils; namespace Aurora.Design.Views.Party { public class HostPartyViewModel : BasePartyViewModel { private IEventManager _eventManager; private ILibraryService _libraryService; private Grpc.Core.Server _server; private RemotePartyController _remotePartyController; private Channel _channel; private int _port = 8080; private bool _isServerStarted = false; public HostPartyViewModel( ISettingsService settingsService, IEventManager eventManager, ILibraryService libraryService, Global global ): base(settingsService, global) { this._eventManager = eventManager; this._global.State = PartyState.Hosting; this._libraryService = libraryService; // Create and start grpc server string host = IpUtil.GetLocalIPAddress(); if(string.IsNullOrWhiteSpace(host)) { // TODO display error to screen throw new System.Exception("This device does not have a valid IP address"); } this._hostname = IpUtil.GetLocalIPAddress(); this.StartServer("test", "test description"); // TODO assign members // TODO assign songList // Register commands PlayCommand = new Command(OnDoubleClickCommandExecute, CanDoubleClickCommandExecute); LeavePartyCommand = new Command(OnLeavePartyCommandExecute, CanLeavePartyCommandExecute); } #region Properties /// /// Public property for playing media command /// /// public Command PlayCommand { get; private set; } /// /// Public property for leave party command /// /// public Command LeavePartyCommand { get; private set; } #endregion Properties /// /// Called by framework when view becomes active /// /// public override Task OnActive() { // Start server if not already started if(!this._isServerStarted) { this._hostname = IpUtil.GetLocalIPAddress(); this.StartServer("test", "test description"); } return Task.FromResult(null); } /// /// Called by framework when view becomes inactive /// /// public override Task OnInactive() { return Task.FromResult(null); } private async void OnLeavePartyCommandExecute() { await this._channel.ShutdownAsync(); await this._server.ShutdownAsync(); this._global.State = PartyState.Idle; this.SetView(typeof(PartyView), typeof(PartyViewModel)); } private bool CanLeavePartyCommandExecute() { return true; } public override void OnPlayButtonCommandExecute() { if (base.IsPlaying()) { //Fire play stopped event AudioMetadata meta = SelectedMedia.Metadata as AudioMetadata; MediaPausedEvent mediaPaused = new MediaPausedEvent(); _eventManager.FireEvent(new BaseEvent() { MediaPausedEvent = mediaPaused }); } else { //Fire play resume event AudioMetadata meta = SelectedMedia.Metadata as AudioMetadata; MediaResumedEvent mediaResumed = new MediaResumedEvent(); _eventManager.FireEvent(new BaseEvent() { MediaResumedEvent = mediaResumed }); } } public override bool CanPlayButtonCommandExecute() { return true; } public override bool CanNextButtonCommandExecute() { return true; } public override bool CanPreviousButtonCommandExecute() { return true; } /// /// On double click execute, fire media playing event /// public void OnDoubleClickCommandExecute() { //Fire Playing event AudioMetadata meta = SelectedMedia.Metadata as AudioMetadata; NewMediaPlayingEvent mediaPlaying = new NewMediaPlayingEvent() { Media = new Media() { //TODO need full resource name Name = SelectedMedia.Id, Title = meta.Title, Artist = meta.Artist, Album = meta.Album, } }; _eventManager.FireEvent(new BaseEvent() { NewMediaPlayingEvent = mediaPlaying }); } public bool CanDoubleClickCommandExecute() { return true; } #region Private Methods private void StartServer(string partyName, string description) { try { // TODO bmw replace with display in UI Console.WriteLine(string.Format("Starting gRPC server at hostname: {0}, port: {1}", _hostname, _port)); _server = new Grpc.Core.Server { Ports = { new ServerPort(_hostname, _port, ServerCredentials.Insecure) } }; //Construct implementations this._remotePartyController = new RemotePartyController( partyName, description, this._libraryService, base._settingsService, _eventManager); // Register grpc RemoteService with singleton server service RemotePartyService.BindService(this._remotePartyController); _server.Start(); this._isServerStarted = true; } catch (Exception ex) { // TODO bmw replace with display in UI Console.WriteLine(string.Format("Error starting gRPC server: {0}", ex.Message)); } } #endregion Private Methods } }