diff --git a/Aurora.gtk/LibVLCSharp.GTK.dll.config b/Aurora.gtk/LibVLCSharp.GTK.dll.config
index 10de482..781c4ac 100644
--- a/Aurora.gtk/LibVLCSharp.GTK.dll.config
+++ b/Aurora.gtk/LibVLCSharp.GTK.dll.config
@@ -1,26 +1,91 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration>
-    <dllmap os="linux" dll="opengl32.dll" target="libGL.so.1" />
-    <dllmap os="linux" dll="glu32.dll" target="libGLU.so.1" />
-    <dllmap os="linux" dll="openal32.dll" target="libopenal.so.1" />
-    <dllmap os="linux" dll="alut.dll" target="libalut.so.0" />
-    <dllmap os="linux" dll="opencl.dll" target="libOpenCL.so" />
-    <dllmap os="linux" dll="libX11" target="libX11.so.6" />
-    <dllmap os="linux" dll="libXi" target="libXi.so.6" />
-    <dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0" />
-    <dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL" />
-    <dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
-    <dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
-    <dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
-    <dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
-    <dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
-    <dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL" />
-    <dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib" />
-    <!-- XQuartz compatibility (X11 on Mac) -->
-    <dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib" />
-    <dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib" />
-    <dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib" />
-    <dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib" />
-    <dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib" />
-    <dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib" />
+    <dllmap
+         os="linux"
+         dll="opengl32.dll"
+         target="libGL.so.1"/>
+    <dllmap
+         os="linux"
+         dll="glu32.dll"
+         target="libGLU.so.1"/>
+    <dllmap
+         os="linux"
+         dll="openal32.dll"
+         target="libopenal.so.1"/>
+    <dllmap
+         os="linux"
+         dll="alut.dll"
+         target="libalut.so.0"/>
+    <dllmap
+         os="linux"
+         dll="opencl.dll"
+         target="libOpenCL.so"/>
+    <dllmap
+         os="linux"
+         dll="libX11"
+         target="libX11.so.6"/>
+    <dllmap
+         os="linux"
+         dll="libXi"
+         target="libXi.so.6"/>
+    <dllmap
+         os="linux"
+         dll="SDL2.dll"
+         target="libSDL2-2.0.so.0"/>
+    <dllmap
+         os="osx"
+         dll="opengl32.dll"
+         target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
+    <dllmap
+         os="osx"
+         dll="openal32.dll"
+         target="/System/Library/Frameworks/OpenAL.framework/OpenAL"/>
+    <dllmap
+         os="osx"
+         dll="alut.dll"
+         target="/System/Library/Frameworks/OpenAL.framework/OpenAL"/>
+    <dllmap
+         os="osx"
+         dll="libGLES.dll"
+         target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES"/>
+    <dllmap
+         os="osx"
+         dll="libGLESv1_CM.dll"
+         target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES"/>
+    <dllmap
+         os="osx"
+         dll="libGLESv2.dll"
+         target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES"/>
+    <dllmap
+         os="osx"
+         dll="opencl.dll"
+         target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
+    <dllmap
+         os="osx"
+         dll="SDL2.dll"
+         target="libSDL2.dylib"/><!-- XQuartz compatibility (X11 on Mac) -->
+    <dllmap
+         os="osx"
+         dll="libGL.so.1"
+         target="/usr/X11/lib/libGL.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libX11"
+         target="/usr/X11R6/lib/libX11.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXcursor.so.1"
+         target="/usr/X11/lib/libXcursor.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXi"
+         target="/usr/X11/lib/libXi.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXinerama"
+         target="/usr/X11/lib/libXinerama.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXrandr.so.2"
+         target="/usr/X11/lib/libXrandr.dylib"/>
 </configuration>
