123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- using System;
- using System.Linq;
- using System.Collections.Generic;
- using System.Reflection;
- using System.Threading;
- using UnityEngine;
- using Unity.WebRTC;
- using Unity.RenderStreaming.Signaling;
- #if UNITY_EDITOR
- using UnityEditor;
- #endif
- namespace Unity.RenderStreaming
- {
- [AddComponentMenu("Render Streaming/Signaling Manager")]
- public sealed class SignalingManager : MonoBehaviour
- {
- #pragma warning disable 0649
- [SerializeField]
- private bool m_useDefault = true;
- [SerializeField]
- internal SignalingSettingsObject signalingSettingsObject;
- [SerializeReference, SignalingSettings]
- private SignalingSettings signalingSettings = new WebSocketSignalingSettings();
- [SerializeField, Tooltip("List of handlers of signaling process.")]
- private List<SignalingHandlerBase> handlers = new List<SignalingHandlerBase>();
- /// <summary>
- ///
- /// </summary>
- [SerializeField, Tooltip("Automatically started when called Awake method.")]
- public bool runOnAwake = true;
- /// <summary>
- ///
- /// </summary>
- [SerializeField, Tooltip("Evaluate commandline arguments if launching runtime on the command line.")]
- public bool evaluateCommandlineArguments = true;
- #pragma warning restore 0649
- private SignalingManagerInternal m_instance;
- private SignalingEventProvider m_provider;
- private bool m_running;
- public bool Running => m_running;
- static ISignaling CreateSignaling(SignalingSettings settings, SynchronizationContext context)
- {
- if (settings.signalingClass == null)
- {
- throw new ArgumentException($"Signaling type is undefined. {settings.signalingClass}");
- }
- object[] args = { settings, context };
- return (ISignaling)Activator.CreateInstance(settings.signalingClass, args);
- }
- /// <summary>
- /// Use settings in Project Settings.
- /// </summary>
- public bool useDefaultSettings
- {
- get { return m_useDefault; }
- set { m_useDefault = value; }
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="settings"></param>
- /// <exception cref="InvalidOperationException"></exception>
- public void SetSignalingSettings(SignalingSettings settings)
- {
- if (m_running)
- throw new InvalidOperationException("The Signaling process has already started.");
- if (settings == null)
- throw new ArgumentNullException("settings");
- signalingSettings = settings;
- }
- /// <summary>
- ///
- /// </summary>
- /// <returns></returns>
- public SignalingSettings GetSignalingSettings()
- {
- return signalingSettings;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="handlerBase"></param>
- public void AddSignalingHandler(SignalingHandlerBase handlerBase)
- {
- if (handlers.Contains(handlerBase))
- {
- return;
- }
- handlers.Add(handlerBase);
- if (!m_running)
- {
- return;
- }
- handlerBase.SetHandler(m_instance);
- m_provider.Subscribe(handlerBase);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="handlerBase"></param>
- public void RemoveSignalingHandler(SignalingHandlerBase handlerBase)
- {
- handlers.Remove(handlerBase);
- if (!m_running)
- {
- return;
- }
- handlerBase.SetHandler(null);
- m_provider.Unsubscribe(handlerBase);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="signaling"></param>
- /// <param name="handlers"></param>
- public void Run(
- ISignaling signaling = null,
- SignalingHandlerBase[] handlers = null)
- {
- Debug.Log("RunRunRunRunRunRunRunRunRunRun");
- _Run(null, signaling, handlers);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="conf"></param>
- /// <param name="signaling"></param>
- /// <param name="handlers"></param>
- /// <remarks> To use this method, Need to depend WebRTC package </remarks>
- public void Run(
- RTCConfiguration conf,
- ISignaling signaling = null,
- SignalingHandlerBase[] handlers = null
- )
- {
- _Run(conf, signaling, handlers);
- }
- #if UNITY_EDITOR
- bool IsValidSignalingSettingsObject(SignalingSettingsObject asset)
- {
- if (asset == null)
- return false;
- if (AssetDatabase.GetAssetPath(asset).IndexOf("Assets", StringComparison.Ordinal) != 0)
- return false;
- return true;
- }
- #endif
- /// <summary>
- ///
- /// </summary>
- /// <param name="conf"></param>
- /// <param name="signaling"></param>
- /// <param name="handlers"></param>
- private void _Run(
- RTCConfiguration? conf = null,
- ISignaling signaling = null,
- SignalingHandlerBase[] handlers = null
- )
- {
- var settings = m_useDefault ? RenderStreaming.GetSignalingSettings<SignalingSettings>() : signalingSettings;
- #if !UNITY_EDITOR
- var arguments = Environment.GetCommandLineArgs();
- if (evaluateCommandlineArguments && arguments.Length > 1)
- {
- if (!EvaluateCommandlineArguments(ref settings, arguments))
- {
- Debug.LogError("Command line arguments are invalid.");
- }
- }
- #endif
- RTCIceServer[] iceServers = settings.iceServers.OfType<RTCIceServer>().ToArray();
- RTCConfiguration _conf =
- conf.GetValueOrDefault(new RTCConfiguration { iceServers = iceServers });
- ISignaling _signaling = signaling ?? CreateSignaling(settings, SynchronizationContext.Current);
- RenderStreamingDependencies dependencies = new RenderStreamingDependencies
- {
- config = _conf,
- signaling = _signaling,
- startCoroutine = StartCoroutine,
- stopCoroutine = StopCoroutine,
- resentOfferInterval = 5.0f,
- };
- var _handlers = (handlers ?? this.handlers.AsEnumerable()).Where(_ => _ != null);
- if (_handlers.Count() == 0)
- throw new InvalidOperationException("Handler list is empty.");
- m_instance = new SignalingManagerInternal(ref dependencies);
- m_provider = new SignalingEventProvider(m_instance);
- foreach (var handler in _handlers)
- {
- handler.SetHandler(m_instance);
- m_provider.Subscribe(handler);
- }
- m_running = true;
- }
- internal static bool EvaluateCommandlineArguments(ref SignalingSettings settings, string[] arguments)
- {
- if (!CommandLineParser.TryParse(arguments))
- return false;
- string signalingTypeName = null;
- if (CommandLineParser.SignalingType.Value != null)
- {
- signalingTypeName = CommandLineParser.SignalingType;
- }
- else if (CommandLineParser.ImportJson.Value != null)
- {
- signalingTypeName = CommandLineParser.ImportJson.Value.Value.signalingType;
- }
- if (signalingTypeName != null)
- {
- Type[] types = RuntimeTypeCache<SignalingSettings>.GetTypesDerivedFrom();
- Dictionary<string, Type> map =
- types.Where(type => type.GetCustomAttribute<SignalingTypeAttribute>() != null)
- .ToDictionary(type => type.GetCustomAttribute<SignalingTypeAttribute>().typename, type => type);
- if (map.ContainsKey(signalingTypeName))
- {
- var type = map[signalingTypeName];
- settings = (SignalingSettings)Activator.CreateInstance(type);
- }
- }
- return settings.ParseArguments(arguments);
- }
- /// <summary>
- ///
- /// </summary>
- public void Stop()
- {
- m_instance?.Dispose();
- m_instance = null;
- m_running = false;
- }
- void Awake()
- {
- if (!runOnAwake || m_running || handlers.Count == 0)
- return;
- var settings = m_useDefault ? RenderStreaming.GetSignalingSettings<SignalingSettings>() : signalingSettings;
- RTCIceServer[] iceServers = settings.iceServers.OfType<RTCIceServer>().ToArray();
- RTCConfiguration conf = new RTCConfiguration { iceServers = iceServers };
- ISignaling signaling = CreateSignaling(settings, SynchronizationContext.Current);
- _Run(conf, signaling, handlers.ToArray());
- }
- void OnDestroy()
- {
- Stop();
- }
- }
- }
|