AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
SharingStage.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 using System;
5 using UnityEngine;
7 using HoloToolkit.Unity;
8 
9 namespace HoloToolkit.Sharing
10 {
14  public class SharingStage : Singleton<SharingStage>
15  {
19  public event EventHandler SharingManagerConnected;
20 
24  public event EventHandler SharingManagerDisconnected;
25 
30  private const string DefaultUserName = "User ";
31 
37  public ClientRole ClientRole = ClientRole.Primary;
38 
42  [Tooltip("Address of the sharing server")]
43  public string ServerAddress = "localhost";
44 
48  public string SessionName
49  {
50  get
51  {
52  return Manager.GetSessionManager() != null && Manager.GetSessionManager().GetCurrentSession() != null
53  ? Manager.GetSessionManager().GetCurrentSession().GetName().GetString()
54  : defaultSessionName;
55  }
56  }
57 
58  [SerializeField]
59  [Tooltip("Name of the session to join.")]
60  private string defaultSessionName = "DefaultSession";
61 
65  public string RoomName
66  {
67  get
68  {
69  return CurrentRoomManager != null && CurrentRoomManager.GetCurrentRoom() != null
70  ? CurrentRoomManager.GetCurrentRoom().GetName().GetString()
71  : defaultRoomName;
72  }
73  }
74 
75  [SerializeField]
76  [Tooltip("Name of the room to join.")]
77  private string defaultRoomName = "DefaultRoom";
78 
82  public bool KeepRoomAlive;
83 
87  [Tooltip("Port of the sharing server")]
88  public int ServerPort = 20602;
89 
90  [Tooltip("Should the app connect to the server at startup")]
91  [SerializeField]
92  private bool connectOnAwake = true;
93 
97  public SharingManager Manager { get; private set; }
98 
99  public bool AutoDiscoverServer;
100 
101  [Tooltip("Determines how often the discovery service should ping the network in search of a server.")]
102  public float PingIntervalSec = 2;
103 
107  public bool IsAudioEndpoint = true;
108 
112  private ConsoleLogWriter logWriter;
113 
117  public SyncRoot Root { get; private set; }
118 
124  public ServerSessionsTracker SessionsTracker { get; private set; }
125 
129  public SessionUsersTracker SessionUsersTracker { get; private set; }
130 
134  public SyncStateListener SyncStateListener { get; private set; }
135 
140  public string AppInstanceUniqueId { get; private set; }
141 
145  public event Action<string> UserNameChanged;
146 
150  private DiscoveryClient discoveryClient;
151 
155  private DiscoveryClientAdapter discoveryClientAdapter;
156 
160  private float pingIntervalCurrent;
161 
165  private bool isTryingToFindServer;
166 
170  [Tooltip("Show Detailed Information for sharing services.")]
171  public bool ShowDetailedLogs;
172 
173  public string UserName
174  {
175  get
176  {
177  using (User user = Manager.GetLocalUser())
178  {
179  using (XString userName = user.GetName())
180  {
181  return userName.GetString();
182  }
183  }
184  }
185  set
186  {
187  using (var userName = new XString(value))
188  {
189  Manager.SetUserName(userName);
190  }
191 
192  UserNameChanged.RaiseEvent(value);
193  }
194  }
195 
200 
201  public RoomManager CurrentRoomManager { get { return Manager != null ? Manager.GetRoomManager() : null; } }
202 
203  public Room CurrentRoom
204  {
205  get { return CurrentRoomManager != null ? CurrentRoomManager.GetCurrentRoom() : null; }
206  }
207 
208  private NetworkConnectionAdapter networkConnectionAdapter;
209 
210  public NetworkConnection Connection
211  {
212  get { return Manager != null ? Manager.GetServerConnection() : null; }
213  }
214 
218  public bool IsConnected
219  {
220  get { return Manager != null && Connection != null && Connection.IsConnected(); }
221  }
222 
223  #region Unity Methods
224 
225  protected override void Awake()
226  {
227  base.Awake();
228 
229  AppInstanceUniqueId = Guid.NewGuid().ToString();
230  logWriter = new ConsoleLogWriter { ShowDetailedLogs = ShowDetailedLogs };
231 
232  if (AutoDiscoverServer)
233  {
234  AutoDiscoverInit();
235  }
236  else
237  {
238  ManagerInit(connectOnAwake);
239  }
240  }
241 
242  private void OnEnable()
243  {
244  Application.logMessageReceived += OnLogReceived;
245  }
246 
247  private void LateUpdate()
248  {
249  if (isTryingToFindServer)
250  {
251  AutoDiscoverUpdate();
252  }
253 
254  if (Manager != null)
255  {
256  // Update the Sharing Manager to processes any network messages that have arrived.
257  Manager.Update();
258  }
259  }
260 
261  private void OnDisable()
262  {
263  Application.logMessageReceived -= OnLogReceived;
264  }
265 
266  protected override void OnDestroy()
267  {
268  if (discoveryClient != null)
269  {
270  discoveryClient.RemoveListener(discoveryClientAdapter);
271  discoveryClient.Dispose();
272  discoveryClient = null;
273 
274  if (discoveryClientAdapter != null)
275  {
276  discoveryClientAdapter.Dispose();
277  discoveryClientAdapter = null;
278  }
279  }
280 
281  if (SessionUsersTracker != null)
282  {
284  SessionUsersTracker = null;
285  }
286 
287  if (SessionsTracker != null)
288  {
289  SessionsTracker.Dispose();
290  SessionsTracker = null;
291  }
292 
293  if (Connection != null)
294  {
295  Connection.RemoveListener((byte)MessageID.StatusOnly, networkConnectionAdapter);
296  Connection.Dispose();
297 
298  if (networkConnectionAdapter != null)
299  {
300  networkConnectionAdapter.Dispose();
301  networkConnectionAdapter = null;
302  }
303  }
304 
305  if (Manager != null)
306  {
307  // Force a disconnection so that we can stop and start Unity without connections hanging around.
308  Manager.GetPairedConnection().Disconnect();
309  Manager.GetServerConnection().Disconnect();
310  Manager.Dispose();
311  Manager = null;
312  }
313 
314  // Forces a garbage collection to try to clean up any additional reference to SWIG-wrapped objects.
315  GC.Collect();
316 
317  base.OnDestroy();
318  }
319 
320  #endregion // Unity Methods
321 
322  #region Event Callbacks
323 
324  private void OnNetworkConnectionChanged(NetworkConnection networkConnection)
325  {
326  if (IsConnected)
327  {
328  if (SharingManagerConnected != null)
329  {
330  SharingManagerConnected(this, EventArgs.Empty);
331  }
332  }
333  else
334  {
335  if (SharingManagerDisconnected != null)
336  {
337  SharingManagerDisconnected(this, EventArgs.Empty);
338  }
339  }
340  }
341 
342  private void OnSystemDiscovered(DiscoveredSystem system)
343  {
344  if (system.GetRole() != SystemRole.SessionDiscoveryServerRole) { return; }
345 
346  // Found a server. Stop pinging the network and connect.
347  discoveryClientAdapter.DiscoveredEvent -= OnSystemDiscovered;
348  isTryingToFindServer = false;
349  ServerAddress = system.GetAddress();
350 
351  if (ShowDetailedLogs)
352  {
353  Debug.Log("Server discovered at: " + ServerAddress);
354  }
355 
356  ManagerInit(true);
357 
358  if (ShowDetailedLogs)
359  {
360  Debug.LogFormat("Connected to: {0}:{1}", ServerAddress, ServerPort.ToString());
361  }
362  }
363 
364  private void OnLogReceived(string logString, string stackTrace, LogType type)
365  {
366  switch (type)
367  {
368  case LogType.Error:
369  case LogType.Assert:
370  case LogType.Exception:
371  Log.Error(string.Format("{0} \n {1}", logString, stackTrace));
372  break;
373 
374  case LogType.Warning:
375  Log.Warning(string.Format("{0} \n {1}", logString, stackTrace));
376  break;
377 
378  case LogType.Log:
379  if (ShowDetailedLogs)
380  {
381  Log.Info(logString);
382  }
383  break;
384  default:
385  throw new ArgumentOutOfRangeException("type", type, "Invalid Message Type");
386  }
387  }
388 
389  #endregion // Event Callbacks
390 
391  private void ManagerInit(bool setConnection)
392  {
393  var config = new ClientConfig(ClientRole);
394  config.SetIsAudioEndpoint(IsAudioEndpoint);
395  config.SetLogWriter(logWriter);
396 
397  if (setConnection)
398  {
399  config.SetServerAddress(ServerAddress);
400  config.SetServerPort(ServerPort);
401  }
402 
403  Manager = SharingManager.Create(config);
404 
405  // Set up callbacks so that we know when we've connected successfully.
406  networkConnectionAdapter = new NetworkConnectionAdapter();
407  networkConnectionAdapter.ConnectedCallback += OnNetworkConnectionChanged;
408  networkConnectionAdapter.DisconnectedCallback += OnNetworkConnectionChanged;
409  Connection.AddListener((byte)MessageID.StatusOnly, networkConnectionAdapter);
410 
412  Manager.RegisterSyncListener(SyncStateListener);
413 
414  Root = new SyncRoot(Manager.GetRootSyncObject());
415 
416  SessionsTracker = new ServerSessionsTracker(Manager.GetSessionManager());
417  SessionUsersTracker = new SessionUsersTracker(SessionsTracker);
418 
419  RoomManagerAdapter = new RoomManagerAdapter();
420 
421  CurrentRoomManager.AddListener(RoomManagerAdapter);
422 
423  using (var userName = new XString(DefaultUserName))
424  {
425 #if UNITY_WSA && !UNITY_EDITOR
426  Manager.SetUserName(SystemInfo.deviceName);
427 #else
428  if (!string.IsNullOrEmpty(Environment.UserName))
429  {
430  Manager.SetUserName(Environment.UserName);
431  }
432  else
433  {
434  User localUser = Manager.GetLocalUser();
435  Manager.SetUserName(userName + localUser.GetID().ToString());
436  }
437 #endif
438  }
439  }
440 
441  private void AutoDiscoverInit()
442  {
443  if (ShowDetailedLogs)
444  {
445  Debug.Log("Looking for servers...");
446  }
447 
448  discoveryClientAdapter = new DiscoveryClientAdapter();
449  discoveryClientAdapter.DiscoveredEvent += OnSystemDiscovered;
450 
451  discoveryClient = DiscoveryClient.Create();
452  discoveryClient.AddListener(discoveryClientAdapter);
453 
454  // Start Finding Server.
455  isTryingToFindServer = true;
456  }
457 
458  private void AutoDiscoverUpdate()
459  {
460  // Searching Enabled-> Update DiscoveryClient to check results, Wait Interval then Ping network.
461  pingIntervalCurrent += Time.deltaTime;
462  if (pingIntervalCurrent > PingIntervalSec)
463  {
464  if (ShowDetailedLogs)
465  {
466  Debug.Log("Looking for servers...");
467  }
468 
469  pingIntervalCurrent = 0;
470  discoveryClient.Ping();
471  }
472 
473  discoveryClient.Update();
474  }
475 
476  public void ConnectToServer(string serverAddress, int port)
477  {
478  ServerAddress = serverAddress;
479  ServerPort = port;
480  ConnectToServer();
481  }
482 
483  public void ConnectToServer()
484  {
485  SessionsTracker.LeaveCurrentSession();
486  Manager.SetServerConnectionInfo(ServerAddress, (uint)ServerPort);
487  }
488  }
489 }
EventHandler SharingManagerConnected
SharingManagerConnected event notifies when the sharing manager is created and connected.
Definition: SharingStage.cs:19
override void OnDestroy()
Base OnDestroy method that destroys the Singleton&#39;s unique instance. Called by Unity when destroying ...
System.Action< NetworkConnection > ConnectedCallback
Keeps track of the users in the current session. Instance is created by Sharing Stage when a connecti...
The ServerSessionsTracker manages the list of sessions on the server and the users in these sessions...
virtual int GetID()
Definition: User.cs:49
static SharingManager Create(ClientConfig config)
static void Warning(string message)
Definition: Log.cs:47
Utility class that writes the sharing service log messages to the Unity Engine&#39;s console.
bool KeepRoomAlive
Indicates if the room should kept around even after all users leave.
Definition: SharingStage.cs:82
void ConnectToServer(string serverAddress, int port)
bool ShowDetailedLogs
Show Detailed Information for sharing services.
virtual void RemoveListener(DiscoveryClientListener oldListener)
static DiscoveryClient Create()
static void Info(string message)
Definition: Log.cs:43
override void Awake()
Base Awake method that sets the Singleton&#39;s unique instance. Called by Unity when initializing a Mono...
C# wrapper for the Sharing SyncListener, making changes available through the Action class...
Action< string > UserNameChanged
Invoked when the local user changes their user name.
Allows users of NetworkConnection to register to receive event callbacks without having their classes...
Allows users of the RoomManager to register to receive event callbacks without having their classes i...
virtual void AddListener(DiscoveryClientListener newListener)
static void Error(string message)
Definition: Log.cs:51
The SharingStage is in charge of managing the core networking layer for the application.
Definition: SharingStage.cs:14
Root of the synchronization data model used by this application.
Definition: SyncRoot.cs:12
System.Action< NetworkConnection > DisconnectedCallback
RoomManagerAdapter RoomManagerAdapter
Provides updates when rooms change.
EventHandler SharingManagerDisconnected
SharingManagerDisconnected event notifies when the sharing manager is disconnected.
Definition: SharingStage.cs:24
Singleton behaviour class, used for components that should only have one instance.
Definition: Singleton.cs:14
virtual XString GetName()
Definition: User.cs:43