| | 1 | | using System; |
| | 2 | | using System.Collections.Generic; |
| | 3 | | using System.Net; |
| | 4 | | using System.Runtime.CompilerServices; |
| | 5 | | using System.Threading.Tasks; |
| | 6 | | using CoreOSC; |
| | 7 | | using NLog; |
| | 8 | | using ReFlex.Core.Common.Components; |
| | 9 | | using ReFlex.Core.Tuio.Components; |
| | 10 | | using ReFlex.Core.Tuio.Interfaces; |
| | 11 | | using ReFlex.Core.Tuio.Util; |
| | 12 | |
|
| | 13 | | [assembly: InternalsVisibleTo("ReFlex.Tuio.Test")] |
| | 14 | | namespace ReFlex.Core.Tuio |
| | 15 | | { |
| | 16 | | public class TuioBroadcast : ITuioBroadcast, IDisposable |
| | 17 | | { |
| | 18 | | #region Fields |
| | 19 | |
|
| 1 | 20 | | private static readonly Logger Log = LogManager.GetCurrentClassLogger(); |
| | 21 | |
|
| | 22 | | private readonly ITuioMessageBuilder _builder; |
| | 23 | | private readonly ITuioSender _sender; |
| | 24 | |
|
| 13 | 25 | | private string _localAddress = "Localhost"; |
| | 26 | |
|
| | 27 | | #endregion |
| | 28 | |
|
| | 29 | | #region Properties |
| | 30 | |
|
| | 31 | | /// <summary> |
| | 32 | | /// Specify whether the instance has a valid configuration |
| | 33 | | /// </summary> |
| 68 | 34 | | public bool IsConfigured { get; private set; } |
| | 35 | |
|
| | 36 | | /// <summary> |
| | 37 | | /// Specifies whether the service is currently sending data. |
| | 38 | | /// </summary> |
| 58 | 39 | | public bool IsSending { get; private set; } |
| | 40 | |
|
| | 41 | | /// <summary> |
| | 42 | | /// Current Configuration for sending |
| | 43 | | /// </summary> |
| 77 | 44 | | public TuioConfiguration Configuration { get; private set; } |
| | 45 | |
|
| | 46 | | /// <summary> |
| | 47 | | /// Storage for Frame Id. Is incremented when <see cref="Broadcast"/> was successful. |
| | 48 | | /// </summary> |
| 29 | 49 | | public int FrameId { get; private set; } |
| | 50 | |
|
| | 51 | | #endregion |
| | 52 | |
|
| | 53 | | #region Constructor |
| | 54 | |
|
| | 55 | | /// <summary> |
| | 56 | | /// internal Constructor for Testing purposes |
| | 57 | | /// </summary> |
| | 58 | | /// <param name="messageBuilder">constructs the TUIO messages</param> |
| | 59 | | /// <param name="sender">sends the data to TUIO server</param> |
| 13 | 60 | | internal TuioBroadcast(ITuioMessageBuilder messageBuilder, ITuioSender sender) |
| 13 | 61 | | { |
| 13 | 62 | | _builder = messageBuilder; |
| 13 | 63 | | _sender = sender; |
| 13 | 64 | | } |
| | 65 | |
|
| | 66 | | /// <summary> |
| | 67 | | /// initializes the Broadcast service. |
| | 68 | | /// Creates a <see cref="TuioMessageBuilder"/> for generating messages according to TUIO specification. |
| | 69 | | /// Creates a <see cref="TuioSender"/> for sending the data. |
| | 70 | | /// Needs to call <see cref="Configure"/> before sending is enabled. |
| | 71 | | /// </summary> |
| 1 | 72 | | public TuioBroadcast() : this(new TuioMessageBuilder(), new TuioSender()) |
| 1 | 73 | | { |
| 1 | 74 | | } |
| | 75 | |
|
| | 76 | | #endregion |
| | 77 | |
|
| | 78 | | #region public Methods |
| | 79 | |
|
| | 80 | | /// <summary> |
| | 81 | | /// Initializes the service with the provided configuration. |
| | 82 | | /// First, all open connections are closed on <see cref="TuioSender"/> |
| | 83 | | /// then current hostname is retrieved and stored as local Address for TUIO identification |
| | 84 | | /// <see cref="Configuration"/> is set |
| | 85 | | /// <see cref="IsConfigured"/> is set to true, if <see cref="Configuration"/> is not null and <see cref="TuioSen |
| | 86 | | /// </summary> |
| | 87 | | /// <param name="config">Configuration containing (at least) server address, port and <see cref="TransportProtoc |
| | 88 | | /// <returns>completed Task</returns> |
| | 89 | | public async Task Configure(TuioConfiguration config) |
| 10 | 90 | | { |
| 10 | 91 | | await _sender.StopAllConnections(); |
| | 92 | |
|
| 10 | 93 | | _sender.Initialize(config); |
| | 94 | |
|
| | 95 | | // Get the Name of HOST |
| 10 | 96 | | var hostName = Dns.GetHostName(); |
| | 97 | |
|
| | 98 | | // Get the IP from GetHostByName method of dns class. |
| 10 | 99 | | var entry = await Dns.GetHostEntryAsync(hostName); |
| | 100 | |
|
| 10 | 101 | | _localAddress = entry.AddressList[0].ToString(); |
| | 102 | |
|
| 10 | 103 | | Configuration = config; |
| | 104 | |
|
| 10 | 105 | | IsConfigured = Configuration != null && _sender.IsInitialized; |
| | 106 | |
|
| 10 | 107 | | Log.Info($"Sucessfully configured {nameof(TuioBroadcast)}: {config?.GetTuioConfigurationString() ?? "No conf |
| 10 | 108 | | } |
| | 109 | |
|
| | 110 | | /// <summary> |
| | 111 | | /// Broadcast data according to the current configuration to TUIO server |
| | 112 | | /// If <see cref="Configuration"/> is null or <see cref="IsConfigured"/> is false, nothing is sent. |
| | 113 | | /// Also checks, if <see cref="IsSending"/> is true and only send if this is not the case. |
| | 114 | | /// Constructs <see cref="TuioParameters"/> from <see cref="interactions"/>, current <see cref="Configuration"/> |
| | 115 | | /// Sends data based on specified <see cref="TransportProtocol"/> in <see cref="Configuration"/> and increases f |
| | 116 | | /// </summary> |
| | 117 | | /// <param name="interactions">interactions that are transformed into TUIO packages</param> |
| | 118 | | /// <returns>completed Task</returns> |
| | 119 | | public async Task<string> Broadcast(List<Interaction> interactions) |
| 8 | 120 | | { |
| 8 | 121 | | if (Configuration == null || !IsConfigured) |
| 1 | 122 | | { |
| 1 | 123 | | Log.Warn( |
| 1 | 124 | | $"Cannot {nameof(Broadcast)} interactions, because {nameof(TuioBroadcast)} is has no valid configura |
| 1 | 125 | | return ""; |
| | 126 | | } |
| | 127 | |
|
| | 128 | | // skip if last message is still being sent |
| 7 | 129 | | if (IsSending) |
| 1 | 130 | | return ""; |
| | 131 | |
|
| 6 | 132 | | var tuioParams = new TuioParameters(_localAddress, Configuration, interactions, FrameId); |
| | 133 | |
|
| 6 | 134 | | var bndl = CreateOscBundle(tuioParams); |
| | 135 | |
|
| 6 | 136 | | IsSending = true; |
| | 137 | |
|
| 6 | 138 | | switch (Configuration.Transport) |
| | 139 | | { |
| | 140 | | case TransportProtocol.Udp: |
| 3 | 141 | | await _sender.SendUdp(bndl); |
| 3 | 142 | | break; |
| | 143 | | case TransportProtocol.Tcp: |
| 1 | 144 | | await _sender.SendTcp(bndl); |
| 1 | 145 | | break; |
| | 146 | | case TransportProtocol.WebSocket: |
| 1 | 147 | | await _sender.SendWebSocket(bndl); |
| 1 | 148 | | break; |
| | 149 | | default: |
| 1 | 150 | | IsSending = false; |
| 1 | 151 | | throw new ArgumentOutOfRangeException(); |
| | 152 | | } |
| | 153 | |
|
| 5 | 154 | | FrameId++; |
| | 155 | |
|
| 5 | 156 | | IsSending = false; |
| | 157 | |
|
| 5 | 158 | | return _builder.GenerateStringRepresentation(bndl); |
| 7 | 159 | | } |
| | 160 | |
|
| | 161 | | /// <summary> |
| | 162 | | /// resets <see cref="IsConfigured"/>, <see cref="IsSending"/>, frame Id. |
| | 163 | | /// Also stops all connections on <see cref="TuioSender"/> |
| | 164 | | /// </summary> |
| | 165 | | public async void Dispose() |
| 13 | 166 | | { |
| 13 | 167 | | IsConfigured = false; |
| 13 | 168 | | FrameId = 0; |
| 13 | 169 | | IsSending = false; |
| 13 | 170 | | IsConfigured = false; |
| 13 | 171 | | await _sender.StopAllConnections(); |
| 13 | 172 | | } |
| | 173 | |
|
| | 174 | | #endregion |
| | 175 | |
|
| | 176 | | #region private Methods |
| | 177 | |
|
| | 178 | | private OscBundle CreateOscBundle(TuioParameters parameters) |
| 6 | 179 | | { |
| 6 | 180 | | return new OscBundle(parameters.Time, CreateOscMessages(Configuration.Protocol, parameters)); |
| 6 | 181 | | } |
| | 182 | |
|
| | 183 | | private IEnumerable<OscMessage> CreateOscMessages(ProtocolVersion tuioVersion, TuioParameters parameters) |
| 6 | 184 | | { |
| 6 | 185 | | return tuioVersion == ProtocolVersion.TUIO_VERSION_1_1 |
| 6 | 186 | | ? _builder.CreateTuio11Messages(parameters, Configuration.Interpretation) |
| 6 | 187 | | : _builder.CreateTuio20Messages(parameters, Configuration.Interpretation); |
| 6 | 188 | | } |
| | 189 | |
|
| | 190 | | #endregion |
| | 191 | | } |
| | 192 | | } |