\ No newline at end of file
diff --git a/Aurora.gtk/LibVLCSharp.dll.config b/Aurora.gtk/LibVLCSharp.dll.config
index 10de482..781c4ac 100644
--- a/Aurora.gtk/LibVLCSharp.dll.config
+++ b/Aurora.gtk/LibVLCSharp.dll.config
@@ -1,26 +1,91 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration>
-    <dllmap os="linux" dll="opengl32.dll" target="libGL.so.1" />
-    <dllmap os="linux" dll="glu32.dll" target="libGLU.so.1" />
-    <dllmap os="linux" dll="openal32.dll" target="libopenal.so.1" />
-    <dllmap os="linux" dll="alut.dll" target="libalut.so.0" />
-    <dllmap os="linux" dll="opencl.dll" target="libOpenCL.so" />
-    <dllmap os="linux" dll="libX11" target="libX11.so.6" />
-    <dllmap os="linux" dll="libXi" target="libXi.so.6" />
-    <dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0" />
-    <dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL" />
-    <dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
-    <dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
-    <dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
-    <dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
-    <dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
-    <dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL" />
-    <dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib" />
-    <!-- XQuartz compatibility (X11 on Mac) -->
-    <dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib" />
-    <dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib" />
-    <dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib" />
-    <dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib" />
-    <dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib" />
-    <dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib" />
+    <dllmap
+         os="linux"
+         dll="opengl32.dll"
+         target="libGL.so.1"/>
+    <dllmap
+         os="linux"
+         dll="glu32.dll"
+         target="libGLU.so.1"/>
+    <dllmap
+         os="linux"
+         dll="openal32.dll"
+         target="libopenal.so.1"/>
+    <dllmap
+         os="linux"
+         dll="alut.dll"
+         target="libalut.so.0"/>
+    <dllmap
+         os="linux"
+         dll="opencl.dll"
+         target="libOpenCL.so"/>
+    <dllmap
+         os="linux"
+         dll="libX11"
+         target="libX11.so.6"/>
+    <dllmap
+         os="linux"
+         dll="libXi"
+         target="libXi.so.6"/>
+    <dllmap
+         os="linux"
+         dll="SDL2.dll"
+         target="libSDL2-2.0.so.0"/>
+    <dllmap
+         os="osx"
+         dll="opengl32.dll"
+         target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
+    <dllmap
+         os="osx"
+         dll="openal32.dll"
+         target="/System/Library/Frameworks/OpenAL.framework/OpenAL"/>
+    <dllmap
+         os="osx"
+         dll="alut.dll"
+         target="/System/Library/Frameworks/OpenAL.framework/OpenAL"/>
+    <dllmap
+         os="osx"
+         dll="libGLES.dll"
+         target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES"/>
+    <dllmap
+         os="osx"
+         dll="libGLESv1_CM.dll"
+         target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES"/>
+    <dllmap
+         os="osx"
+         dll="libGLESv2.dll"
+         target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES"/>
+    <dllmap
+         os="osx"
+         dll="opencl.dll"
+         target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
+    <dllmap
+         os="osx"
+         dll="SDL2.dll"
+         target="libSDL2.dylib"/><!-- XQuartz compatibility (X11 on Mac) -->
+    <dllmap
+         os="osx"
+         dll="libGL.so.1"
+         target="/usr/X11/lib/libGL.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libX11"
+         target="/usr/X11R6/lib/libX11.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXcursor.so.1"
+         target="/usr/X11/lib/libXcursor.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXi"
+         target="/usr/X11/lib/libXi.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXinerama"
+         target="/usr/X11/lib/libXinerama.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXrandr.so.2"
+         target="/usr/X11/lib/libXrandr.dylib"/>
 </configuration>
