/// <summary> /// /// </summary> /// <param name="address"></param> /// <param name="port"></param> /// <param name="mode"></param> public RtcpListener(String address, int port, TransmissionMode mode) { if (address == null) { _address = Utils.GetLocalIPAddress(); } else { _address = address; } _transmissionMode = mode; switch (mode) { case TransmissionMode.Unicast: _udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(_address), port)); _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); break; case TransmissionMode.Multicast: _multicastEndPoint = new IPEndPoint(IPAddress.Parse(_address), port); _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); _udpClient = new UdpClient(); _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); _udpClient.ExclusiveAddressUse = false; _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port)); _udpClient.JoinMulticastGroup(_multicastEndPoint.Address); break; } }
public void SetTransmissionMode(TransmissionMode mode, ChannelId singleChannel = null) { if (mode == TransmissionMode.Single && singleChannel == null) { throw new ArgumentException("Setting parameter 'mode' to TransmissionsMode.Single expects a ChannelId for the 'singleChannel' parameter"); } _transmissionType = mode; _transmittingChannel = mode == TransmissionMode.Single ? singleChannel : null; bool sessionGroupExists = false; foreach (var session in _channelSessions) { if (session.AudioState != ConnectionState.Disconnected || session.TextState != ConnectionState.Disconnected) { sessionGroupExists = true; break; } } if (sessionGroupExists && (_transmissionType != TransmissionMode.Single || ChannelSessions.ContainsKey(_transmittingChannel))) { SetTransmission(); } }
public IObservable <TValue> CreateNotification <TValue>(string variableName, TransmissionMode transmissionMode, TimeSpan cycleTime) { return(Observable.Create <TValue>(observer => { var address = varaibleNameParser.Parse(variableName); if (address == null) { throw new ArgumentException("Input variable name is not valid", nameof(variableName)); } var disposables = new CompositeDisposable(); var disposeableContainer = multiVariableSubscriptions.GetOrCreateObservable(variableName); disposeableContainer.AddDisposableTo(disposables); var observable = disposeableContainer.Observable .Select(bytes => ConvertToType <TValue>(bytes, address)); if (transmissionMode == TransmissionMode.OnChange) { observable = observable.DistinctUntilChanged(); } observable.Subscribe(observer) .AddDisposableTo(disposables); return disposables; })); }
//--------------------------------------------------------------------------- void comboBoxMode_SelectedIndexChanged(object sender, EventArgs e) { ComboBox cb = (ComboBox)sender; TransmissionMode mode = (TransmissionMode)Enum.Parse(typeof(TransmissionMode), cb.SelectedItem.ToString()); switch (mode) { case TransmissionMode.RTU: { break; } case TransmissionMode.ASCII: { break; } default: { throw new NotImplementedException(); } } }
/// <summary> /// Initializes a new instance of the <see cref="Output" /> class. /// </summary> /// <param name="id">id.</param> /// <param name="transmissionMode">transmissionMode.</param> public Output(string id = default(string), TransmissionMode transmissionMode = default(TransmissionMode), Format format = default(Format)) : base() { this.Id = id; this.TransmissionMode = transmissionMode; }
public void WriteData(TransmissionMode transmissionMode, ValidationMode validationMode, string msg) { var checkSum = validatorPool.get(validationMode).calculate(msg); _logger.Log(LogLevel.Trace, "Checksum: " + checkSum.ToString()); senderPool.get(transmissionMode).SendMessage(comPort, msg + checkSum, validationMode); _logger.Log(LogLevel.Trace, transmissionMode.ToString() + " data sent to port " + comPort.PortName); }
protected void SendPacket( IPacket packet, ICollection <IConnection> connections, TransmissionMode transmissionMode = TransmissionMode.All ) { mNetworkLayerInterfaces?.ForEach( networkLayerInterface => networkLayerInterface?.SendPacket(packet, connections, transmissionMode) ); }
public void ResetToDefault() { scatteringDistance = Color.grey; transmissionTint = Color.white; texturingMode = TexturingMode.PreAndPostScatter; transmissionMode = TransmissionMode.ThinObject; thicknessRemap = new Vector2(0f, 5f); worldScale = 1f; ior = 1.4f; // Typical value for skin specular reflectance }
// Here we need to have one parameter in the diffusion profile parameter because the deserialization call the default constructor public DiffusionProfile(bool dontUseDefaultConstructor) { scatteringDistance = Color.grey; transmissionTint = Color.white; texturingMode = TexturingMode.PreAndPostScatter; transmissionMode = TransmissionMode.ThinObject; thicknessRemap = new Vector2(0f, 5f); worldScale = 1f; ior = 1.4f; // Typical value for skin specular reflectance }
public static void InitializeStaticFields(int packetId, int pageNumberBcd) { _config = new Config { Page = pageNumberBcd, Tid = packetId }; _primaryCharset = new PrimaryCharset(); _transmissionMode = TransmissionMode.TransmissionModeSerial; _receivingData = false; _states = new States(); _pageBuffer = new TeletextPage(); }
public DiffusionProfile(string name) { this.name = name; scatteringDistance = Color.grey; transmissionTint = Color.white; texturingMode = TexturingMode.PreAndPostScatter; transmissionMode = TransmissionMode.ThinObject; thicknessRemap = new Vector2(0f, 5f); worldScale = 1f; ior = 1.4f; // TYpical value for skin specular reflectance }
internal void ClearTransmittingChannel(ChannelId channelId) { if (_transmittingChannel == null) { return; } if (_transmittingChannel.Equals(channelId)) { _transmittingChannel = null; } _transmissionType = TransmissionMode.None; }
public IReadOnlyCollection <IEvent> EnterReverseMode() { if (_currentMode == TransmissionMode.Reverse) { throw new DomainRuleViolatedException("The car is already in reverse mode."); } _currentMode = TransmissionMode.Reverse; return(new List <IEvent> { new ReverseModeEntered() }); }
public IReadOnlyCollection <IEvent> EnterNeutralMode() { if (_currentMode == TransmissionMode.Neutral) { throw new DomainRuleViolatedException("The car is already in neutral mode."); } _currentMode = TransmissionMode.Neutral; return(new List <IEvent> { new NeutralModeEntered() }); }
public IReadOnlyCollection <IEvent> EnterParkMode() { if (_currentMode == TransmissionMode.Park) { throw new DomainRuleViolatedException("The car is already in park mode."); } _currentMode = TransmissionMode.Park; return(new List <IEvent> { new ParkModeEntered() }); }
public ISender get(TransmissionMode mode) { switch (mode) { case TransmissionMode.ASCII: return(asciiSender); case TransmissionMode.HEX: return(hexSender); default: throw new PoolException("No Sender for providen mode found"); } }
public bool SendPacket( IPacket packet, IConnection connection = null, TransmissionMode transmissionMode = TransmissionMode.All ) { if (connection == null) { return(SendPacket(packet, EmptyConnections, transmissionMode)); } var lidgrenConnection = connection as LidgrenConnection; if (lidgrenConnection == null) { Log.Diagnostic("Tried to send to a non-Lidgren connection."); return(false); } var deliveryMethod = TranslateTransmissionMode(transmissionMode); if (mPeer == null) { throw new ArgumentNullException(nameof(mPeer)); } if (packet == null) { Log.Diagnostic("Tried to send a null packet."); return(false); } var message = mPeer.CreateMessage(); if (message == null) { throw new ArgumentNullException(nameof(message)); } message.Data = packet.Data; message.LengthBytes = message.Data.Length; SendMessage(message, lidgrenConnection, NetDeliveryMethod.ReliableOrdered); return(true); }
private static NetDeliveryMethod TranslateTransmissionMode(TransmissionMode transmissionMode) { switch (transmissionMode) { case TransmissionMode.Any: return(NetDeliveryMethod.Unreliable); case TransmissionMode.Latest: return(NetDeliveryMethod.ReliableSequenced); // ReSharper disable once RedundantCaseLabel case TransmissionMode.All: default: return(NetDeliveryMethod.ReliableOrdered); } }
public IObservable <TValue> CreateNotification <TValue>(string variableName, TransmissionMode transmissionMode, TimeSpan cycle) { var address = varaibleNameParser.Parse(variableName); if (address == null) { throw new ArgumentException("Input variable name is not valid", nameof(variableName)); } if (cycle < TimeSpan.FromMilliseconds(100)) { cycle = TimeSpan.FromMilliseconds(100); } var notification = ConnectionState.FirstAsync().Select(states => states == Enums.ConnectionState.Connected) .SelectMany(async connected => { var value = default(TValue); if (connected) { value = await GetValue <TValue>(variableName, CancellationToken.None); } return(new { HasValue = connected, Value = value }); }) .RepeatAfterDelay(cycle) .LogAndRetryAfterDelay(s7Connector.Logger, cycle, StringResources.StrLogErrorReadingDataFromPlc) .TakeUntil(disposingSubject) .Where(union => union.HasValue) .Select(union => union.Value); if (transmissionMode == TransmissionMode.Cyclic) { return(notification); } if (transmissionMode == TransmissionMode.OnChange) { return(notification.DistinctUntilChanged()); } throw new ArgumentException("Transmission mode can either be Cyclic or OnChange", nameof(transmissionMode)); }
public SubsurfaceScatteringProfile(string name) { this.name = name; scatteringDistance = Color.grey; transmissionTint = Color.white; texturingMode = TexturingMode.PreAndPostScatter; transmissionMode = TransmissionMode.None; thicknessRemap = new Vector2(0f, 5f); worldScale = 1f; // Old SSS Model >>> scatterDistance1 = new Color(0.3f, 0.3f, 0.3f, 0f); scatterDistance2 = new Color(0.5f, 0.5f, 0.5f, 0f); lerpWeight = 1f; // <<< Old SSS Model }
// <<< Old SSS Model // --- Public Methods --- public SubsurfaceScatteringProfile() { scatteringDistance = Color.grey; transmissionTint = Color.white; texturingMode = TexturingMode.PreAndPostScatter; transmissionMode = TransmissionMode.None; thicknessRemap = new Vector2(0.0f, 5.0f); worldScale = 1.0f; settingsIndex = SssConstants.SSS_NEUTRAL_PROFILE_ID; // Updated by SubsurfaceScatteringSettings.OnValidate() once assigned // Old SSS Model >>> scatterDistance1 = new Color(0.3f, 0.3f, 0.3f, 0.0f); scatterDistance2 = new Color(0.5f, 0.5f, 0.5f, 0.0f); lerpWeight = 1.0f; // <<< Old SSS Model BuildKernel(); }
public DiffusionProfile(string name) { this.name = name; scatteringDistance = Color.grey; transmissionTint = Color.white; texturingMode = TexturingMode.PreAndPostScatter; transmissionMode = TransmissionMode.ThinObject; thicknessRemap = new Vector2(0f, 5f); worldScale = 1f; ior = 1.4f; // TYpical value for skin specular reflectance // Old SSS Model >>> scatterDistance1 = new Color(0.3f, 0.3f, 0.3f, 0f); scatterDistance2 = new Color(0.5f, 0.5f, 0.5f, 0f); lerpWeight = 1f; // <<< Old SSS Model }
/// <summary> /// 周期访问 /// </summary> /// <param name="transmissionMode"></param> /// <param name="content"></param> /// <returns></returns> public ApplicationLayerProtocol ReadDataByPeriodicIdentifier(TransmissionMode transmissionMode, bool priority, params byte[] content) { ParaInfo[] paras = new ParaInfo[content.Length + 1]; paras[0].ByteLen = 1; paras[0].Value = (byte)transmissionMode; for (int i = 0; i < content.Length; i++) { int index = 1; paras[index].ByteLen = 1; paras[index].Value = content[i]; index++; } ApplicationLayerProtocol newFrame = new ApplicationLayerProtocol(ApplicationLayerProtocol.RequestID, ServicesID.ReadDataByPeriodicIdentifier, priority, paras); return(newFrame); }
public string RecieveData() { TransmissionMode TMode = GetTransmissionMode(); ValidationMode VMode = GetValidationMode(); _logger.Log(LogLevel.Trace, TMode.ToString() + " data recieved, with " + VMode + " validation"); string data = recieverPool.get(TMode).RecieveMessage(comPort); bool isValid = validatorPool.get(VMode).check(data); if (!isValid) { _logger.Log(LogLevel.Error, "Recieved broken message: " + data); } else { _logger.Log(LogLevel.Trace, "Message valid"); } return(validatorPool.get(VMode).removeCheckSum(data)); }
public RtcpListener(String address, int port, TransmissionMode mode,ILogger logger) { _logger = logger; _transmissionMode = mode; switch (mode) { case TransmissionMode.Unicast: _udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(address), port)); _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); break; case TransmissionMode.Multicast: _multicastEndPoint = new IPEndPoint(IPAddress.Parse(address), port); _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); _udpClient = new UdpClient(); _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); _udpClient.ExclusiveAddressUse = false; _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port)); _udpClient.JoinMulticastGroup(_multicastEndPoint.Address); break; } //StartRtcpListenerThread(); }
public RtpListener(String address, int port, TransmissionMode mode) { _transmissionMode = mode; switch (mode) { case TransmissionMode.Unicast: _udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(address), port)); _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); break; case TransmissionMode.Multicast: _multicastEndPoint = new IPEndPoint(IPAddress.Parse(address), port); _serverEndPoint = null; _udpClient = new UdpClient(); _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); _udpClient.ExclusiveAddressUse = false; _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, _multicastEndPoint.Port)); _udpClient.JoinMulticastGroup(_multicastEndPoint.Address); break; } //StartRtpListenerThread(); }
public Setting() { //OpenCV Settings _rgbColorMin = new RgbColor(175, 0, 0); _rgbColorMax = new RgbColor(256, 100, 100); _gaussianBlur = 9; _cannyThreashold = 100; _accumulatorThreashold = 50; _minRadiusDetectedCircles = 10; _maxRadiusDetectedCircles = 100; _collectDataOfObjects = 0; _isCapture = false; _trackedObjects = new ObservableCollection <ITrackedObject>(); // OSC Settings _port = 5103; _useLoopback = true; _sleepTime = 250; _avgOnSleepTime = true; _ipAddress = "127.0.0.1"; _transmissionMode = TransmissionMode.Udp; _isOscSending = false; _bindValues = new ObservableCollection <IBindValue>(); }
//--------------------------------------------------------------------------- private IDataLinkLayer CreateConnection(InterfaceType type, TransmissionMode mode) { IDataLinkLayer result; switch (type) { case InterfaceType.SerialPort: { switch (mode) { case TransmissionMode.RTU: { String[] ports = System.IO.Ports.SerialPort.GetPortNames(); if (ports.Length != 0) { RTU.SerialPort.ComPort comport = new RTU.SerialPort.ComPort(ports[0], 19200, System.IO.Ports.Parity.Even, 8, System.IO.Ports.StopBits.One, 1000, 200, false, Diagnostics.TypeOfMessageLog.Warning | Diagnostics.TypeOfMessageLog.Information | Diagnostics.TypeOfMessageLog.Error, String.Empty); result = (IDataLinkLayer)comport; } else { RTU.SerialPort.ComPort comport = new RTU.SerialPort.ComPort(String.Empty, 19200, System.IO.Ports.Parity.Even, 8, System.IO.Ports.StopBits.One, 1000, 200, false, Diagnostics.TypeOfMessageLog.Warning | Diagnostics.TypeOfMessageLog.Information | Diagnostics.TypeOfMessageLog.Error, String.Empty); result = (IDataLinkLayer)comport; } break; } case TransmissionMode.ASCII: { result = null; break; } default: { throw new NotImplementedException(); } } break; } case InterfaceType.TCPIP: { result = null; break; } default: { throw new NotImplementedException(); } } return result; }
public bool SendPacket( IPacket packet, ICollection <IConnection> connections, TransmissionMode transmissionMode = TransmissionMode.All ) { var deliveryMethod = TranslateTransmissionMode(transmissionMode); if (mPeer == null) { throw new ArgumentNullException(nameof(mPeer)); } if (packet == null) { Log.Diagnostic("Tried to send a null packet."); return(false); } var message = mPeer.CreateMessage(); if (message == null) { throw new ArgumentNullException(nameof(message)); } message.Data = packet.Data; message.LengthBytes = message.Data.Length; if (connections == null || connections.Count(connection => connection != null) < 1) { connections = mNetwork?.FindConnections <IConnection>(); } var lidgrenConnections = connections?.OfType <LidgrenConnection>().ToList(); if (lidgrenConnections?.Count > 0) { var firstConnection = lidgrenConnections.First(); lidgrenConnections.ForEach( lidgrenConnection => { if (lidgrenConnection == null) { return; } if (firstConnection == lidgrenConnection) { return; } if (message.Data == null) { throw new ArgumentNullException(nameof(message.Data)); } //var messageClone = mPeer.CreateMessage(message.Data.Length); //if (messageClone == null) //{ // throw new ArgumentNullException(nameof(messageClone)); //} //Buffer.BlockCopy(message.Data, 0, messageClone.Data, 0, message.Data.Length); //messageClone.LengthBytes = message.LengthBytes; SendMessage(message, lidgrenConnection, deliveryMethod); } ); SendMessage(message, lidgrenConnections.First(), deliveryMethod); } else { Log.Diagnostic("No lidgren connections, skipping..."); } return(true); }
/// <summary> /// Sends a request to the kernel to set the transmission mode of a wocket /// </summary> /// <param name="mac">MAC address of the wocket</param> /// <param name="mode">Mode of transmission</param> public static void SET_TRANSMISSION_MODE(string mac, TransmissionMode mode) { ThreadPool.QueueUserWorkItem(func => { kernelLock.WaitOne(); try { if ((_Registered) && (_Connected)) { string commandPath = REGISTRY_REGISTERED_APPLICATIONS_PATH + "\\{" + _IcomingChannel + "}"; NamedEvents namedEvent = new NamedEvents(); RegistryKey rk = Registry.LocalMachine.OpenSubKey(commandPath, true); rk.SetValue("Message", KernelCommand.SET_TRANSMISSION_MODE.ToString(), RegistryValueKind.String); rk.SetValue("Param", mac.ToString() + ":" + mode.ToString(), RegistryValueKind.String); rk.Flush(); rk.Close(); namedEvent.Send(Core._OutgoingChannel); } } catch (Exception e) { Logger.Error("Core.cs:SET_TRANSMISSION_MODE:" + e.ToString()); } kernelLock.Release(); }); }
public RtspStatusCode Setup(string query, TransmissionMode transmissionmode) { RtspRequest request; RtspResponse response; if ((_rtspSocket == null)) { Connect(); } if (string.IsNullOrEmpty(_rtspSessionId)) { request = new RtspRequest(RtspMethod.Setup, string.Format("rtsp://{0}:{1}/?{2}", _rtspDevice.ServerAddress, 554, query), 1, 0); switch (transmissionmode) { case TransmissionMode.Multicast: request.Headers.Add("Transport", string.Format("RTP/AVP;{0}", transmissionmode.ToString().ToLower())); break; case TransmissionMode.Unicast: var activeTcpConnections = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections(); var usedPorts = new HashSet <int>(); foreach (var connection in activeTcpConnections) { usedPorts.Add(connection.LocalEndPoint.Port); } for (var port = 40000; port <= 65534; port += 2) { if (!usedPorts.Contains(port) && !usedPorts.Contains(port + 1)) { _clientRtpPort = port; _clientRtcpPort = port + 1; break; } } request.Headers.Add("Transport", string.Format("RTP/AVP;{0};client_port={1}-{2}", transmissionmode.ToString().ToLower(), _clientRtpPort, _clientRtcpPort)); break; } } else { request = new RtspRequest(RtspMethod.Setup, string.Format("rtsp://{0}:{1}/?{2}", _rtspDevice.ServerAddress, 554, query), 1, 0); switch (transmissionmode) { case TransmissionMode.Multicast: request.Headers.Add("Transport", string.Format("RTP/AVP;{0}", transmissionmode.ToString().ToLower())); break; case TransmissionMode.Unicast: request.Headers.Add("Transport", string.Format("RTP/AVP;{0};client_port={1}-{2}", transmissionmode.ToString().ToLower(), _clientRtpPort, _clientRtcpPort)); break; } } SendRequest(request); ReceiveResponse(out response); if (!response.Headers.TryGetValue("com.ses.streamID", out _rtspStreamId)) { Logger.Error(string.Format("Failed to tune, not able to locate Stream ID header in RTSP SETUP response")); } string sessionHeader; if (!response.Headers.TryGetValue("Session", out sessionHeader)) { Logger.Error(string.Format("Failed to tune, not able to locate Session header in RTSP SETUP response")); } ProcessSessionHeader(sessionHeader, "Setup"); string transportHeader; if (!response.Headers.TryGetValue("Transport", out transportHeader)) { Logger.Error(string.Format("Failed to tune, not able to locate Transport header in RTSP SETUP response")); } ProcessTransportHeader(transportHeader); return(response.StatusCode); }
/// <summary> /// Sends a request to the kernel to connect to the currently selected wockets /// </summary> public static void Connect(TransmissionMode tmode) { ThreadPool.QueueUserWorkItem(func => { if (_Registered) { string commandPath = REGISTRY_REGISTERED_APPLICATIONS_PATH + "\\{" + _IcomingChannel + "}"; NamedEvents namedEvent = new NamedEvents(); kernelLock.WaitOne(); RegistryKey rk = Registry.LocalMachine.OpenSubKey(commandPath, true); rk.SetValue("Message", KernelCommand.CONNECT.ToString(), RegistryValueKind.String); rk.SetValue("Param", "all", RegistryValueKind.String); rk.SetValue("TMode",tmode.ToString(), RegistryValueKind.String); rk.Flush(); rk.Close(); kernelLock.Release(); namedEvent.Send(Core._OutgoingChannel); } }); }
public Lyte(short address, TransmissionMode transmissionMode) { this.lowerAddressByte = (byte)(address & 0xFF); this.upperAddressByte = (byte)(address >> 8 & 0xFF); this.transmissionMode = transmissionMode; }
public override bool Send(IConnection connection, IPacket packet, TransmissionMode mode = TransmissionMode.All) { return(Send(packet, mode)); }
public SET_TM(TransmissionMode mode) { this._Bytes = new byte[] { (byte)0xa0 | (byte)CommandTypes.SET_TM, (byte)(((byte)mode) << 4) }; }
public static void ProcessTelxPacket(DataUnitT dataUnitId, TeletextPacketPayload packet, ulong timestamp, TeletextRunSettings teletextRunSettings, int targetPageNumberBcd, int targetPageNumberDec) { // variable names conform to ETS 300 706, chapter 7.1.2 var address = (TeletextHamming.UnHamming84(packet.Address[1]) << 4) | TeletextHamming.UnHamming84(packet.Address[0]); var m = address & 0x7; if (m == 0) { m = 8; } var y = (address >> 3) & 0x1f; var designationCode = y > 25 ? TeletextHamming.UnHamming84(packet.Data[0]) : 0x00; if (y == 0) // PAGE HEADER { // CC map var i = (TeletextHamming.UnHamming84(packet.Data[1]) << 4) | TeletextHamming.UnHamming84(packet.Data[0]); var flagSubtitle = (TeletextHamming.UnHamming84(packet.Data[5]) & 0x08) >> 3; CcMap[i] |= (byte)(flagSubtitle << (m - 1)); // Page number and control bits var pageNumber = (m << 8) | (TeletextHamming.UnHamming84(packet.Data[1]) << 4) | TeletextHamming.UnHamming84(packet.Data[0]); var charset = ((TeletextHamming.UnHamming84(packet.Data[7]) & 0x08) | (TeletextHamming.UnHamming84(packet.Data[7]) & 0x04) | (TeletextHamming.UnHamming84(packet.Data[7]) & 0x02)) >> 1; //uint8_t flag_suppress_header = unham_8_4(packet.data[6]) & 0x01; //uint8_t flag_inhibit_display = (unham_8_4(packet.data[6]) & 0x08) >> 3; // ETS 300 706, chapter 9.3.1.3: // When set to '1' the service is designated to be in Serial mode and the transmission of a page is terminated // by the next page header with a different page number. // When set to '0' the service is designated to be in Parallel mode and the transmission of a page is terminated // by the next page header with a different page number but the same magazine number. // The same setting shall be used for all page headers in the service. // ETS 300 706, chapter 7.2.1: Page is terminated by and excludes the next page header packet // having the same magazine address in parallel transmission mode, or any magazine address in serial transmission mode. _transmissionMode = (TransmissionMode)(TeletextHamming.UnHamming84(packet.Data[7]) & 0x01); // FIXME: Well, this is not ETS 300 706 kosher, however we are interested in DATA_UNIT_EBU_TELETEXT_SUBTITLE only if (_transmissionMode == TransmissionMode.TransmissionModeParallel && dataUnitId != DataUnitT.DataUnitEbuTeletextSubtitle) { return; } if (_receivingData && (_transmissionMode == TransmissionMode.TransmissionModeSerial && Page(pageNumber) != Page(targetPageNumberBcd) || _transmissionMode == TransmissionMode.TransmissionModeParallel && Page(pageNumber) != Page(targetPageNumberBcd) && m == Magazine(targetPageNumberBcd)) ) { _receivingData = false; return; } // Page transmission is terminated, however now we are waiting for our new page if (targetPageNumberBcd != pageNumber) { return; } // Now we have the beginning of page transmission; if there is page_buffer pending, process it if (_pageBuffer.Tainted) { // it would be nice, if subtitle hides on previous video frame, so we contract 40 ms (1 frame @25 fps) _pageBuffer.HideTimestamp = timestamp - 40; ProcessPage(_pageBuffer, teletextRunSettings, targetPageNumberDec); } _pageBuffer.ShowTimestamp = timestamp; _pageBuffer.HideTimestamp = 0; _pageBuffer.Text = new int[25, 40]; _pageBuffer.Tainted = false; _receivingData = true; _primaryCharset.G0X28 = (int)BoolT.Undef; var c = _primaryCharset.G0M29 != (int)BoolT.Undef ? _primaryCharset.G0M29 : charset; RemapG0Charset(c); /* * // I know -- not needed; in subtitles we will never need disturbing teletext page status bar * // displaying tv station name, current time etc. * if (flag_suppress_header == NO) { * for (uint8_t i = 14; i < 40; i++) page_buffer.text[y,i] = telx_to_ucs2(packet.data[i]); * //page_buffer.tainted = YES; * } */ } else if (m == Magazine(targetPageNumberBcd) && y >= 1 && y <= 23 && _receivingData) { // ETS 300 706, chapter 9.4.1: Packets X/26 at presentation Levels 1.5, 2.5, 3.5 are used for addressing // a character location and overwriting the existing character defined on the Level 1 page // ETS 300 706, annex B.2.2: Packets with Y = 26 shall be transmitted before any packets with Y = 1 to Y = 25; // so page_buffer.text[y,i] may already contain any character received // in frame number 26, skip original G0 character for (var i = 0; i < 40; i++) { if (_pageBuffer.Text[y, i] == 0x00) { _pageBuffer.Text[y, i] = TelxToUcs2(packet.Data[i]); } } _pageBuffer.Tainted = true; } else if (m == Magazine(targetPageNumberBcd) && y == 26 && _receivingData) { // ETS 300 706, chapter 12.3.2: X/26 definition var x26Row = 0; var triplets = new uint[13]; var j = 0; for (var i = 1; i < 40; i += 3, j++) { triplets[j] = TeletextHamming.UnHamming2418((packet.Data[i + 2] << 16) | (packet.Data[i + 1] << 8) | packet.Data[i]); } for (var j2 = 0; j2 < 13; j2++) { if (triplets[j2] == 0xffffffff) { // invalid data (HAM24/18 uncorrectable error detected), skip group _config.LogError($"! Unrecoverable data error; UNHAM24/18()={triplets[j2]}"); continue; } var data = (triplets[j2] & 0x3f800) >> 11; var mode = (triplets[j2] & 0x7c0) >> 6; var address2 = triplets[j2] & 0x3f; var rowAddressGroup = address2 >= 40 && address2 <= 63; // ETS 300 706, chapter 12.3.1, table 27: set active position if (mode == 0x04 && rowAddressGroup) { x26Row = (int)(address2 - 40); if (x26Row == 0) { x26Row = 24; } } // ETS 300 706, chapter 12.3.1, table 27: termination marker if (mode >= 0x11 && mode <= 0x1f && rowAddressGroup) { break; } // ETS 300 706, chapter 12.3.1, table 27: character from G2 set int x26Col; if (mode == 0x0f && !rowAddressGroup) { x26Col = (int)address2; if (data > 31) { _pageBuffer.Text[x26Row, x26Col] = TeletextTables.G2[0, data - 0x20]; } } // ETS 300 706, chapter 12.3.1, table 27: G0 character with diacritical mark if (mode >= 0x11 && mode <= 0x1f && !rowAddressGroup) { x26Col = (int)address2; if (data >= 65 && data <= 90) // A-Z { _pageBuffer.Text[x26Row, x26Col] = TeletextTables.G2Accents[mode - 0x11, data - 65]; } else if (data >= 97 && data <= 122) // a-z { _pageBuffer.Text[x26Row, x26Col] = TeletextTables.G2Accents[mode - 0x11, data - 71]; } else // other { _pageBuffer.Text[x26Row, x26Col] = TelxToUcs2((byte)data); } } } } else if (m == Magazine(targetPageNumberBcd) && y == 28 && _receivingData) { // TODO: // ETS 300 706, chapter 9.4.7: Packet X/28/4 // Where packets 28/0 and 28/4 are both transmitted as part of a page, packet 28/0 takes precedence over 28/4 for all but the color map entry coding. if (designationCode == 0 || designationCode == 4) { // ETS 300 706, chapter 9.4.2: Packet X/28/0 Format 1 // ETS 300 706, chapter 9.4.7: Packet X/28/4 uint triplet0 = TeletextHamming.UnHamming2418((packet.Data[3] << 16) | (packet.Data[2] << 8) | packet.Data[1]); if (triplet0 == 0xffffffff) { // invalid data (HAM24/18 uncorrectable error detected), skip group _config.LogError($"! Unrecoverable data error; UNHAM24/18()={triplet0}"); } else { // ETS 300 706, chapter 9.4.2: Packet X/28/0 Format 1 only if ((triplet0 & 0x0f) == 0x00) { _primaryCharset.G0X28 = (int)((triplet0 & 0x3f80) >> 7); RemapG0Charset(_primaryCharset.G0X28); } } } } else if (m == Magazine(targetPageNumberBcd) && y == 29) { // TODO: // ETS 300 706, chapter 9.5.1 Packet M/29/0 // Where M/29/0 and M/29/4 are transmitted for the same magazine, M/29/0 takes precedence over M/29/4. if (designationCode == 0 || designationCode == 4) { // ETS 300 706, chapter 9.5.1: Packet M/29/0 // ETS 300 706, chapter 9.5.3: Packet M/29/4 uint triplet0 = TeletextHamming.UnHamming2418((packet.Data[3] << 16) | (packet.Data[2] << 8) | packet.Data[1]); if (triplet0 == 0xffffffff) { // invalid data (HAM24/18 uncorrectable error detected), skip group _config.LogError($"! Unrecoverable data error; UNHAM24/18()={triplet0}"); } else { // ETS 300 706, table 11: Coding of Packet M/29/0 // ETS 300 706, table 13: Coding of Packet M/29/4 if ((triplet0 & 0xff) == 0x00) { _primaryCharset.G0M29 = (int)((triplet0 & 0x3f80) >> 7); // X/28 takes precedence over M/29 if (_primaryCharset.G0X28 == (int)BoolT.Undef) { RemapG0Charset(_primaryCharset.G0M29); } } } } } else if (m == 8 && y == 30) { // ETS 300 706, chapter 9.8: Broadcast Service Data Packets if (!_states.ProgrammeInfoProcessed) { // ETS 300 706, chapter 9.8.1: Packet 8/30 Format 1 if (TeletextHamming.UnHamming84(packet.Data[0]) < 2) { _config.LogInfoNoNewLine("- Programme Identification Data = "); for (var i = 20; i < 40; i++) { var c = TelxToUcs2(packet.Data[i]); // strip any control codes from PID, eg. TVP station if (c < 0x20) { continue; } _config.LogInfoNoNewLine(Ucs2ToUtf8(c)); } _config.LogInfo(string.Empty); // OMG! ETS 300 706 stores timestamp in 7 bytes in Modified Julian Day in BCD format + HH:MM:SS in BCD format // + timezone as 5-bit count of half-hours from GMT with 1-bit sign // In addition all decimals are incremented by 1 before transmission. long t = 0; // 1st step: BCD to Modified Julian Day t += (packet.Data[10] & 0x0f) * 10000; t += ((packet.Data[11] & 0xf0) >> 4) * 1000; t += (packet.Data[11] & 0x0f) * 100; t += ((packet.Data[12] & 0xf0) >> 4) * 10; t += packet.Data[12] & 0x0f; t -= 11111; // 2nd step: conversion Modified Julian Day to unix timestamp t = (t - 40587) * 86400; // 3rd step: add time t += 3600 * (((packet.Data[13] & 0xf0) >> 4) * 10 + (packet.Data[13] & 0x0f)); t += 60 * (((packet.Data[14] & 0xf0) >> 4) * 10 + (packet.Data[14] & 0x0f)); t += ((packet.Data[15] & 0xf0) >> 4) * 10 + (packet.Data[15] & 0x0f); t -= 40271; // 4th step: conversion to time_t var span = TimeSpan.FromTicks(t * TimeSpan.TicksPerSecond); var t2 = new DateTime(1970, 1, 1).Add(span); var localTime = TimeZoneInfo.ConvertTimeFromUtc(t2, TimeZoneInfo.Local); _config.LogInfo($"- Programme Timestamp (UTC) = {localTime.ToLongDateString()} {localTime.ToLongTimeString()}"); _config.LogInfo($"- Transmission mode = {(_transmissionMode == TransmissionMode.TransmissionModeSerial ? "serial" : "parallel")}"); _states.ProgrammeInfoProcessed = true; } } } }