\ No newline at end of file
diff --git a/Aurora.gtk/OpenTK.dll.config b/Aurora.gtk/OpenTK.dll.config
index 716277d..ca5c33c 100644
--- a/Aurora.gtk/OpenTK.dll.config
+++ b/Aurora.gtk/OpenTK.dll.config
@@ -1,26 +1,91 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration>
-    <dllmap os="linux" dll="opengl32.dll" target="libGL.so.1" />
-    <dllmap os="linux" dll="glu32.dll" target="libGLU.so.1" />
-    <dllmap os="linux" dll="openal32.dll" target="libopenal.so.1" />
-    <dllmap os="linux" dll="alut.dll" target="libalut.so.0" />
-    <dllmap os="linux" dll="opencl.dll" target="libOpenCL.so" />
-    <dllmap os="linux" dll="libX11" target="libX11.so.6" />
-    <dllmap os="linux" dll="libXi" target="libXi.so.6" />
-    <dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0" />
-    <dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL" />
-    <dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
-    <dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
-    <dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
-    <dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
-    <dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
-    <dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL" />
-    <dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib" />
-    <!-- XQuartz compatibility (X11 on Mac) -->
-    <dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib" />
-    <dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib" />
-    <dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib" />
-    <dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib" />
-    <dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib" />
-    <dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib" />
+    <dllmap
+         os="linux"
+         dll="opengl32.dll"
+         target="libGL.so.1"/>
+    <dllmap
+         os="linux"
+         dll="glu32.dll"
+         target="libGLU.so.1"/>
+    <dllmap
+         os="linux"
+         dll="openal32.dll"
+         target="libopenal.so.1"/>
+    <dllmap
+         os="linux"
+         dll="alut.dll"
+         target="libalut.so.0"/>
+    <dllmap
+         os="linux"
+         dll="opencl.dll"
+         target="libOpenCL.so"/>
+    <dllmap
+         os="linux"
+         dll="libX11"
+         target="libX11.so.6"/>
+    <dllmap
+         os="linux"
+         dll="libXi"
+         target="libXi.so.6"/>
+    <dllmap
+         os="linux"
+         dll="SDL2.dll"
+         target="libSDL2-2.0.so.0"/>
+    <dllmap
+         os="osx"
+         dll="opengl32.dll"
+         target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
+    <dllmap
+         os="osx"
+         dll="openal32.dll"
+         target="/System/Library/Frameworks/OpenAL.framework/OpenAL"/>
+    <dllmap
+         os="osx"
+         dll="alut.dll"
+         target="/System/Library/Frameworks/OpenAL.framework/OpenAL"/>
+    <dllmap
+         os="osx"
+         dll="libGLES.dll"
+         target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES"/>
+    <dllmap
+         os="osx"
+         dll="libGLESv1_CM.dll"
+         target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES"/>
+    <dllmap
+         os="osx"
+         dll="libGLESv2.dll"
+         target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES"/>
+    <dllmap
+         os="osx"
+         dll="opencl.dll"
+         target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
+    <dllmap
+         os="osx"
+         dll="SDL2.dll"
+         target="libSDL2.dylib"/><!-- XQuartz compatibility (X11 on Mac) -->
+    <dllmap
+         os="osx"
+         dll="libGL.so.1"
+         target="/usr/X11/lib/libGL.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libX11"
+         target="/usr/X11R6/lib/libX11.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXcursor.so.1"
+         target="/usr/X11/lib/libXcursor.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXi"
+         target="/usr/X11/lib/libXi.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXinerama"
+         target="/usr/X11/lib/libXinerama.dylib"/>
+    <dllmap
+         os="osx"
+         dll="libXrandr.so.2"
+         target="/usr/X11/lib/libXrandr.dylib"/>
 </configuration>
\ No newline at end of file
diff --git a/Aurora/Design/Views/Albums/AlbumsViewModel.cs b/Aurora/Design/Views/Albums/AlbumsViewModel.cs
index 9c50673..56dda23 100644
--- a/Aurora/Design/Views/Albums/AlbumsViewModel.cs
+++ b/Aurora/Design/Views/Albums/AlbumsViewModel.cs
@@ -1,7 +1,7 @@
 using System;
 namespace Aurora.Design.Views.Albums
 {
-    public class AlbumsViewModel
+    public class AlbumsViewModel : BaseViewModel
     {
         public AlbumsViewModel()
         {
diff --git a/Aurora/Design/Views/Party/PartyViewModel.cs b/Aurora/Design/Views/Party/PartyViewModel.cs
index 54dd646..9ff2c46 100644
--- a/Aurora/Design/Views/Party/PartyViewModel.cs
+++ b/Aurora/Design/Views/Party/PartyViewModel.cs
@@ -10,6 +10,7 @@ using Aurora.Proto.General;
 using Aurora.Proto.Party;
 using Aurora.Proto.Playback;
 using Aurora.Proto.Events;
+using Aurora.Services.ClientService;
 
 namespace Aurora.Design.Views.Party
 {
@@ -26,14 +27,6 @@ namespace Aurora.Design.Views.Party
         private string _hostname;
         private ObservableCollection<PartyMember> _members;
 
-        //Client fields
-        private Channel _channel;
-        private RemotePartyService.RemotePartyServiceClient _remotePartyClient;
-        private RemotePlaybackService.RemotePlaybackServiceClient _remotePlaybackClient;
-        private RemoteEventService.RemoteEventServiceClient _remoteEventsClient;
-        CancellationTokenSource _eventCancellationTokenSource;
-
-
         public PartyViewModel()
         {
             this.JoinCommand = new Command(OnJoinExecute, CanJoinExecute);
@@ -42,11 +35,14 @@ namespace Aurora.Design.Views.Party
             _members = new ObservableCollection<PartyMember>();
 
             SetState(PartyState.SelectingHost);
+
+            //Hook up event handler
+            ClientService.Instance.EventReceived += this.OnEventReceived;
         }
 
         ~PartyViewModel()
         {
-            Task.Run(ServerService.Instance.Stop);
+            //Task.Run(ServerService.Instance.Stop);
         }
 
         #region Properties
@@ -84,11 +80,55 @@ namespace Aurora.Design.Views.Party
 
         #endregion Properties
 
-        #region Commands
-        private void OnJoinExecute()
+        #region Events
+        /// <summary>
+        /// An event handler for the client receiving update events
+        /// </summary>
+        /// <param name="sender">The object that sent the event</param>
+        /// <param name="eventArgs">The event arguments</param>
+        public void OnEventReceived(object sender, EventReceivedEventArgs eventArgs)
         {
-            InitializeClients(Hostname, SettingsService.Instance.DefaultPort.ToString());
-            JoinParty();
+            switch (eventArgs.BaseEvent.DerivedEventCase)
+            {
+                case BaseEvent.DerivedEventOneofCase.None:
+                    {
+                        throw new InvalidOperationException();
+                    }
+                case BaseEvent.DerivedEventOneofCase.PartyMemberJoinedEvent:
+                    {
+                        PartyMemberJoinedEvent derivedEvent = eventArgs.BaseEvent.PartyMemberJoinedEvent;
+                        PartyMember member = new PartyMember
+                        {
+                            UserName = derivedEvent.Member.UserName,
+                            Id = derivedEvent.Member.Id,
+                            IpAddress = derivedEvent.Member.IpAddress,
+                            Port = derivedEvent.Member.Port
+                        };
+
+                        AddMember(member);
+
+                        break;
+                    }
+                case BaseEvent.DerivedEventOneofCase.PartyMemberLeftEvent:
+                    {
+                        PartyMemberJoinedEvent derivedEvent = eventArgs.BaseEvent.PartyMemberJoinedEvent;
+                        var found = Members.Where(x => x.Id == derivedEvent.Member.Id);
+                        foreach (PartyMember member in found)
+                        {
+                            _members.Remove(member);
+                        }
+                        break;
+                    }
+            }
+        }
+
+        #endregion Events
+
+        #region Commands
+        private async void OnJoinExecute()
+        {
+            ClientService.Instance.Start(Hostname, SettingsService.Instance.DefaultPort.ToString());
+            await JoinParty();
 
             SetState(PartyState.Connecting);
         }
@@ -98,12 +138,14 @@ namespace Aurora.Design.Views.Party
             return true;
         }
 
-        private void OnHostExecute()
+        private async void OnHostExecute()
         {
             ServerService.Instance.Start();
             string localHost = ServerService.GetLocalIPAddress();
-            InitializeClients(localHost, SettingsService.Instance.DefaultPort.ToString());
-            JoinParty();
+            ClientService.Instance.Start(localHost, SettingsService.Instance.DefaultPort.ToString());
+            await JoinParty();
+
+            ClientService.Instance.GetEvents();
 
             //Change state
             SetState(PartyState.Connecting);
@@ -118,55 +160,40 @@ namespace Aurora.Design.Views.Party
         #endregion Commands
 
         #region Private Methods
-
-        private void InitializeClients(string hostname, string port)
-        {
-            _channel = new Channel(string.Format("{0}:{1}", hostname, port), ChannelCredentials.Insecure);
-
-            _remotePartyClient = new RemotePartyService.RemotePartyServiceClient(_channel);
-            _remotePlaybackClient = new RemotePlaybackService.RemotePlaybackServiceClient(_channel);
-            _remoteEventsClient = new RemoteEventService.RemoteEventServiceClient(_channel);
-
-            //Assign but don't start task
-            _eventCancellationTokenSource = new CancellationTokenSource();
-        }
-
         /// <summary>
         /// Join the remote party.
         /// </summary>
         /// <returns></returns>
-        private async void JoinParty()
+        private async Task JoinParty()
         {
-            JoinPartyResponse resp = await _remotePartyClient.JoinPartyAsync(new JoinPartyRequest
-            {
-                UserName = SettingsService.Instance.Username,
-            });
-
-            SettingsService.Instance.ClientId = resp.ClientId;
-
-            RefreshMembers();
-
-            //Subscribe to events
-            SubscribeRequest req = new SubscribeRequest();
-            req.EventTypes.Add(EventType.PartyMemberJoined);
-            req.EventTypes.Add(EventType.PartyMemberLeft);
-            if (!string.IsNullOrWhiteSpace(SettingsService.Instance.ClientId))
-            {
-                req.ClientId = SettingsService.Instance.ClientId;
-            }
-
             try
             {
+                JoinPartyResponse resp = await ClientService.Instance.RemotePartyClient.JoinPartyAsync(new JoinPartyRequest
+                {
+                    UserName = SettingsService.Instance.Username,
+                });
+
+                SettingsService.Instance.ClientId = resp.ClientId;
+
+                RefreshMembers();
+
+                //Subscribe to events
+                SubscribeRequest req = new SubscribeRequest();
+                req.EventTypes.Add(EventType.PartyMemberJoined);
+                req.EventTypes.Add(EventType.PartyMemberLeft);
+                if (!string.IsNullOrWhiteSpace(SettingsService.Instance.ClientId))
+                {
+                    req.ClientId = SettingsService.Instance.ClientId;
+                }
+
+
                 Console.WriteLine(string.Format("CLIENT {0} - SubscribeToEvents called from client with id", SettingsService.Instance.ClientId));
-                _remoteEventsClient.SubscribeToEvents(req);
+                ClientService.Instance.RemoteEventClient.SubscribeToEvents(req);
             }
             catch (Exception ex)
             {
                 Console.WriteLine("Error subscribing to events: " + ex.Message);
             }
-
-            GetEvents();
-
         }
 
         /// <summary>
@@ -174,21 +201,12 @@ namespace Aurora.Design.Views.Party
         /// </summary>
         private void RefreshMembers()
         {
-            MembersResponse response = _remotePartyClient.GetPartyMembers(new Empty());
+            MembersResponse response = ClientService.Instance.RemotePartyClient.GetPartyMembers(new Empty());
             //Add members
             foreach (PartyMember member in response.Members)
             {
                 Members.Add(member);
             }
-
-            //Remove out of date members
-            // foreach (PartyMember member in Members)
-            // {
-            //     if (!response.Members.Contains(member))
-            //     {
-            //         Members.Remove(member);
-            //     }
-            // }
         }
 
         private void SetState(PartyState state)
@@ -203,70 +221,6 @@ namespace Aurora.Design.Views.Party
             Members.Add(member);
         }
 
-
-        /// <summary>
-        /// Asynchronous function for processing events off of the event stream.
-        /// </summary>
-        /// <returns></returns>
-        private async void GetEvents()
-        {
-            Console.WriteLine(string.Format("CLIENT {0} - GetEvents called from client with id", SettingsService.Instance.ClientId));
-            using (AsyncServerStreamingCall<BaseEvent> eventStream = _remoteEventsClient
-                .GetEvents(new EventsRequest { ClientId = SettingsService.Instance.ClientId }))
-            {
-                while (!_eventCancellationTokenSource.Token.IsCancellationRequested &&
-                    await eventStream.ResponseStream.MoveNext(_eventCancellationTokenSource.Token))
-                {
-                    Console.WriteLine(string.Format("CLIENT {0} - Event received for client with id", SettingsService.Instance.ClientId));
-                    try
-                    {
-                        //Convert derived event type
-                        BaseEvent e = new BaseEvent(eventStream.ResponseStream.Current);
-
-                        switch (e.DerivedEventCase)
-                        {
-                            case BaseEvent.DerivedEventOneofCase.None:
-                                {
-                                    throw new InvalidOperationException();
-                                }
-                            case BaseEvent.DerivedEventOneofCase.PartyMemberJoinedEvent:
-                                {
-                                    PartyMemberJoinedEvent derivedEvent = e.PartyMemberJoinedEvent;
-                                    PartyMember member = new PartyMember
-                                    {
-                                        UserName = derivedEvent.Member.UserName,
-                                        Id = derivedEvent.Member.Id,
-                                        IpAddress = derivedEvent.Member.IpAddress,
-                                        Port = derivedEvent.Member.Port
-                                    };
-
-                                    AddMember(member);
-
-                                    break;
-                                }
-                            case BaseEvent.DerivedEventOneofCase.PartyMemberLeftEvent:
-                                {
-                                    PartyMemberJoinedEvent derivedEvent = e.PartyMemberJoinedEvent;
-                                    var found = Members.Where(x => x.Id == derivedEvent.Member.Id);
-                                    foreach (PartyMember member in found)
-                                    {
-                                        _members.Remove(member);
-                                    }
-                                    break;
-                                }
-                        }
-
-                    }
-                    catch (Exception ex)
-                    {
-                        Console.WriteLine(string.Format("EXCEPTION --- " + ex.Message));
-                    }
-
-                    OnPropertyChanged("Members");
-                }
-            }
-        }
-
         #endregion Private Methods
     }
 }
\ No newline at end of file
diff --git a/Aurora/Services/ClientService/ClientService.cs b/Aurora/Services/ClientService/ClientService.cs
new file mode 100644
index 0000000..bbd29a5
--- /dev/null
+++ b/Aurora/Services/ClientService/ClientService.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Threading.Tasks;
+using System.Threading;
+using Grpc.Core;
+using Aurora.Proto.Events;
+using Aurora.Proto.Party;
+using Aurora.Proto.Playback;
+using Aurora.Services.ClientService;
+
+namespace Aurora.Services.ClientService
+{
+    public class ClientService : BaseService<ClientService>
+    {
+        private RemotePartyService.RemotePartyServiceClient _remotePartyClient;
+        private RemotePlaybackService.RemotePlaybackServiceClient _remotePlaybackClient;
+        private RemoteEventService.RemoteEventServiceClient _remoteEventsClient;
+        private Channel _channel;
+        CancellationTokenSource _eventCancellationTokenSource;
+
+        public ClientService()
+        {
+
+        }
+
+        public EventReceivedEventHandler EventReceived;
+
+        public RemotePartyService.RemotePartyServiceClient RemotePartyClient
+        {
+            get
+            {
+                return _remotePartyClient;
+            }
+        }
+
+        public RemotePlaybackService.RemotePlaybackServiceClient RemotePlaybackServiceClient
+        {
+            get
+            {
+                return _remotePlaybackClient;
+            }
+        }
+
+        public RemoteEventService.RemoteEventServiceClient RemoteEventClient
+        {
+            get { return _remoteEventsClient; }
+        }
+
+        public bool IsStarted
+        {
+            get
+            {
+                return _remoteEventsClient != null &&
+                    _remotePartyClient != null &&
+                    _remotePlaybackClient != null;
+            }
+        }
+
+        public void Start(string hostname, string port)
+        {
+            _channel = new Channel(string.Format("{0}:{1}", hostname, port), ChannelCredentials.Insecure);
+
+            _remotePartyClient = new RemotePartyService.RemotePartyServiceClient(_channel);
+            _remotePlaybackClient = new RemotePlaybackService.RemotePlaybackServiceClient(_channel);
+            _remoteEventsClient = new RemoteEventService.RemoteEventServiceClient(_channel);
+
+            //Assign but don't start task
+            _eventCancellationTokenSource = new CancellationTokenSource();
+        }
+
+        public async void Close()
+        {
+            _eventCancellationTokenSource.Cancel();
+            await _channel.ShutdownAsync();
+
+            _remotePartyClient = null;
+            _remotePlaybackClient = null;
+            _remoteEventsClient = null;
+        }
+
+        /// <summary>
+        /// Asynchronous function for processing events off of the event stream.
+        /// </summary>
+        /// <returns></returns>
+        public async Task GetEvents()
+        {
+            string clientId = SettingsService.Instance.ClientId;
+            Console.WriteLine(string.Format("CLIENT {0} - GetEvents called from client with id", clientId));
+            using (AsyncServerStreamingCall<BaseEvent> eventStream = _remoteEventsClient
+                .GetEvents(new EventsRequest { ClientId = SettingsService.Instance.ClientId }))
+            {
+                try
+                {
+                    while (!_eventCancellationTokenSource.Token.IsCancellationRequested &&
+                        await eventStream.ResponseStream.MoveNext(_eventCancellationTokenSource.Token))
+                    {
+                        BaseEvent e = new BaseEvent(eventStream.ResponseStream.Current);
+                        if (this.EventReceived != null)
+                        {
+                            this.EventReceived.Invoke(this, new EventReceivedEventArgs(e));
+                        }
+                    }
+                }
+                catch (Exception ex)
+                {
+                    Console.WriteLine(string.Format("EXCEPTION --- " + ex.Message));
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Aurora/Services/ClientService/EventReceivedEvent.cs b/Aurora/Services/ClientService/EventReceivedEvent.cs
new file mode 100644
index 0000000..18aeb65
--- /dev/null
+++ b/Aurora/Services/ClientService/EventReceivedEvent.cs
@@ -0,0 +1,16 @@
+using System;
+using Aurora.Proto.Events;
+
+namespace Aurora.Services.ClientService
+{
+    public delegate void EventReceivedEventHandler(object sender, EventReceivedEventArgs e);
+
+    public class EventReceivedEventArgs
+    {
+        public BaseEvent BaseEvent { get; private set; }
+        public EventReceivedEventArgs(BaseEvent e)
+        {
+            BaseEvent = e;
+        }
+    }
+}
\ No newline at end of file