diff --git a/Radio/App_radio/.vs/App_radio.slnx/DesignTimeBuild/.dtbcache.v2 b/Radio/App_radio/.vs/App_radio.slnx/DesignTimeBuild/.dtbcache.v2 new file mode 100644 index 0000000..b72c47b Binary files /dev/null and b/Radio/App_radio/.vs/App_radio.slnx/DesignTimeBuild/.dtbcache.v2 differ diff --git a/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/12ba9c2f-8307-4a9f-ad2f-70f7f027f4fb.vsidx b/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/12ba9c2f-8307-4a9f-ad2f-70f7f027f4fb.vsidx new file mode 100644 index 0000000..c403b3f Binary files /dev/null and b/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/12ba9c2f-8307-4a9f-ad2f-70f7f027f4fb.vsidx differ diff --git a/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/197c3513-c6be-4921-bf25-2bfd87d8975a.vsidx b/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/197c3513-c6be-4921-bf25-2bfd87d8975a.vsidx new file mode 100644 index 0000000..3307522 Binary files /dev/null and b/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/197c3513-c6be-4921-bf25-2bfd87d8975a.vsidx differ diff --git a/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/4a0ad72a-c342-4977-9500-79a26e09e354.vsidx b/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/4a0ad72a-c342-4977-9500-79a26e09e354.vsidx new file mode 100644 index 0000000..c403b3f Binary files /dev/null and b/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/4a0ad72a-c342-4977-9500-79a26e09e354.vsidx differ diff --git a/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/8491757c-1846-4dca-a475-564ec2a0a1f8.vsidx b/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/8491757c-1846-4dca-a475-564ec2a0a1f8.vsidx new file mode 100644 index 0000000..c403b3f Binary files /dev/null and b/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/8491757c-1846-4dca-a475-564ec2a0a1f8.vsidx differ diff --git a/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/e6b121fb-f728-41b5-b0a3-22b3ed941af6.vsidx b/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/e6b121fb-f728-41b5-b0a3-22b3ed941af6.vsidx new file mode 100644 index 0000000..c403b3f Binary files /dev/null and b/Radio/App_radio/.vs/App_radio.slnx/FileContentIndex/e6b121fb-f728-41b5-b0a3-22b3ed941af6.vsidx differ diff --git a/Radio/App_radio/.vs/App_radio.slnx/v18/.futdcache.v2 b/Radio/App_radio/.vs/App_radio.slnx/v18/.futdcache.v2 new file mode 100644 index 0000000..4b6a771 Binary files /dev/null and b/Radio/App_radio/.vs/App_radio.slnx/v18/.futdcache.v2 differ diff --git a/Radio/App_radio/.vs/App_radio.slnx/v18/.suo b/Radio/App_radio/.vs/App_radio.slnx/v18/.suo new file mode 100644 index 0000000..e56c709 Binary files /dev/null and b/Radio/App_radio/.vs/App_radio.slnx/v18/.suo differ diff --git a/Radio/App_radio/.vs/App_radio.slnx/v18/DocumentLayout.backup.json b/Radio/App_radio/.vs/App_radio.slnx/v18/DocumentLayout.backup.json new file mode 100644 index 0000000..0246904 --- /dev/null +++ b/Radio/App_radio/.vs/App_radio.slnx/v18/DocumentLayout.backup.json @@ -0,0 +1,85 @@ +{ + "Version": 1, + "WorkspaceRootPath": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\", + "Documents": [ + { + "AbsoluteMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|c:\\users\\alvar\\desktop\\barcelona_software\\aaradio_bluetooth\\app_radio\\audioengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|solutionrelative:audioengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|c:\\users\\alvar\\desktop\\barcelona_software\\aaradio_bluetooth\\app_radio\\radioserialservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|solutionrelative:radioserialservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|c:\\users\\alvar\\desktop\\barcelona_software\\aaradio_bluetooth\\app_radio\\radiocontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|solutionrelative:radiocontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|c:\\users\\alvar\\desktop\\barcelona_software\\aaradio_bluetooth\\app_radio\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + } + ], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": 1, + "Children": [ + { + "$type": "Document", + "DocumentIndex": 1, + "Title": "RadioSerialService.cs", + "DocumentMoniker": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\RadioSerialService.cs", + "RelativeDocumentMoniker": "RadioSerialService.cs", + "ToolTip": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\RadioSerialService.cs", + "RelativeToolTip": "RadioSerialService.cs", + "ViewState": "AgIAAPIAAAAAAAAAAAAswAcBAAAJAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-07-23T17:01:10.725Z" + }, + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "AudioEngine.cs", + "DocumentMoniker": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\AudioEngine.cs", + "RelativeDocumentMoniker": "AudioEngine.cs", + "ToolTip": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\AudioEngine.cs", + "RelativeToolTip": "AudioEngine.cs", + "ViewState": "AgIAAE0AAAAAAAAAAAAgwGEAAAASAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-07-23T16:52:37.679Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 3, + "Title": "Program.cs", + "DocumentMoniker": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\Program.cs", + "RelativeDocumentMoniker": "Program.cs", + "ToolTip": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\Program.cs", + "RelativeToolTip": "Program.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAA8AAAAFAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-07-23T16:51:47.037Z" + }, + { + "$type": "Document", + "DocumentIndex": 2, + "Title": "RadioController.cs", + "DocumentMoniker": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\RadioController.cs", + "RelativeDocumentMoniker": "RadioController.cs", + "ToolTip": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\RadioController.cs", + "RelativeToolTip": "RadioController.cs", + "ViewState": "AgIAAPAAAAAAAAAAAAAawAIBAAAlAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-07-23T16:51:43.945Z" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/Radio/App_radio/.vs/App_radio.slnx/v18/DocumentLayout.json b/Radio/App_radio/.vs/App_radio.slnx/v18/DocumentLayout.json new file mode 100644 index 0000000..0246904 --- /dev/null +++ b/Radio/App_radio/.vs/App_radio.slnx/v18/DocumentLayout.json @@ -0,0 +1,85 @@ +{ + "Version": 1, + "WorkspaceRootPath": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\", + "Documents": [ + { + "AbsoluteMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|c:\\users\\alvar\\desktop\\barcelona_software\\aaradio_bluetooth\\app_radio\\audioengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|solutionrelative:audioengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|c:\\users\\alvar\\desktop\\barcelona_software\\aaradio_bluetooth\\app_radio\\radioserialservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|solutionrelative:radioserialservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|c:\\users\\alvar\\desktop\\barcelona_software\\aaradio_bluetooth\\app_radio\\radiocontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|solutionrelative:radiocontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|c:\\users\\alvar\\desktop\\barcelona_software\\aaradio_bluetooth\\app_radio\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{7CFA4CBA-C3C7-53E8-BAB7-F6260C1F73C8}|App_radio.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + } + ], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": 1, + "Children": [ + { + "$type": "Document", + "DocumentIndex": 1, + "Title": "RadioSerialService.cs", + "DocumentMoniker": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\RadioSerialService.cs", + "RelativeDocumentMoniker": "RadioSerialService.cs", + "ToolTip": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\RadioSerialService.cs", + "RelativeToolTip": "RadioSerialService.cs", + "ViewState": "AgIAAPIAAAAAAAAAAAAswAcBAAAJAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-07-23T17:01:10.725Z" + }, + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "AudioEngine.cs", + "DocumentMoniker": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\AudioEngine.cs", + "RelativeDocumentMoniker": "AudioEngine.cs", + "ToolTip": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\AudioEngine.cs", + "RelativeToolTip": "AudioEngine.cs", + "ViewState": "AgIAAE0AAAAAAAAAAAAgwGEAAAASAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-07-23T16:52:37.679Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 3, + "Title": "Program.cs", + "DocumentMoniker": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\Program.cs", + "RelativeDocumentMoniker": "Program.cs", + "ToolTip": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\Program.cs", + "RelativeToolTip": "Program.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAA8AAAAFAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-07-23T16:51:47.037Z" + }, + { + "$type": "Document", + "DocumentIndex": 2, + "Title": "RadioController.cs", + "DocumentMoniker": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\RadioController.cs", + "RelativeDocumentMoniker": "RadioController.cs", + "ToolTip": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\RadioController.cs", + "RelativeToolTip": "RadioController.cs", + "ViewState": "AgIAAPAAAAAAAAAAAAAawAIBAAAlAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-07-23T16:51:43.945Z" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/Radio/App_radio/.vs/ProjectEvaluation/app_radio.metadata.v10.bin b/Radio/App_radio/.vs/ProjectEvaluation/app_radio.metadata.v10.bin new file mode 100644 index 0000000..8ed0937 Binary files /dev/null and b/Radio/App_radio/.vs/ProjectEvaluation/app_radio.metadata.v10.bin differ diff --git a/Radio/App_radio/.vs/ProjectEvaluation/app_radio.projects.v10.bin b/Radio/App_radio/.vs/ProjectEvaluation/app_radio.projects.v10.bin new file mode 100644 index 0000000..ee6aa0b Binary files /dev/null and b/Radio/App_radio/.vs/ProjectEvaluation/app_radio.projects.v10.bin differ diff --git a/Radio/App_radio/.vs/ProjectEvaluation/app_radio.strings.v10.bin b/Radio/App_radio/.vs/ProjectEvaluation/app_radio.strings.v10.bin new file mode 100644 index 0000000..bdee179 Binary files /dev/null and b/Radio/App_radio/.vs/ProjectEvaluation/app_radio.strings.v10.bin differ diff --git a/Radio/App_radio/App_radio.csproj b/Radio/App_radio/App_radio.csproj new file mode 100644 index 0000000..7f7a6db --- /dev/null +++ b/Radio/App_radio/App_radio.csproj @@ -0,0 +1,18 @@ + + + + WinExe + net10.0-windows + enable + true + enable + App_radio + App_radio + + + + + + + + \ No newline at end of file diff --git a/Radio/App_radio/App_radio.csproj.user b/Radio/App_radio/App_radio.csproj.user new file mode 100644 index 0000000..e8991cf --- /dev/null +++ b/Radio/App_radio/App_radio.csproj.user @@ -0,0 +1,9 @@ + + + + + + Form + + + \ No newline at end of file diff --git a/Radio/App_radio/App_radio.slnx b/Radio/App_radio/App_radio.slnx new file mode 100644 index 0000000..3552d82 --- /dev/null +++ b/Radio/App_radio/App_radio.slnx @@ -0,0 +1,3 @@ + + + diff --git a/Radio/App_radio/AudioEngine.cs b/Radio/App_radio/AudioEngine.cs new file mode 100644 index 0000000..42de25b --- /dev/null +++ b/Radio/App_radio/AudioEngine.cs @@ -0,0 +1,410 @@ +using NAudio.Wave; + +namespace App_radio; + +/// +/// Captura el micrófono del PC y reproduce el audio recibido por la radio. +/// Conserva el formato del programa C++ original: 8000 Hz, mono, PCM signed 8-bit por radio. +/// +internal sealed class AudioEngine : IDisposable +{ + private const int SampleRate = 8000; + private const int Channels = 1; + private const int MicrophoneFrameSamples = 1600; + + private readonly object _stateLock = new(); + private readonly object _captureLock = new(); + private readonly MicrophoneFilter _microphoneFilter = new(); + private readonly sbyte[] _microphoneFrame = new sbyte[MicrophoneFrameSamples]; + + private WaveInEvent? _capture; + private WaveOutEvent? _playback; + private BufferedWaveProvider? _playbackBuffer; + + private int _microphoneFrameIndex; + private bool _started; + private bool _pttActive; + private float _microphoneGain = 1.0f; + private float _playbackGain = 1.0f; + + public event EventHandler? MicrophoneFrameReady; + public event EventHandler? Error; + + public bool IsStarted + { + get + { + lock (_stateLock) + { + return _started; + } + } + } + + public bool PttActive + { + get + { + lock (_captureLock) + { + return _pttActive; + } + } + } + + public void Start() + { + lock (_stateLock) + { + if (_started) + { + return; + } + + var playbackBuffer = new BufferedWaveProvider(new WaveFormat(SampleRate, 16, Channels)) + { + BufferDuration = TimeSpan.FromSeconds(2), + DiscardOnBufferOverflow = true, + ReadFully = true + }; + + var playback = new WaveOutEvent + { + DesiredLatency = 100, + NumberOfBuffers = 3 + }; + + var capture = new WaveInEvent + { + WaveFormat = new WaveFormat(SampleRate, 16, Channels), + BufferMilliseconds = 20, + NumberOfBuffers = 4 + }; + + capture.DataAvailable += Capture_DataAvailable; + capture.RecordingStopped += Capture_RecordingStopped; + + try + { + playback.Init(playbackBuffer); + playback.Play(); + + _playbackBuffer = playbackBuffer; + _playback = playback; + _capture = capture; + _started = true; + + ResetMicrophoneState(); + //capture.StartRecording(); + } + catch + { + capture.DataAvailable -= Capture_DataAvailable; + capture.RecordingStopped -= Capture_RecordingStopped; + capture.Dispose(); + + try + { + playback.Stop(); + } + catch + { + // No hay nada más que limpiar si el dispositivo no llegó a arrancar. + } + + playback.Dispose(); + _playbackBuffer = null; + _playback = null; + _capture = null; + _started = false; + throw; + } + } + } + + public void Stop() + { + WaveInEvent? capture; + WaveOutEvent? playback; + + lock (_stateLock) + { + if (!_started && _capture is null && _playback is null) + { + return; + } + + _started = false; + capture = _capture; + playback = _playback; + _capture = null; + _playback = null; + _playbackBuffer = null; + } + + SetPtt(false); + + if (capture is not null) + { + capture.DataAvailable -= Capture_DataAvailable; + capture.RecordingStopped -= Capture_RecordingStopped; + + try + { + capture.StopRecording(); + } + catch + { + // El dispositivo puede estar ya detenido si se desconectó físicamente. + } + + capture.Dispose(); + } + + if (playback is not null) + { + try + { + playback.Stop(); + } + catch + { + // El dispositivo puede estar ya detenido si se desconectó físicamente. + } + + playback.Dispose(); + } + + ResetMicrophoneState(); + } + + public void SetPtt(bool active) + { + lock (_captureLock) + { + if (_pttActive == active) + { + return; + } + + _pttActive = active; + _microphoneFrameIndex = 0; + _microphoneFilter.Reset(); + } + + // No se vacia ni se detiene la reproduccion al cambiar el PTT. + // Captura y salida permanecen activas de forma simultanea. + } + + public void SetMicrophoneGain(float gain) + { + lock (_captureLock) + { + _microphoneGain = Math.Clamp(gain, 0.0f, 2.0f); + } + } + + public void SetPlaybackGain(float gain) + { + lock (_stateLock) + { + _playbackGain = Math.Clamp(gain, 0.0f, 2.0f); + } + } + + public void PushReceivedFrame(sbyte[] frame) + { + if (frame.Length == 0) + { + return; + } + + lock (_stateLock) + { + if (!_started || _playbackBuffer is null) + { + return; + } + + // Si se ha acumulado demasiado audio, vaciamos para no escuchar voz atrasada. + if (_playbackBuffer.BufferedDuration > TimeSpan.FromMilliseconds(900)) + { + _playbackBuffer.ClearBuffer(); + } + + var pcm16 = new byte[frame.Length * 2]; + float gain = _playbackGain; + + for (int i = 0; i < frame.Length; i++) + { + int sample = (int)MathF.Round(frame[i] * 256.0f * gain); + sample = Math.Clamp(sample, short.MinValue, short.MaxValue); + + short sample16 = (short)sample; + pcm16[i * 2] = (byte)(sample16 & 0xFF); + pcm16[i * 2 + 1] = (byte)((sample16 >> 8) & 0xFF); + } + + _playbackBuffer.AddSamples(pcm16, 0, pcm16.Length); + } + } + + public void ClearPlaybackBuffer() + { + lock (_stateLock) + { + _playbackBuffer?.ClearBuffer(); + } + } + + private void Capture_DataAvailable(object? sender, WaveInEventArgs e) + { + List? completedFrames = null; + + lock (_captureLock) + { + if (!_pttActive) + { + _microphoneFrameIndex = 0; + return; + } + + float gain = _microphoneGain; + + // El formato solicitado a NAudio es signed 16-bit, mono, little-endian. + for (int i = 0; i + 1 < e.BytesRecorded; i += 2) + { + short inputSample = (short)(e.Buffer[i] | (e.Buffer[i + 1] << 8)); + short filteredSample = _microphoneFilter.Process(inputSample); + + int amplified = (int)MathF.Round(filteredSample * gain); + amplified = Math.Clamp(amplified, short.MinValue, short.MaxValue); + + _microphoneFrame[_microphoneFrameIndex] = (sbyte)(amplified >> 8); + _microphoneFrameIndex++; + + if (_microphoneFrameIndex >= MicrophoneFrameSamples) + { + var frame = new sbyte[MicrophoneFrameSamples]; + Array.Copy(_microphoneFrame, frame, MicrophoneFrameSamples); + + completedFrames ??= new List(); + completedFrames.Add(frame); + _microphoneFrameIndex = 0; + } + } + } + + if (completedFrames is null) + { + return; + } + + foreach (sbyte[] frame in completedFrames) + { + MicrophoneFrameReady?.Invoke(this, frame); + } + } + + private void Capture_RecordingStopped(object? sender, StoppedEventArgs e) + { + if (e.Exception is not null) + { + Error?.Invoke(this, $"El micrófono se detuvo: {e.Exception.Message}"); + } + } + + private void ResetMicrophoneState() + { + lock (_captureLock) + { + _microphoneFrameIndex = 0; + _microphoneFilter.Reset(); + } + } + + public void Dispose() + { + Stop(); + } + + /// + /// Filtro trasladado del programa C++: pasa-altos, pasa-bajos y noise gate. + /// + private sealed class MicrophoneFilter + { + private const int NoiseGateOpenThreshold = 800; + private const int NoiseGateCloseThreshold = 400; + private const int NoiseGateHoldSamples = 640; + + private const int HighPassRQ8 = 250; + private const int LowPassAlphaQ8 = 170; + private const int GateAttackQ8 = 24; + private const int GateReleaseQ8 = 6; + + private int _highPassPreviousInput; + private int _highPassPreviousOutput; + private int _lowPassOutput; + private int _gateHold; + private int _gateLevelQ8; + + public short Process(short sample) + { + int input = sample; + + int highPass = input - _highPassPreviousInput + + ((_highPassPreviousOutput * HighPassRQ8) / 256); + + _highPassPreviousInput = input; + _highPassPreviousOutput = highPass; + highPass = Math.Clamp(highPass, short.MinValue, short.MaxValue); + + _lowPassOutput += ((highPass - _lowPassOutput) * LowPassAlphaQ8) / 256; + _lowPassOutput = Math.Clamp(_lowPassOutput, short.MinValue, short.MaxValue); + + int amplitude = Math.Abs(_lowPassOutput); + + if (amplitude >= NoiseGateOpenThreshold) + { + _gateHold = NoiseGateHoldSamples; + } + else if (_gateHold > 0) + { + _gateHold--; + } + + if (_gateHold > 0 || amplitude >= NoiseGateOpenThreshold) + { + _gateLevelQ8 = Math.Min(256, _gateLevelQ8 + GateAttackQ8); + } + else if (amplitude <= NoiseGateCloseThreshold) + { + _gateLevelQ8 = Math.Max(0, _gateLevelQ8 - GateReleaseQ8); + } + else + { + _gateLevelQ8 = Math.Max(0, _gateLevelQ8 - GateReleaseQ8); + } + + int output = (_lowPassOutput * _gateLevelQ8) / 256; + + // Elimina los últimos residuos digitales cuando la puerta está casi cerrada. + if (_gateLevelQ8 == 0 || Math.Abs(output) < 16) + { + output = 0; + } + + output = Math.Clamp(output, short.MinValue, short.MaxValue); + return (short)output; + } + + public void Reset() + { + _highPassPreviousInput = 0; + _highPassPreviousOutput = 0; + _lowPassOutput = 0; + _gateHold = 0; + _gateLevelQ8 = 0; + } + } +} diff --git a/Radio/App_radio/Backup/App_radio.slnx b/Radio/App_radio/Backup/App_radio.slnx new file mode 100644 index 0000000..3552d82 --- /dev/null +++ b/Radio/App_radio/Backup/App_radio.slnx @@ -0,0 +1,3 @@ + + + diff --git a/Radio/App_radio/Program.cs b/Radio/App_radio/Program.cs new file mode 100644 index 0000000..0a2c395 --- /dev/null +++ b/Radio/App_radio/Program.cs @@ -0,0 +1,17 @@ +namespace App_radio +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new RadioMain()); + } + } +} \ No newline at end of file diff --git a/Radio/App_radio/RadioController.cs b/Radio/App_radio/RadioController.cs new file mode 100644 index 0000000..cc892ec --- /dev/null +++ b/Radio/App_radio/RadioController.cs @@ -0,0 +1,402 @@ +using System.Threading.Channels; + +namespace App_radio; + +/// +/// Une la interfaz, el audio y el puerto serie. +/// +internal sealed class RadioController : IDisposable +{ + private const int MaxQueuedMicrophoneFrames = 2; + + private readonly RadioSerialService _serial = new(); + private readonly AudioEngine _audio = new(); + private readonly object _stateLock = new(); + private readonly object _pttSessionLock = new(); + + private Channel? _transmitChannel; + private CancellationTokenSource? _transmitCancellation; + private Task? _transmitTask; + private bool _connected; + private int _pttActive; + private int _pttSessionId; + private int _queuedMicrophoneFrames; + private bool _disposed; + + public event EventHandler? Error; + public event EventHandler? PilotAudioReceived; + public event EventHandler? ConnectionFaulted; + + public RadioController() + { + _serial.AudioFrameReceived += Serial_AudioFrameReceived; + _serial.Error += Serial_Error; + _audio.MicrophoneFrameReady += Audio_MicrophoneFrameReady; + _audio.Error += Audio_Error; + } + + public bool IsConnected => Volatile.Read(ref _connected) && _serial.IsOpen; + + public bool IsPttActive => Volatile.Read(ref _pttActive) != 0; + + public void Connect(string portName) + { + ThrowIfDisposed(); + + lock (_stateLock) + { + if (_connected) + { + return; + } + } + + var channel = Channel.CreateUnbounded(new UnboundedChannelOptions + { + SingleReader = true, + SingleWriter = false, + AllowSynchronousContinuations = false + }); + + var cancellation = new CancellationTokenSource(); + + try + { + _serial.Open(portName); + _audio.Start(); + + lock (_stateLock) + { + _transmitChannel = channel; + _transmitCancellation = cancellation; + Volatile.Write(ref _connected, true); + Volatile.Write(ref _pttActive, 0); + Volatile.Write(ref _queuedMicrophoneFrames, 0); + _pttSessionId = 0; + _transmitTask = Task.Run(() => TransmitLoopAsync(channel.Reader, cancellation.Token), cancellation.Token); + } + } + catch + { + cancellation.Cancel(); + cancellation.Dispose(); + _audio.Stop(); + _serial.Close(); + throw; + } + } + + public async Task DisconnectAsync() + { + Channel? channel; + CancellationTokenSource? cancellation; + Task? transmitTask; + + bool alreadyDisconnected; + + lock (_stateLock) + { + alreadyDisconnected = !_connected && _transmitTask is null; + Volatile.Write(ref _connected, false); + + channel = _transmitChannel; + cancellation = _transmitCancellation; + transmitTask = _transmitTask; + + _transmitChannel = null; + _transmitCancellation = null; + _transmitTask = null; + } + + if (alreadyDisconnected) + { + _audio.Stop(); + _serial.Close(); + return; + } + + SetPtt(false); + _audio.Stop(); + + channel?.Writer.TryComplete(); + cancellation?.Cancel(); + + if (transmitTask is not null) + { + try + { + await transmitTask.ConfigureAwait(false); + } + catch (OperationCanceledException) + { + // Cancelación normal al desconectar. + } + } + + cancellation?.Dispose(); + Volatile.Write(ref _queuedMicrophoneFrames, 0); + _serial.Close(); + } + + public bool SetPtt(bool active) + { + if (active && !IsConnected) + { + return false; + } + + lock (_pttSessionLock) + { + int requestedState = active ? 1 : 0; + int previousState = Volatile.Read(ref _pttActive); + + if (previousState == requestedState) + { + return true; + } + + Channel? channel; + lock (_stateLock) + { + channel = _transmitChannel; + } + + try + { + if (active) + { + unchecked + { + ++_pttSessionId; + } + + // START y el modo de transmisión se activan bajo el mismo lock + // de escritura. Así no puede cruzarse un STOP de la pulsación anterior. + _serial.BeginTransmitSession(); + Volatile.Write(ref _pttActive, 1); + _audio.SetPtt(true); + } + else + { + // Se deja de capturar inmediatamente, pero NO se vacía la cola ni se + // desactiva el puerto. El marcador END se procesa después de todos los + // frames ya grabados y solo entonces envía STOP al piloto. + Volatile.Write(ref _pttActive, 0); + _audio.SetPtt(false); + + if (channel is not null) + { + channel.Writer.TryWrite(TransmitItem.EndPtt(_pttSessionId)); + } + else + { + _serial.EndTransmitSession(); + } + } + + return true; + } + catch (Exception ex) when (ex is IOException + or InvalidOperationException + or UnauthorizedAccessException + or TimeoutException) + { + _audio.SetPtt(false); + _serial.SetTransmitMode(false); + Volatile.Write(ref _pttActive, 0); + Error?.Invoke(this, $"Error cambiando el PTT: {ex.Message}"); + ConnectionFaulted?.Invoke(this, EventArgs.Empty); + return false; + } + } + } + + public void SetBoxVolume(int percent, bool muted) + { + float gain = muted ? 0.0f : PercentToGain(percent); + _audio.SetPlaybackGain(gain); + } + + public void SetPilotVolume(int percent, bool muted) + { + float gain = muted ? 0.0f : PercentToGain(percent); + _audio.SetMicrophoneGain(gain); + } + + public static float PercentToGain(int percent) + { + // 0 -> 0.00x, 50 -> 1.00x y 100 -> 2.00x. + // Así el control no multiplica directamente por 50 ni por 100. + return Math.Clamp(percent, 0, 100) / 50.0f; + } + + private async Task TransmitLoopAsync(ChannelReader reader, CancellationToken cancellationToken) + { + try + { + await foreach (TransmitItem item in reader.ReadAllAsync(cancellationToken)) + { + if (item.Kind == TransmitItemKind.Audio) + { + try + { + if (IsConnected && item.Audio is not null) + { + // Los frames que ya estaban en la cola se envían aunque el + // usuario haya soltado PTT. Eso conserva el final del mensaje. + _serial.SendAudioFrame(item.Audio); + } + } + catch (Exception ex) when (ex is IOException + or InvalidOperationException + or UnauthorizedAccessException + or TimeoutException) + { + Error?.Invoke(this, $"Error enviando audio: {ex.Message}"); + ConnectionFaulted?.Invoke(this, EventArgs.Empty); + return; + } + finally + { + Interlocked.Decrement(ref _queuedMicrophoneFrames); + } + + continue; + } + + lock (_pttSessionLock) + { + // Si el usuario volvió a pulsar antes de llegar aquí, este END es + // antiguo y no debe mandar STOP ni cerrar la nueva transmisión. + if (!IsConnected || IsPttActive || item.SessionId != _pttSessionId) + { + continue; + } + + try + { + _serial.EndTransmitSession(); + } + catch (Exception ex) when (ex is IOException + or InvalidOperationException + or UnauthorizedAccessException + or TimeoutException) + { + Error?.Invoke(this, $"Error terminando el envío de audio: {ex.Message}"); + ConnectionFaulted?.Invoke(this, EventArgs.Empty); + return; + } + } + } + } + catch (OperationCanceledException) + { + // Cancelación normal al desconectar. + } + } + + private void Audio_MicrophoneFrameReady(object? sender, sbyte[] frame) + { + lock (_pttSessionLock) + { + Channel? channel; + int sessionId; + + lock (_stateLock) + { + if (!_connected || !IsPttActive) + { + return; + } + + channel = _transmitChannel; + sessionId = _pttSessionId; + } + + if (channel is null) + { + return; + } + + int queued = Interlocked.Increment(ref _queuedMicrophoneFrames); + if (queued > MaxQueuedMicrophoneFrames) + { + Interlocked.Decrement(ref _queuedMicrophoneFrames); + return; + } + + if (!channel.Writer.TryWrite(TransmitItem.AudioFrame(frame, sessionId))) + { + Interlocked.Decrement(ref _queuedMicrophoneFrames); + } + } + } + + private void Serial_AudioFrameReceived(object? sender, sbyte[] frame) + { + // La recepción no depende del PTT: el box puede transmitir y escuchar + // al piloto simultáneamente. + if (!IsConnected) + { + return; + } + + _audio.PushReceivedFrame(frame); + PilotAudioReceived?.Invoke(this, EventArgs.Empty); + } + + private void Serial_Error(object? sender, string message) + { + Error?.Invoke(this, message); + } + + private void Audio_Error(object? sender, string message) + { + Error?.Invoke(this, message); + ConnectionFaulted?.Invoke(this, EventArgs.Empty); + } + + private void ThrowIfDisposed() + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(RadioController)); + } + } + + public void Dispose() + { + if (_disposed) + { + return; + } + + _disposed = true; + + try + { + DisconnectAsync().GetAwaiter().GetResult(); + } + finally + { + _audio.MicrophoneFrameReady -= Audio_MicrophoneFrameReady; + _audio.Error -= Audio_Error; + _serial.AudioFrameReceived -= Serial_AudioFrameReceived; + _serial.Error -= Serial_Error; + _audio.Dispose(); + _serial.Dispose(); + } + } + + private enum TransmitItemKind + { + Audio, + EndPtt + } + + private readonly record struct TransmitItem(TransmitItemKind Kind, sbyte[]? Audio, int SessionId) + { + public static TransmitItem AudioFrame(sbyte[] audio, int sessionId) => new(TransmitItemKind.Audio, audio, sessionId); + public static TransmitItem EndPtt(int sessionId) => new(TransmitItemKind.EndPtt, null, sessionId); + } +} diff --git a/Radio/App_radio/RadioMain.Designer.cs b/Radio/App_radio/RadioMain.Designer.cs new file mode 100644 index 0000000..f94586d --- /dev/null +++ b/Radio/App_radio/RadioMain.Designer.cs @@ -0,0 +1,348 @@ +namespace App_radio +{ + partial class RadioMain + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + PuertoLabel = new Label(); + PuertoBox = new ComboBox(); + ActualizarButton = new Button(); + ConectarButton = new Button(); + PuertosTab = new TabControl(); + ComunicacionTab = new TabPage(); + label2 = new Label(); + EstadoRadioLabel = new Label(); + PttButton = new Button(); + tabPage1 = new TabPage(); + ConectadoPilotoLabel = new Label(); + ConectadoBoxLabel = new Label(); + EstadoPilotoLabel = new Label(); + EstadoBoxLabel = new Label(); + VolumenTab = new TabPage(); + SilenciarPilotoCheck = new CheckBox(); + SilenciarBoxCheck = new CheckBox(); + VolumenPilotoUpdown = new NumericUpDown(); + VolumenBoxUpdown = new NumericUpDown(); + VolumenPilotoLabel = new Label(); + VolumenBoxLabel = new Label(); + RegistrosTab = new TabPage(); + RegistrosTextBox = new RichTextBox(); + PuertosTab.SuspendLayout(); + ComunicacionTab.SuspendLayout(); + tabPage1.SuspendLayout(); + VolumenTab.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)VolumenPilotoUpdown).BeginInit(); + ((System.ComponentModel.ISupportInitialize)VolumenBoxUpdown).BeginInit(); + RegistrosTab.SuspendLayout(); + SuspendLayout(); + // + // PuertoLabel + // + PuertoLabel.AutoSize = true; + PuertoLabel.Location = new Point(17, 46); + PuertoLabel.Name = "PuertoLabel"; + PuertoLabel.Size = new Size(98, 15); + PuertoLabel.TabIndex = 0; + PuertoLabel.Text = "Selección puerto:"; + // + // PuertoBox + // + PuertoBox.FormattingEnabled = true; + PuertoBox.Location = new Point(143, 43); + PuertoBox.Name = "PuertoBox"; + PuertoBox.Size = new Size(121, 23); + PuertoBox.TabIndex = 1; + // + // ActualizarButton + // + ActualizarButton.Location = new Point(298, 42); + ActualizarButton.Name = "ActualizarButton"; + ActualizarButton.Size = new Size(75, 23); + ActualizarButton.TabIndex = 2; + ActualizarButton.Text = "Actualizar"; + ActualizarButton.UseVisualStyleBackColor = true; + // + // ConectarButton + // + ConectarButton.Location = new Point(389, 42); + ConectarButton.Name = "ConectarButton"; + ConectarButton.Size = new Size(75, 23); + ConectarButton.TabIndex = 3; + ConectarButton.Text = "Conectar\r\n"; + ConectarButton.UseVisualStyleBackColor = true; + // + // PuertosTab + // + PuertosTab.Controls.Add(ComunicacionTab); + PuertosTab.Controls.Add(tabPage1); + PuertosTab.Controls.Add(VolumenTab); + PuertosTab.Controls.Add(RegistrosTab); + PuertosTab.Dock = DockStyle.Fill; + PuertosTab.Location = new Point(0, 0); + PuertosTab.Name = "PuertosTab"; + PuertosTab.SelectedIndex = 0; + PuertosTab.Size = new Size(500, 248); + PuertosTab.TabIndex = 4; + // + // ComunicacionTab + // + ComunicacionTab.Controls.Add(label2); + ComunicacionTab.Controls.Add(EstadoRadioLabel); + ComunicacionTab.Controls.Add(PttButton); + ComunicacionTab.Location = new Point(4, 24); + ComunicacionTab.Name = "ComunicacionTab"; + ComunicacionTab.Padding = new Padding(3); + ComunicacionTab.Size = new Size(492, 220); + ComunicacionTab.TabIndex = 3; + ComunicacionTab.Text = "Comunicacion"; + ComunicacionTab.UseVisualStyleBackColor = true; + // + // label2 + // + label2.AutoSize = true; + label2.ForeColor = Color.Gray; + label2.Location = new Point(248, 174); + label2.Name = "label2"; + label2.Size = new Size(87, 15); + label2.TabIndex = 2; + label2.Text = "● Desconectada"; + // + // EstadoRadioLabel + // + EstadoRadioLabel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; + EstadoRadioLabel.AutoSize = true; + EstadoRadioLabel.Location = new Point(146, 174); + EstadoRadioLabel.Name = "EstadoRadioLabel"; + EstadoRadioLabel.Size = new Size(75, 15); + EstadoRadioLabel.TabIndex = 1; + EstadoRadioLabel.Text = "Estado radio:"; + // + // PttButton + // + PttButton.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0); + PttButton.Location = new Point(98, 26); + PttButton.Name = "PttButton"; + PttButton.Size = new Size(273, 126); + PttButton.TabIndex = 0; + PttButton.Text = "Pulsar para hablar"; + PttButton.UseVisualStyleBackColor = true; + // + // tabPage1 + // + tabPage1.Controls.Add(ConectadoPilotoLabel); + tabPage1.Controls.Add(ConectadoBoxLabel); + tabPage1.Controls.Add(EstadoPilotoLabel); + tabPage1.Controls.Add(EstadoBoxLabel); + tabPage1.Controls.Add(PuertoLabel); + tabPage1.Controls.Add(ConectarButton); + tabPage1.Controls.Add(PuertoBox); + tabPage1.Controls.Add(ActualizarButton); + tabPage1.Location = new Point(4, 24); + tabPage1.Name = "tabPage1"; + tabPage1.Padding = new Padding(3); + tabPage1.Size = new Size(492, 220); + tabPage1.TabIndex = 0; + tabPage1.Text = "Puertos"; + tabPage1.UseVisualStyleBackColor = true; + // + // ConectadoPilotoLabel + // + ConectadoPilotoLabel.AutoSize = true; + ConectadoPilotoLabel.ForeColor = Color.Gray; + ConectadoPilotoLabel.Location = new Point(143, 146); + ConectadoPilotoLabel.Name = "ConectadoPilotoLabel"; + ConectadoPilotoLabel.Size = new Size(75, 15); + ConectadoPilotoLabel.TabIndex = 7; + ConectadoPilotoLabel.Text = "● Desconectado"; + // + // ConectadoBoxLabel + // + ConectadoBoxLabel.AutoSize = true; + ConectadoBoxLabel.ForeColor = Color.Gray; + ConectadoBoxLabel.Location = new Point(143, 111); + ConectadoBoxLabel.Name = "ConectadoBoxLabel"; + ConectadoBoxLabel.Size = new Size(75, 15); + ConectadoBoxLabel.TabIndex = 6; + ConectadoBoxLabel.Text = "● Desconectado"; + // + // EstadoPilotoLabel + // + EstadoPilotoLabel.AutoSize = true; + EstadoPilotoLabel.Location = new Point(17, 146); + EstadoPilotoLabel.Name = "EstadoPilotoLabel"; + EstadoPilotoLabel.Size = new Size(109, 15); + EstadoPilotoLabel.TabIndex = 5; + EstadoPilotoLabel.Text = "Estado radio piloto:"; + // + // EstadoBoxLabel + // + EstadoBoxLabel.AutoSize = true; + EstadoBoxLabel.Location = new Point(17, 111); + EstadoBoxLabel.Name = "EstadoBoxLabel"; + EstadoBoxLabel.Size = new Size(97, 15); + EstadoBoxLabel.TabIndex = 4; + EstadoBoxLabel.Text = "Estado radio box:"; + // + // VolumenTab + // + VolumenTab.Controls.Add(SilenciarPilotoCheck); + VolumenTab.Controls.Add(SilenciarBoxCheck); + VolumenTab.Controls.Add(VolumenPilotoUpdown); + VolumenTab.Controls.Add(VolumenBoxUpdown); + VolumenTab.Controls.Add(VolumenPilotoLabel); + VolumenTab.Controls.Add(VolumenBoxLabel); + VolumenTab.Location = new Point(4, 24); + VolumenTab.Name = "VolumenTab"; + VolumenTab.Padding = new Padding(3); + VolumenTab.Size = new Size(492, 220); + VolumenTab.TabIndex = 1; + VolumenTab.Text = "Volumen"; + VolumenTab.UseVisualStyleBackColor = true; + // + // SilenciarPilotoCheck + // + SilenciarPilotoCheck.AutoSize = true; + SilenciarPilotoCheck.Location = new Point(309, 91); + SilenciarPilotoCheck.Name = "SilenciarPilotoCheck"; + SilenciarPilotoCheck.Size = new Size(70, 19); + SilenciarPilotoCheck.TabIndex = 5; + SilenciarPilotoCheck.Text = "Silenciar"; + SilenciarPilotoCheck.UseVisualStyleBackColor = true; + // + // SilenciarBoxCheck + // + SilenciarBoxCheck.AutoSize = true; + SilenciarBoxCheck.Location = new Point(309, 43); + SilenciarBoxCheck.Name = "SilenciarBoxCheck"; + SilenciarBoxCheck.Size = new Size(70, 19); + SilenciarBoxCheck.TabIndex = 4; + SilenciarBoxCheck.Text = "Silenciar"; + SilenciarBoxCheck.UseVisualStyleBackColor = true; + // + // VolumenPilotoUpdown + // + VolumenPilotoUpdown.Location = new Point(155, 87); + VolumenPilotoUpdown.Name = "VolumenPilotoUpdown"; + VolumenPilotoUpdown.Size = new Size(120, 23); + VolumenPilotoUpdown.TabIndex = 3; + VolumenPilotoUpdown.Value = new decimal(new int[] { 50, 0, 0, 0 }); + // + // VolumenBoxUpdown + // + VolumenBoxUpdown.Location = new Point(155, 39); + VolumenBoxUpdown.Name = "VolumenBoxUpdown"; + VolumenBoxUpdown.Size = new Size(120, 23); + VolumenBoxUpdown.TabIndex = 2; + VolumenBoxUpdown.Value = new decimal(new int[] { 50, 0, 0, 0 }); + // + // VolumenPilotoLabel + // + VolumenPilotoLabel.AutoSize = true; + VolumenPilotoLabel.Location = new Point(29, 89); + VolumenPilotoLabel.Name = "VolumenPilotoLabel"; + VolumenPilotoLabel.Size = new Size(91, 15); + VolumenPilotoLabel.TabIndex = 1; + VolumenPilotoLabel.Text = "Volumen piloto:"; + // + // VolumenBoxLabel + // + VolumenBoxLabel.AutoSize = true; + VolumenBoxLabel.Location = new Point(29, 41); + VolumenBoxLabel.Name = "VolumenBoxLabel"; + VolumenBoxLabel.Size = new Size(79, 15); + VolumenBoxLabel.TabIndex = 0; + VolumenBoxLabel.Text = "Volumen box:"; + // + // RegistrosTab + // + RegistrosTab.Controls.Add(RegistrosTextBox); + RegistrosTab.Location = new Point(4, 24); + RegistrosTab.Name = "RegistrosTab"; + RegistrosTab.Padding = new Padding(3); + RegistrosTab.Size = new Size(492, 220); + RegistrosTab.TabIndex = 2; + RegistrosTab.Text = "Registros"; + RegistrosTab.UseVisualStyleBackColor = true; + // + // RegistrosTextBox + // + RegistrosTextBox.Dock = DockStyle.Fill; + RegistrosTextBox.Location = new Point(3, 3); + RegistrosTextBox.Name = "RegistrosTextBox"; + RegistrosTextBox.ReadOnly = true; + RegistrosTextBox.Size = new Size(486, 214); + RegistrosTextBox.TabIndex = 0; + RegistrosTextBox.Text = ""; + // + // RadioMain + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(500, 248); + Controls.Add(PuertosTab); + Name = "RadioMain"; + Text = "Radio - Formula Gades"; + PuertosTab.ResumeLayout(false); + ComunicacionTab.ResumeLayout(false); + ComunicacionTab.PerformLayout(); + tabPage1.ResumeLayout(false); + tabPage1.PerformLayout(); + VolumenTab.ResumeLayout(false); + VolumenTab.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)VolumenPilotoUpdown).EndInit(); + ((System.ComponentModel.ISupportInitialize)VolumenBoxUpdown).EndInit(); + RegistrosTab.ResumeLayout(false); + ResumeLayout(false); + } + + #endregion + + private Label PuertoLabel; + private ComboBox PuertoBox; + private Button ActualizarButton; + private Button ConectarButton; + private TabControl PuertosTab; + private TabPage tabPage1; + private TabPage VolumenTab; + private Label VolumenBoxLabel; + private Label VolumenPilotoLabel; + private NumericUpDown VolumenPilotoUpdown; + private NumericUpDown VolumenBoxUpdown; + private CheckBox SilenciarBoxCheck; + private CheckBox SilenciarPilotoCheck; + private TabPage RegistrosTab; + private Label EstadoPilotoLabel; + private Label EstadoBoxLabel; + private Label ConectadoPilotoLabel; + private Label ConectadoBoxLabel; + private TabPage ComunicacionTab; + private Button PttButton; + private Label label2; + private Label EstadoRadioLabel; + private RichTextBox RegistrosTextBox; + } +} diff --git a/Radio/App_radio/RadioMain.cs b/Radio/App_radio/RadioMain.cs new file mode 100644 index 0000000..8693f0a --- /dev/null +++ b/Radio/App_radio/RadioMain.cs @@ -0,0 +1,458 @@ +using System.IO.Ports; + +namespace App_radio; + +public partial class RadioMain : Form +{ + private readonly RadioController _radioController = new(); + + private bool _pilotConfirmed; + private bool _disconnectingAfterFault; + private bool _closing; + private bool _closeReady; + private bool _pttTransitionInProgress; + + public RadioMain() + { + InitializeComponent(); + ConfigureControls(); + SubscribeEvents(); + LoadPorts(); + ApplyVolumes(); + ShowDisconnectedState(); + AddLog("Aplicación iniciada."); + } + + private void ConfigureControls() + { + PuertoBox.DropDownStyle = ComboBoxStyle.DropDownList; + + VolumenBoxUpdown.Minimum = 0; + VolumenBoxUpdown.Maximum = 100; + VolumenBoxUpdown.Increment = 1; + + VolumenPilotoUpdown.Minimum = 0; + VolumenPilotoUpdown.Maximum = 100; + VolumenPilotoUpdown.Increment = 1; + + PttButton.Enabled = false; + PttButton.Cursor = Cursors.Hand; + } + + private void SubscribeEvents() + { + ActualizarButton.Click += ActualizarButton_Click; + ConectarButton.Click += ConectarButton_Click; + + PttButton.MouseDown += PttButton_MouseDown; + PttButton.MouseUp += PttButton_MouseUp; + PttButton.MouseCaptureChanged += PttButton_MouseCaptureChanged; + + VolumenBoxUpdown.ValueChanged += VolumeControl_Changed; + VolumenPilotoUpdown.ValueChanged += VolumeControl_Changed; + SilenciarBoxCheck.CheckedChanged += VolumeControl_Changed; + SilenciarPilotoCheck.CheckedChanged += VolumeControl_Changed; + + Deactivate += RadioMain_Deactivate; + FormClosing += RadioMain_FormClosing; + + _radioController.Error += RadioController_Error; + _radioController.PilotAudioReceived += RadioController_PilotAudioReceived; + _radioController.ConnectionFaulted += RadioController_ConnectionFaulted; + } + + private void LoadPorts() + { + string? previousSelection = PuertoBox.SelectedItem?.ToString(); + + PuertoBox.Items.Clear(); + string[] availablePorts = SerialPort.GetPortNames(); + Array.Sort(availablePorts, ComparePortNames); + PuertoBox.Items.AddRange(availablePorts); + + if (previousSelection is not null && PuertoBox.Items.Contains(previousSelection)) + { + PuertoBox.SelectedItem = previousSelection; + } + else if (PuertoBox.Items.Count > 0) + { + PuertoBox.SelectedIndex = 0; + } + + if (PuertoBox.Items.Count == 0) + { + AddLog("No se ha encontrado ningún puerto COM."); + } + } + + private static int ComparePortNames(string? left, string? right) + { + int leftNumber = ExtractPortNumber(left); + int rightNumber = ExtractPortNumber(right); + + int numberComparison = leftNumber.CompareTo(rightNumber); + return numberComparison != 0 + ? numberComparison + : string.Compare(left, right, StringComparison.OrdinalIgnoreCase); + } + + private static int ExtractPortNumber(string? portName) + { + if (portName is not null + && portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase) + && int.TryParse(portName.AsSpan(3), out int number)) + { + return number; + } + + return int.MaxValue; + } + + private void ActualizarButton_Click(object? sender, EventArgs e) + { + LoadPorts(); + AddLog($"Puertos actualizados: {PuertoBox.Items.Count} encontrado(s)."); + } + + private async void ConectarButton_Click(object? sender, EventArgs e) + { + if (_radioController.IsConnected) + { + await DisconnectRadioAsync("Desconectado por el usuario."); + return; + } + + string? selectedPort = PuertoBox.SelectedItem?.ToString(); + if (string.IsNullOrWhiteSpace(selectedPort)) + { + MessageBox.Show( + this, + "Selecciona un puerto COM antes de conectar.", + "Puerto no seleccionado", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + return; + } + + SetConnectionControlsEnabled(false); + SetStatus(ConectadoBoxLabel, "● Conectando...", Color.DarkOrange); + SetGeneralRadioStatus("● Conectando...", Color.DarkOrange); + AddLog($"Abriendo {selectedPort} a 115200 baudios..."); + + try + { + await Task.Run(() => _radioController.Connect(selectedPort)); + + _pilotConfirmed = false; + SetStatus(ConectadoBoxLabel, "● Conectado", Color.Green); + SetStatus(ConectadoPilotoLabel, "● Sin confirmar", Color.Gray); + SetGeneralRadioStatus("● Escuchando", Color.Green); + + ConectarButton.Text = "Desconectar"; + PttButton.Enabled = true; + PuertoBox.Enabled = false; + ActualizarButton.Enabled = false; + ConectarButton.Enabled = true; + + ApplyVolumes(); + AddLog($"Radio del box conectada en {selectedPort}."); + AddLog("Mantén pulsado el botón PTT para hablar."); + } + catch (Exception ex) + { + ShowDisconnectedState(); + AddLog($"No se pudo conectar: {ex.Message}"); + + MessageBox.Show( + this, + $"No se pudo iniciar la radio.\n\n{ex.Message}", + "Error de conexión", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + } + } + + private void PttButton_MouseDown(object? sender, MouseEventArgs e) + { + if (e.Button != MouseButtons.Left || !_radioController.IsConnected) + { + return; + } + + PttButton.Capture = true; + + if (_radioController.SetPtt(true)) + { + PttButton.Text = "HABLANDO...\nEscucha simultánea activa"; + PttButton.UseVisualStyleBackColor = false; + PttButton.BackColor = Color.IndianRed; + SetGeneralRadioStatus("● Transmitiendo y escuchando", Color.Red); + AddLog("PTT activado: transmitiendo y manteniendo activa la escucha."); + } + } + + private void PttButton_MouseUp(object? sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + StopPtt(); + } + } + + private void PttButton_MouseCaptureChanged(object? sender, EventArgs e) + { + if (!PttButton.Capture && _radioController.IsPttActive) + { + StopPtt(); + } + } + + private void RadioMain_Deactivate(object? sender, EventArgs e) + { + StopPtt(); + } + + private void StopPtt() + { + if (_pttTransitionInProgress) + { + return; + } + + _pttTransitionInProgress = true; + + try + { + bool wasActive = _radioController.IsPttActive; + + // El controlador corta la transmisión de forma inmediata y el + // servicio serie deja de enviar al terminar como máximo el fragmento + // actual de 200 bytes. + _radioController.SetPtt(false); + + PttButton.Capture = false; + PttButton.Text = "Pulsar para hablar"; + PttButton.UseVisualStyleBackColor = true; + PttButton.BackColor = SystemColors.Control; + + if (_radioController.IsConnected) + { + SetGeneralRadioStatus("● Escuchando", Color.Green); + } + else + { + SetGeneralRadioStatus("● Desconectada", Color.Gray); + } + + // Fuerza el repintado antes de añadir el registro, para que el botón + // nunca parezca quedarse pulsado mientras se actualiza el RichTextBox. + PttButton.Invalidate(); + PttButton.Update(); + + if (wasActive) + { + AddLog("PTT desactivado: escuchando la radio del piloto."); + } + } + finally + { + _pttTransitionInProgress = false; + } + } + + private void VolumeControl_Changed(object? sender, EventArgs e) + { + ApplyVolumes(); + } + + private void ApplyVolumes() + { + int boxPercent = Decimal.ToInt32(VolumenBoxUpdown.Value); + int pilotPercent = Decimal.ToInt32(VolumenPilotoUpdown.Value); + + _radioController.SetBoxVolume(boxPercent, SilenciarBoxCheck.Checked); + _radioController.SetPilotVolume(pilotPercent, SilenciarPilotoCheck.Checked); + } + + private void RadioController_PilotAudioReceived(object? sender, EventArgs e) + { + RunOnUiThread(() => + { + if (_pilotConfirmed) + { + return; + } + + _pilotConfirmed = true; + SetStatus(ConectadoPilotoLabel, "● Conectado", Color.Green); + AddLog("Se ha recibido un frame de audio válido de la radio del piloto."); + }); + } + + private void RadioController_Error(object? sender, string message) + { + AddLog(message); + } + + private void RadioController_ConnectionFaulted(object? sender, EventArgs e) + { + RunOnUiThread(async () => + { + if (_disconnectingAfterFault || !_radioController.IsConnected) + { + return; + } + + _disconnectingAfterFault = true; + try + { + await DisconnectRadioAsync("La conexión se ha cerrado por un error."); + } + finally + { + _disconnectingAfterFault = false; + } + }); + } + + private async Task DisconnectRadioAsync(string logMessage) + { + StopPtt(); + SetConnectionControlsEnabled(false); + + try + { + await _radioController.DisconnectAsync(); + } + catch (Exception ex) + { + AddLog($"Error al cerrar la conexión: {ex.Message}"); + } + finally + { + ShowDisconnectedState(); + AddLog(logMessage); + } + } + + private void ShowDisconnectedState() + { + _pilotConfirmed = false; + SetStatus(ConectadoBoxLabel, "● Desconectado", Color.Gray); + SetStatus(ConectadoPilotoLabel, "● Desconectado", Color.Gray); + SetGeneralRadioStatus("● Desconectada", Color.Gray); + + ConectarButton.Text = "Conectar"; + ConectarButton.Enabled = true; + PuertoBox.Enabled = true; + ActualizarButton.Enabled = true; + PttButton.Enabled = false; + PttButton.Text = "Pulsar para hablar"; + PttButton.UseVisualStyleBackColor = true; + PttButton.BackColor = SystemColors.Control; + } + + private void SetConnectionControlsEnabled(bool enabled) + { + ConectarButton.Enabled = enabled; + PuertoBox.Enabled = enabled; + ActualizarButton.Enabled = enabled; + PttButton.Enabled = enabled && _radioController.IsConnected; + } + + private static void SetStatus(Label label, string text, Color color) + { + label.Text = text; + label.ForeColor = color; + } + + private void SetGeneralRadioStatus(string text, Color color) + { + label2.Text = text; + label2.ForeColor = color; + } + + private void AddLog(string message) + { + RunOnUiThread(() => + { + if (RegistrosTextBox.TextLength > 100_000) + { + RegistrosTextBox.Select(0, 20_000); + RegistrosTextBox.SelectedText = string.Empty; + } + + RegistrosTextBox.AppendText( + $"[{DateTime.Now:HH:mm:ss}] {message}{Environment.NewLine}"); + RegistrosTextBox.SelectionStart = RegistrosTextBox.TextLength; + RegistrosTextBox.ScrollToCaret(); + }); + } + + private void RunOnUiThread(Action action) + { + if (IsDisposed || Disposing) + { + return; + } + + if (InvokeRequired) + { + try + { + BeginInvoke(action); + } + catch (InvalidOperationException) + { + // La ventana se está cerrando. + } + } + else + { + action(); + } + } + + private async void RadioMain_FormClosing(object? sender, FormClosingEventArgs e) + { + if (_closeReady) + { + return; + } + + e.Cancel = true; + + if (_closing) + { + return; + } + + _closing = true; + + // La ventana desaparece al instante. La limpieza del audio y del puerto + // se realiza después, con un límite de tiempo para que la X nunca deje la + // aplicación bloqueada en pantalla. + StopPtt(); + Enabled = false; + Hide(); + + Task disconnectTask = Task.Run(async () => await _radioController.DisconnectAsync()); + + try + { + await disconnectTask.WaitAsync(TimeSpan.FromSeconds(2)); + } + catch (TimeoutException) + { + // Cerramos igualmente la interfaz. La tarea de limpieza podrá acabar + // en segundo plano sin impedir que termine la aplicación. + } + catch (Exception) + { + // Durante el cierre no mostramos cuadros de error que puedan volver a + // bloquear la salida de la aplicación. + } + _closeReady = true; + Close(); + } +} diff --git a/Radio/App_radio/RadioMain.resx b/Radio/App_radio/RadioMain.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/Radio/App_radio/RadioMain.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Radio/App_radio/RadioSerialService.cs b/Radio/App_radio/RadioSerialService.cs new file mode 100644 index 0000000..6b14eb4 --- /dev/null +++ b/Radio/App_radio/RadioSerialService.cs @@ -0,0 +1,609 @@ +using System.IO.Ports; + +namespace App_radio; + +/// +/// Comunicación USB-serie con el ESP32 y protocolo de audio heredado del programa C++. +/// +internal sealed class RadioSerialService : IDisposable +{ + private const int BaudRate = 115200; + private const int AudioFrameMax = 1600; + private const int AudioChunkMax = 200; + private const int AudioChunkTotalMax = 8; + private const int HeaderSize = 11; + private const byte ControlMagic1 = 0xE5; + private const byte ControlMagic2 = 0x5F; + private const byte ControlCommandBoxPtt = 0x01; + + private readonly object _portLock = new(); + private readonly object _writeLock = new(); + private readonly object _parserLock = new(); + private readonly AudioPacketParser _parser = new(); + + private SerialPort? _port; + private int _transmitMode; + private byte _txFrameSequence; + + public event EventHandler? AudioFrameReceived; + public event EventHandler? Error; + + public bool IsOpen + { + get + { + lock (_portLock) + { + return _port?.IsOpen == true; + } + } + } + + public string? PortName + { + get + { + lock (_portLock) + { + return _port?.PortName; + } + } + } + + public void Open(string portName) + { + if (string.IsNullOrWhiteSpace(portName)) + { + throw new ArgumentException("Debes seleccionar un puerto COM.", nameof(portName)); + } + + lock (_portLock) + { + if (_port?.IsOpen == true) + { + throw new InvalidOperationException("El puerto serie ya está abierto."); + } + + var port = new SerialPort(portName, BaudRate, Parity.None, 8, StopBits.One) + { + Handshake = Handshake.None, + DtrEnable = true, + RtsEnable = true, + ReadBufferSize = 8192, + WriteBufferSize = 8192, + ReadTimeout = 100, + // Se escriben fragmentos de 200 bytes. Un timeout corto evita que + // soltar PTT o cerrar la ventana deje bloqueada la interfaz. + WriteTimeout = 150 + }; + + port.DataReceived += Port_DataReceived; + port.ErrorReceived += Port_ErrorReceived; + + try + { + port.Open(); + port.DiscardInBuffer(); + port.DiscardOutBuffer(); + + lock (_parserLock) + { + _parser.Reset(); + } + + Volatile.Write(ref _transmitMode, 0); + _txFrameSequence = 0; + _port = port; + } + catch + { + port.DataReceived -= Port_DataReceived; + port.ErrorReceived -= Port_ErrorReceived; + port.Dispose(); + throw; + } + } + } + + public void Close() + { + SerialPort? port; + + // Primero apartamos el puerto para impedir escrituras nuevas. + lock (_portLock) + { + port = _port; + _port = null; + + if (port is not null) + { + port.DataReceived -= Port_DataReceived; + port.ErrorReceived -= Port_ErrorReceived; + } + } + + Volatile.Write(ref _transmitMode, 0); + + lock (_parserLock) + { + _parser.Reset(); + } + + if (port is null) + { + return; + } + + // Si había un fragmento de audio escribiéndose, solo esperamos a que + // termine ese fragmento (máximo el WriteTimeout), no un frame completo. + lock (_writeLock) + { + try + { + if (port.IsOpen) + { + port.Close(); + } + } + catch (Exception ex) when (ex is IOException + or InvalidOperationException + or UnauthorizedAccessException) + { + Error?.Invoke(this, $"Error cerrando el puerto serie: {ex.Message}"); + } + finally + { + try + { + port.Dispose(); + } + catch + { + // El dispositivo ya no está disponible; no queda ningún recurso útil que cerrar. + } + } + } + } + + public void SetTransmitMode(bool transmitting) + { + Volatile.Write(ref _transmitMode, transmitting ? 1 : 0); + } + + /// + /// Abre una sesión de transmisión y envía START sin permitir que se cruce + /// con el STOP de una pulsación anterior. + /// + public void BeginTransmitSession() + { + lock (_writeLock) + { + SerialPort port = GetOpenPort(); + Volatile.Write(ref _transmitMode, 1); + WritePttControlLocked(port, true); + } + } + + /// + /// Envía STOP después de que el bucle de transmisión haya vaciado todos los + /// frames grabados. Solo entonces desactiva el envío de audio. + /// + public void EndTransmitSession() + { + lock (_writeLock) + { + SerialPort port = GetOpenPort(); + WritePttControlLocked(port, false); + Volatile.Write(ref _transmitMode, 0); + } + } + + /// + /// Envía un control corto y separado del audio. Formato: E5 5F 01 estado. + /// + public void SendPttControl(bool active) + { + lock (_writeLock) + { + SerialPort port = GetOpenPort(); + WritePttControlLocked(port, active); + } + } + + private SerialPort GetOpenPort() + { + lock (_portLock) + { + SerialPort port = _port + ?? throw new InvalidOperationException("El puerto serie no está abierto."); + + if (!port.IsOpen) + { + throw new InvalidOperationException("El puerto serie no está abierto."); + } + + return port; + } + } + + private static void WritePttControlLocked(SerialPort port, bool active) + { + byte[] packet = + { + ControlMagic1, + ControlMagic2, + ControlCommandBoxPtt, + active ? (byte)1 : (byte)0 + }; + + port.Write(packet, 0, packet.Length); + } + + public void SendAudioFrame(sbyte[] samples) + { + ArgumentNullException.ThrowIfNull(samples); + + if (samples.Length == 0 || samples.Length > AudioFrameMax) + { + throw new ArgumentOutOfRangeException( + nameof(samples), + $"El frame debe contener entre 1 y {AudioFrameMax} muestras."); + } + + if (Volatile.Read(ref _transmitMode) == 0) + { + return; + } + + int frameLength = samples.Length; + int chunkTotal = (frameLength + AudioChunkMax - 1) / AudioChunkMax; + + if (chunkTotal <= 0 || chunkTotal > AudioChunkTotalMax) + { + throw new InvalidOperationException("El frame genera un número de fragmentos no válido."); + } + + lock (_writeLock) + { + SerialPort port; + byte frameSequence; + + lock (_portLock) + { + port = _port + ?? throw new InvalidOperationException("El puerto serie no está abierto."); + + if (!port.IsOpen) + { + throw new InvalidOperationException("El puerto serie no está abierto."); + } + + // Una vez iniciado, el frame se envía completo. El STOP se coloca + // detrás de la cola de audio y nunca corta un frame a la mitad. + frameSequence = _txFrameSequence++; + } + + int offset = 0; + + for (int chunkIndex = 0; chunkIndex < chunkTotal; chunkIndex++) + { + int chunkLength = Math.Min(AudioChunkMax, frameLength - offset); + var packet = new byte[HeaderSize + chunkLength]; + + packet[0] = 0xE5; + packet[1] = 0x5E; + packet[2] = frameSequence; + packet[3] = (byte)chunkIndex; + packet[4] = (byte)chunkTotal; + packet[5] = (byte)(frameLength & 0xFF); + packet[6] = (byte)((frameLength >> 8) & 0xFF); + packet[7] = (byte)(offset & 0xFF); + packet[8] = (byte)((offset >> 8) & 0xFF); + packet[9] = (byte)(chunkLength & 0xFF); + packet[10] = (byte)((chunkLength >> 8) & 0xFF); + + for (int i = 0; i < chunkLength; i++) + { + packet[HeaderSize + i] = unchecked((byte)samples[offset + i]); + } + + port.Write(packet, 0, packet.Length); + offset += chunkLength; + } + } + } + + private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e) + { + if (sender is not SerialPort port) + { + return; + } + + try + { + byte[] buffer; + int bytesRead; + + // El lock del puerto solo se mantiene mientras se extraen los bytes. + lock (_portLock) + { + if (!ReferenceEquals(port, _port) || !port.IsOpen) + { + return; + } + + int available = port.BytesToRead; + if (available <= 0) + { + return; + } + + buffer = new byte[available]; + bytesRead = port.Read(buffer, 0, buffer.Length); + } + + List? completedFrames = null; + + lock (_parserLock) + { + for (int i = 0; i < bytesRead; i++) + { + _parser.ProcessByte(buffer[i], frame => + { + completedFrames ??= new List(); + completedFrames.Add(frame); + }); + } + } + + if (completedFrames is not null) + { + foreach (sbyte[] frame in completedFrames) + { + AudioFrameReceived?.Invoke(this, frame); + } + } + } + catch (Exception ex) when (ex is IOException + or InvalidOperationException + or UnauthorizedAccessException + or TimeoutException) + { + Error?.Invoke(this, $"Error leyendo el puerto serie: {ex.Message}"); + } + } + + private void Port_ErrorReceived(object sender, SerialErrorReceivedEventArgs e) + { + Error?.Invoke(this, $"Error del puerto serie: {e.EventType}"); + } + + public void Dispose() + { + Close(); + } + + private enum ReceiveState + { + WaitE5, + Wait5E, + ReadFrameSequence, + ReadChunkIndex, + ReadChunkTotal, + ReadFrameLengthLow, + ReadFrameLengthHigh, + ReadOffsetLow, + ReadOffsetHigh, + ReadChunkLengthLow, + ReadChunkLengthHigh, + ReadAudio + } + + private sealed class AudioPacketParser + { + private readonly sbyte[] _frameBuffer = new sbyte[AudioFrameMax]; + private readonly bool[] _receivedChunks = new bool[AudioChunkTotalMax]; + + private ReceiveState _state = ReceiveState.WaitE5; + private byte _frameSequence; + private byte _chunkIndex; + private byte _chunkTotal; + private ushort _frameLength; + private ushort _offset; + private ushort _chunkLength; + private byte[] _audio = Array.Empty(); + private int _audioIndex; + + private bool _frameActive; + private byte _currentFrameSequence; + private byte _currentChunkTotal; + private ushort _currentFrameLength; + private int _receivedChunkCount; + + public void ProcessByte(byte value, Action onFrameCompleted) + { + switch (_state) + { + case ReceiveState.WaitE5: + if (value == 0xE5) + { + _state = ReceiveState.Wait5E; + } + break; + + case ReceiveState.Wait5E: + if (value == 0x5E) + { + ResetPacket(); + _state = ReceiveState.ReadFrameSequence; + } + else + { + _state = value == 0xE5 + ? ReceiveState.Wait5E + : ReceiveState.WaitE5; + } + break; + + case ReceiveState.ReadFrameSequence: + _frameSequence = value; + _state = ReceiveState.ReadChunkIndex; + break; + + case ReceiveState.ReadChunkIndex: + _chunkIndex = value; + _state = ReceiveState.ReadChunkTotal; + break; + + case ReceiveState.ReadChunkTotal: + _chunkTotal = value; + _state = ReceiveState.ReadFrameLengthLow; + break; + + case ReceiveState.ReadFrameLengthLow: + _frameLength = value; + _state = ReceiveState.ReadFrameLengthHigh; + break; + + case ReceiveState.ReadFrameLengthHigh: + _frameLength |= (ushort)(value << 8); + _state = ReceiveState.ReadOffsetLow; + break; + + case ReceiveState.ReadOffsetLow: + _offset = value; + _state = ReceiveState.ReadOffsetHigh; + break; + + case ReceiveState.ReadOffsetHigh: + _offset |= (ushort)(value << 8); + _state = ReceiveState.ReadChunkLengthLow; + break; + + case ReceiveState.ReadChunkLengthLow: + _chunkLength = value; + _state = ReceiveState.ReadChunkLengthHigh; + break; + + case ReceiveState.ReadChunkLengthHigh: + _chunkLength |= (ushort)(value << 8); + + if (!HeaderIsValid()) + { + _state = ReceiveState.WaitE5; + break; + } + + _audio = new byte[_chunkLength]; + _audioIndex = 0; + _state = ReceiveState.ReadAudio; + break; + + case ReceiveState.ReadAudio: + _audio[_audioIndex++] = value; + + if (_audioIndex >= _audio.Length) + { + CompletePacket(onFrameCompleted); + _state = ReceiveState.WaitE5; + } + break; + } + } + + public void Reset() + { + _state = ReceiveState.WaitE5; + _frameActive = false; + ResetPacket(); + Array.Clear(_frameBuffer, 0, _frameBuffer.Length); + Array.Clear(_receivedChunks, 0, _receivedChunks.Length); + } + + private bool HeaderIsValid() + { + if (_chunkTotal == 0 || _chunkTotal > AudioChunkTotalMax) + { + return false; + } + + if (_chunkIndex >= _chunkTotal || _chunkIndex >= AudioChunkTotalMax) + { + return false; + } + + if (_frameLength == 0 || _frameLength > AudioFrameMax) + { + return false; + } + + if (_chunkLength == 0 || _chunkLength > AudioChunkMax) + { + return false; + } + + return _offset + _chunkLength <= _frameLength + && _offset + _chunkLength <= AudioFrameMax; + } + + private void CompletePacket(Action onFrameCompleted) + { + if (!_frameActive || _frameSequence != _currentFrameSequence) + { + StartFrame(); + } + + if (_frameLength != _currentFrameLength || _chunkTotal != _currentChunkTotal) + { + _frameActive = false; + return; + } + + for (int i = 0; i < _audio.Length; i++) + { + _frameBuffer[_offset + i] = unchecked((sbyte)_audio[i]); + } + + if (!_receivedChunks[_chunkIndex]) + { + _receivedChunks[_chunkIndex] = true; + _receivedChunkCount++; + } + + if (_receivedChunkCount < _currentChunkTotal) + { + return; + } + + var completedFrame = new sbyte[_currentFrameLength]; + Array.Copy(_frameBuffer, completedFrame, _currentFrameLength); + _frameActive = false; + onFrameCompleted(completedFrame); + } + + private void StartFrame() + { + Array.Clear(_frameBuffer, 0, _frameBuffer.Length); + Array.Clear(_receivedChunks, 0, _receivedChunks.Length); + + _currentFrameSequence = _frameSequence; + _currentChunkTotal = _chunkTotal; + _currentFrameLength = _frameLength; + _receivedChunkCount = 0; + _frameActive = true; + } + + private void ResetPacket() + { + _frameSequence = 0; + _chunkIndex = 0; + _chunkTotal = 0; + _frameLength = 0; + _offset = 0; + _chunkLength = 0; + _audio = Array.Empty(); + _audioIndex = 0; + } + } +} diff --git a/Radio/App_radio/UpgradeLog.htm b/Radio/App_radio/UpgradeLog.htm new file mode 100644 index 0000000..e6ce872 --- /dev/null +++ b/Radio/App_radio/UpgradeLog.htm @@ -0,0 +1,275 @@ + + + + Informe de migración +

+ Informe de migración -

\ No newline at end of file diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.deps.json b/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.deps.json new file mode 100644 index 0000000..2163c27 --- /dev/null +++ b/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.deps.json @@ -0,0 +1,470 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v10.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v10.0": { + "App_radio/1.0.0": { + "dependencies": { + "NAudio": "2.3.0", + "System.IO.Ports": "10.0.9" + }, + "runtime": { + "App_radio.dll": {} + } + }, + "NAudio/2.3.0": { + "dependencies": { + "NAudio.Asio": "2.3.0", + "NAudio.Core": "2.3.0", + "NAudio.Midi": "2.3.0", + "NAudio.Wasapi": "2.3.0", + "NAudio.WinForms": "2.3.0", + "NAudio.WinMM": "2.3.0" + }, + "runtime": { + "lib/net6.0-windows7.0/NAudio.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.Asio/2.3.0": { + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "runtime": { + "lib/net8.0-windows7.0/NAudio.Asio.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.Core/2.3.0": { + "runtime": { + "lib/netstandard2.0/NAudio.Core.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.Midi/2.3.0": { + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "runtime": { + "lib/netstandard2.0/NAudio.Midi.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.Wasapi/2.3.0": { + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "runtime": { + "lib/netstandard2.0/NAudio.Wasapi.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.WinForms/2.3.0": { + "dependencies": { + "NAudio.WinMM": "2.3.0" + }, + "runtime": { + "lib/netcoreapp3.1/NAudio.WinForms.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.WinMM/2.3.0": { + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "runtime": { + "lib/net6.0/NAudio.WinMM.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "runtime.android-arm.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/android-arm/native/libSystem.IO.Ports.Native.so": { + "rid": "android-arm", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.android-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/android-arm64/native/libSystem.IO.Ports.Native.so": { + "rid": "android-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.android-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/android-x64/native/libSystem.IO.Ports.Native.so": { + "rid": "android-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.android-x86.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/android-x86/native/libSystem.IO.Ports.Native.so": { + "rid": "android-x86", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-arm.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-arm/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-arm", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-bionic-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-bionic-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-bionic-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-bionic-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-musl-arm.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-musl-arm", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-musl-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-musl-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-musl-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-musl-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-x64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.maccatalyst-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib": { + "rid": "maccatalyst-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.maccatalyst-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib": { + "rid": "maccatalyst-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.native.System.IO.Ports/10.0.9": { + "dependencies": { + "runtime.android-arm.runtime.native.System.IO.Ports": "10.0.9", + "runtime.android-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.android-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.android-x86.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-arm.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-bionic-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-bionic-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-musl-arm.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-musl-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-musl-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.maccatalyst-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.maccatalyst-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.osx-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.osx-x64.runtime.native.System.IO.Ports": "10.0.9" + } + }, + "runtime.osx-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib": { + "rid": "osx-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.osx-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib": { + "rid": "osx-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "System.IO.Ports/10.0.9": { + "dependencies": { + "runtime.native.System.IO.Ports": "10.0.9" + }, + "runtime": { + "lib/net10.0/System.IO.Ports.dll": { + "assemblyVersion": "10.0.0.9", + "fileVersion": "10.0.926.27113" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/net10.0/System.IO.Ports.dll": { + "rid": "unix", + "assetType": "runtime", + "assemblyVersion": "10.0.0.9", + "fileVersion": "10.0.926.27113" + }, + "runtimes/win/lib/net10.0/System.IO.Ports.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "10.0.0.9", + "fileVersion": "10.0.926.27113" + } + } + } + } + }, + "libraries": { + "App_radio/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "NAudio/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-xN+Lzlu9DmXqBiL6XkP0VZmgTxZPdSGjVSWtKG9HKuar3LhIYNOIYQETieigS+QDS+nrs1QmHbBWWOru0nWA5A==", + "path": "naudio/2.3.0", + "hashPath": "naudio.2.3.0.nupkg.sha512" + }, + "NAudio.Asio/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-I+rAAPT8vmSEw4d4ie+AoSkrvNK6ylRrXznnjQKS+qZgTA9Jnt1Pxe0EaU8nXxOOq5h8ucBSWccBEw6I/J0nkQ==", + "path": "naudio.asio/2.3.0", + "hashPath": "naudio.asio.2.3.0.nupkg.sha512" + }, + "NAudio.Core/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-jMd7r6dB6tAtXhOYL58ntPqwERNm1/Rhw5MKOIYvsnXzuX+PTGsa2VMam6n0npZYSwlSidKa4GAm4bFcXFUlcg==", + "path": "naudio.core/2.3.0", + "hashPath": "naudio.core.2.3.0.nupkg.sha512" + }, + "NAudio.Midi/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-t8wvPFPHHQOHhoNMCaDE8OiYZoJuxmY4H6UPBtmnf+xx7oQuajFCqlG4Q00ID+tiEyj471WeVb4Nkylr4tDoow==", + "path": "naudio.midi/2.3.0", + "hashPath": "naudio.midi.2.3.0.nupkg.sha512" + }, + "NAudio.Wasapi/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-y5K2BxrLnvohgu5znzg5wRsai3YcuNXfrpo68i7PmCQqpK5MC/R24e5aO3OyN/XhfRr12e0QYV0OnUWEHi5SzA==", + "path": "naudio.wasapi/2.3.0", + "hashPath": "naudio.wasapi.2.3.0.nupkg.sha512" + }, + "NAudio.WinForms/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-vyKqFUlAZrZ0QPcCM1T+zimjYgC1cNDloHaiOdtV4S1eK4AGu3Dz1EE4yy/WgcneJwQNjGFaELY7b2TsL+g56w==", + "path": "naudio.winforms/2.3.0", + "hashPath": "naudio.winforms.2.3.0.nupkg.sha512" + }, + "NAudio.WinMM/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5G1dRjsZm50T3luyuqcmI2BSvj3K4ZJaD/x776/0Epj88qOsOryDZG40+MufwIk1UFJSFWhRobBqtJYFc8Ss4g==", + "path": "naudio.winmm/2.3.0", + "hashPath": "naudio.winmm.2.3.0.nupkg.sha512" + }, + "runtime.android-arm.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-7QwWCqZ4hRpmSySAFslZD5oFhV8ib/FhO2eGgPrImEI3V8U5P1FtIc5M4pB+5xOBfzW5VzjmItKFezkB8MGDqw==", + "path": "runtime.android-arm.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.android-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.android-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-mOZanUMgwxreyyoZRHaeLbfaevCgaadM4RafsRclY0I+cwV/QbYhzjELYc6C68acd+4z/Fj9zh66u6nu3evP0A==", + "path": "runtime.android-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.android-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.android-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-rUvnhurQfEkaduyDlESUgttOjAjMniC38B9IMVfx2480OvBWzhy5vzvcg2WIlTCJErb4sCN+QTzhHBpOYFRoxw==", + "path": "runtime.android-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.android-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.android-x86.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ykG02K8zQqj8VcWfyjsvG9+lT2ODaqjF17Sid2/s7Kgp+ugn9eh4V2FZpzV0qa+JfVH5eohB4JaF7K/XpdTHCQ==", + "path": "runtime.android-x86.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.android-x86.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-arm.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-DHRGpEI+51UCQR74jrkA30s7luDaUw3NC4Jp3MNLTnseuCVTRQ5ocbjpApt7mM9quoP7YZKMG+iUA+xJ6yJW8Q==", + "path": "runtime.linux-arm.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-G67fx6Vv/z5DFvfa5MiqAa9lONQv0d+WGxICW+Nvp+LNA6iJvv4j6/GTjGXtK44T/n+8sYk9dho7pKtuCoMZWQ==", + "path": "runtime.linux-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-bionic-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-E08Eipi4Iiq3+JV/mpNxS+loN68ZJlrlaHCfiXmUL3Qlcpq9slGXyw5N97v4nL9dzpCIBnLstQEFC32HTpCduw==", + "path": "runtime.linux-bionic-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-bionic-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-bionic-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-FaATvKgabe3xHU9aYnj2h4Pp4DeY91SwMmHdv4/+Wmzp6fqwGT25xCNBzJ2FOHEdJLNO52raXcL3Xwo2/eLXKg==", + "path": "runtime.linux-bionic-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-bionic-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-musl-arm.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-OsROr3mGvkb4U/cizz5s3y+Oa8OBjGCCo8QWEmuUEdM40wp0JbWMEwaqOmScxVCZNzobHHfHeuX/o3oTGj3OmA==", + "path": "runtime.linux-musl-arm.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-musl-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-musl-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-vDGYpx/8dAAMlJccGLCWLaJ20AzASKax33suoHw7s/alEjwYp1mpD6Vso4qbX5QJLonE+lnx3vfB+maKV4CtAA==", + "path": "runtime.linux-musl-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-musl-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-musl-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-JwGn9azjl7+AuwzgEdeJLghTcK8nCqKCf7h/gq7Pzi2HMuv6D2EBzDZpl95qKkdBCT6bsWdv3flZQJZf2uY2ew==", + "path": "runtime.linux-musl-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-musl-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-01ppayPym92n42VR74iSt/MNw5UoltX0tQOVvA5P0bUszvtDRPkAM5SEkujIVBs6+kERZ2OgZN8mMDPJKTfh2Q==", + "path": "runtime.linux-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.maccatalyst-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-z9OvFgFoV9jScx7pmjasXvmixG8qK8QdN3fcsP2TptMbfU+/4bz/SKjpgw3MRROJcfiTQWdJE4Cdx4vG86bulA==", + "path": "runtime.maccatalyst-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.maccatalyst-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.maccatalyst-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-45LNikgDcVaFWkVxUr1h5ZaM6o0LT05TdKzmFI1OnZIEaT4/yWJukrouzsEZfm2kyN05EA/U686HSnuqMS7+6A==", + "path": "runtime.maccatalyst-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.maccatalyst-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-PoZf6+MaLVHqj37ozGdAc98w+UtwGLJGqQ4QeKT+qvQaX9EqpKmrhmImoGI68wrkJkRbwGCP1jIsFKpMu4iBKg==", + "path": "runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.osx-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-fW857DfzCX6QsEuVH1/WohiHh1BphhHcGsjpLX5h3sgm0Y67QVWijykrJSZC4Ct9Gfm40pfmSo+L53deIQ9MZQ==", + "path": "runtime.osx-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.osx-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.osx-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Ugf+Hlb6dJB1tXLZqU/q4iXclQ/lojiJWtLCFqmRiE2bXA8fOnUHz9U40dJxHdqPO9BEyfzWEliRCUtZCblNmQ==", + "path": "runtime.osx-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.osx-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-JHijtblIg7c1wCxBtuPjqWK+BxTlO0qTE3Y5PSety2NGkZRL5LFL6JoabbGebmO1PuOtUqlvAc+6hbLvlLSTqQ==", + "path": "system.io.ports/10.0.9", + "hashPath": "system.io.ports.10.0.9.nupkg.sha512" + } + } +} \ No newline at end of file diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.dll b/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.dll new file mode 100644 index 0000000..786ea37 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.dll differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.exe b/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.exe new file mode 100644 index 0000000..232e716 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.exe differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.pdb b/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.pdb new file mode 100644 index 0000000..d6cbf0e Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.pdb differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.runtimeconfig.json b/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.runtimeconfig.json new file mode 100644 index 0000000..3c285dd --- /dev/null +++ b/Radio/App_radio/bin/Debug/net10.0-windows/App_radio.runtimeconfig.json @@ -0,0 +1,19 @@ +{ + "runtimeOptions": { + "tfm": "net10.0", + "frameworks": [ + { + "name": "Microsoft.NETCore.App", + "version": "10.0.0" + }, + { + "name": "Microsoft.WindowsDesktop.App", + "version": "10.0.0" + } + ], + "configProperties": { + "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false, + "CSWINRT_USE_WINDOWS_UI_XAML_PROJECTIONS": false + } + } +} \ No newline at end of file diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Asio.dll b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Asio.dll new file mode 100644 index 0000000..1a79fd0 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Asio.dll differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Core.dll b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Core.dll new file mode 100644 index 0000000..00514d8 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Core.dll differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Midi.dll b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Midi.dll new file mode 100644 index 0000000..b3c21d8 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Midi.dll differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Wasapi.dll b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Wasapi.dll new file mode 100644 index 0000000..430379c Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.Wasapi.dll differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.WinForms.dll b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.WinForms.dll new file mode 100644 index 0000000..d481c86 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.WinForms.dll differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.WinMM.dll b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.WinMM.dll new file mode 100644 index 0000000..313b671 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.WinMM.dll differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.dll b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.dll new file mode 100644 index 0000000..ae09ff5 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/NAudio.dll differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/System.IO.Ports.dll b/Radio/App_radio/bin/Debug/net10.0-windows/System.IO.Ports.dll new file mode 100644 index 0000000..65131c2 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/System.IO.Ports.dll differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-arm/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-arm/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..5cae8eb Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-arm/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-arm64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-arm64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..f15d5f1 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-arm64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-x64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-x64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..94f651f Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-x64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-x86/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-x86/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..89fe091 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/android-x86/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-arm/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-arm/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..78e6c27 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-arm/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..2e9c501 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..f49fc3c Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..561c8e8 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..1ab431a Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..d34c50b Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..f6242a5 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-x64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-x64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..357d521 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/linux-x64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib new file mode 100644 index 0000000..8d8cf5b Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib new file mode 100644 index 0000000..3d8c34d Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib new file mode 100644 index 0000000..14fa4a4 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib new file mode 100644 index 0000000..9f72fe6 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/unix/lib/net10.0/System.IO.Ports.dll b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/unix/lib/net10.0/System.IO.Ports.dll new file mode 100644 index 0000000..c00494c Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/unix/lib/net10.0/System.IO.Ports.dll differ diff --git a/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/win/lib/net10.0/System.IO.Ports.dll b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/win/lib/net10.0/System.IO.Ports.dll new file mode 100644 index 0000000..c76b4c8 Binary files /dev/null and b/Radio/App_radio/bin/Debug/net10.0-windows/runtimes/win/lib/net10.0/System.IO.Ports.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/App_radio.deps.json b/Radio/App_radio/bin/Release/net10.0-windows/App_radio.deps.json new file mode 100644 index 0000000..2163c27 --- /dev/null +++ b/Radio/App_radio/bin/Release/net10.0-windows/App_radio.deps.json @@ -0,0 +1,470 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v10.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v10.0": { + "App_radio/1.0.0": { + "dependencies": { + "NAudio": "2.3.0", + "System.IO.Ports": "10.0.9" + }, + "runtime": { + "App_radio.dll": {} + } + }, + "NAudio/2.3.0": { + "dependencies": { + "NAudio.Asio": "2.3.0", + "NAudio.Core": "2.3.0", + "NAudio.Midi": "2.3.0", + "NAudio.Wasapi": "2.3.0", + "NAudio.WinForms": "2.3.0", + "NAudio.WinMM": "2.3.0" + }, + "runtime": { + "lib/net6.0-windows7.0/NAudio.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.Asio/2.3.0": { + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "runtime": { + "lib/net8.0-windows7.0/NAudio.Asio.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.Core/2.3.0": { + "runtime": { + "lib/netstandard2.0/NAudio.Core.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.Midi/2.3.0": { + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "runtime": { + "lib/netstandard2.0/NAudio.Midi.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.Wasapi/2.3.0": { + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "runtime": { + "lib/netstandard2.0/NAudio.Wasapi.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.WinForms/2.3.0": { + "dependencies": { + "NAudio.WinMM": "2.3.0" + }, + "runtime": { + "lib/netcoreapp3.1/NAudio.WinForms.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "NAudio.WinMM/2.3.0": { + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "runtime": { + "lib/net6.0/NAudio.WinMM.dll": { + "assemblyVersion": "2.3.0.0", + "fileVersion": "2.3.0.0" + } + } + }, + "runtime.android-arm.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/android-arm/native/libSystem.IO.Ports.Native.so": { + "rid": "android-arm", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.android-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/android-arm64/native/libSystem.IO.Ports.Native.so": { + "rid": "android-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.android-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/android-x64/native/libSystem.IO.Ports.Native.so": { + "rid": "android-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.android-x86.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/android-x86/native/libSystem.IO.Ports.Native.so": { + "rid": "android-x86", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-arm.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-arm/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-arm", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-bionic-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-bionic-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-bionic-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-bionic-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-musl-arm.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-musl-arm", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-musl-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-musl-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-musl-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-musl-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.linux-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/linux-x64/native/libSystem.IO.Ports.Native.so": { + "rid": "linux-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.maccatalyst-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib": { + "rid": "maccatalyst-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.maccatalyst-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib": { + "rid": "maccatalyst-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.native.System.IO.Ports/10.0.9": { + "dependencies": { + "runtime.android-arm.runtime.native.System.IO.Ports": "10.0.9", + "runtime.android-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.android-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.android-x86.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-arm.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-bionic-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-bionic-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-musl-arm.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-musl-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-musl-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.maccatalyst-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.maccatalyst-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.osx-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.osx-x64.runtime.native.System.IO.Ports": "10.0.9" + } + }, + "runtime.osx-arm64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib": { + "rid": "osx-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "runtime.osx-x64.runtime.native.System.IO.Ports/10.0.9": { + "runtimeTargets": { + "runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib": { + "rid": "osx-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "System.IO.Ports/10.0.9": { + "dependencies": { + "runtime.native.System.IO.Ports": "10.0.9" + }, + "runtime": { + "lib/net10.0/System.IO.Ports.dll": { + "assemblyVersion": "10.0.0.9", + "fileVersion": "10.0.926.27113" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/net10.0/System.IO.Ports.dll": { + "rid": "unix", + "assetType": "runtime", + "assemblyVersion": "10.0.0.9", + "fileVersion": "10.0.926.27113" + }, + "runtimes/win/lib/net10.0/System.IO.Ports.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "10.0.0.9", + "fileVersion": "10.0.926.27113" + } + } + } + } + }, + "libraries": { + "App_radio/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "NAudio/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-xN+Lzlu9DmXqBiL6XkP0VZmgTxZPdSGjVSWtKG9HKuar3LhIYNOIYQETieigS+QDS+nrs1QmHbBWWOru0nWA5A==", + "path": "naudio/2.3.0", + "hashPath": "naudio.2.3.0.nupkg.sha512" + }, + "NAudio.Asio/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-I+rAAPT8vmSEw4d4ie+AoSkrvNK6ylRrXznnjQKS+qZgTA9Jnt1Pxe0EaU8nXxOOq5h8ucBSWccBEw6I/J0nkQ==", + "path": "naudio.asio/2.3.0", + "hashPath": "naudio.asio.2.3.0.nupkg.sha512" + }, + "NAudio.Core/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-jMd7r6dB6tAtXhOYL58ntPqwERNm1/Rhw5MKOIYvsnXzuX+PTGsa2VMam6n0npZYSwlSidKa4GAm4bFcXFUlcg==", + "path": "naudio.core/2.3.0", + "hashPath": "naudio.core.2.3.0.nupkg.sha512" + }, + "NAudio.Midi/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-t8wvPFPHHQOHhoNMCaDE8OiYZoJuxmY4H6UPBtmnf+xx7oQuajFCqlG4Q00ID+tiEyj471WeVb4Nkylr4tDoow==", + "path": "naudio.midi/2.3.0", + "hashPath": "naudio.midi.2.3.0.nupkg.sha512" + }, + "NAudio.Wasapi/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-y5K2BxrLnvohgu5znzg5wRsai3YcuNXfrpo68i7PmCQqpK5MC/R24e5aO3OyN/XhfRr12e0QYV0OnUWEHi5SzA==", + "path": "naudio.wasapi/2.3.0", + "hashPath": "naudio.wasapi.2.3.0.nupkg.sha512" + }, + "NAudio.WinForms/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-vyKqFUlAZrZ0QPcCM1T+zimjYgC1cNDloHaiOdtV4S1eK4AGu3Dz1EE4yy/WgcneJwQNjGFaELY7b2TsL+g56w==", + "path": "naudio.winforms/2.3.0", + "hashPath": "naudio.winforms.2.3.0.nupkg.sha512" + }, + "NAudio.WinMM/2.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5G1dRjsZm50T3luyuqcmI2BSvj3K4ZJaD/x776/0Epj88qOsOryDZG40+MufwIk1UFJSFWhRobBqtJYFc8Ss4g==", + "path": "naudio.winmm/2.3.0", + "hashPath": "naudio.winmm.2.3.0.nupkg.sha512" + }, + "runtime.android-arm.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-7QwWCqZ4hRpmSySAFslZD5oFhV8ib/FhO2eGgPrImEI3V8U5P1FtIc5M4pB+5xOBfzW5VzjmItKFezkB8MGDqw==", + "path": "runtime.android-arm.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.android-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.android-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-mOZanUMgwxreyyoZRHaeLbfaevCgaadM4RafsRclY0I+cwV/QbYhzjELYc6C68acd+4z/Fj9zh66u6nu3evP0A==", + "path": "runtime.android-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.android-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.android-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-rUvnhurQfEkaduyDlESUgttOjAjMniC38B9IMVfx2480OvBWzhy5vzvcg2WIlTCJErb4sCN+QTzhHBpOYFRoxw==", + "path": "runtime.android-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.android-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.android-x86.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ykG02K8zQqj8VcWfyjsvG9+lT2ODaqjF17Sid2/s7Kgp+ugn9eh4V2FZpzV0qa+JfVH5eohB4JaF7K/XpdTHCQ==", + "path": "runtime.android-x86.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.android-x86.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-arm.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-DHRGpEI+51UCQR74jrkA30s7luDaUw3NC4Jp3MNLTnseuCVTRQ5ocbjpApt7mM9quoP7YZKMG+iUA+xJ6yJW8Q==", + "path": "runtime.linux-arm.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-G67fx6Vv/z5DFvfa5MiqAa9lONQv0d+WGxICW+Nvp+LNA6iJvv4j6/GTjGXtK44T/n+8sYk9dho7pKtuCoMZWQ==", + "path": "runtime.linux-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-bionic-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-E08Eipi4Iiq3+JV/mpNxS+loN68ZJlrlaHCfiXmUL3Qlcpq9slGXyw5N97v4nL9dzpCIBnLstQEFC32HTpCduw==", + "path": "runtime.linux-bionic-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-bionic-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-bionic-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-FaATvKgabe3xHU9aYnj2h4Pp4DeY91SwMmHdv4/+Wmzp6fqwGT25xCNBzJ2FOHEdJLNO52raXcL3Xwo2/eLXKg==", + "path": "runtime.linux-bionic-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-bionic-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-musl-arm.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-OsROr3mGvkb4U/cizz5s3y+Oa8OBjGCCo8QWEmuUEdM40wp0JbWMEwaqOmScxVCZNzobHHfHeuX/o3oTGj3OmA==", + "path": "runtime.linux-musl-arm.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-musl-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-musl-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-vDGYpx/8dAAMlJccGLCWLaJ20AzASKax33suoHw7s/alEjwYp1mpD6Vso4qbX5QJLonE+lnx3vfB+maKV4CtAA==", + "path": "runtime.linux-musl-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-musl-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-musl-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-JwGn9azjl7+AuwzgEdeJLghTcK8nCqKCf7h/gq7Pzi2HMuv6D2EBzDZpl95qKkdBCT6bsWdv3flZQJZf2uY2ew==", + "path": "runtime.linux-musl-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-musl-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.linux-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-01ppayPym92n42VR74iSt/MNw5UoltX0tQOVvA5P0bUszvtDRPkAM5SEkujIVBs6+kERZ2OgZN8mMDPJKTfh2Q==", + "path": "runtime.linux-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.linux-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.maccatalyst-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-z9OvFgFoV9jScx7pmjasXvmixG8qK8QdN3fcsP2TptMbfU+/4bz/SKjpgw3MRROJcfiTQWdJE4Cdx4vG86bulA==", + "path": "runtime.maccatalyst-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.maccatalyst-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.maccatalyst-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-45LNikgDcVaFWkVxUr1h5ZaM6o0LT05TdKzmFI1OnZIEaT4/yWJukrouzsEZfm2kyN05EA/U686HSnuqMS7+6A==", + "path": "runtime.maccatalyst-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.maccatalyst-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-PoZf6+MaLVHqj37ozGdAc98w+UtwGLJGqQ4QeKT+qvQaX9EqpKmrhmImoGI68wrkJkRbwGCP1jIsFKpMu4iBKg==", + "path": "runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.osx-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-fW857DfzCX6QsEuVH1/WohiHh1BphhHcGsjpLX5h3sgm0Y67QVWijykrJSZC4Ct9Gfm40pfmSo+L53deIQ9MZQ==", + "path": "runtime.osx-arm64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.osx-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "runtime.osx-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Ugf+Hlb6dJB1tXLZqU/q4iXclQ/lojiJWtLCFqmRiE2bXA8fOnUHz9U40dJxHdqPO9BEyfzWEliRCUtZCblNmQ==", + "path": "runtime.osx-x64.runtime.native.system.io.ports/10.0.9", + "hashPath": "runtime.osx-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512" + }, + "System.IO.Ports/10.0.9": { + "type": "package", + "serviceable": true, + "sha512": "sha512-JHijtblIg7c1wCxBtuPjqWK+BxTlO0qTE3Y5PSety2NGkZRL5LFL6JoabbGebmO1PuOtUqlvAc+6hbLvlLSTqQ==", + "path": "system.io.ports/10.0.9", + "hashPath": "system.io.ports.10.0.9.nupkg.sha512" + } + } +} \ No newline at end of file diff --git a/Radio/App_radio/bin/Release/net10.0-windows/App_radio.dll b/Radio/App_radio/bin/Release/net10.0-windows/App_radio.dll new file mode 100644 index 0000000..0c71ec5 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/App_radio.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/App_radio.exe b/Radio/App_radio/bin/Release/net10.0-windows/App_radio.exe new file mode 100644 index 0000000..232e716 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/App_radio.exe differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/App_radio.pdb b/Radio/App_radio/bin/Release/net10.0-windows/App_radio.pdb new file mode 100644 index 0000000..d0a3a5c Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/App_radio.pdb differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/App_radio.runtimeconfig.json b/Radio/App_radio/bin/Release/net10.0-windows/App_radio.runtimeconfig.json new file mode 100644 index 0000000..e344539 --- /dev/null +++ b/Radio/App_radio/bin/Release/net10.0-windows/App_radio.runtimeconfig.json @@ -0,0 +1,20 @@ +{ + "runtimeOptions": { + "tfm": "net10.0", + "frameworks": [ + { + "name": "Microsoft.NETCore.App", + "version": "10.0.0" + }, + { + "name": "Microsoft.WindowsDesktop.App", + "version": "10.0.0" + } + ], + "configProperties": { + "System.Reflection.Metadata.MetadataUpdater.IsSupported": false, + "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false, + "CSWINRT_USE_WINDOWS_UI_XAML_PROJECTIONS": false + } + } +} \ No newline at end of file diff --git a/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Asio.dll b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Asio.dll new file mode 100644 index 0000000..1a79fd0 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Asio.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Core.dll b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Core.dll new file mode 100644 index 0000000..00514d8 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Core.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Midi.dll b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Midi.dll new file mode 100644 index 0000000..b3c21d8 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Midi.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Wasapi.dll b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Wasapi.dll new file mode 100644 index 0000000..430379c Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.Wasapi.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/NAudio.WinForms.dll b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.WinForms.dll new file mode 100644 index 0000000..d481c86 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.WinForms.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/NAudio.WinMM.dll b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.WinMM.dll new file mode 100644 index 0000000..313b671 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.WinMM.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/NAudio.dll b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.dll new file mode 100644 index 0000000..ae09ff5 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/NAudio.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/System.IO.Ports.dll b/Radio/App_radio/bin/Release/net10.0-windows/System.IO.Ports.dll new file mode 100644 index 0000000..65131c2 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/System.IO.Ports.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-arm/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-arm/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..5cae8eb Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-arm/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-arm64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-arm64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..f15d5f1 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-arm64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-x64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-x64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..94f651f Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-x64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-x86/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-x86/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..89fe091 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/android-x86/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-arm/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-arm/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..78e6c27 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-arm/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..2e9c501 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..f49fc3c Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..561c8e8 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..1ab431a Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..d34c50b Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..f6242a5 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-x64/native/libSystem.IO.Ports.Native.so b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-x64/native/libSystem.IO.Ports.Native.so new file mode 100644 index 0000000..357d521 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/linux-x64/native/libSystem.IO.Ports.Native.so differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib new file mode 100644 index 0000000..8d8cf5b Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib new file mode 100644 index 0000000..3d8c34d Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib new file mode 100644 index 0000000..14fa4a4 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib new file mode 100644 index 0000000..9f72fe6 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/unix/lib/net10.0/System.IO.Ports.dll b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/unix/lib/net10.0/System.IO.Ports.dll new file mode 100644 index 0000000..c00494c Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/unix/lib/net10.0/System.IO.Ports.dll differ diff --git a/Radio/App_radio/bin/Release/net10.0-windows/runtimes/win/lib/net10.0/System.IO.Ports.dll b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/win/lib/net10.0/System.IO.Ports.dll new file mode 100644 index 0000000..c76b4c8 Binary files /dev/null and b/Radio/App_radio/bin/Release/net10.0-windows/runtimes/win/lib/net10.0/System.IO.Ports.dll differ diff --git a/Radio/App_radio/obj/App_radio.csproj.nuget.dgspec.json b/Radio/App_radio/obj/App_radio.csproj.nuget.dgspec.json new file mode 100644 index 0000000..ba3977b --- /dev/null +++ b/Radio/App_radio/obj/App_radio.csproj.nuget.dgspec.json @@ -0,0 +1,374 @@ +{ + "format": 1, + "restore": { + "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\App_radio.csproj": {} + }, + "projects": { + "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\App_radio.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\App_radio.csproj", + "projectName": "App_radio", + "projectPath": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\App_radio.csproj", + "packagesPath": "C:\\Users\\alvar\\.nuget\\packages\\", + "outputPath": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\obj\\", + "projectStyle": "PackageReference", + "configFilePaths": [ + "C:\\Users\\alvar\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net10.0-windows" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net10.0-windows": { + "framework": "net10.0-windows7.0", + "targetAlias": "net10.0-windows", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "all" + }, + "SdkAnalysisLevel": "10.0.300" + }, + "frameworks": { + "net10.0-windows": { + "framework": "net10.0-windows7.0", + "targetAlias": "net10.0-windows", + "dependencies": { + "NAudio": { + "target": "Package", + "version": "[2.3.0, )" + }, + "System.IO.Ports": { + "target": "Package", + "version": "[10.0.9, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + }, + "Microsoft.WindowsDesktop.App.WindowsForms": { + "privateAssets": "none" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.302/PortableRuntimeIdentifierGraph.json", + "packagesToPrune": { + "Microsoft.CSharp": "(,4.7.32767]", + "Microsoft.VisualBasic": "(,10.4.32767]", + "Microsoft.Win32.Primitives": "(,4.3.32767]", + "Microsoft.Win32.Registry": "(,5.0.32767]", + "Microsoft.Win32.Registry.AccessControl": "(,10.0.32767]", + "Microsoft.Win32.SystemEvents": "(,10.0.32767]", + "runtime.any.System.Collections": "(,4.3.32767]", + "runtime.any.System.Diagnostics.Tools": "(,4.3.32767]", + "runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]", + "runtime.any.System.Globalization": "(,4.3.32767]", + "runtime.any.System.Globalization.Calendars": "(,4.3.32767]", + "runtime.any.System.IO": "(,4.3.32767]", + "runtime.any.System.Reflection": "(,4.3.32767]", + "runtime.any.System.Reflection.Extensions": "(,4.3.32767]", + "runtime.any.System.Reflection.Primitives": "(,4.3.32767]", + "runtime.any.System.Resources.ResourceManager": "(,4.3.32767]", + "runtime.any.System.Runtime": "(,4.3.32767]", + "runtime.any.System.Runtime.Handles": "(,4.3.32767]", + "runtime.any.System.Runtime.InteropServices": "(,4.3.32767]", + "runtime.any.System.Text.Encoding": "(,4.3.32767]", + "runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]", + "runtime.any.System.Threading.Tasks": "(,4.3.32767]", + "runtime.any.System.Threading.Timer": "(,4.3.32767]", + "runtime.aot.System.Collections": "(,4.3.32767]", + "runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]", + "runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]", + "runtime.aot.System.Globalization": "(,4.3.32767]", + "runtime.aot.System.Globalization.Calendars": "(,4.3.32767]", + "runtime.aot.System.IO": "(,4.3.32767]", + "runtime.aot.System.Reflection": "(,4.3.32767]", + "runtime.aot.System.Reflection.Extensions": "(,4.3.32767]", + "runtime.aot.System.Reflection.Primitives": "(,4.3.32767]", + "runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]", + "runtime.aot.System.Runtime": "(,4.3.32767]", + "runtime.aot.System.Runtime.Handles": "(,4.3.32767]", + "runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]", + "runtime.aot.System.Text.Encoding": "(,4.3.32767]", + "runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]", + "runtime.aot.System.Threading.Tasks": "(,4.3.32767]", + "runtime.aot.System.Threading.Timer": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]", + "runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]", + "runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]", + "runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]", + "runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]", + "runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]", + "runtime.unix.System.Console": "(,4.3.32767]", + "runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]", + "runtime.unix.System.IO.FileSystem": "(,4.3.32767]", + "runtime.unix.System.Net.Primitives": "(,4.3.32767]", + "runtime.unix.System.Net.Sockets": "(,4.3.32767]", + "runtime.unix.System.Private.Uri": "(,4.3.32767]", + "runtime.unix.System.Runtime.Extensions": "(,4.3.32767]", + "runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]", + "runtime.win.System.Console": "(,4.3.32767]", + "runtime.win.System.Diagnostics.Debug": "(,4.3.32767]", + "runtime.win.System.IO.FileSystem": "(,4.3.32767]", + "runtime.win.System.Net.Primitives": "(,4.3.32767]", + "runtime.win.System.Net.Sockets": "(,4.3.32767]", + "runtime.win.System.Runtime.Extensions": "(,4.3.32767]", + "runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]", + "runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]", + "runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]", + "runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.win7.System.Private.Uri": "(,4.3.32767]", + "runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]", + "System.AppContext": "(,4.3.32767]", + "System.Buffers": "(,5.0.32767]", + "System.CodeDom": "(,10.0.32767]", + "System.Collections": "(,4.3.32767]", + "System.Collections.Concurrent": "(,4.3.32767]", + "System.Collections.Immutable": "(,10.0.32767]", + "System.Collections.NonGeneric": "(,4.3.32767]", + "System.Collections.Specialized": "(,4.3.32767]", + "System.ComponentModel": "(,4.3.32767]", + "System.ComponentModel.Annotations": "(,4.3.32767]", + "System.ComponentModel.EventBasedAsync": "(,4.3.32767]", + "System.ComponentModel.Primitives": "(,4.3.32767]", + "System.ComponentModel.TypeConverter": "(,4.3.32767]", + "System.Configuration.ConfigurationManager": "(,10.0.32767]", + "System.Console": "(,4.3.32767]", + "System.Data.Common": "(,4.3.32767]", + "System.Data.DataSetExtensions": "(,4.4.32767]", + "System.Diagnostics.Contracts": "(,4.3.32767]", + "System.Diagnostics.Debug": "(,4.3.32767]", + "System.Diagnostics.DiagnosticSource": "(,10.0.32767]", + "System.Diagnostics.EventLog": "(,10.0.32767]", + "System.Diagnostics.FileVersionInfo": "(,4.3.32767]", + "System.Diagnostics.PerformanceCounter": "(,10.0.32767]", + "System.Diagnostics.Process": "(,4.3.32767]", + "System.Diagnostics.StackTrace": "(,4.3.32767]", + "System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]", + "System.Diagnostics.Tools": "(,4.3.32767]", + "System.Diagnostics.TraceSource": "(,4.3.32767]", + "System.Diagnostics.Tracing": "(,4.3.32767]", + "System.DirectoryServices": "(,10.0.32767]", + "System.Drawing.Common": "(,10.0.32767]", + "System.Drawing.Primitives": "(,4.3.32767]", + "System.Dynamic.Runtime": "(,4.3.32767]", + "System.Formats.Asn1": "(,10.0.32767]", + "System.Formats.Nrbf": "(,10.0.32767]", + "System.Formats.Tar": "(,10.0.32767]", + "System.Globalization": "(,4.3.32767]", + "System.Globalization.Calendars": "(,4.3.32767]", + "System.Globalization.Extensions": "(,4.3.32767]", + "System.IO": "(,4.3.32767]", + "System.IO.Compression": "(,4.3.32767]", + "System.IO.Compression.ZipFile": "(,4.3.32767]", + "System.IO.FileSystem": "(,4.3.32767]", + "System.IO.FileSystem.AccessControl": "(,4.4.32767]", + "System.IO.FileSystem.DriveInfo": "(,4.3.32767]", + "System.IO.FileSystem.Primitives": "(,4.3.32767]", + "System.IO.FileSystem.Watcher": "(,4.3.32767]", + "System.IO.IsolatedStorage": "(,4.3.32767]", + "System.IO.MemoryMappedFiles": "(,4.3.32767]", + "System.IO.Packaging": "(,10.0.32767]", + "System.IO.Pipelines": "(,10.0.32767]", + "System.IO.Pipes": "(,4.3.32767]", + "System.IO.Pipes.AccessControl": "(,5.0.32767]", + "System.IO.UnmanagedMemoryStream": "(,4.3.32767]", + "System.Linq": "(,4.3.32767]", + "System.Linq.AsyncEnumerable": "(,10.0.32767]", + "System.Linq.Expressions": "(,4.3.32767]", + "System.Linq.Parallel": "(,4.3.32767]", + "System.Linq.Queryable": "(,4.3.32767]", + "System.Memory": "(,5.0.32767]", + "System.Net.Http": "(,4.3.32767]", + "System.Net.Http.Json": "(,10.0.32767]", + "System.Net.NameResolution": "(,4.3.32767]", + "System.Net.NetworkInformation": "(,4.3.32767]", + "System.Net.Ping": "(,4.3.32767]", + "System.Net.Primitives": "(,4.3.32767]", + "System.Net.Requests": "(,4.3.32767]", + "System.Net.Security": "(,4.3.32767]", + "System.Net.ServerSentEvents": "(,10.0.32767]", + "System.Net.Sockets": "(,4.3.32767]", + "System.Net.WebHeaderCollection": "(,4.3.32767]", + "System.Net.WebSockets": "(,4.3.32767]", + "System.Net.WebSockets.Client": "(,4.3.32767]", + "System.Numerics.Vectors": "(,5.0.32767]", + "System.ObjectModel": "(,4.3.32767]", + "System.Private.DataContractSerialization": "(,4.3.32767]", + "System.Private.Uri": "(,4.3.32767]", + "System.Reflection": "(,4.3.32767]", + "System.Reflection.DispatchProxy": "(,6.0.32767]", + "System.Reflection.Emit": "(,4.7.32767]", + "System.Reflection.Emit.ILGeneration": "(,4.7.32767]", + "System.Reflection.Emit.Lightweight": "(,4.7.32767]", + "System.Reflection.Extensions": "(,4.3.32767]", + "System.Reflection.Metadata": "(,10.0.32767]", + "System.Reflection.Primitives": "(,4.3.32767]", + "System.Reflection.TypeExtensions": "(,4.3.32767]", + "System.Resources.Extensions": "(,10.0.32767]", + "System.Resources.Reader": "(,4.3.32767]", + "System.Resources.ResourceManager": "(,4.3.32767]", + "System.Resources.Writer": "(,4.3.32767]", + "System.Runtime": "(,4.3.32767]", + "System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]", + "System.Runtime.CompilerServices.VisualC": "(,4.3.32767]", + "System.Runtime.Extensions": "(,4.3.32767]", + "System.Runtime.Handles": "(,4.3.32767]", + "System.Runtime.InteropServices": "(,4.3.32767]", + "System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]", + "System.Runtime.Loader": "(,4.3.32767]", + "System.Runtime.Numerics": "(,4.3.32767]", + "System.Runtime.Serialization.Formatters": "(,4.3.32767]", + "System.Runtime.Serialization.Json": "(,4.3.32767]", + "System.Runtime.Serialization.Primitives": "(,4.3.32767]", + "System.Runtime.Serialization.Xml": "(,4.3.32767]", + "System.Security.AccessControl": "(,6.0.32767]", + "System.Security.Claims": "(,4.3.32767]", + "System.Security.Cryptography.Algorithms": "(,4.3.32767]", + "System.Security.Cryptography.Cng": "(,5.0.32767]", + "System.Security.Cryptography.Csp": "(,4.3.32767]", + "System.Security.Cryptography.Encoding": "(,4.3.32767]", + "System.Security.Cryptography.OpenSsl": "(,5.0.32767]", + "System.Security.Cryptography.Pkcs": "(,10.0.32767]", + "System.Security.Cryptography.Primitives": "(,4.3.32767]", + "System.Security.Cryptography.ProtectedData": "(,10.0.32767]", + "System.Security.Cryptography.X509Certificates": "(,4.3.32767]", + "System.Security.Cryptography.Xml": "(,10.0.32767]", + "System.Security.Permissions": "(,10.0.32767]", + "System.Security.Principal": "(,4.3.32767]", + "System.Security.Principal.Windows": "(,5.0.32767]", + "System.Security.SecureString": "(,4.3.32767]", + "System.Text.Encoding": "(,4.3.32767]", + "System.Text.Encoding.CodePages": "(,10.0.32767]", + "System.Text.Encoding.Extensions": "(,4.3.32767]", + "System.Text.Encodings.Web": "(,10.0.32767]", + "System.Text.Json": "(,10.0.32767]", + "System.Text.RegularExpressions": "(,4.3.32767]", + "System.Threading": "(,4.3.32767]", + "System.Threading.AccessControl": "(,10.0.32767]", + "System.Threading.Channels": "(,10.0.32767]", + "System.Threading.Overlapped": "(,4.3.32767]", + "System.Threading.Tasks": "(,4.3.32767]", + "System.Threading.Tasks.Dataflow": "(,10.0.32767]", + "System.Threading.Tasks.Extensions": "(,5.0.32767]", + "System.Threading.Tasks.Parallel": "(,4.3.32767]", + "System.Threading.Thread": "(,4.3.32767]", + "System.Threading.ThreadPool": "(,4.3.32767]", + "System.Threading.Timer": "(,4.3.32767]", + "System.ValueTuple": "(,4.5.32767]", + "System.Windows.Extensions": "(,10.0.32767]", + "System.Xml.ReaderWriter": "(,4.3.32767]", + "System.Xml.XDocument": "(,4.3.32767]", + "System.Xml.XmlDocument": "(,4.3.32767]", + "System.Xml.XmlSerializer": "(,4.3.32767]", + "System.Xml.XPath": "(,4.3.32767]", + "System.Xml.XPath.XDocument": "(,5.0.32767]" + } + } + } + } + } +} \ No newline at end of file diff --git a/Radio/App_radio/obj/App_radio.csproj.nuget.g.props b/Radio/App_radio/obj/App_radio.csproj.nuget.g.props new file mode 100644 index 0000000..2ec73b3 --- /dev/null +++ b/Radio/App_radio/obj/App_radio.csproj.nuget.g.props @@ -0,0 +1,15 @@ + + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + $(UserProfile)\.nuget\packages\ + C:\Users\alvar\.nuget\packages\ + PackageReference + 7.0.0 + + + + + \ No newline at end of file diff --git a/Radio/App_radio/obj/App_radio.csproj.nuget.g.targets b/Radio/App_radio/obj/App_radio.csproj.nuget.g.targets new file mode 100644 index 0000000..3dc06ef --- /dev/null +++ b/Radio/App_radio/obj/App_radio.csproj.nuget.g.targets @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs b/Radio/App_radio/obj/Debug/net10.0-windows/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs new file mode 100644 index 0000000..925b135 --- /dev/null +++ b/Radio/App_radio/obj/Debug/net10.0-windows/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")] diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.AssemblyInfo.cs b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.AssemblyInfo.cs new file mode 100644 index 0000000..a92b1d1 --- /dev/null +++ b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.AssemblyInfo.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------ +// +// Este código fue generado por una herramienta. +// Versión de runtime:4.0.30319.42000 +// +// Los cambios en este archivo podrían causar un comportamiento incorrecto y se perderán si +// se vuelve a generar el código. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("App_radio")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("App_radio")] +[assembly: System.Reflection.AssemblyTitleAttribute("App_radio")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] +[assembly: System.Runtime.Versioning.TargetPlatformAttribute("Windows7.0")] +[assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.AssemblyInfoInputs.cache b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.AssemblyInfoInputs.cache new file mode 100644 index 0000000..174af70 --- /dev/null +++ b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +0b160f71b5bcbec8190dec27628788a44df803979ca593b8f6d546503376aba5 diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.GeneratedMSBuildEditorConfig.editorconfig b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..58856ee --- /dev/null +++ b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,25 @@ +is_global = true +build_property.ApplicationManifest = +build_property.StartupObject = +build_property.ApplicationDefaultFont = +build_property.ApplicationHighDpiMode = +build_property.ApplicationUseCompatibleTextRendering = +build_property.ApplicationVisualStyles = +build_property.TargetFramework = net10.0-windows +build_property.TargetFrameworkIdentifier = .NETCoreApp +build_property.TargetFrameworkVersion = v10.0 +build_property.TargetPlatformMinVersion = 7.0 +build_property.UsingMicrosoftNETSdkWeb = +build_property.ProjectTypeGuids = +build_property.InvariantGlobalization = +build_property.PlatformNeutralAssembly = +build_property.EnforceExtendedAnalyzerRules = +build_property.EntryPointFilePath = +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property.RootNamespace = App_radio +build_property.ProjectDir = C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.CsWinRTUseWindowsUIXamlProjections = false +build_property.EffectiveAnalysisLevelStyle = 10.0 +build_property.EnableCodeStyleSeverity = diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.GlobalUsings.g.cs b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.GlobalUsings.g.cs new file mode 100644 index 0000000..18cabb0 --- /dev/null +++ b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.GlobalUsings.g.cs @@ -0,0 +1,10 @@ +// +global using System; +global using System.Collections.Generic; +global using System.Drawing; +global using System.IO; +global using System.Linq; +global using System.Net.Http; +global using System.Threading; +global using System.Threading.Tasks; +global using System.Windows.Forms; diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.RadioMain.resources b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.RadioMain.resources new file mode 100644 index 0000000..6c05a97 Binary files /dev/null and b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.RadioMain.resources differ diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.assets.cache b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.assets.cache new file mode 100644 index 0000000..08235b8 Binary files /dev/null and b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.assets.cache differ diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.AssemblyReference.cache b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.AssemblyReference.cache new file mode 100644 index 0000000..a6b3182 Binary files /dev/null and b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.AssemblyReference.cache differ diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.BuildWithSkipAnalyzers b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.BuildWithSkipAnalyzers new file mode 100644 index 0000000..e69de29 diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.CoreCompileInputs.cache b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..3833667 --- /dev/null +++ b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +af1fac5e31db0abbecb2c2e167742d7f8beddfc09491e12036d53f4d9eafa81f diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.FileListAbsolute.txt b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..fc8aa5f --- /dev/null +++ b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.FileListAbsolute.txt @@ -0,0 +1,176 @@ +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\App_radio.exe +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\App_radio.deps.json +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\App_radio.runtimeconfig.json +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\App_radio.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\App_radio.pdb +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\NAudio.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\NAudio.Asio.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\NAudio.Core.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\NAudio.Midi.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\NAudio.Wasapi.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\NAudio.WinForms.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\NAudio.WinMM.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\System.IO.Ports.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\android-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\android-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\android-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\android-x86\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\linux-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\linux-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\linux-bionic-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\linux-bionic-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\linux-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\maccatalyst-arm64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\maccatalyst-x64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\osx-arm64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\osx-x64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\unix\lib\net10.0\System.IO.Ports.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\bin\Debug\net10.0-windows\runtimes\win\lib\net10.0\System.IO.Ports.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.AssemblyReference.cache +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.RadioMain.resources +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.GenerateResource.cache +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.GeneratedMSBuildEditorConfig.editorconfig +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.AssemblyInfoInputs.cache +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.AssemblyInfo.cs +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.CoreCompileInputs.cache +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.Up2Date +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\refint\App_radio.dll +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.pdb +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\App_radio.genruntimeconfig.cache +C:\Users\alvar\Desktop\Pruebas\App_radio\obj\Debug\net10.0-windows\ref\App_radio.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\App_radio.exe +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\App_radio.deps.json +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\App_radio.runtimeconfig.json +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\App_radio.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\App_radio.pdb +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.Asio.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.Core.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.Midi.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.Wasapi.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.WinForms.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.WinMM.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\System.IO.Ports.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\android-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\android-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\android-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\android-x86\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-bionic-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-bionic-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\maccatalyst-arm64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\maccatalyst-x64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\osx-arm64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\osx-x64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\unix\lib\net10.0\System.IO.Ports.dll +C:\Users\alvar\Desktop\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\win\lib\net10.0\System.IO.Ports.dll +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.AssemblyReference.cache +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.RadioMain.resources +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.GenerateResource.cache +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.GeneratedMSBuildEditorConfig.editorconfig +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.AssemblyInfoInputs.cache +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.AssemblyInfo.cs +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.CoreCompileInputs.cache +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.Up2Date +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.dll +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\refint\App_radio.dll +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.pdb +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.genruntimeconfig.cache +C:\Users\alvar\Desktop\AARadio\App_radio\obj\Debug\net10.0-windows\ref\App_radio.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\App_radio.exe +C:\AARadio\App_radio\bin\Debug\net10.0-windows\App_radio.deps.json +C:\AARadio\App_radio\bin\Debug\net10.0-windows\App_radio.runtimeconfig.json +C:\AARadio\App_radio\bin\Debug\net10.0-windows\App_radio.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\App_radio.pdb +C:\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.Asio.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.Core.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.Midi.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.Wasapi.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.WinForms.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\NAudio.WinMM.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\System.IO.Ports.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\android-arm\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\android-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\android-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\android-x86\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-arm\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-bionic-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-bionic-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-arm\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\linux-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\maccatalyst-arm64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\maccatalyst-x64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\osx-arm64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\osx-x64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\unix\lib\net10.0\System.IO.Ports.dll +C:\AARadio\App_radio\bin\Debug\net10.0-windows\runtimes\win\lib\net10.0\System.IO.Ports.dll +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.AssemblyReference.cache +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.RadioMain.resources +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.GenerateResource.cache +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.GeneratedMSBuildEditorConfig.editorconfig +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.AssemblyInfoInputs.cache +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.AssemblyInfo.cs +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.CoreCompileInputs.cache +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.Up2Date +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.dll +C:\AARadio\App_radio\obj\Debug\net10.0-windows\refint\App_radio.dll +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.pdb +C:\AARadio\App_radio\obj\Debug\net10.0-windows\App_radio.genruntimeconfig.cache +C:\AARadio\App_radio\obj\Debug\net10.0-windows\ref\App_radio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\App_radio.exe +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\App_radio.deps.json +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\App_radio.runtimeconfig.json +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\App_radio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\App_radio.pdb +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\NAudio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\NAudio.Asio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\NAudio.Core.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\NAudio.Midi.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\NAudio.Wasapi.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\NAudio.WinForms.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\NAudio.WinMM.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\System.IO.Ports.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\android-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\android-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\android-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\android-x86\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\linux-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\linux-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\linux-bionic-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\linux-bionic-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\linux-musl-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\linux-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\maccatalyst-arm64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\maccatalyst-x64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\osx-arm64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\osx-x64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\unix\lib\net10.0\System.IO.Ports.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Debug\net10.0-windows\runtimes\win\lib\net10.0\System.IO.Ports.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.AssemblyReference.cache +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.RadioMain.resources +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.GenerateResource.cache +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.GeneratedMSBuildEditorConfig.editorconfig +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.AssemblyInfoInputs.cache +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.AssemblyInfo.cs +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.CoreCompileInputs.cache +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.csproj.Up2Date +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\refint\App_radio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.pdb +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\App_radio.genruntimeconfig.cache +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Debug\net10.0-windows\ref\App_radio.dll diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.GenerateResource.cache b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.GenerateResource.cache new file mode 100644 index 0000000..fe081f8 Binary files /dev/null and b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.GenerateResource.cache differ diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.Up2Date b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.csproj.Up2Date new file mode 100644 index 0000000..e69de29 diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.dll b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.dll new file mode 100644 index 0000000..786ea37 Binary files /dev/null and b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.dll differ diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.genruntimeconfig.cache b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.genruntimeconfig.cache new file mode 100644 index 0000000..142377d --- /dev/null +++ b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.genruntimeconfig.cache @@ -0,0 +1 @@ +755ac33c48352a47bc759947a3eaadbfe4896495adb79968bd3c6192cd08a180 diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.pdb b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.pdb new file mode 100644 index 0000000..d6cbf0e Binary files /dev/null and b/Radio/App_radio/obj/Debug/net10.0-windows/App_radio.pdb differ diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/apphost.exe b/Radio/App_radio/obj/Debug/net10.0-windows/apphost.exe new file mode 100644 index 0000000..232e716 Binary files /dev/null and b/Radio/App_radio/obj/Debug/net10.0-windows/apphost.exe differ diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/ref/App_radio.dll b/Radio/App_radio/obj/Debug/net10.0-windows/ref/App_radio.dll new file mode 100644 index 0000000..a89a7ef Binary files /dev/null and b/Radio/App_radio/obj/Debug/net10.0-windows/ref/App_radio.dll differ diff --git a/Radio/App_radio/obj/Debug/net10.0-windows/refint/App_radio.dll b/Radio/App_radio/obj/Debug/net10.0-windows/refint/App_radio.dll new file mode 100644 index 0000000..a89a7ef Binary files /dev/null and b/Radio/App_radio/obj/Debug/net10.0-windows/refint/App_radio.dll differ diff --git a/Radio/App_radio/obj/Release/net10.0-windows/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs b/Radio/App_radio/obj/Release/net10.0-windows/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs new file mode 100644 index 0000000..925b135 --- /dev/null +++ b/Radio/App_radio/obj/Release/net10.0-windows/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")] diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.AssemblyInfo.cs b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.AssemblyInfo.cs new file mode 100644 index 0000000..3ca8c84 --- /dev/null +++ b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.AssemblyInfo.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------ +// +// Este código fue generado por una herramienta. +// Versión de runtime:4.0.30319.42000 +// +// Los cambios en este archivo podrían causar un comportamiento incorrecto y se perderán si +// se vuelve a generar el código. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("App_radio")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("App_radio")] +[assembly: System.Reflection.AssemblyTitleAttribute("App_radio")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] +[assembly: System.Runtime.Versioning.TargetPlatformAttribute("Windows7.0")] +[assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.AssemblyInfoInputs.cache b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.AssemblyInfoInputs.cache new file mode 100644 index 0000000..1553d21 --- /dev/null +++ b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +9241e5d87f543c4d71a6b26b4dd7f16946a2ac6c8bc4023fb8d64cf668179dd3 diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.GeneratedMSBuildEditorConfig.editorconfig b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..58856ee --- /dev/null +++ b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,25 @@ +is_global = true +build_property.ApplicationManifest = +build_property.StartupObject = +build_property.ApplicationDefaultFont = +build_property.ApplicationHighDpiMode = +build_property.ApplicationUseCompatibleTextRendering = +build_property.ApplicationVisualStyles = +build_property.TargetFramework = net10.0-windows +build_property.TargetFrameworkIdentifier = .NETCoreApp +build_property.TargetFrameworkVersion = v10.0 +build_property.TargetPlatformMinVersion = 7.0 +build_property.UsingMicrosoftNETSdkWeb = +build_property.ProjectTypeGuids = +build_property.InvariantGlobalization = +build_property.PlatformNeutralAssembly = +build_property.EnforceExtendedAnalyzerRules = +build_property.EntryPointFilePath = +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property.RootNamespace = App_radio +build_property.ProjectDir = C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.CsWinRTUseWindowsUIXamlProjections = false +build_property.EffectiveAnalysisLevelStyle = 10.0 +build_property.EnableCodeStyleSeverity = diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.GlobalUsings.g.cs b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.GlobalUsings.g.cs new file mode 100644 index 0000000..18cabb0 --- /dev/null +++ b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.GlobalUsings.g.cs @@ -0,0 +1,10 @@ +// +global using System; +global using System.Collections.Generic; +global using System.Drawing; +global using System.IO; +global using System.Linq; +global using System.Net.Http; +global using System.Threading; +global using System.Threading.Tasks; +global using System.Windows.Forms; diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.RadioMain.resources b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.RadioMain.resources new file mode 100644 index 0000000..6c05a97 Binary files /dev/null and b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.RadioMain.resources differ diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.assets.cache b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.assets.cache new file mode 100644 index 0000000..3f3d273 Binary files /dev/null and b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.assets.cache differ diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.AssemblyReference.cache b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.AssemblyReference.cache new file mode 100644 index 0000000..a6b3182 Binary files /dev/null and b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.AssemblyReference.cache differ diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.BuildWithSkipAnalyzers b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.BuildWithSkipAnalyzers new file mode 100644 index 0000000..e69de29 diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.CoreCompileInputs.cache b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..3253c1a --- /dev/null +++ b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +0e4916d273eb627656bb4371c31fd8ea0af8688f19c46911501298ca2c3c5995 diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.FileListAbsolute.txt b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..a33a88b --- /dev/null +++ b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.FileListAbsolute.txt @@ -0,0 +1,132 @@ +C:\AARadio\App_radio\bin\Release\net10.0-windows\App_radio.exe +C:\AARadio\App_radio\bin\Release\net10.0-windows\App_radio.deps.json +C:\AARadio\App_radio\bin\Release\net10.0-windows\App_radio.runtimeconfig.json +C:\AARadio\App_radio\bin\Release\net10.0-windows\App_radio.dll +C:\AARadio\App_radio\bin\Release\net10.0-windows\App_radio.pdb +C:\AARadio\App_radio\bin\Release\net10.0-windows\NAudio.dll +C:\AARadio\App_radio\bin\Release\net10.0-windows\NAudio.Asio.dll +C:\AARadio\App_radio\bin\Release\net10.0-windows\NAudio.Core.dll +C:\AARadio\App_radio\bin\Release\net10.0-windows\NAudio.Midi.dll +C:\AARadio\App_radio\bin\Release\net10.0-windows\NAudio.Wasapi.dll +C:\AARadio\App_radio\bin\Release\net10.0-windows\NAudio.WinForms.dll +C:\AARadio\App_radio\bin\Release\net10.0-windows\NAudio.WinMM.dll +C:\AARadio\App_radio\bin\Release\net10.0-windows\System.IO.Ports.dll +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\android-arm\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\android-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\android-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\android-x86\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\linux-arm\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\linux-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\linux-bionic-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\linux-bionic-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\linux-musl-arm\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\linux-musl-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\linux-musl-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\linux-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\maccatalyst-arm64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\maccatalyst-x64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\osx-arm64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\osx-x64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\unix\lib\net10.0\System.IO.Ports.dll +C:\AARadio\App_radio\bin\Release\net10.0-windows\runtimes\win\lib\net10.0\System.IO.Ports.dll +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.csproj.AssemblyReference.cache +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.RadioMain.resources +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.csproj.GenerateResource.cache +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.GeneratedMSBuildEditorConfig.editorconfig +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.AssemblyInfoInputs.cache +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.AssemblyInfo.cs +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.csproj.CoreCompileInputs.cache +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.csproj.Up2Date +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.dll +C:\AARadio\App_radio\obj\Release\net10.0-windows\refint\App_radio.dll +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.pdb +C:\AARadio\App_radio\obj\Release\net10.0-windows\App_radio.genruntimeconfig.cache +C:\AARadio\App_radio\obj\Release\net10.0-windows\ref\App_radio.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\App_radio.exe +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\App_radio.deps.json +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\App_radio.runtimeconfig.json +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\App_radio.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\App_radio.pdb +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.Asio.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.Core.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.Midi.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.Wasapi.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.WinForms.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.WinMM.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\System.IO.Ports.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\android-arm\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\android-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\android-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\android-x86\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-arm\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-bionic-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-bionic-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-musl-arm\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-musl-arm64\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-musl-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-x64\native\libSystem.IO.Ports.Native.so +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\maccatalyst-arm64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\maccatalyst-x64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\osx-arm64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\osx-x64\native\libSystem.IO.Ports.Native.dylib +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\unix\lib\net10.0\System.IO.Ports.dll +C:\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\win\lib\net10.0\System.IO.Ports.dll +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.csproj.AssemblyReference.cache +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.RadioMain.resources +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.csproj.GenerateResource.cache +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.GeneratedMSBuildEditorConfig.editorconfig +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.AssemblyInfoInputs.cache +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.AssemblyInfo.cs +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.csproj.CoreCompileInputs.cache +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.csproj.Up2Date +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.dll +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\refint\App_radio.dll +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.pdb +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.genruntimeconfig.cache +C:\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\ref\App_radio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\App_radio.exe +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\App_radio.deps.json +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\App_radio.runtimeconfig.json +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\App_radio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\App_radio.pdb +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.Asio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.Core.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.Midi.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.Wasapi.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.WinForms.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\NAudio.WinMM.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\System.IO.Ports.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\android-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\android-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\android-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\android-x86\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-bionic-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-bionic-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-musl-arm\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-musl-arm64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-musl-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\linux-x64\native\libSystem.IO.Ports.Native.so +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\maccatalyst-arm64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\maccatalyst-x64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\osx-arm64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\osx-x64\native\libSystem.IO.Ports.Native.dylib +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\unix\lib\net10.0\System.IO.Ports.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\bin\Release\net10.0-windows\runtimes\win\lib\net10.0\System.IO.Ports.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.csproj.AssemblyReference.cache +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.RadioMain.resources +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.csproj.GenerateResource.cache +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.GeneratedMSBuildEditorConfig.editorconfig +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.AssemblyInfoInputs.cache +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.AssemblyInfo.cs +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.csproj.CoreCompileInputs.cache +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.csproj.Up2Date +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\refint\App_radio.dll +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.pdb +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\App_radio.genruntimeconfig.cache +C:\Users\alvar\Desktop\Barcelona_software\AARadio_bluetooth\App_radio\obj\Release\net10.0-windows\ref\App_radio.dll diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.GenerateResource.cache b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.GenerateResource.cache new file mode 100644 index 0000000..fe081f8 Binary files /dev/null and b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.GenerateResource.cache differ diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.Up2Date b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.csproj.Up2Date new file mode 100644 index 0000000..e69de29 diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.dll b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.dll new file mode 100644 index 0000000..0c71ec5 Binary files /dev/null and b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.dll differ diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.genruntimeconfig.cache b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.genruntimeconfig.cache new file mode 100644 index 0000000..536048b --- /dev/null +++ b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.genruntimeconfig.cache @@ -0,0 +1 @@ +a4c38f154db4f36e89a578c8d1a62a3decbe891d3468f06139ae593071cf8551 diff --git a/Radio/App_radio/obj/Release/net10.0-windows/App_radio.pdb b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.pdb new file mode 100644 index 0000000..d0a3a5c Binary files /dev/null and b/Radio/App_radio/obj/Release/net10.0-windows/App_radio.pdb differ diff --git a/Radio/App_radio/obj/Release/net10.0-windows/apphost.exe b/Radio/App_radio/obj/Release/net10.0-windows/apphost.exe new file mode 100644 index 0000000..232e716 Binary files /dev/null and b/Radio/App_radio/obj/Release/net10.0-windows/apphost.exe differ diff --git a/Radio/App_radio/obj/Release/net10.0-windows/ref/App_radio.dll b/Radio/App_radio/obj/Release/net10.0-windows/ref/App_radio.dll new file mode 100644 index 0000000..0c4ac60 Binary files /dev/null and b/Radio/App_radio/obj/Release/net10.0-windows/ref/App_radio.dll differ diff --git a/Radio/App_radio/obj/Release/net10.0-windows/refint/App_radio.dll b/Radio/App_radio/obj/Release/net10.0-windows/refint/App_radio.dll new file mode 100644 index 0000000..0c4ac60 Binary files /dev/null and b/Radio/App_radio/obj/Release/net10.0-windows/refint/App_radio.dll differ diff --git a/Radio/App_radio/obj/project.assets.json b/Radio/App_radio/obj/project.assets.json new file mode 100644 index 0000000..c10e6bb --- /dev/null +++ b/Radio/App_radio/obj/project.assets.json @@ -0,0 +1,2319 @@ +{ + "version": 4, + "targets": { + "net10.0-windows": { + "NAudio/2.3.0": { + "type": "package", + "dependencies": { + "NAudio.Asio": "2.3.0", + "NAudio.Core": "2.3.0", + "NAudio.Midi": "2.3.0", + "NAudio.Wasapi": "2.3.0", + "NAudio.WinForms": "2.3.0", + "NAudio.WinMM": "2.3.0" + }, + "compile": { + "lib/net6.0-windows7.0/NAudio.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0-windows7.0/NAudio.dll": { + "related": ".xml" + } + } + }, + "NAudio.Asio/2.3.0": { + "type": "package", + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "compile": { + "lib/net8.0-windows7.0/NAudio.Asio.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0-windows7.0/NAudio.Asio.dll": { + "related": ".xml" + } + } + }, + "NAudio.Core/2.3.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/NAudio.Core.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/NAudio.Core.dll": { + "related": ".xml" + } + } + }, + "NAudio.Midi/2.3.0": { + "type": "package", + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "compile": { + "lib/netstandard2.0/NAudio.Midi.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/NAudio.Midi.dll": { + "related": ".xml" + } + } + }, + "NAudio.Wasapi/2.3.0": { + "type": "package", + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "compile": { + "lib/netstandard2.0/NAudio.Wasapi.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/NAudio.Wasapi.dll": { + "related": ".xml" + } + } + }, + "NAudio.WinForms/2.3.0": { + "type": "package", + "dependencies": { + "NAudio.WinMM": "2.3.0" + }, + "compile": { + "lib/netcoreapp3.1/NAudio.WinForms.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp3.1/NAudio.WinForms.dll": { + "related": ".xml" + } + }, + "frameworkReferences": [ + "Microsoft.WindowsDesktop.App.WindowsForms" + ] + }, + "NAudio.WinMM/2.3.0": { + "type": "package", + "dependencies": { + "NAudio.Core": "2.3.0" + }, + "compile": { + "lib/net6.0/NAudio.WinMM.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/NAudio.WinMM.dll": { + "related": ".xml" + } + } + }, + "runtime.android-arm.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.android-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.android-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.android-x86.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.linux-arm.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.linux-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.linux-bionic-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.linux-bionic-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.linux-musl-arm.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.linux-musl-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.linux-musl-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.linux-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/libSystem.IO.Ports.Native.so": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.maccatalyst-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.maccatalyst-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "dependencies": { + "runtime.android-arm.runtime.native.System.IO.Ports": "10.0.9", + "runtime.android-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.android-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.android-x86.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-arm.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-bionic-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-bionic-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-musl-arm.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-musl-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-musl-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.linux-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.maccatalyst-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.maccatalyst-x64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.osx-arm64.runtime.native.System.IO.Ports": "10.0.9", + "runtime.osx-x64.runtime.native.System.IO.Ports": "10.0.9" + } + }, + "runtime.osx-arm64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/_._": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "runtime.osx-x64.runtime.native.System.IO.Ports/10.0.9": { + "type": "package", + "runtimeTargets": { + "runtimes/android-arm/native/_._": { + "assetType": "native", + "rid": "android-arm" + }, + "runtimes/android-arm64/native/_._": { + "assetType": "native", + "rid": "android-arm64" + }, + "runtimes/android-x64/native/_._": { + "assetType": "native", + "rid": "android-x64" + }, + "runtimes/android-x86/native/_._": { + "assetType": "native", + "rid": "android-x86" + }, + "runtimes/linux-arm/native/_._": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/_._": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-bionic-arm64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-arm64" + }, + "runtimes/linux-bionic-x64/native/_._": { + "assetType": "native", + "rid": "linux-bionic-x64" + }, + "runtimes/linux-musl-arm/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm" + }, + "runtimes/linux-musl-arm64/native/_._": { + "assetType": "native", + "rid": "linux-musl-arm64" + }, + "runtimes/linux-musl-x64/native/_._": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/_._": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/maccatalyst-arm64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-arm64" + }, + "runtimes/maccatalyst-x64/native/_._": { + "assetType": "native", + "rid": "maccatalyst-x64" + }, + "runtimes/osx-arm64/native/_._": { + "assetType": "native", + "rid": "osx-arm64" + }, + "runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "System.IO.Ports/10.0.9": { + "type": "package", + "dependencies": { + "runtime.native.System.IO.Ports": "10.0.9" + }, + "compile": { + "lib/net10.0/System.IO.Ports.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net10.0/System.IO.Ports.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + }, + "runtimeTargets": { + "runtimes/unix/lib/net10.0/System.IO.Ports.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/net10.0/System.IO.Ports.dll": { + "assetType": "runtime", + "rid": "win" + } + } + } + } + }, + "libraries": { + "NAudio/2.3.0": { + "sha512": "xN+Lzlu9DmXqBiL6XkP0VZmgTxZPdSGjVSWtKG9HKuar3LhIYNOIYQETieigS+QDS+nrs1QmHbBWWOru0nWA5A==", + "type": "package", + "path": "naudio/2.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net472/NAudio.dll", + "lib/net472/NAudio.xml", + "lib/net6.0-windows7.0/NAudio.dll", + "lib/net6.0-windows7.0/NAudio.xml", + "lib/net6.0/NAudio.dll", + "lib/net6.0/NAudio.xml", + "lib/netcoreapp3.1/NAudio.dll", + "lib/netcoreapp3.1/NAudio.xml", + "naudio-icon.png", + "naudio.2.3.0.nupkg.sha512", + "naudio.nuspec" + ] + }, + "NAudio.Asio/2.3.0": { + "sha512": "I+rAAPT8vmSEw4d4ie+AoSkrvNK6ylRrXznnjQKS+qZgTA9Jnt1Pxe0EaU8nXxOOq5h8ucBSWccBEw6I/J0nkQ==", + "type": "package", + "path": "naudio.asio/2.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net8.0-windows7.0/NAudio.Asio.dll", + "lib/net8.0-windows7.0/NAudio.Asio.xml", + "lib/netstandard2.0/NAudio.Asio.dll", + "lib/netstandard2.0/NAudio.Asio.xml", + "naudio-icon.png", + "naudio.asio.2.3.0.nupkg.sha512", + "naudio.asio.nuspec" + ] + }, + "NAudio.Core/2.3.0": { + "sha512": "jMd7r6dB6tAtXhOYL58ntPqwERNm1/Rhw5MKOIYvsnXzuX+PTGsa2VMam6n0npZYSwlSidKa4GAm4bFcXFUlcg==", + "type": "package", + "path": "naudio.core/2.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/NAudio.Core.dll", + "lib/netstandard2.0/NAudio.Core.xml", + "naudio-icon.png", + "naudio.core.2.3.0.nupkg.sha512", + "naudio.core.nuspec" + ] + }, + "NAudio.Midi/2.3.0": { + "sha512": "t8wvPFPHHQOHhoNMCaDE8OiYZoJuxmY4H6UPBtmnf+xx7oQuajFCqlG4Q00ID+tiEyj471WeVb4Nkylr4tDoow==", + "type": "package", + "path": "naudio.midi/2.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/NAudio.Midi.dll", + "lib/netstandard2.0/NAudio.Midi.xml", + "naudio-icon.png", + "naudio.midi.2.3.0.nupkg.sha512", + "naudio.midi.nuspec" + ] + }, + "NAudio.Wasapi/2.3.0": { + "sha512": "y5K2BxrLnvohgu5znzg5wRsai3YcuNXfrpo68i7PmCQqpK5MC/R24e5aO3OyN/XhfRr12e0QYV0OnUWEHi5SzA==", + "type": "package", + "path": "naudio.wasapi/2.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net9.0-windows10.0.26100/NAudio.Wasapi.dll", + "lib/net9.0-windows10.0.26100/NAudio.Wasapi.xml", + "lib/netstandard2.0/NAudio.Wasapi.dll", + "lib/netstandard2.0/NAudio.Wasapi.xml", + "naudio-icon.png", + "naudio.wasapi.2.3.0.nupkg.sha512", + "naudio.wasapi.nuspec" + ] + }, + "NAudio.WinForms/2.3.0": { + "sha512": "vyKqFUlAZrZ0QPcCM1T+zimjYgC1cNDloHaiOdtV4S1eK4AGu3Dz1EE4yy/WgcneJwQNjGFaELY7b2TsL+g56w==", + "type": "package", + "path": "naudio.winforms/2.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net472/NAudio.WinForms.dll", + "lib/net472/NAudio.WinForms.xml", + "lib/netcoreapp3.1/NAudio.WinForms.dll", + "lib/netcoreapp3.1/NAudio.WinForms.xml", + "naudio-icon.png", + "naudio.winforms.2.3.0.nupkg.sha512", + "naudio.winforms.nuspec" + ] + }, + "NAudio.WinMM/2.3.0": { + "sha512": "5G1dRjsZm50T3luyuqcmI2BSvj3K4ZJaD/x776/0Epj88qOsOryDZG40+MufwIk1UFJSFWhRobBqtJYFc8Ss4g==", + "type": "package", + "path": "naudio.winmm/2.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net6.0/NAudio.WinMM.dll", + "lib/net6.0/NAudio.WinMM.xml", + "lib/netstandard2.0/NAudio.WinMM.dll", + "lib/netstandard2.0/NAudio.WinMM.xml", + "naudio-icon.png", + "naudio.winmm.2.3.0.nupkg.sha512", + "naudio.winmm.nuspec" + ] + }, + "runtime.android-arm.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "7QwWCqZ4hRpmSySAFslZD5oFhV8ib/FhO2eGgPrImEI3V8U5P1FtIc5M4pB+5xOBfzW5VzjmItKFezkB8MGDqw==", + "type": "package", + "path": "runtime.android-arm.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.android-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.android-arm.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/libSystem.IO.Ports.Native.so", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.android-arm64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "mOZanUMgwxreyyoZRHaeLbfaevCgaadM4RafsRclY0I+cwV/QbYhzjELYc6C68acd+4z/Fj9zh66u6nu3evP0A==", + "type": "package", + "path": "runtime.android-arm64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.android-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.android-arm64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/libSystem.IO.Ports.Native.so", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.android-x64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "rUvnhurQfEkaduyDlESUgttOjAjMniC38B9IMVfx2480OvBWzhy5vzvcg2WIlTCJErb4sCN+QTzhHBpOYFRoxw==", + "type": "package", + "path": "runtime.android-x64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.android-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.android-x64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/libSystem.IO.Ports.Native.so", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.android-x86.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "ykG02K8zQqj8VcWfyjsvG9+lT2ODaqjF17Sid2/s7Kgp+ugn9eh4V2FZpzV0qa+JfVH5eohB4JaF7K/XpdTHCQ==", + "type": "package", + "path": "runtime.android-x86.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.android-x86.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.android-x86.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/libSystem.IO.Ports.Native.so", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.linux-arm.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "DHRGpEI+51UCQR74jrkA30s7luDaUw3NC4Jp3MNLTnseuCVTRQ5ocbjpApt7mM9quoP7YZKMG+iUA+xJ6yJW8Q==", + "type": "package", + "path": "runtime.linux-arm.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.linux-arm.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/libSystem.IO.Ports.Native.so", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.linux-arm64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "G67fx6Vv/z5DFvfa5MiqAa9lONQv0d+WGxICW+Nvp+LNA6iJvv4j6/GTjGXtK44T/n+8sYk9dho7pKtuCoMZWQ==", + "type": "package", + "path": "runtime.linux-arm64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.linux-arm64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.linux-bionic-arm64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "E08Eipi4Iiq3+JV/mpNxS+loN68ZJlrlaHCfiXmUL3Qlcpq9slGXyw5N97v4nL9dzpCIBnLstQEFC32HTpCduw==", + "type": "package", + "path": "runtime.linux-bionic-arm64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-bionic-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.linux-bionic-arm64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.linux-bionic-x64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "FaATvKgabe3xHU9aYnj2h4Pp4DeY91SwMmHdv4/+Wmzp6fqwGT25xCNBzJ2FOHEdJLNO52raXcL3Xwo2/eLXKg==", + "type": "package", + "path": "runtime.linux-bionic-x64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-bionic-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.linux-bionic-x64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.linux-musl-arm.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "OsROr3mGvkb4U/cizz5s3y+Oa8OBjGCCo8QWEmuUEdM40wp0JbWMEwaqOmScxVCZNzobHHfHeuX/o3oTGj3OmA==", + "type": "package", + "path": "runtime.linux-musl-arm.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-musl-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.linux-musl-arm.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.linux-musl-arm64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "vDGYpx/8dAAMlJccGLCWLaJ20AzASKax33suoHw7s/alEjwYp1mpD6Vso4qbX5QJLonE+lnx3vfB+maKV4CtAA==", + "type": "package", + "path": "runtime.linux-musl-arm64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-musl-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.linux-musl-arm64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.linux-musl-x64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "JwGn9azjl7+AuwzgEdeJLghTcK8nCqKCf7h/gq7Pzi2HMuv6D2EBzDZpl95qKkdBCT6bsWdv3flZQJZf2uY2ew==", + "type": "package", + "path": "runtime.linux-musl-x64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-musl-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.linux-musl-x64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.linux-x64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "01ppayPym92n42VR74iSt/MNw5UoltX0tQOVvA5P0bUszvtDRPkAM5SEkujIVBs6+kERZ2OgZN8mMDPJKTfh2Q==", + "type": "package", + "path": "runtime.linux-x64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.linux-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.linux-x64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/libSystem.IO.Ports.Native.so", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.maccatalyst-arm64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "z9OvFgFoV9jScx7pmjasXvmixG8qK8QdN3fcsP2TptMbfU+/4bz/SKjpgw3MRROJcfiTQWdJE4Cdx4vG86bulA==", + "type": "package", + "path": "runtime.maccatalyst-arm64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.maccatalyst-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.maccatalyst-arm64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.maccatalyst-x64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "45LNikgDcVaFWkVxUr1h5ZaM6o0LT05TdKzmFI1OnZIEaT4/yWJukrouzsEZfm2kyN05EA/U686HSnuqMS7+6A==", + "type": "package", + "path": "runtime.maccatalyst-x64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.maccatalyst-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.maccatalyst-x64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.native.System.IO.Ports/10.0.9": { + "sha512": "PoZf6+MaLVHqj37ozGdAc98w+UtwGLJGqQ4QeKT+qvQaX9EqpKmrhmImoGI68wrkJkRbwGCP1jIsFKpMu4iBKg==", + "type": "package", + "path": "runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.native.system.io.ports.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "runtime.osx-arm64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "fW857DfzCX6QsEuVH1/WohiHh1BphhHcGsjpLX5h3sgm0Y67QVWijykrJSZC4Ct9Gfm40pfmSo+L53deIQ9MZQ==", + "type": "package", + "path": "runtime.osx-arm64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.osx-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.osx-arm64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib", + "runtimes/osx-x64/native/_._", + "useSharedDesignerContext.txt" + ] + }, + "runtime.osx-x64.runtime.native.System.IO.Ports/10.0.9": { + "sha512": "Ugf+Hlb6dJB1tXLZqU/q4iXclQ/lojiJWtLCFqmRiE2bXA8fOnUHz9U40dJxHdqPO9BEyfzWEliRCUtZCblNmQ==", + "type": "package", + "path": "runtime.osx-x64.runtime.native.system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "runtime.osx-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "runtime.osx-x64.runtime.native.system.io.ports.nuspec", + "runtimes/android-arm/native/_._", + "runtimes/android-arm64/native/_._", + "runtimes/android-x64/native/_._", + "runtimes/android-x86/native/_._", + "runtimes/linux-arm/native/_._", + "runtimes/linux-arm64/native/_._", + "runtimes/linux-bionic-arm64/native/_._", + "runtimes/linux-bionic-x64/native/_._", + "runtimes/linux-musl-arm/native/_._", + "runtimes/linux-musl-arm64/native/_._", + "runtimes/linux-musl-x64/native/_._", + "runtimes/linux-x64/native/_._", + "runtimes/maccatalyst-arm64/native/_._", + "runtimes/maccatalyst-x64/native/_._", + "runtimes/osx-arm64/native/_._", + "runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib", + "useSharedDesignerContext.txt" + ] + }, + "System.IO.Ports/10.0.9": { + "sha512": "JHijtblIg7c1wCxBtuPjqWK+BxTlO0qTE3Y5PSety2NGkZRL5LFL6JoabbGebmO1PuOtUqlvAc+6hbLvlLSTqQ==", + "type": "package", + "path": "system.io.ports/10.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.IO.Ports.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/System.IO.Ports.targets", + "lib/net10.0/System.IO.Ports.dll", + "lib/net10.0/System.IO.Ports.xml", + "lib/net462/System.IO.Ports.dll", + "lib/net462/System.IO.Ports.xml", + "lib/net8.0/System.IO.Ports.dll", + "lib/net8.0/System.IO.Ports.xml", + "lib/net9.0/System.IO.Ports.dll", + "lib/net9.0/System.IO.Ports.xml", + "lib/netstandard2.0/System.IO.Ports.dll", + "lib/netstandard2.0/System.IO.Ports.xml", + "runtimes/unix/lib/net10.0/System.IO.Ports.dll", + "runtimes/unix/lib/net10.0/System.IO.Ports.xml", + "runtimes/unix/lib/net8.0/System.IO.Ports.dll", + "runtimes/unix/lib/net8.0/System.IO.Ports.xml", + "runtimes/unix/lib/net9.0/System.IO.Ports.dll", + "runtimes/unix/lib/net9.0/System.IO.Ports.xml", + "runtimes/win/lib/net10.0/System.IO.Ports.dll", + "runtimes/win/lib/net10.0/System.IO.Ports.xml", + "runtimes/win/lib/net8.0/System.IO.Ports.dll", + "runtimes/win/lib/net8.0/System.IO.Ports.xml", + "runtimes/win/lib/net9.0/System.IO.Ports.dll", + "runtimes/win/lib/net9.0/System.IO.Ports.xml", + "system.io.ports.10.0.9.nupkg.sha512", + "system.io.ports.nuspec", + "useSharedDesignerContext.txt" + ] + } + }, + "projectFileDependencyGroups": { + "net10.0-windows": [ + "NAudio >= 2.3.0", + "System.IO.Ports >= 10.0.9" + ] + }, + "packageFolders": { + "C:\\Users\\alvar\\.nuget\\packages\\": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\App_radio.csproj", + "projectName": "App_radio", + "projectPath": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\App_radio.csproj", + "packagesPath": "C:\\Users\\alvar\\.nuget\\packages\\", + "outputPath": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\obj\\", + "projectStyle": "PackageReference", + "configFilePaths": [ + "C:\\Users\\alvar\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net10.0-windows" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net10.0-windows": { + "framework": "net10.0-windows7.0", + "targetAlias": "net10.0-windows", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "all" + }, + "SdkAnalysisLevel": "10.0.300" + }, + "frameworks": { + "net10.0-windows": { + "framework": "net10.0-windows7.0", + "targetAlias": "net10.0-windows", + "dependencies": { + "NAudio": { + "target": "Package", + "version": "[2.3.0, )" + }, + "System.IO.Ports": { + "target": "Package", + "version": "[10.0.9, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + }, + "Microsoft.WindowsDesktop.App.WindowsForms": { + "privateAssets": "none" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.302/PortableRuntimeIdentifierGraph.json", + "packagesToPrune": { + "Microsoft.CSharp": "(,4.7.32767]", + "Microsoft.VisualBasic": "(,10.4.32767]", + "Microsoft.Win32.Primitives": "(,4.3.32767]", + "Microsoft.Win32.Registry": "(,5.0.32767]", + "Microsoft.Win32.Registry.AccessControl": "(,10.0.32767]", + "Microsoft.Win32.SystemEvents": "(,10.0.32767]", + "runtime.any.System.Collections": "(,4.3.32767]", + "runtime.any.System.Diagnostics.Tools": "(,4.3.32767]", + "runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]", + "runtime.any.System.Globalization": "(,4.3.32767]", + "runtime.any.System.Globalization.Calendars": "(,4.3.32767]", + "runtime.any.System.IO": "(,4.3.32767]", + "runtime.any.System.Reflection": "(,4.3.32767]", + "runtime.any.System.Reflection.Extensions": "(,4.3.32767]", + "runtime.any.System.Reflection.Primitives": "(,4.3.32767]", + "runtime.any.System.Resources.ResourceManager": "(,4.3.32767]", + "runtime.any.System.Runtime": "(,4.3.32767]", + "runtime.any.System.Runtime.Handles": "(,4.3.32767]", + "runtime.any.System.Runtime.InteropServices": "(,4.3.32767]", + "runtime.any.System.Text.Encoding": "(,4.3.32767]", + "runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]", + "runtime.any.System.Threading.Tasks": "(,4.3.32767]", + "runtime.any.System.Threading.Timer": "(,4.3.32767]", + "runtime.aot.System.Collections": "(,4.3.32767]", + "runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]", + "runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]", + "runtime.aot.System.Globalization": "(,4.3.32767]", + "runtime.aot.System.Globalization.Calendars": "(,4.3.32767]", + "runtime.aot.System.IO": "(,4.3.32767]", + "runtime.aot.System.Reflection": "(,4.3.32767]", + "runtime.aot.System.Reflection.Extensions": "(,4.3.32767]", + "runtime.aot.System.Reflection.Primitives": "(,4.3.32767]", + "runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]", + "runtime.aot.System.Runtime": "(,4.3.32767]", + "runtime.aot.System.Runtime.Handles": "(,4.3.32767]", + "runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]", + "runtime.aot.System.Text.Encoding": "(,4.3.32767]", + "runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]", + "runtime.aot.System.Threading.Tasks": "(,4.3.32767]", + "runtime.aot.System.Threading.Timer": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]", + "runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]", + "runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]", + "runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]", + "runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]", + "runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]", + "runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]", + "runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]", + "runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]", + "runtime.unix.System.Console": "(,4.3.32767]", + "runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]", + "runtime.unix.System.IO.FileSystem": "(,4.3.32767]", + "runtime.unix.System.Net.Primitives": "(,4.3.32767]", + "runtime.unix.System.Net.Sockets": "(,4.3.32767]", + "runtime.unix.System.Private.Uri": "(,4.3.32767]", + "runtime.unix.System.Runtime.Extensions": "(,4.3.32767]", + "runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]", + "runtime.win.System.Console": "(,4.3.32767]", + "runtime.win.System.Diagnostics.Debug": "(,4.3.32767]", + "runtime.win.System.IO.FileSystem": "(,4.3.32767]", + "runtime.win.System.Net.Primitives": "(,4.3.32767]", + "runtime.win.System.Net.Sockets": "(,4.3.32767]", + "runtime.win.System.Runtime.Extensions": "(,4.3.32767]", + "runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]", + "runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]", + "runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]", + "runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]", + "runtime.win7.System.Private.Uri": "(,4.3.32767]", + "runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]", + "System.AppContext": "(,4.3.32767]", + "System.Buffers": "(,5.0.32767]", + "System.CodeDom": "(,10.0.32767]", + "System.Collections": "(,4.3.32767]", + "System.Collections.Concurrent": "(,4.3.32767]", + "System.Collections.Immutable": "(,10.0.32767]", + "System.Collections.NonGeneric": "(,4.3.32767]", + "System.Collections.Specialized": "(,4.3.32767]", + "System.ComponentModel": "(,4.3.32767]", + "System.ComponentModel.Annotations": "(,4.3.32767]", + "System.ComponentModel.EventBasedAsync": "(,4.3.32767]", + "System.ComponentModel.Primitives": "(,4.3.32767]", + "System.ComponentModel.TypeConverter": "(,4.3.32767]", + "System.Configuration.ConfigurationManager": "(,10.0.32767]", + "System.Console": "(,4.3.32767]", + "System.Data.Common": "(,4.3.32767]", + "System.Data.DataSetExtensions": "(,4.4.32767]", + "System.Diagnostics.Contracts": "(,4.3.32767]", + "System.Diagnostics.Debug": "(,4.3.32767]", + "System.Diagnostics.DiagnosticSource": "(,10.0.32767]", + "System.Diagnostics.EventLog": "(,10.0.32767]", + "System.Diagnostics.FileVersionInfo": "(,4.3.32767]", + "System.Diagnostics.PerformanceCounter": "(,10.0.32767]", + "System.Diagnostics.Process": "(,4.3.32767]", + "System.Diagnostics.StackTrace": "(,4.3.32767]", + "System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]", + "System.Diagnostics.Tools": "(,4.3.32767]", + "System.Diagnostics.TraceSource": "(,4.3.32767]", + "System.Diagnostics.Tracing": "(,4.3.32767]", + "System.DirectoryServices": "(,10.0.32767]", + "System.Drawing.Common": "(,10.0.32767]", + "System.Drawing.Primitives": "(,4.3.32767]", + "System.Dynamic.Runtime": "(,4.3.32767]", + "System.Formats.Asn1": "(,10.0.32767]", + "System.Formats.Nrbf": "(,10.0.32767]", + "System.Formats.Tar": "(,10.0.32767]", + "System.Globalization": "(,4.3.32767]", + "System.Globalization.Calendars": "(,4.3.32767]", + "System.Globalization.Extensions": "(,4.3.32767]", + "System.IO": "(,4.3.32767]", + "System.IO.Compression": "(,4.3.32767]", + "System.IO.Compression.ZipFile": "(,4.3.32767]", + "System.IO.FileSystem": "(,4.3.32767]", + "System.IO.FileSystem.AccessControl": "(,4.4.32767]", + "System.IO.FileSystem.DriveInfo": "(,4.3.32767]", + "System.IO.FileSystem.Primitives": "(,4.3.32767]", + "System.IO.FileSystem.Watcher": "(,4.3.32767]", + "System.IO.IsolatedStorage": "(,4.3.32767]", + "System.IO.MemoryMappedFiles": "(,4.3.32767]", + "System.IO.Packaging": "(,10.0.32767]", + "System.IO.Pipelines": "(,10.0.32767]", + "System.IO.Pipes": "(,4.3.32767]", + "System.IO.Pipes.AccessControl": "(,5.0.32767]", + "System.IO.UnmanagedMemoryStream": "(,4.3.32767]", + "System.Linq": "(,4.3.32767]", + "System.Linq.AsyncEnumerable": "(,10.0.32767]", + "System.Linq.Expressions": "(,4.3.32767]", + "System.Linq.Parallel": "(,4.3.32767]", + "System.Linq.Queryable": "(,4.3.32767]", + "System.Memory": "(,5.0.32767]", + "System.Net.Http": "(,4.3.32767]", + "System.Net.Http.Json": "(,10.0.32767]", + "System.Net.NameResolution": "(,4.3.32767]", + "System.Net.NetworkInformation": "(,4.3.32767]", + "System.Net.Ping": "(,4.3.32767]", + "System.Net.Primitives": "(,4.3.32767]", + "System.Net.Requests": "(,4.3.32767]", + "System.Net.Security": "(,4.3.32767]", + "System.Net.ServerSentEvents": "(,10.0.32767]", + "System.Net.Sockets": "(,4.3.32767]", + "System.Net.WebHeaderCollection": "(,4.3.32767]", + "System.Net.WebSockets": "(,4.3.32767]", + "System.Net.WebSockets.Client": "(,4.3.32767]", + "System.Numerics.Vectors": "(,5.0.32767]", + "System.ObjectModel": "(,4.3.32767]", + "System.Private.DataContractSerialization": "(,4.3.32767]", + "System.Private.Uri": "(,4.3.32767]", + "System.Reflection": "(,4.3.32767]", + "System.Reflection.DispatchProxy": "(,6.0.32767]", + "System.Reflection.Emit": "(,4.7.32767]", + "System.Reflection.Emit.ILGeneration": "(,4.7.32767]", + "System.Reflection.Emit.Lightweight": "(,4.7.32767]", + "System.Reflection.Extensions": "(,4.3.32767]", + "System.Reflection.Metadata": "(,10.0.32767]", + "System.Reflection.Primitives": "(,4.3.32767]", + "System.Reflection.TypeExtensions": "(,4.3.32767]", + "System.Resources.Extensions": "(,10.0.32767]", + "System.Resources.Reader": "(,4.3.32767]", + "System.Resources.ResourceManager": "(,4.3.32767]", + "System.Resources.Writer": "(,4.3.32767]", + "System.Runtime": "(,4.3.32767]", + "System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]", + "System.Runtime.CompilerServices.VisualC": "(,4.3.32767]", + "System.Runtime.Extensions": "(,4.3.32767]", + "System.Runtime.Handles": "(,4.3.32767]", + "System.Runtime.InteropServices": "(,4.3.32767]", + "System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]", + "System.Runtime.Loader": "(,4.3.32767]", + "System.Runtime.Numerics": "(,4.3.32767]", + "System.Runtime.Serialization.Formatters": "(,4.3.32767]", + "System.Runtime.Serialization.Json": "(,4.3.32767]", + "System.Runtime.Serialization.Primitives": "(,4.3.32767]", + "System.Runtime.Serialization.Xml": "(,4.3.32767]", + "System.Security.AccessControl": "(,6.0.32767]", + "System.Security.Claims": "(,4.3.32767]", + "System.Security.Cryptography.Algorithms": "(,4.3.32767]", + "System.Security.Cryptography.Cng": "(,5.0.32767]", + "System.Security.Cryptography.Csp": "(,4.3.32767]", + "System.Security.Cryptography.Encoding": "(,4.3.32767]", + "System.Security.Cryptography.OpenSsl": "(,5.0.32767]", + "System.Security.Cryptography.Pkcs": "(,10.0.32767]", + "System.Security.Cryptography.Primitives": "(,4.3.32767]", + "System.Security.Cryptography.ProtectedData": "(,10.0.32767]", + "System.Security.Cryptography.X509Certificates": "(,4.3.32767]", + "System.Security.Cryptography.Xml": "(,10.0.32767]", + "System.Security.Permissions": "(,10.0.32767]", + "System.Security.Principal": "(,4.3.32767]", + "System.Security.Principal.Windows": "(,5.0.32767]", + "System.Security.SecureString": "(,4.3.32767]", + "System.Text.Encoding": "(,4.3.32767]", + "System.Text.Encoding.CodePages": "(,10.0.32767]", + "System.Text.Encoding.Extensions": "(,4.3.32767]", + "System.Text.Encodings.Web": "(,10.0.32767]", + "System.Text.Json": "(,10.0.32767]", + "System.Text.RegularExpressions": "(,4.3.32767]", + "System.Threading": "(,4.3.32767]", + "System.Threading.AccessControl": "(,10.0.32767]", + "System.Threading.Channels": "(,10.0.32767]", + "System.Threading.Overlapped": "(,4.3.32767]", + "System.Threading.Tasks": "(,4.3.32767]", + "System.Threading.Tasks.Dataflow": "(,10.0.32767]", + "System.Threading.Tasks.Extensions": "(,5.0.32767]", + "System.Threading.Tasks.Parallel": "(,4.3.32767]", + "System.Threading.Thread": "(,4.3.32767]", + "System.Threading.ThreadPool": "(,4.3.32767]", + "System.Threading.Timer": "(,4.3.32767]", + "System.ValueTuple": "(,4.5.32767]", + "System.Windows.Extensions": "(,10.0.32767]", + "System.Xml.ReaderWriter": "(,4.3.32767]", + "System.Xml.XDocument": "(,4.3.32767]", + "System.Xml.XmlDocument": "(,4.3.32767]", + "System.Xml.XmlSerializer": "(,4.3.32767]", + "System.Xml.XPath": "(,4.3.32767]", + "System.Xml.XPath.XDocument": "(,5.0.32767]" + } + } + } + } +} \ No newline at end of file diff --git a/Radio/App_radio/obj/project.nuget.cache b/Radio/App_radio/obj/project.nuget.cache new file mode 100644 index 0000000..c94b7ae --- /dev/null +++ b/Radio/App_radio/obj/project.nuget.cache @@ -0,0 +1,34 @@ +{ + "version": 2, + "dgSpecHash": "7hNv4dUw2/Y=", + "success": true, + "projectFilePath": "C:\\Users\\alvar\\Desktop\\Barcelona_software\\AARadio_bluetooth\\App_radio\\App_radio.csproj", + "expectedPackageFiles": [ + "C:\\Users\\alvar\\.nuget\\packages\\naudio\\2.3.0\\naudio.2.3.0.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\naudio.asio\\2.3.0\\naudio.asio.2.3.0.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\naudio.core\\2.3.0\\naudio.core.2.3.0.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\naudio.midi\\2.3.0\\naudio.midi.2.3.0.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\naudio.wasapi\\2.3.0\\naudio.wasapi.2.3.0.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\naudio.winforms\\2.3.0\\naudio.winforms.2.3.0.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\naudio.winmm\\2.3.0\\naudio.winmm.2.3.0.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.android-arm.runtime.native.system.io.ports\\10.0.9\\runtime.android-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.android-arm64.runtime.native.system.io.ports\\10.0.9\\runtime.android-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.android-x64.runtime.native.system.io.ports\\10.0.9\\runtime.android-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.android-x86.runtime.native.system.io.ports\\10.0.9\\runtime.android-x86.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.linux-arm.runtime.native.system.io.ports\\10.0.9\\runtime.linux-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.linux-arm64.runtime.native.system.io.ports\\10.0.9\\runtime.linux-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.linux-bionic-arm64.runtime.native.system.io.ports\\10.0.9\\runtime.linux-bionic-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.linux-bionic-x64.runtime.native.system.io.ports\\10.0.9\\runtime.linux-bionic-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.linux-musl-arm.runtime.native.system.io.ports\\10.0.9\\runtime.linux-musl-arm.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.linux-musl-arm64.runtime.native.system.io.ports\\10.0.9\\runtime.linux-musl-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.linux-musl-x64.runtime.native.system.io.ports\\10.0.9\\runtime.linux-musl-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.linux-x64.runtime.native.system.io.ports\\10.0.9\\runtime.linux-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.maccatalyst-arm64.runtime.native.system.io.ports\\10.0.9\\runtime.maccatalyst-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.maccatalyst-x64.runtime.native.system.io.ports\\10.0.9\\runtime.maccatalyst-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.native.system.io.ports\\10.0.9\\runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.osx-arm64.runtime.native.system.io.ports\\10.0.9\\runtime.osx-arm64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\runtime.osx-x64.runtime.native.system.io.ports\\10.0.9\\runtime.osx-x64.runtime.native.system.io.ports.10.0.9.nupkg.sha512", + "C:\\Users\\alvar\\.nuget\\packages\\system.io.ports\\10.0.9\\system.io.ports.10.0.9.nupkg.sha512" + ], + "logs": [] +} \ No newline at end of file diff --git a/Radio/LEEME.txt b/Radio/LEEME.txt new file mode 100644 index 0000000..12a4451 --- /dev/null +++ b/Radio/LEEME.txt @@ -0,0 +1,134 @@ +VERSION V5 - CORRECCION V6 PRO+ + +Esta version corrige dos problemas observados en el monitor serie: +- Acepta el comando propietario AT +SUGCODEC=1 con OK. +- No vuelve a lanzar esp_hf_ag_slc_connect mientras RFCOMM/SLC sigue negociando. + +La conexion completa se confirma SOLO al aparecer: + *** SLC_CONNECTED: control HFP listo. *** + +Despues debe aparecer: + *** AUDIO CONECTADO: CVSD 8 kHz ... *** + +VERSION V4 - AJUSTADA AL INTERCOM DETECTADO + +Intercom detectado: V6 Pro+ +MAC Bluetooth Classic: 00:12:6F:60:F2:98 + +Esta version intenta conectar directamente con esa MAC, sin esperar a que el nombre coincida con EJEAS/V4. + +VERSION V3 - CORRECCION ARDUINO-ESP32 3.3.11 +================================================ + +Esta version incluye esp32-hal-alloc-bt-classic-mem.h para impedir que +Arduino libere la memoria de Bluetooth Classic antes de ejecutar setup(). +Corrige el mensaje: + ERROR: btStartMode(BT_MODE_CLASSIC_BT) ha fallado. + +VERSION CORREGIDA PARA ARDUINO-ESP32 3.3.11 +- Corregida incompatibilidad const de esp_bd_addr_t con la API HFP AG. + +PRUEBA EJEAS V4 PLUS + ESP32-AUDIO-KIT V2.2 / ESP32-A1S +======================================================== + +QUE HACE +-------- +El ESP32 actua como un telefono Bluetooth HFP Audio Gateway. Busca el EJEAS, +lo empareja, simula una llamada y abre el audio de voz SCO/eSCO. + +No usa el ES8388, los jacks de audio, UART2, ESP-NOW ni la aplicacion del PC. +Es una prueba aislada para confirmar que el EJEAS acepta al ESP32 como telefono +y que el audio HFP llega al programa. + +REQUISITO IMPORTANTE +-------------------- +Arduino IDE -> Gestor de placas: + esp32 by Espressif Systems 3.3.8 o posterior + +Placa recomendada: + Herramientas -> Placa -> ESP32 Arduino -> ESP32 Dev Module + +Ajustes recomendados: + Upload Speed: 921600 o 460800 + CPU Frequency: 240 MHz + Flash Frequency: 80 MHz + Flash Mode: QIO + Flash Size: 4 MB + Partition Scheme: Default 4MB with spiffs + PSRAM: Disabled + Puerto: el COM de la ESP32-Audio-Kit + +PASOS +----- +1. Apaga el Bluetooth del movil que normalmente usa el EJEAS. +2. Si el EJEAS intenta reconectarse al movil, elimina temporalmente esa conexion + o aleja/apaga el movil. +3. Pon el EJEAS V4 Plus en modo de emparejamiento CON TELEFONO. No uses el modo + de emparejamiento entre dos intercoms. +4. Abre Prueba_EJEAS_HFP_AG.ino con Arduino IDE. +5. Selecciona ESP32 Dev Module y carga el programa. +6. Abre el monitor serie a 115200 baudios. +7. Deben aparecer, en este orden aproximado: + + Encontrado: ... nombre="EJEAS..." o "V4..." + Emparejamiento correcto + HFP conexion: SLC_CONNECTED + Audio HFP: CONNECTED_CVSD_8_KHZ o CONNECTED_MSBC_16_KHZ + +8. El modo inicial es LOOPBACK. Habla por el microfono del casco: deberias oir + tu propia voz con un pequeno retardo. +9. Escribe t en el monitor serie para escuchar un tono de 1 kHz. +10. Escribe l para volver al retorno del microfono. + +COMANDOS +-------- +h ayuda +s repetir busqueda Bluetooth +c conectar HFP a la MAC guardada +a simular llamada activa y abrir audio +o abrir solamente SCO +l loopback del microfono +t tono de 1 kHz +x cerrar audio y finalizar llamada +d desconectar el intercom +b borrar MAC y emparejamiento +i mostrar estado + +SI NO ENCUENTRA EL NOMBRE +------------------------- +El monitor serie imprime todos los dispositivos encontrados. Si ves el EJEAS +pero su nombre no contiene EJEAS ni V4, agrega ese texto al array TARGET_WORDS +del principio del .ino. + +Tambien puedes fijar su MAC: + + static constexpr bool USE_FIXED_MAC = true; + static const uint8_t FIXED_MAC[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; + +Sustituye los bytes por la MAC que aparece en el monitor serie. + +SI DA ERROR DE CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI +------------------------------------------------ +La version de esp32 by Espressif Systems es antigua o sus librerias no tienen +Voice-over-HCI. Actualiza el paquete a 3.3.8 o posterior. + +QUE LOG NECESITO PARA CORREGIRLO +-------------------------------- +Copia desde la primera linea de arranque hasta 10 segundos despues del fallo. +Los mensajes mas importantes son: + + esp_hf_ag_init + Estado de busqueda + Emparejamiento correcto/error + HFP conexion + SLC_CONNECTED + Audio HFP + AUDIO [CVSD8k/...] + +LIMITACION DE ESTA PRUEBA +------------------------- +El codigo esta preparado a partir de las APIs oficiales de Espressif, pero no +se puede confirmar desde fuera que el firmware concreto del EJEAS mantenga SCO +abierto sin una llamada real. La llamada simulada esta incluida precisamente +para comprobarlo. Si SLC conecta pero SCO no, el log permitira ajustar la +secuencia de llamada que espera el EJEAS. diff --git a/Radio/Prueba_EJEAS_HFP_AG/Prueba_EJEAS_HFP_AG.ino b/Radio/Prueba_EJEAS_HFP_AG/Prueba_EJEAS_HFP_AG.ino new file mode 100644 index 0000000..860c38b --- /dev/null +++ b/Radio/Prueba_EJEAS_HFP_AG/Prueba_EJEAS_HFP_AG.ino @@ -0,0 +1,1121 @@ +/* + Prueba EJEAS V6 Pro+ <-> ESP32-Audio-Kit ESP32-A1S + =================================================== + + Objetivo: + - El ESP32 actua como HFP Audio Gateway (como si fuera un telefono). + - El EJEAS actua como manos libres HFP. + - Busca automaticamente nombres que contengan EJEAS, V4 o V6. Tambien usa la MAC fija detectada 00:12:6F:60:F2:98. + - Empareja mediante SSP o PIN 0000. + - Simula una llamada activa para abrir el audio SCO. + - Permite probar: + * Tono: ESP32 -> altavoces del intercom. + * Loopback: microfono del intercom -> ESP32 -> altavoces del intercom. + + Requisitos: + - ESP32 clasico (ESP32-A1S sirve; ESP32-S3/C3 no sirven para BT Classic). + - Arduino-ESP32 de Espressif 3.3.8 o posterior. + - Placa recomendada en Arduino IDE: "ESP32 Dev Module". + - Monitor serie: 115200 baudios, final de linea "Nueva linea". + + Antes de encender la placa: + 1. Apaga el Bluetooth del movil que suele usar el EJEAS. + 2. Pon el EJEAS V4 Plus en modo de emparejamiento CON TELEFONO. + 3. Enciende/reinicia el ESP32. + + Esta prueba NO utiliza el codec ES8388, los jacks ni UART2. +*/ + +#include +#include +#include +#include + +// Arduino-ESP32 3.3.7+ libera antes de setup() la memoria de Bluetooth +// que no detecta como utilizada. Como aqui usamos la API HFP de ESP-IDF +// directamente, debemos marcar expresamente que Bluetooth Classic se usa. +#include "esp32-hal-alloc-bt-classic-mem.h" +#include "esp32-hal-bt.h" +#include "esp_bt.h" +#include "esp_bt_device.h" +#include "esp_bt_main.h" +#include "esp_gap_bt_api.h" +#include "esp_hf_ag_api.h" +#include "esp_timer.h" +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/stream_buffer.h" + +// ----------------------------------------------------------------------------- +// Comprobaciones de compilacion +// ----------------------------------------------------------------------------- +#if !defined(CONFIG_IDF_TARGET_ESP32) +#error "Este programa necesita un ESP32 clasico con Bluetooth Classic (por ejemplo ESP32-A1S)." +#endif + +#if !defined(CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI) || !(CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI) +#error "El core instalado no tiene HFP Voice-over-HCI activado. Instala esp32 by Espressif Systems 3.3.8 o posterior." +#endif + +// ----------------------------------------------------------------------------- +// Ajustes de usuario +// ----------------------------------------------------------------------------- +static constexpr char LOCAL_BT_NAME[] = "FORMULA_GADES_HFP"; + +// Se conecta al primer nombre que contenga una de estas cadenas. +static constexpr const char *TARGET_WORDS[] = { + "ejeas", + "v4 plus", + "v4plus", + "v4", + "v6 pro+", + "v6 pro", + "v6" +}; + +// Si el escaneo por nombre no encuentra el intercom, puedes poner su MAC aqui. +// Ejemplo: {0xC8, 0x7F, 0x54, 0x12, 0x34, 0x56} +static constexpr bool USE_FIXED_MAC = true; +static const uint8_t FIXED_MAC[ESP_BD_ADDR_LEN] = {0x00, 0x12, 0x6F, 0x60, 0xF2, 0x98}; + +// Al conseguir SLC, simula una llamada y abre SCO automaticamente. +static constexpr bool AUTO_START_AUDIO = true; + +// Audio inicial. LOOPBACK permite comprobar microfono y altavoz a la vez. +enum class AudioTestMode : uint8_t { + LOOPBACK, + TONE +}; +static AudioTestMode audioMode = AudioTestMode::LOOPBACK; + +static constexpr uint32_t SERIAL_BAUD = 115200; +static constexpr uint32_t DISCOVERY_RETRY_MS = 3000; +static constexpr uint32_t SLC_RETRY_MS = 5000; +static constexpr uint32_t AUDIO_RETRY_MS = 3000; +static constexpr uint32_t AUTO_CALL_DELAY_MS = 1200; +static constexpr uint32_t AUDIO_OPEN_DELAY_MS = 600; +static constexpr uint8_t DISCOVERY_LENGTH = 10; // 10 x 1,28 s aproximadamente +static constexpr size_t AUDIO_RING_BYTES = 8192; +static constexpr uint32_t CVSD_TRIGGER_US = 4000; +static constexpr uint32_t MSBC_TRIGGER_US = 7500; +static constexpr float TEST_TONE_HZ = 1000.0f; +static constexpr int16_t TEST_TONE_AMPLITUDE = 7000; +static char TEST_NUMBER[] = "100"; + +// ----------------------------------------------------------------------------- +// Estado global +// ----------------------------------------------------------------------------- +Preferences prefs; +static const char PREF_NAMESPACE[] = "ejeas_hfp"; +static const char PREF_BDA_KEY[] = "peer_bda"; + +static esp_bd_addr_t remoteBda = {0}; +static bool haveRemoteBda = false; +static bool saveRemotePending = false; +static bool hfpReady = false; +static bool discoveryRunning = false; +static bool connectPending = false; +static bool slcConnected = false; +static bool slcInProgress = false; +static bool audioConnecting = false; +static bool audioConnected = false; +static bool callActive = false; +static bool codecMsbc = false; + +static uint32_t lastDiscoveryAttemptMs = 0; +static uint32_t lastSlcAttemptMs = 0; +static uint32_t lastAudioAttemptMs = 0; +static uint32_t autoCallAtMs = 0; +static uint32_t audioOpenAtMs = 0; +static uint32_t lastDiagnosticMs = 0; + +static StreamBufferHandle_t audioRing = nullptr; +static esp_timer_handle_t audioTimer = nullptr; +static float tonePhase = 0.0f; + +static volatile uint32_t rxFrames = 0; +static volatile uint32_t rxBytes = 0; +static volatile uint32_t rxDrops = 0; +static volatile uint32_t txFrames = 0; +static volatile uint32_t txBytes = 0; +static volatile uint32_t txUnderruns = 0; +static volatile uint32_t lastRequestedBytes = 0; + +// ----------------------------------------------------------------------------- +// Declaraciones +// ----------------------------------------------------------------------------- +static void gapCallback(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param); +static void hfpCallback(esp_hf_cb_event_t event, esp_hf_cb_param_t *param); +static void incomingAudioCallback(const uint8_t *buf, uint32_t len); +static uint32_t outgoingAudioCallback(uint8_t *buf, uint32_t len); + +// ----------------------------------------------------------------------------- +// Utilidades +// ----------------------------------------------------------------------------- +static void logEsp(const char *name, esp_err_t err) { + if (err == ESP_OK) { + Serial.printf("%s: OK\n", name); + } else { + Serial.printf("%s: %s (0x%04X)\n", name, esp_err_to_name(err), static_cast(err)); + } +} + +static void printBda(const uint8_t *bda) { + Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X", bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); +} + +static void setRemoteBda(const uint8_t *bda, bool saveLater) { + memcpy(remoteBda, bda, ESP_BD_ADDR_LEN); + haveRemoteBda = true; + if (saveLater) { + saveRemotePending = true; + } +} + +static bool loadSavedBda() { + prefs.begin(PREF_NAMESPACE, false); + if (prefs.getBytesLength(PREF_BDA_KEY) != ESP_BD_ADDR_LEN) { + return false; + } + + if (prefs.getBytes(PREF_BDA_KEY, remoteBda, ESP_BD_ADDR_LEN) != ESP_BD_ADDR_LEN) { + return false; + } + + haveRemoteBda = true; + Serial.print("MAC EJEAS guardada: "); + printBda(remoteBda); + Serial.println(); + return true; +} + +static void saveBdaIfNeeded() { + if (!saveRemotePending || !haveRemoteBda) { + return; + } + + saveRemotePending = false; + const size_t written = prefs.putBytes(PREF_BDA_KEY, remoteBda, ESP_BD_ADDR_LEN); + Serial.printf("MAC guardada en NVS: %s\n", written == ESP_BD_ADDR_LEN ? "SI" : "NO"); +} + +static bool containsIgnoreCase(const char *text, const char *word) { + if (!text || !word || !*word) { + return false; + } + + String haystack(text); + String needle(word); + haystack.toLowerCase(); + needle.toLowerCase(); + return haystack.indexOf(needle) >= 0; +} + +static bool isTargetName(const char *name) { + if (!name || !*name) { + return false; + } + + for (const char *word : TARGET_WORDS) { + if (containsIgnoreCase(name, word)) { + return true; + } + } + return false; +} + +static bool getNameFromEir(uint8_t *eir, char *name, size_t nameCapacity) { + if (!eir || !name || nameCapacity < 2) { + return false; + } + + uint8_t nameLen = 0; + uint8_t *nameData = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME, &nameLen); + if (!nameData) { + nameData = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &nameLen); + } + if (!nameData || nameLen == 0) { + return false; + } + + const size_t copyLen = min(static_cast(nameLen), nameCapacity - 1); + memcpy(name, nameData, copyLen); + name[copyLen] = '\0'; + return true; +} + +static const char *connectionStateName(esp_hf_connection_state_t state) { + switch (state) { + case ESP_HF_CONNECTION_STATE_DISCONNECTED: return "DISCONNECTED"; + case ESP_HF_CONNECTION_STATE_CONNECTING: return "CONNECTING"; + case ESP_HF_CONNECTION_STATE_CONNECTED: return "RFCOMM_CONNECTED"; + case ESP_HF_CONNECTION_STATE_SLC_CONNECTED: return "SLC_CONNECTED"; + case ESP_HF_CONNECTION_STATE_DISCONNECTING: return "DISCONNECTING"; + default: return "UNKNOWN"; + } +} + +static const char *audioStateName(esp_hf_audio_state_t state) { + switch (state) { + case ESP_HF_AUDIO_STATE_DISCONNECTED: return "DISCONNECTED"; + case ESP_HF_AUDIO_STATE_CONNECTING: return "CONNECTING"; + case ESP_HF_AUDIO_STATE_CONNECTED: return "CONNECTED_CVSD_8_KHZ"; + case ESP_HF_AUDIO_STATE_CONNECTED_MSBC: return "CONNECTED_MSBC_16_KHZ"; + default: return "UNKNOWN"; + } +} + +static void printHelp() { + Serial.println(); + Serial.println("================ COMANDOS ================"); + Serial.println("h -> mostrar esta ayuda"); + Serial.println("s -> buscar de nuevo el EJEAS"); + Serial.println("c -> conectar HFP usando la MAC recordada"); + Serial.println("a -> simular llamada activa y abrir audio"); + Serial.println("o -> intentar abrir solo el canal SCO"); + Serial.println("l -> modo LOOPBACK: micro EJEAS vuelve a sus altavoces"); + Serial.println("t -> modo TONO: genera 1 kHz hacia los altavoces"); + Serial.println("x -> cerrar audio y terminar la llamada simulada"); + Serial.println("d -> desconectar completamente el intercom"); + Serial.println("b -> borrar MAC y emparejamiento y volver a buscar"); + Serial.println("i -> mostrar estado actual"); + Serial.println("=========================================="); + Serial.println(); +} + +static void printStatus() { + Serial.println(); + Serial.println("--------------- ESTADO ----------------"); + Serial.printf("HFP preparado: %s\n", hfpReady ? "SI" : "NO"); + Serial.printf("Buscando: %s\n", discoveryRunning ? "SI" : "NO"); + Serial.printf("MAC conocida: %s", haveRemoteBda ? "SI, " : "NO"); + if (haveRemoteBda) { + printBda(remoteBda); + } + Serial.println(); + Serial.printf("SLC conectado: %s\n", slcConnected ? "SI" : "NO"); + Serial.printf("Llamada simulada: %s\n", callActive ? "ACTIVA" : "INACTIVA"); + Serial.printf("Audio SCO: %s\n", audioConnected ? "CONECTADO" : (audioConnecting ? "CONECTANDO" : "DESCONECTADO")); + Serial.printf("Codec: %s\n", codecMsbc ? "mSBC 16 kHz" : "CVSD 8 kHz / pendiente"); + Serial.printf("Modo de prueba: %s\n", audioMode == AudioTestMode::LOOPBACK ? "LOOPBACK" : "TONO 1 kHz"); + Serial.println("---------------------------------------"); + Serial.println(); +} + +// ----------------------------------------------------------------------------- +// Escaneo y conexion +// ----------------------------------------------------------------------------- +static void startDiscovery(bool force) { + if (!hfpReady || slcConnected || discoveryRunning) { + return; + } + + const uint32_t now = millis(); + if (!force && now - lastDiscoveryAttemptMs < DISCOVERY_RETRY_MS) { + return; + } + + lastDiscoveryAttemptMs = now; + Serial.println("\nBuscando dispositivos Bluetooth Classic..."); + Serial.println("Pon el EJEAS en modo PHONE PAIRING y apaga el Bluetooth del movil."); + const esp_err_t err = esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, DISCOVERY_LENGTH, 0); + logEsp("esp_bt_gap_start_discovery", err); + if (err == ESP_OK) { + discoveryRunning = true; + } +} + +static void requestSlcConnect(bool force) { + if (!hfpReady || !haveRemoteBda || slcConnected || slcInProgress) { + return; + } + + const uint32_t now = millis(); + if (!force && now - lastSlcAttemptMs < SLC_RETRY_MS) { + return; + } + + if (discoveryRunning) { + esp_bt_gap_cancel_discovery(); + connectPending = true; + return; + } + + lastSlcAttemptMs = now; + Serial.print("Conectando HFP/SLC con "); + printBda(remoteBda); + Serial.println("..."); + const esp_err_t err = esp_hf_ag_slc_connect(remoteBda); + logEsp("esp_hf_ag_slc_connect", err); + if (err == ESP_OK) { + slcInProgress = true; + } +} + +// ----------------------------------------------------------------------------- +// Llamada simulada y audio +// ----------------------------------------------------------------------------- +static void startFakeCall() { + if (!slcConnected || !haveRemoteBda) { + Serial.println("No se puede iniciar la llamada: falta SLC_CONNECTED."); + return; + } + + callActive = true; + Serial.println("Simulando llamada activa para que el EJEAS habilite el audio..."); + logEsp( + "esp_hf_ag_out_call", + esp_hf_ag_out_call( + remoteBda, + 1, + 0, + ESP_HF_CALL_STATUS_CALL_IN_PROGRESS, + ESP_HF_CALL_SETUP_STATUS_IDLE, + TEST_NUMBER, + ESP_HF_CALL_ADDR_TYPE_UNKNOWN + ) + ); + audioOpenAtMs = millis() + AUDIO_OPEN_DELAY_MS; +} + +static void requestAudioConnect(bool force) { + if (!slcConnected || !haveRemoteBda || audioConnected) { + return; + } + + const uint32_t now = millis(); + if (!force && audioConnecting && now - lastAudioAttemptMs < AUDIO_RETRY_MS) { + return; + } + + lastAudioAttemptMs = now; + audioConnecting = true; + Serial.println("Abriendo canal de audio SCO/eSCO..."); + logEsp("esp_hf_ag_audio_connect", esp_hf_ag_audio_connect(remoteBda)); +} + +static void stopTestCall() { + audioOpenAtMs = 0; + autoCallAtMs = 0; + + if (audioConnected || audioConnecting) { + logEsp("esp_hf_ag_audio_disconnect", esp_hf_ag_audio_disconnect(remoteBda)); + } + + if (slcConnected && callActive) { + logEsp( + "esp_hf_ag_end_call", + esp_hf_ag_end_call( + remoteBda, + 0, + 0, + ESP_HF_CALL_STATUS_NO_CALLS, + ESP_HF_CALL_SETUP_STATUS_IDLE, + TEST_NUMBER, + ESP_HF_CALL_ADDR_TYPE_UNKNOWN + ) + ); + } + + callActive = false; + audioConnecting = false; +} + +// ----------------------------------------------------------------------------- +// Pipeline de audio HCI +// ----------------------------------------------------------------------------- +static void audioTimerCallback(void *arg) { + (void)arg; + if (audioConnected) { + esp_hf_ag_outgoing_data_ready(); + } +} + +static void stopAudioPipeline() { + if (audioTimer) { + esp_timer_stop(audioTimer); + esp_timer_delete(audioTimer); + audioTimer = nullptr; + } + + if (audioRing) { + vStreamBufferDelete(audioRing); + audioRing = nullptr; + } +} + +static void startAudioPipeline(bool msbc) { + stopAudioPipeline(); + + audioRing = xStreamBufferCreate(AUDIO_RING_BYTES, 1); + if (!audioRing) { + Serial.println("ERROR: no se pudo crear el buffer circular de audio."); + return; + } + + esp_timer_create_args_t timerArgs = {}; + timerArgs.callback = audioTimerCallback; + timerArgs.arg = nullptr; + timerArgs.dispatch_method = ESP_TIMER_TASK; + timerArgs.name = "hfp_audio"; + timerArgs.skip_unhandled_events = true; + + esp_err_t err = esp_timer_create(&timerArgs, &audioTimer); + if (err != ESP_OK) { + logEsp("esp_timer_create", err); + vStreamBufferDelete(audioRing); + audioRing = nullptr; + return; + } + + err = esp_timer_start_periodic(audioTimer, msbc ? MSBC_TRIGGER_US : CVSD_TRIGGER_US); + if (err != ESP_OK) { + logEsp("esp_timer_start_periodic", err); + esp_timer_delete(audioTimer); + audioTimer = nullptr; + vStreamBufferDelete(audioRing); + audioRing = nullptr; + return; + } + + rxFrames = 0; + rxBytes = 0; + rxDrops = 0; + txFrames = 0; + txBytes = 0; + txUnderruns = 0; + lastRequestedBytes = 0; + tonePhase = 0.0f; + lastDiagnosticMs = millis(); +} + +static void incomingAudioCallback(const uint8_t *buf, uint32_t len) { + if (!buf || len == 0) { + return; + } + + ++rxFrames; + rxBytes += len; + + if (audioMode != AudioTestMode::LOOPBACK || !audioRing) { + return; + } + + if (xStreamBufferSpacesAvailable(audioRing) < len) { + ++rxDrops; + return; + } + + const size_t written = xStreamBufferSend(audioRing, buf, len, 0); + if (written != len) { + ++rxDrops; + } +} + +static uint32_t outgoingAudioCallback(uint8_t *buf, uint32_t len) { + if (!buf || len == 0 || !audioConnected) { + return 0; + } + + lastRequestedBytes = len; + + if (audioMode == AudioTestMode::TONE) { + const float sampleRate = codecMsbc ? 16000.0f : 8000.0f; + const float phaseStep = 2.0f * PI * TEST_TONE_HZ / sampleRate; + const uint32_t samples = len / sizeof(int16_t); + int16_t *pcm = reinterpret_cast(buf); + + for (uint32_t i = 0; i < samples; ++i) { + pcm[i] = static_cast(sinf(tonePhase) * TEST_TONE_AMPLITUDE); + tonePhase += phaseStep; + if (tonePhase >= 2.0f * PI) { + tonePhase -= 2.0f * PI; + } + } + + if (len & 1U) { + buf[len - 1] = 0; + } + + ++txFrames; + txBytes += len; + return len; + } + + if (!audioRing || xStreamBufferBytesAvailable(audioRing) < len) { + ++txUnderruns; + return 0; + } + + const size_t received = xStreamBufferReceive(audioRing, buf, len, 0); + if (received != len) { + ++txUnderruns; + return 0; + } + + ++txFrames; + txBytes += received; + return static_cast(received); +} + +// ----------------------------------------------------------------------------- +// Respuestas HFP obligatorias/basicas +// ----------------------------------------------------------------------------- +static void sendIndicatorState(esp_bd_addr_t addr) { + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_CALL, callActive ? ESP_HF_CALL_STATUS_CALL_IN_PROGRESS : ESP_HF_CALL_STATUS_NO_CALLS); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_CALLSETUP, ESP_HF_CALL_SETUP_STATUS_IDLE); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_SERVICE, ESP_HF_NETWORK_STATE_AVAILABLE); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_SIGNAL, 5); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_ROAM, ESP_HF_ROAMING_STATUS_INACTIVE); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_BATTCHG, 5); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_CALLHELD, ESP_HF_CALL_HELD_STATUS_NONE); +} + +static void answerCurrentCall(esp_bd_addr_t addr) { + callActive = true; + logEsp( + "esp_hf_ag_answer_call", + esp_hf_ag_answer_call( + addr, + 1, + 0, + ESP_HF_CALL_STATUS_CALL_IN_PROGRESS, + ESP_HF_CALL_SETUP_STATUS_IDLE, + TEST_NUMBER, + ESP_HF_CALL_ADDR_TYPE_UNKNOWN + ) + ); + audioOpenAtMs = millis() + AUDIO_OPEN_DELAY_MS; +} + +// ----------------------------------------------------------------------------- +// Callback GAP: escaneo y emparejamiento +// ----------------------------------------------------------------------------- +static void gapCallback(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) { + switch (event) { + case ESP_BT_GAP_DISC_RES_EVT: { + char name[ESP_BT_GAP_MAX_BDNAME_LEN + 1] = {0}; + int8_t rssi = 0; + + for (int i = 0; i < param->disc_res.num_prop; ++i) { + const esp_bt_gap_dev_prop_t &prop = param->disc_res.prop[i]; + + if (prop.type == ESP_BT_GAP_DEV_PROP_BDNAME && prop.val && prop.len > 0) { + const size_t copyLen = min(static_cast(prop.len), sizeof(name) - 1); + memcpy(name, prop.val, copyLen); + name[copyLen] = '\0'; + } else if (prop.type == ESP_BT_GAP_DEV_PROP_EIR && name[0] == '\0') { + getNameFromEir(static_cast(prop.val), name, sizeof(name)); + } else if (prop.type == ESP_BT_GAP_DEV_PROP_RSSI && prop.val) { + rssi = *static_cast(prop.val); + } + } + + Serial.print("Encontrado: "); + printBda(param->disc_res.bda); + Serial.printf(" RSSI=%d nombre=\"%s\"\n", rssi, name[0] ? name : "sin nombre"); + + if (!slcConnected && isTargetName(name)) { + Serial.println("*** Coincide con EJEAS/V4. Guardando y conectando. ***"); + setRemoteBda(param->disc_res.bda, true); + connectPending = true; + esp_bt_gap_cancel_discovery(); + } + break; + } + + case ESP_BT_GAP_DISC_STATE_CHANGED_EVT: + discoveryRunning = (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED); + Serial.printf("Estado de busqueda: %s\n", discoveryRunning ? "INICIADA" : "TERMINADA"); + if (!discoveryRunning && connectPending) { + connectPending = false; + requestSlcConnect(true); + } + break; + + case ESP_BT_GAP_AUTH_CMPL_EVT: + if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { + Serial.print("Emparejamiento correcto con "); + printBda(param->auth_cmpl.bda); + Serial.printf(" nombre=\"%s\"\n", param->auth_cmpl.device_name); + setRemoteBda(param->auth_cmpl.bda, true); + } else { + Serial.printf("ERROR de emparejamiento. Estado=%d\n", param->auth_cmpl.stat); + } + break; + + case ESP_BT_GAP_CFM_REQ_EVT: + Serial.printf("SSP: aceptando automaticamente el codigo %06lu para ", static_cast(param->cfm_req.num_val)); + printBda(param->cfm_req.bda); + Serial.println(); + setRemoteBda(param->cfm_req.bda, true); + logEsp("esp_bt_gap_ssp_confirm_reply", esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true)); + break; + + case ESP_BT_GAP_PIN_REQ_EVT: { + esp_bt_pin_code_t pinCode = {'0', '0', '0', '0'}; + Serial.print("PIN solicitado por "); + printBda(param->pin_req.bda); + Serial.println(". Respondiendo 0000."); + setRemoteBda(param->pin_req.bda, true); + logEsp("esp_bt_gap_pin_reply", esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pinCode)); + break; + } + + default: + break; + } +} + +// ----------------------------------------------------------------------------- +// Callback HFP Audio Gateway +// ----------------------------------------------------------------------------- +static void hfpCallback(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) { + switch (event) { + case ESP_HF_PROF_STATE_EVT: + hfpReady = (param->prof_stat.state == ESP_HF_INIT_SUCCESS || param->prof_stat.state == ESP_HF_INIT_ALREADY); + Serial.printf("Perfil HFP AG: estado=%d, preparado=%s\n", param->prof_stat.state, hfpReady ? "SI" : "NO"); + if (hfpReady) { + if (USE_FIXED_MAC) { + setRemoteBda(FIXED_MAC, false); + } + if (haveRemoteBda) { + requestSlcConnect(true); + } else { + startDiscovery(true); + } + } + break; + + case ESP_HF_CONNECTION_STATE_EVT: { + setRemoteBda(param->conn_stat.remote_bda, true); + const esp_hf_connection_state_t state = param->conn_stat.state; + slcConnected = (state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED); + slcInProgress = (state == ESP_HF_CONNECTION_STATE_CONNECTING || state == ESP_HF_CONNECTION_STATE_CONNECTED); + + Serial.printf( + "HFP conexion: %s peer_feat=0x%08lX chld=0x%08lX ", + connectionStateName(state), + static_cast(param->conn_stat.peer_feat), + static_cast(param->conn_stat.chld_feat) + ); + printBda(param->conn_stat.remote_bda); + Serial.println(); + + if (state == ESP_HF_CONNECTION_STATE_DISCONNECTED) { + slcConnected = false; + slcInProgress = false; + audioConnecting = false; + audioConnected = false; + callActive = false; + codecMsbc = false; + autoCallAtMs = 0; + audioOpenAtMs = 0; + stopAudioPipeline(); + } else if (slcConnected) { + slcInProgress = false; + Serial.println("*** SLC_CONNECTED: control HFP listo. ***"); + logEsp("volumen altavoz", esp_hf_ag_volume_control(remoteBda, ESP_HF_VOLUME_CONTROL_TARGET_SPK, 12)); + logEsp("volumen microfono", esp_hf_ag_volume_control(remoteBda, ESP_HF_VOLUME_CONTROL_TARGET_MIC, 15)); + if (AUTO_START_AUDIO) { + autoCallAtMs = millis() + AUTO_CALL_DELAY_MS; + } + } + break; + } + + case ESP_HF_AUDIO_STATE_EVT: { + const esp_hf_audio_state_t state = param->audio_stat.state; + audioConnecting = (state == ESP_HF_AUDIO_STATE_CONNECTING); + audioConnected = (state == ESP_HF_AUDIO_STATE_CONNECTED || state == ESP_HF_AUDIO_STATE_CONNECTED_MSBC); + codecMsbc = (state == ESP_HF_AUDIO_STATE_CONNECTED_MSBC); + + Serial.printf( + "Audio HFP: %s, frame recomendado=%u bytes, handle=%u\n", + audioStateName(state), + param->audio_stat.preferred_frame_size, + param->audio_stat.sync_conn_handle + ); + + if (audioConnected) { + audioConnecting = false; + logEsp("esp_hf_ag_register_data_callback", esp_hf_ag_register_data_callback(incomingAudioCallback, outgoingAudioCallback)); + startAudioPipeline(codecMsbc); + Serial.printf( + "*** AUDIO CONECTADO: %s. Modo=%s ***\n", + codecMsbc ? "mSBC 16 kHz" : "CVSD 8 kHz", + audioMode == AudioTestMode::LOOPBACK ? "LOOPBACK" : "TONO" + ); + } else if (state == ESP_HF_AUDIO_STATE_DISCONNECTED) { + audioConnecting = false; + codecMsbc = false; + stopAudioPipeline(); + } + break; + } + + case ESP_HF_IND_UPDATE_EVT: + sendIndicatorState(param->ind_upd.remote_addr); + break; + + case ESP_HF_CIND_RESPONSE_EVT: + logEsp( + "esp_hf_ag_cind_response", + esp_hf_ag_cind_response( + param->cind_rep.remote_addr, + callActive ? ESP_HF_CALL_STATUS_CALL_IN_PROGRESS : ESP_HF_CALL_STATUS_NO_CALLS, + ESP_HF_CALL_SETUP_STATUS_IDLE, + ESP_HF_NETWORK_STATE_AVAILABLE, + 5, + ESP_HF_ROAMING_STATUS_INACTIVE, + 5, + ESP_HF_CALL_HELD_STATUS_NONE + ) + ); + break; + + case ESP_HF_COPS_RESPONSE_EVT: { + static char operatorName[] = "FormulaGades"; + logEsp("esp_hf_ag_cops_response", esp_hf_ag_cops_response(param->cops_rep.remote_addr, operatorName)); + break; + } + + case ESP_HF_CLCC_RESPONSE_EVT: + if (callActive) { + esp_hf_ag_clcc_response( + param->clcc_rep.remote_addr, + 1, + ESP_HF_CURRENT_CALL_DIRECTION_OUTGOING, + ESP_HF_CURRENT_CALL_STATUS_ACTIVE, + ESP_HF_CURRENT_CALL_MODE_VOICE, + ESP_HF_CURRENT_CALL_MPTY_TYPE_SINGLE, + TEST_NUMBER, + ESP_HF_CALL_ADDR_TYPE_UNKNOWN + ); + } + esp_hf_ag_clcc_response( + param->clcc_rep.remote_addr, + 0, + ESP_HF_CURRENT_CALL_DIRECTION_OUTGOING, + ESP_HF_CURRENT_CALL_STATUS_ACTIVE, + ESP_HF_CURRENT_CALL_MODE_VOICE, + ESP_HF_CURRENT_CALL_MPTY_TYPE_SINGLE, + TEST_NUMBER, + ESP_HF_CALL_ADDR_TYPE_UNKNOWN + ); + break; + + case ESP_HF_CNUM_RESPONSE_EVT: + logEsp( + "esp_hf_ag_cnum_response", + esp_hf_ag_cnum_response(param->cnum_rep.remote_addr, TEST_NUMBER, 129, ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE) + ); + break; + + case ESP_HF_ATA_RESPONSE_EVT: + Serial.println("El EJEAS ha enviado ATA (responder llamada)."); + answerCurrentCall(param->ata_rep.remote_addr); + break; + + case ESP_HF_CHUP_RESPONSE_EVT: + Serial.println("El EJEAS ha solicitado colgar."); + stopTestCall(); + break; + + case ESP_HF_DIAL_EVT: + Serial.println("El EJEAS ha solicitado marcar. Aceptando como llamada de prueba."); + logEsp("respuesta OK", esp_hf_ag_cmee_send(param->out_call.remote_addr, ESP_HF_AT_RESPONSE_CODE_OK, ESP_HF_CME_AG_FAILURE)); + answerCurrentCall(param->out_call.remote_addr); + break; + + case ESP_HF_UNAT_RESPONSE_EVT: { + const char *cmd = param->unat_rep.unat ? param->unat_rep.unat : "(null)"; + Serial.printf("AT propietario/no reconocido: %s\n", cmd); + + // El V6 Pro+ envia +SUGCODEC=1 durante la negociacion HFP. + // Arduino-ESP32 3.3.11 no lo interpreta, asi que lo aceptamos para + // que el intercom continue hasta SLC_CONNECTED en lugar de desconectar. + static char okResponse[] = "OK"; + logEsp( + "respuesta AT propietario OK", + esp_hf_ag_unknown_at_send(param->unat_rep.remote_addr, okResponse) + ); + break; + } + + case ESP_HF_VOLUME_CONTROL_EVT: + Serial.printf("Volumen desde EJEAS: destino=%d, valor=%d\n", param->volume_control.type, param->volume_control.volume); + break; + + case ESP_HF_NREC_RESPONSE_EVT: + Serial.printf("NREC solicitado: %d\n", param->nrec.state); + break; + + case ESP_HF_BVRA_RESPONSE_EVT: + Serial.printf("Reconocimiento de voz: %d\n", param->vra_rep.value); + break; + +#if defined(CONFIG_BT_HFP_WBS_ENABLE) && CONFIG_BT_HFP_WBS_ENABLE + case ESP_HF_WBS_RESPONSE_EVT: + Serial.printf("WBS: codec=%d\n", param->wbs_rep.codec); + break; +#endif + + case ESP_HF_BCS_RESPONSE_EVT: + Serial.printf("Negociacion de codec BCS: modo=%d\n", param->bcs_rep.mode); + break; + + default: + break; + } +} + +// ----------------------------------------------------------------------------- +// Inicializacion Bluetooth +// ----------------------------------------------------------------------------- +static bool initBluetooth() { + Serial.println("Iniciando controlador Bluetooth Classic..."); + + if (!btStarted()) { + if (!btStartMode(BT_MODE_CLASSIC_BT)) { + Serial.println("ERROR: btStartMode(BT_MODE_CLASSIC_BT) ha fallado."); + Serial.printf("Memoria BT Classic liberada antes de setup(): %s\n", btMemReleased(BT_MODE_CLASSIC_BT) ? "SI" : "NO"); + Serial.println("Comprueba que el sketch incluye esp32-hal-alloc-bt-classic-mem.h."); + return false; + } + } + + esp_bluedroid_status_t status = esp_bluedroid_get_status(); + if (status == ESP_BLUEDROID_STATUS_UNINITIALIZED) { + const esp_err_t err = esp_bluedroid_init(); + logEsp("esp_bluedroid_init", err); + if (err != ESP_OK) { + return false; + } + } + + status = esp_bluedroid_get_status(); + if (status != ESP_BLUEDROID_STATUS_ENABLED) { + const esp_err_t err = esp_bluedroid_enable(); + logEsp("esp_bluedroid_enable", err); + if (err != ESP_OK) { + return false; + } + } + + logEsp("esp_bt_gap_register_callback", esp_bt_gap_register_callback(gapCallback)); + + esp_bt_io_cap_t ioCapability = ESP_BT_IO_CAP_NONE; + logEsp( + "esp_bt_gap_set_security_param", + esp_bt_gap_set_security_param(ESP_BT_SP_IOCAP_MODE, &ioCapability, sizeof(ioCapability)) + ); + + esp_bt_pin_code_t unusedPin = {0}; + logEsp("esp_bt_gap_set_pin", esp_bt_gap_set_pin(ESP_BT_PIN_TYPE_VARIABLE, 0, unusedPin)); + logEsp("esp_bt_dev_set_device_name", esp_bt_dev_set_device_name(LOCAL_BT_NAME)); + + esp_bt_cod_t cod = {}; + cod.major = ESP_BT_COD_MAJOR_DEV_PHONE; + cod.minor = 0x00; + cod.service = ESP_BT_COD_SRVC_AUDIO | ESP_BT_COD_SRVC_TELEPHONY; + logEsp("esp_bt_gap_set_cod", esp_bt_gap_set_cod(cod, ESP_BT_SET_COD_ALL)); + + logEsp( + "esp_bt_gap_set_scan_mode", + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE) + ); + + // Esta llamada y los callbacks deben estar preparados antes de iniciar HFP. + logEsp("esp_bredr_sco_datapath_set", esp_bredr_sco_datapath_set(ESP_SCO_DATA_PATH_HCI)); + logEsp("esp_hf_ag_register_callback", esp_hf_ag_register_callback(hfpCallback)); + logEsp( + "esp_hf_ag_register_data_callback", + esp_hf_ag_register_data_callback(incomingAudioCallback, outgoingAudioCallback) + ); + logEsp("esp_hf_ag_init", esp_hf_ag_init()); + + return true; +} + +// ----------------------------------------------------------------------------- +// Comandos del monitor serie +// ----------------------------------------------------------------------------- +static void forgetIntercom() { + stopTestCall(); + + if (slcConnected && haveRemoteBda) { + esp_hf_ag_slc_disconnect(remoteBda); + } + + if (haveRemoteBda) { + const esp_err_t err = esp_bt_gap_remove_bond_device(remoteBda); + logEsp("esp_bt_gap_remove_bond_device", err); + } + + prefs.remove(PREF_BDA_KEY); + memset(remoteBda, 0, sizeof(remoteBda)); + haveRemoteBda = false; + saveRemotePending = false; + slcConnected = false; + callActive = false; + audioConnected = false; + audioConnecting = false; + Serial.println("MAC y emparejamiento borrados."); + lastDiscoveryAttemptMs = 0; + startDiscovery(true); +} + +static void processSerialCommand(char command) { + switch (command) { + case 'h': + case '?': + printHelp(); + break; + + case 's': + if (discoveryRunning) { + esp_bt_gap_cancel_discovery(); + } + memset(remoteBda, 0, sizeof(remoteBda)); + haveRemoteBda = false; + lastDiscoveryAttemptMs = 0; + startDiscovery(true); + break; + + case 'c': + requestSlcConnect(true); + break; + + case 'a': + startFakeCall(); + break; + + case 'o': + requestAudioConnect(true); + break; + + case 'l': + audioMode = AudioTestMode::LOOPBACK; + Serial.println("Modo LOOPBACK activado. Habla: deberias oirte con un pequeno retardo."); + break; + + case 't': + audioMode = AudioTestMode::TONE; + Serial.println("Modo TONO activado. Deberias oir un tono de 1 kHz."); + break; + + case 'x': + stopTestCall(); + break; + + case 'd': + stopTestCall(); + if (slcConnected && haveRemoteBda) { + logEsp("esp_hf_ag_slc_disconnect", esp_hf_ag_slc_disconnect(remoteBda)); + } + break; + + case 'b': + forgetIntercom(); + break; + + case 'i': + printStatus(); + break; + + case '\r': + case '\n': + case ' ': + break; + + default: + Serial.printf("Comando desconocido: '%c'. Escribe h.\n", command); + break; + } +} + +// ----------------------------------------------------------------------------- +// Arduino setup/loop +// ----------------------------------------------------------------------------- +void setup() { + Serial.begin(SERIAL_BAUD); + delay(1200); + + Serial.println(); + Serial.println("===================================================="); + Serial.println(" PRUEBA EJEAS V6 PRO+ - ESP32 HFP AUDIO GATEWAY V5"); + Serial.println("===================================================="); + Serial.println("El ESP32 se presenta como un telefono HFP."); + Serial.println("Pon el EJEAS en modo de emparejamiento con TELEFONO."); + Serial.println(); + + loadSavedBda(); + printHelp(); + + if (!initBluetooth()) { + Serial.println("ERROR FATAL inicializando Bluetooth."); + return; + } +} + +void loop() { + while (Serial.available() > 0) { + processSerialCommand(static_cast(Serial.read())); + } + + saveBdaIfNeeded(); + + const uint32_t now = millis(); + + if (hfpReady && !slcConnected) { + if (haveRemoteBda) { + requestSlcConnect(false); + } else { + startDiscovery(false); + } + } + + if (slcConnected && autoCallAtMs != 0 && static_cast(now - autoCallAtMs) >= 0) { + autoCallAtMs = 0; + startFakeCall(); + } + + if (slcConnected && callActive && audioOpenAtMs != 0 && static_cast(now - audioOpenAtMs) >= 0) { + audioOpenAtMs = 0; + requestAudioConnect(true); + } + + if (audioConnecting && !audioConnected && now - lastAudioAttemptMs >= AUDIO_RETRY_MS) { + requestAudioConnect(false); + } + + if (audioConnected && now - lastDiagnosticMs >= 1000) { + lastDiagnosticMs = now; + + noInterrupts(); + const uint32_t rxF = rxFrames; + const uint32_t rxB = rxBytes; + const uint32_t rxD = rxDrops; + const uint32_t txF = txFrames; + const uint32_t txB = txBytes; + const uint32_t txU = txUnderruns; + const uint32_t req = lastRequestedBytes; + interrupts(); + + Serial.printf( + "AUDIO [%s/%s] RX=%lu frames, %lu B, drops=%lu | TX=%lu frames, %lu B, underrun=%lu | pedido=%lu B\n", + codecMsbc ? "mSBC16k" : "CVSD8k", + audioMode == AudioTestMode::LOOPBACK ? "LOOPBACK" : "TONO", + static_cast(rxF), + static_cast(rxB), + static_cast(rxD), + static_cast(txF), + static_cast(txB), + static_cast(txU), + static_cast(req) + ); + } + + delay(20); +} diff --git a/Radio/Radio_intermediario/Radio_intermediario.ino b/Radio/Radio_intermediario/Radio_intermediario.ino new file mode 100644 index 0000000..2958790 --- /dev/null +++ b/Radio/Radio_intermediario/Radio_intermediario.ino @@ -0,0 +1,29 @@ +#include +#include "bridge.hpp" +#include "config.hpp" + +void setup() +{ + Serial.begin(115200); + delay(700); + + Serial.println(); + Serial.println("============================================"); + Serial.println(" WROOM-32U intermediario UART / ESP-NOW LR"); + Serial.println(" DEBUG PERMANENTE ACTIVADO"); + Serial.println("============================================"); + + if (!bridge_init()) { + Serial.println("FALLO iniciando el intermediario"); + + while (true) { + Serial.println("El intermediario sigue detenido por un error de inicio."); + delay(2000); + } + } +} + +void loop() +{ + bridge_process(); +} diff --git a/Radio/Radio_intermediario/bridge.cpp b/Radio/Radio_intermediario/bridge.cpp new file mode 100644 index 0000000..d2c3a04 --- /dev/null +++ b/Radio/Radio_intermediario/bridge.cpp @@ -0,0 +1,726 @@ +#include "bridge.hpp" +#include "config.hpp" + +#include +#include +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" + +struct EspNowRxItem { + uint32_t epoch; + uint16_t len; + uint8_t data[RADIO_PACKET_MAX_LEN]; +}; + + +static HardwareSerial PilotUart(2); +static QueueHandle_t box_audio_queue = nullptr; + +static portMUX_TYPE control_mux = portMUX_INITIALIZER_UNLOCKED; +static volatile bool box_ptt_active = false; +static volatile bool box_stop_pending = false; +static volatile uint32_t box_stream_epoch = 0; +static volatile uint32_t box_control_version = 0; + +static volatile bool espnow_send_busy = false; +static volatile bool espnow_last_send_ok = false; +static volatile uint32_t espnow_rx_dropped = 0; + +/* Diagnóstico permanente: no modifica el protocolo ni las MAC. */ +static volatile uint32_t debug_uart_rx_bytes = 0; +static volatile uint32_t debug_pilot_audio_packets = 0; +static volatile uint32_t debug_pilot_invalid_packets = 0; +static volatile uint32_t debug_espnow_api_ok = 0; +static volatile uint32_t debug_espnow_api_fail = 0; +static volatile uint32_t debug_espnow_ack_ok = 0; +static volatile uint32_t debug_espnow_ack_fail = 0; +static volatile uint32_t debug_espnow_forward_fail = 0; +static volatile uint32_t debug_espnow_rx_raw = 0; +static volatile uint32_t debug_espnow_rx_from_box = 0; +static volatile uint32_t debug_espnow_rx_foreign_mac = 0; +static volatile uint32_t debug_box_audio_packets = 0; +static volatile uint32_t debug_box_control_packets = 0; +static volatile uint32_t debug_box_invalid_packets = 0; +static volatile uint32_t debug_uart_tx_bytes = 0; +static volatile uint32_t debug_uart_tx_fail = 0; +static uint32_t debug_last_report_ms = 0; + +static uint32_t last_control_version_sent = 0; +static uint32_t last_control_epoch_sent = 0; +static bool last_control_state_sent = false; +static uint32_t last_control_sent_ms = 0; +static volatile uint32_t debug_control_heartbeats = 0; + +static uint16_t read_le_u16(const uint8_t *p) +{ + return (uint16_t)p[0] | ((uint16_t)p[1] << 8); +} + +static bool mac_is_zero(const uint8_t *mac) +{ + static const uint8_t zero[6] = {}; + return mac == nullptr || memcmp(mac, zero, sizeof(zero)) == 0; +} + +static bool audio_packet_valid(const uint8_t *data, int len) +{ + if (data == nullptr || len < RADIO_PACKET_HEADER_LEN || len > RADIO_PACKET_MAX_LEN) { + return false; + } + + if (data[0] != RADIO_AUDIO_MAGIC_1 || data[1] != RADIO_AUDIO_MAGIC_2) { + return false; + } + + const uint8_t chunk_index = data[3]; + const uint8_t chunk_total = data[4]; + const uint16_t frame_len = read_le_u16(&data[5]); + const uint16_t offset = read_le_u16(&data[7]); + const uint16_t chunk_len = read_le_u16(&data[9]); + + if (chunk_total == 0 || chunk_total > 16 || chunk_index >= chunk_total) { + return false; + } + + if (frame_len == 0 || frame_len > 2000) { + return false; + } + + if (chunk_len == 0 || chunk_len > RADIO_AUDIO_CHUNK) { + return false; + } + + if ((uint32_t)offset + chunk_len > frame_len) { + return false; + } + + return len == RADIO_PACKET_HEADER_LEN + chunk_len; +} + +static bool control_packet_valid(const uint8_t *data, int len) +{ + return data != nullptr && + len == RADIO_CONTROL_PACKET_LEN && + data[0] == RADIO_CONTROL_MAGIC_1 && + data[1] == RADIO_CONTROL_MAGIC_2 && + data[2] == RADIO_CONTROL_COMMAND_BOX_PTT && + (data[3] == 0 || data[3] == 1); +} + +static void snapshot_control( + bool *active, + bool *stop_pending, + uint32_t *epoch, + uint32_t *version) +{ + portENTER_CRITICAL(&control_mux); + if (active != nullptr) { + *active = box_ptt_active; + } + if (stop_pending != nullptr) { + *stop_pending = box_stop_pending; + } + if (epoch != nullptr) { + *epoch = box_stream_epoch; + } + if (version != nullptr) { + *version = box_control_version; + } + portEXIT_CRITICAL(&control_mux); +} + +static bool ensure_peer_registered(const uint8_t *mac) +{ + if (mac_is_zero(mac)) { + return false; + } + + if (esp_now_is_peer_exist(mac)) { + return true; + } + + esp_now_peer_info_t peer = {}; + memcpy(peer.peer_addr, mac, 6); + peer.channel = ESPNOW_CHANNEL; + peer.ifidx = WIFI_IF_STA; + peer.encrypt = false; + + return esp_now_add_peer(&peer) == ESP_OK; +} + +static void on_espnow_sent(const wifi_tx_info_t *tx_info, esp_now_send_status_t status) +{ + (void)tx_info; + + espnow_last_send_ok = (status == ESP_NOW_SEND_SUCCESS); + + if (espnow_last_send_ok) { + ++debug_espnow_ack_ok; + } else { + ++debug_espnow_ack_fail; + } + + espnow_send_busy = false; +} + +static void on_espnow_recv( + const esp_now_recv_info_t *info, + const uint8_t *data, + int len) +{ + ++debug_espnow_rx_raw; + + if (info == nullptr || info->src_addr == nullptr || data == nullptr) { + ++debug_box_invalid_packets; + return; + } + + if (memcmp(info->src_addr, BOX_RECEIVER_MAC, 6) != 0) { + ++debug_espnow_rx_foreign_mac; + return; + } + + ++debug_espnow_rx_from_box; + + if (control_packet_valid(data, len)) { + ++debug_box_control_packets; + const bool active = data[3] != 0; + + portENTER_CRITICAL(&control_mux); + if (active) { + // Un START nuevo cancela un cierre pendiente. Si el stream ya estaba + // activo no se cambia el epoch, por lo que la cola anterior termina + // y la nueva pulsación continúa sin cortes. + if (!box_ptt_active) { + box_ptt_active = true; + ++box_stream_epoch; + ++box_control_version; + } + box_stop_pending = false; + } else if (box_ptt_active) { + // STOP no se reenvía todavía: primero se vacía la cola de audio que + // ya llegó por ESP-NOW para no cortar el final del mensaje. + box_stop_pending = true; + } + portEXIT_CRITICAL(&control_mux); + return; + } + + if (!audio_packet_valid(data, len) || box_audio_queue == nullptr) { + ++debug_box_invalid_packets; + return; + } + + ++debug_box_audio_packets; + + bool active = false; + bool stop_pending = false; + uint32_t epoch = 0; + snapshot_control(&active, &stop_pending, &epoch, nullptr); + + if (!active || stop_pending) { + return; + } + + EspNowRxItem item = {}; + item.epoch = epoch; + item.len = (uint16_t)len; + memcpy(item.data, data, len); + + if (xQueueSend(box_audio_queue, &item, 0) != pdTRUE) { + EspNowRxItem discarded = {}; + xQueueReceive(box_audio_queue, &discarded, 0); + if (xQueueSend(box_audio_queue, &item, 0) != pdTRUE) { + ++espnow_rx_dropped; + } + } +} + +static bool uart_write_all(const uint8_t *data, size_t len) +{ + if (data == nullptr || len == 0) { + return false; + } + + size_t sent = 0; + const uint32_t started = millis(); + + while (sent < len) { + sent += PilotUart.write(data + sent, len - sent); + + if (sent >= len) { + debug_uart_tx_bytes += (uint32_t)len; + return true; + } + + if ((uint32_t)(millis() - started) >= PILOT_UART_WRITE_TIMEOUT_MS) { + ++debug_uart_tx_fail; + return false; + } + + delay(0); + } + + return true; +} + +static bool send_pending_control_to_pilot() +{ + bool active = false; + uint32_t epoch = 0; + uint32_t version = 0; + snapshot_control(&active, nullptr, &epoch, &version); + + const bool heartbeat_due = + active && + (uint32_t)(millis() - last_control_sent_ms) >= BOX_PTT_HEARTBEAT_MS; + + if (version == last_control_version_sent && !heartbeat_due) { + return true; + } + + const uint8_t packet[RADIO_CONTROL_PACKET_LEN] = { + RADIO_CONTROL_MAGIC_1, + RADIO_CONTROL_MAGIC_2, + RADIO_CONTROL_COMMAND_BOX_PTT, + active ? (uint8_t)1 : (uint8_t)0 + }; + + if (!uart_write_all(packet, sizeof(packet))) { + return false; + } + + if (version == last_control_version_sent && heartbeat_due) { + ++debug_control_heartbeats; + } + + last_control_version_sent = version; + last_control_epoch_sent = epoch; + last_control_state_sent = active; + last_control_sent_ms = millis(); + + return true; +} + +static bool finalize_box_stop_if_drained() +{ + if (box_audio_queue == nullptr || uxQueueMessagesWaiting(box_audio_queue) != 0) { + return false; + } + + bool changed = false; + + portENTER_CRITICAL(&control_mux); + if (box_stop_pending && box_ptt_active) { + box_stop_pending = false; + box_ptt_active = false; + ++box_stream_epoch; + ++box_control_version; + changed = true; + } + portEXIT_CRITICAL(&control_mux); + + return changed; +} + +static void forward_box_audio_to_pilot() +{ + if (!send_pending_control_to_pilot() || box_audio_queue == nullptr) { + return; + } + + EspNowRxItem item = {}; + uint8_t processed = 0; + + // Limitar cada pasada evita que una cola grande bloquee el sentido contrario. + while (processed < MAX_BOX_TO_PILOT_PACKETS_PER_PASS && + xQueueReceive(box_audio_queue, &item, 0) == pdTRUE) { + ++processed; + + bool active = false; + uint32_t epoch = 0; + uint32_t version = 0; + snapshot_control(&active, nullptr, &epoch, &version); + + if (!active || item.epoch != epoch) { + continue; + } + + if (last_control_version_sent != version || + last_control_epoch_sent != epoch || + !last_control_state_sent) { + if (!send_pending_control_to_pilot()) { + return; + } + } + + if (!uart_write_all(item.data, item.len)) { + Serial.println("ERROR: no se pudo enviar audio al Audio Kit por UART"); + return; + } + } + + // El STOP solo viaja después del último paquete que ya estaba en la cola. + if (finalize_box_stop_if_drained()) { + send_pending_control_to_pilot(); + } +} + +bool bridge_send_espnow(const byte *data, size_t len, byte intentos) +{ + if (data == nullptr || len == 0 || len > 250 || intentos == 0) { + return false; + } + + if (!ensure_peer_registered(BOX_RECEIVER_MAC)) { + return false; + } + + for (byte attempt = 0; attempt < intentos; ++attempt) { + const uint32_t wait_start = millis(); + while (espnow_send_busy && + (uint32_t)(millis() - wait_start) < ESPNOW_SEND_TIMEOUT_MS) { + delay(1); + } + + if (espnow_send_busy) { + espnow_send_busy = false; + } + + espnow_last_send_ok = false; + espnow_send_busy = true; + + const esp_err_t err = esp_now_send(BOX_RECEIVER_MAC, data, len); + if (err != ESP_OK) { + ++debug_espnow_api_fail; + espnow_send_busy = false; + delay(1); + continue; + } + + ++debug_espnow_api_ok; + + const uint32_t ack_start = millis(); + while (espnow_send_busy && + (uint32_t)(millis() - ack_start) < ESPNOW_SEND_TIMEOUT_MS) { + delay(1); + } + + if (!espnow_send_busy && espnow_last_send_ok) { + return true; + } + + delay(1); + } + + ++debug_espnow_forward_fail; + return false; +} + +static bool send_audio_packet(const byte *data, size_t len) +{ + if (!audio_packet_valid(data, (int)len)) { + return false; + } + + return bridge_send_espnow(data, len, ESPNOW_SEND_RETRIES); +} + +static void process_pilot_uart_to_espnow() +{ + enum ParserState { + WAIT_MAGIC_1, + WAIT_MAGIC_2, + READ_AUDIO_HEADER, + READ_AUDIO_BODY, + SKIP_CONTROL + }; + + static ParserState state = WAIT_MAGIC_1; + static uint8_t packet[RADIO_PACKET_MAX_LEN] = {}; + static size_t index = 0; + static uint16_t expected_audio_len = 0; + static uint8_t control_bytes = 0; + static uint32_t last_byte_ms = 0; + uint8_t processed_packets = 0; + + auto reset_parser = [&]() { + state = WAIT_MAGIC_1; + index = 0; + expected_audio_len = 0; + control_bytes = 0; + }; + + while (PilotUart.available() > 0) { + const int value = PilotUart.read(); + if (value < 0) { + break; + } + + const uint8_t b = (uint8_t)value; + ++debug_uart_rx_bytes; + + const uint32_t now = millis(); + + if (state != WAIT_MAGIC_1 && (uint32_t)(now - last_byte_ms) > 120) { + ++debug_pilot_invalid_packets; + reset_parser(); + } + last_byte_ms = now; + + switch (state) { + case WAIT_MAGIC_1: + if (b == RADIO_AUDIO_MAGIC_1) { + packet[0] = b; + index = 1; + state = WAIT_MAGIC_2; + } + break; + + case WAIT_MAGIC_2: + if (b == RADIO_AUDIO_MAGIC_2) { + packet[1] = b; + index = 2; + state = READ_AUDIO_HEADER; + } else if (b == RADIO_CONTROL_MAGIC_2) { + // El Audio Kit no necesita mandar controles al box, pero se + // consume un posible paquete para mantener sincronía. + control_bytes = 2; + state = SKIP_CONTROL; + } else if (b == RADIO_AUDIO_MAGIC_1) { + packet[0] = b; + index = 1; + } else { + reset_parser(); + } + break; + + case SKIP_CONTROL: + ++control_bytes; + if (control_bytes >= RADIO_CONTROL_PACKET_LEN) { + reset_parser(); + } + break; + + case READ_AUDIO_HEADER: + if (index >= sizeof(packet)) { + reset_parser(); + break; + } + + packet[index++] = b; + if (index >= RADIO_PACKET_HEADER_LEN) { + const uint16_t frame_len = read_le_u16(&packet[5]); + const uint16_t offset = read_le_u16(&packet[7]); + expected_audio_len = read_le_u16(&packet[9]); + + if (packet[4] == 0 || packet[4] > 16 || + packet[3] >= packet[4] || + frame_len == 0 || frame_len > 2000 || + expected_audio_len == 0 || expected_audio_len > RADIO_AUDIO_CHUNK || + (uint32_t)offset + expected_audio_len > frame_len) { + ++debug_pilot_invalid_packets; + reset_parser(); + break; + } + + state = READ_AUDIO_BODY; + } + break; + + case READ_AUDIO_BODY: + if (index >= sizeof(packet)) { + reset_parser(); + break; + } + + packet[index++] = b; + if (index >= RADIO_PACKET_HEADER_LEN + expected_audio_len) { + ++debug_pilot_audio_packets; + + send_audio_packet(packet, index); + reset_parser(); + + ++processed_packets; + if (processed_packets >= MAX_PILOT_TO_BOX_PACKETS_PER_PASS) { + return; + } + } + break; + } + } +} + +static void print_permanent_debug() +{ + const uint32_t now = millis(); + if ((uint32_t)(now - debug_last_report_ms) < INTERMEDIARY_DEBUG_INTERVAL_MS) { + return; + } + debug_last_report_ms = now; + + bool ptt_active = false; + bool ptt_stop_pending = false; + uint32_t ptt_epoch = 0; + uint32_t ptt_version = 0; + snapshot_control(&ptt_active, &ptt_stop_pending, &ptt_epoch, &ptt_version); + + const UBaseType_t queue_items = + box_audio_queue != nullptr ? uxQueueMessagesWaiting(box_audio_queue) : 0; + + Serial.println(); + Serial.println("========== DEBUG INTERMEDIARIO =========="); + Serial.printf( + "PILOTO -> UART: bytes=%lu | paquetes_audio=%lu | invalidos=%lu\n", + (unsigned long)debug_uart_rx_bytes, + (unsigned long)debug_pilot_audio_packets, + (unsigned long)debug_pilot_invalid_packets + ); + Serial.printf( + "INTERMEDIARIO -> BOX: API_OK=%lu | API_FALLO=%lu | ACK_OK=%lu | ACK_FALLO=%lu | paquetes_fallidos=%lu\n", + (unsigned long)debug_espnow_api_ok, + (unsigned long)debug_espnow_api_fail, + (unsigned long)debug_espnow_ack_ok, + (unsigned long)debug_espnow_ack_fail, + (unsigned long)debug_espnow_forward_fail + ); + Serial.printf( + "BOX -> ESP-NOW: RAW=%lu | desde_MAC_box=%lu | audio=%lu | controles=%lu | invalidos=%lu | MAC_ajena=%lu\n", + (unsigned long)debug_espnow_rx_raw, + (unsigned long)debug_espnow_rx_from_box, + (unsigned long)debug_box_audio_packets, + (unsigned long)debug_box_control_packets, + (unsigned long)debug_box_invalid_packets, + (unsigned long)debug_espnow_rx_foreign_mac + ); + Serial.printf( + "INTERMEDIARIO -> PILOTO: bytes_UART=%lu | fallos_UART=%lu | cola=%u | descartados=%lu\n", + (unsigned long)debug_uart_tx_bytes, + (unsigned long)debug_uart_tx_fail, + (unsigned int)queue_items, + (unsigned long)espnow_rx_dropped + ); + Serial.printf( + "PTT BOX: %s | cierre_pendiente=%s | epoch=%lu | version=%lu | latidos_START=%lu\n", + ptt_active ? "ACTIVO" : "INACTIVO", + ptt_stop_pending ? "SI" : "NO", + (unsigned long)ptt_epoch, + (unsigned long)ptt_version, + (unsigned long)debug_control_heartbeats + ); + Serial.println("========================================="); +} + +bool bridge_init() +{ + box_audio_queue = xQueueCreate(ESPNOW_RX_QUEUE_SIZE, sizeof(EspNowRxItem)); + if (box_audio_queue == nullptr) { + Serial.println("ERROR creando cola ESP-NOW"); + return false; + } + + PilotUart.setRxBufferSize(PILOT_UART_RX_BUFFER_SIZE); + PilotUart.begin( + PILOT_UART_BAUD, + SERIAL_8N1, + PILOT_UART_RX_GPIO, + PILOT_UART_TX_GPIO + ); + + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + WiFi.setSleep(false); + delay(50); + + if (esp_wifi_set_ps(WIFI_PS_NONE) != ESP_OK) { + return false; + } + + if (esp_wifi_set_protocol( + WIFI_IF_STA, + WIFI_PROTOCOL_11B | + WIFI_PROTOCOL_11G | + WIFI_PROTOCOL_11N | + WIFI_PROTOCOL_LR) != ESP_OK) { + return false; + } + + if (esp_wifi_set_channel(ESPNOW_CHANNEL, WIFI_SECOND_CHAN_NONE) != ESP_OK) { + return false; + } + + // El driver puede limitar el valor según chip, alimentación y normativa. + esp_wifi_set_max_tx_power(ESPNOW_TX_POWER_QDBM); + + if (esp_now_init() != ESP_OK) { + return false; + } + + if (esp_now_register_send_cb(on_espnow_sent) != ESP_OK || + esp_now_register_recv_cb(on_espnow_recv) != ESP_OK) { + return false; + } + + if (!ensure_peer_registered(BOX_RECEIVER_MAC)) { + return false; + } + + int8_t tx_power = 0; + esp_wifi_get_max_tx_power(&tx_power); + + Serial.println("Intermediario UART <-> ESP-NOW LR iniciado"); + Serial.print("MAC WiFi STA del intermediario: "); + Serial.println(WiFi.macAddress()); + + Serial.printf( + "MAC fija del receptor BOX: %02X:%02X:%02X:%02X:%02X:%02X\n", + BOX_RECEIVER_MAC[0], + BOX_RECEIVER_MAC[1], + BOX_RECEIVER_MAC[2], + BOX_RECEIVER_MAC[3], + BOX_RECEIVER_MAC[4], + BOX_RECEIVER_MAC[5] + ); + Serial.printf("UART: RX GPIO%d / TX GPIO%d / %d baudios\n", + PILOT_UART_RX_GPIO, + PILOT_UART_TX_GPIO, + PILOT_UART_BAUD); + Serial.printf("Canal ESP-NOW: %d\n", ESPNOW_CHANNEL); + Serial.print("Potencia configurada aprox.: "); + Serial.print(tx_power * 0.25f); + Serial.println(" dBm"); + + return true; +} + + +void bridge_process() +{ + static bool box_first = true; + + // El control START/STOP siempre tiene prioridad sobre los paquetes de audio. + send_pending_control_to_pilot(); + + // Alternar la prioridad en cada pasada evita que un flujo continuo pueda + // monopolizar el loop y cortar el audio del sentido opuesto. + if (box_first) { + forward_box_audio_to_pilot(); + process_pilot_uart_to_espnow(); + } else { + process_pilot_uart_to_espnow(); + forward_box_audio_to_pilot(); + } + box_first = !box_first; + + // Por si STOP llegó mientras se enviaba un paquete hacia boxes. + send_pending_control_to_pilot(); + + // Diagnóstico siempre activo, una vez por segundo. + print_permanent_debug(); + delay(0); +} diff --git a/Radio/Radio_intermediario/bridge.hpp b/Radio/Radio_intermediario/bridge.hpp new file mode 100644 index 0000000..fb67139 --- /dev/null +++ b/Radio/Radio_intermediario/bridge.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include + +bool bridge_init(); +void bridge_process(); +bool bridge_send_espnow(const byte *data, size_t len, byte intentos); diff --git a/Radio/Radio_intermediario/config.hpp b/Radio/Radio_intermediario/config.hpp new file mode 100644 index 0000000..55afbdd --- /dev/null +++ b/Radio/Radio_intermediario/config.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include + +/* UART2 entre WROOM-U y Audio Kit */ +#define PILOT_UART_BAUD 460800 +#define PILOT_UART_RX_GPIO 16 +#define PILOT_UART_TX_GPIO 17 +#define PILOT_UART_RX_BUFFER_SIZE 8192 +#define PILOT_UART_WRITE_TIMEOUT_MS 120 +#define BOX_PTT_HEARTBEAT_MS 250 + +/* Protocolo de audio/control */ +#define RADIO_AUDIO_CHUNK 200 +#define RADIO_PACKET_HEADER_LEN 11 +#define RADIO_PACKET_MAX_LEN (RADIO_PACKET_HEADER_LEN + RADIO_AUDIO_CHUNK) +#define RADIO_AUDIO_MAGIC_1 0xE5 +#define RADIO_AUDIO_MAGIC_2 0x5E +#define RADIO_CONTROL_MAGIC_1 0xE5 +#define RADIO_CONTROL_MAGIC_2 0x5F +#define RADIO_CONTROL_COMMAND_BOX_PTT 0x01 +#define RADIO_CONTROL_PACKET_LEN 4 + +/* ESP-NOW Long Range */ +#define ESPNOW_CHANNEL 1 +#define ESPNOW_TX_POWER_QDBM 84 +#define ESPNOW_SEND_RETRIES 3 +#define ESPNOW_SEND_TIMEOUT_MS 35 +#define ESPNOW_RX_QUEUE_SIZE 40 + +/* Reparto justo del tiempo entre los dos sentidos de audio. */ +#define MAX_BOX_TO_PILOT_PACKETS_PER_PASS 2 +#define MAX_PILOT_TO_BOX_PACKETS_PER_PASS 2 + +/* + MAC WiFi STA del ESP32 receptor conectado al PC. + Esta es la MAC que ya figuraba en el proyecto anterior. Cámbiala si la + MAC real de tu receptor de boxes es distinta. +*/ +static constexpr uint8_t BOX_RECEIVER_MAC[6] = { + 0x28, 0x05, 0xA5, 0xE1, 0xCA, 0x10 +}; + +#define INTERMEDIARY_DEBUG_SERIAL 1 +#define INTERMEDIARY_DEBUG_INTERVAL_MS 1000 diff --git a/Radio/Radio_piloto/Radio_piloto.ino b/Radio/Radio_piloto/Radio_piloto.ino new file mode 100644 index 0000000..2d85eed --- /dev/null +++ b/Radio/Radio_piloto/Radio_piloto.ino @@ -0,0 +1,109 @@ +#include + +// Evita que Arduino-ESP32 libere la memoria de Bluetooth Classic antes de setup(). +#if __has_include("esp32-hal-alloc-bt-classic-mem.h") +#include "esp32-hal-alloc-bt-classic-mem.h" +#elif __has_include("esp32-hal-bt-mem.h") +#include "esp32-hal-bt-mem.h" +#else +#error "Actualiza esp32 by Espressif Systems a la version 3.3.8 o posterior." +#endif + +#include "audio.hpp" +#include "config.hpp" +#include "ptt.hpp" +#include "uart_audio.hpp" + +static uint8_t audio_frame_sequence = 0; +static TaskHandle_t pilot_tx_task_handle = nullptr; + +static void pilot_tx_task(void *parameter) +{ + (void)parameter; + bool microphone_enabled = false; + + for (;;) { + const bool ptt_pressed = ptt_is_pressed(); + + if (ptt_pressed != microphone_enabled) { + microphone_enabled = ptt_pressed; + audio_set_microphone_enabled(microphone_enabled); + } + + if (!ptt_pressed) { + vTaskDelay(pdMS_TO_TICKS(1)); + continue; + } + + const int8_t *audio = nullptr; + uint16_t audio_len = 0; + + if (audio_capture_frame(&audio, &audio_len) && ptt_is_pressed()) { + uart_send_audio(audio_frame_sequence++, audio, audio_len); + } + + vTaskDelay(pdMS_TO_TICKS(1)); + } +} + +static void stop_forever(const char *reason) +{ +#if PILOT_DEBUG_SERIAL + Serial.println(reason); +#endif + while (true) { + delay(1000); + } +} + +void setup() +{ + Serial.begin(115200); + delay(500); + +#if PILOT_DEBUG_SERIAL + Serial.println(); + Serial.println("================================================"); + Serial.println(" Radio piloto: INTERCOM BLUETOOTH <-> UART"); + Serial.println("================================================"); +#endif + + if (!ptt_init()) { + stop_forever("FALLO: no se pudo iniciar el PTT KEY2"); + } + + if (!audio_init()) { + stop_forever("FALLO: no se pudo iniciar Bluetooth HFP"); + } + + if (!uart_audio_init()) { + stop_forever("FALLO: no se pudo iniciar el enlace UART"); + } + + const BaseType_t tx_task_result = xTaskCreatePinnedToCore( + pilot_tx_task, + "pilot_audio_tx", + PILOT_TX_TASK_STACK, + nullptr, + PILOT_TX_TASK_PRIORITY, + &pilot_tx_task_handle, + PILOT_TX_TASK_CORE + ); + + if (tx_task_result != pdPASS) { + stop_forever("FALLO: no se pudo iniciar la tarea de transmision del piloto"); + } + +#if PILOT_DEBUG_SERIAL + Serial.println("Radio lista. Enciende el V6 Pro+; se conectara automaticamente."); + Serial.println("KEY2 pulsado = enviar micro; la escucha del box sigue activa."); +#endif +} + +void loop() +{ + audio_process(); + uart_process_received_audio(true); + uart_audio_debug_report(); + delay(1); +} diff --git a/Radio/Radio_piloto/audio.cpp b/Radio/Radio_piloto/audio.cpp new file mode 100644 index 0000000..d614732 --- /dev/null +++ b/Radio/Radio_piloto/audio.cpp @@ -0,0 +1,767 @@ +#include "audio.hpp" +#include "config.hpp" + +#include +#include + +#include "esp32-hal-bt.h" +#include "esp_bt.h" +#include "esp_bt_device.h" +#include "esp_bt_main.h" +#include "esp_gap_bt_api.h" +#include "esp_hf_ag_api.h" +#include "esp_timer.h" +#include "esp_err.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/stream_buffer.h" + +#if !defined(CONFIG_IDF_TARGET_ESP32) +#error "Bluetooth HFP necesita un ESP32 clasico, como el ESP32-A1S." +#endif + +#if !defined(CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI) || !(CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI) +#error "Instala esp32 by Espressif Systems 3.3.8 o posterior para usar HFP por HCI." +#endif + +/* ============================================================ + ESTADO BLUETOOTH + ============================================================ */ + +static esp_bd_addr_t intercom_addr = INTERCOM_BT_MAC; +static char test_number[] = "100"; + +static volatile bool hfp_ready = false; +static volatile bool slc_connected = false; +static volatile bool slc_connecting = false; +static volatile bool audio_connected = false; +static volatile bool audio_connecting = false; +static volatile bool call_active = false; +static volatile bool codec_msbc = false; + +static uint32_t last_slc_attempt_ms = 0; +static uint32_t last_audio_attempt_ms = 0; +static uint32_t call_start_at_ms = 0; +static uint32_t audio_open_at_ms = 0; + +/* ============================================================ + BUFFERS DE AUDIO + + mic_buffer: + PCM del micro ya convertido a 8 bits / 8 kHz para la radio. + + speaker_buffer: + PCM de 16 bits a la frecuencia negociada por HFP para el intercom. + ============================================================ */ + +static StreamBufferHandle_t mic_buffer = nullptr; +static StreamBufferHandle_t speaker_buffer = nullptr; +static esp_timer_handle_t hfp_audio_timer = nullptr; + +static volatile bool microphone_enabled = false; +static volatile bool playback_enabled = false; +static volatile bool speaker_clear_requested = true; +static volatile bool downsample_phase = false; + +static int8_t mic_frame[AUDIO_SAMPLES_PER_BLOCK]; + +/* ============================================================ + UTILIDADES + ============================================================ */ + +static void print_esp_result(const char *name, esp_err_t err) +{ +#if PILOT_DEBUG_SERIAL + if (err == ESP_OK) { + Serial.printf("%s: OK\n", name); + } else { + Serial.printf("%s: %s (0x%04X)\n", name, esp_err_to_name(err), (unsigned)err); + } +#else + (void)name; + (void)err; +#endif +} + +static void print_intercom_mac() +{ +#if PILOT_DEBUG_SERIAL + Serial.printf( + "%02X:%02X:%02X:%02X:%02X:%02X", + intercom_addr[0], intercom_addr[1], intercom_addr[2], + intercom_addr[3], intercom_addr[4], intercom_addr[5] + ); +#endif +} + +static void drain_microphone_buffer() +{ + if (mic_buffer == nullptr) { + return; + } + + uint8_t discarded[128]; + while (xStreamBufferReceive(mic_buffer, discarded, sizeof(discarded), 0) > 0) { + } +} + +static void drain_speaker_buffer_from_reader(uint8_t *temporary, size_t temporary_len) +{ + if (speaker_buffer == nullptr || temporary == nullptr || temporary_len == 0) { + return; + } + + while (xStreamBufferReceive(speaker_buffer, temporary, temporary_len, 0) > 0) { + } +} + +/* ============================================================ + PIPELINE HFP + ============================================================ */ + +static void audio_timer_callback(void *arg) +{ + (void)arg; + if (audio_connected) { + esp_hf_ag_outgoing_data_ready(); + } +} + +static void stop_hfp_audio_timer() +{ + if (hfp_audio_timer != nullptr) { + esp_timer_stop(hfp_audio_timer); + esp_timer_delete(hfp_audio_timer); + hfp_audio_timer = nullptr; + } +} + +static bool start_hfp_audio_timer() +{ + stop_hfp_audio_timer(); + + esp_timer_create_args_t timer_args = {}; + timer_args.callback = audio_timer_callback; + timer_args.arg = nullptr; + timer_args.dispatch_method = ESP_TIMER_TASK; + timer_args.name = "hfp_audio"; + timer_args.skip_unhandled_events = true; + + esp_err_t err = esp_timer_create(&timer_args, &hfp_audio_timer); + if (err != ESP_OK) { + print_esp_result("esp_timer_create", err); + return false; + } + + err = esp_timer_start_periodic( + hfp_audio_timer, + codec_msbc ? INTERCOM_MSBC_TRIGGER_US : INTERCOM_CVSD_TRIGGER_US + ); + + if (err != ESP_OK) { + print_esp_result("esp_timer_start_periodic", err); + stop_hfp_audio_timer(); + return false; + } + + return true; +} + +/* + HFP entrega PCM mono de 16 bits. + - CVSD: 8 kHz -> se usa cada muestra. + - mSBC: 16 kHz -> se toma una de cada dos muestras. + + No se aplica paso alto, paso bajo, puerta de ruido ni ganancia digital. +*/ +static void incoming_audio_callback(const uint8_t *buf, uint32_t len) +{ + if (buf == nullptr || len < sizeof(int16_t) || !microphone_enabled || mic_buffer == nullptr) { + return; + } + + const int16_t *samples = reinterpret_cast(buf); + const size_t sample_count = len / sizeof(int16_t); + int8_t converted[128]; + size_t converted_count = 0; + + for (size_t i = 0; i < sample_count; ++i) { + bool keep = true; + + if (codec_msbc) { + keep = !downsample_phase; + downsample_phase = !downsample_phase; + } + + if (!keep) { + continue; + } + + converted[converted_count++] = (int8_t)(samples[i] / 256); + + if (converted_count == sizeof(converted)) { + xStreamBufferSend(mic_buffer, converted, converted_count, 0); + converted_count = 0; + } + } + + if (converted_count > 0) { + xStreamBufferSend(mic_buffer, converted, converted_count, 0); + } +} + +/* + El intercom solicita PCM mono de 16 bits. + Si no hay audio del box disponible, se devuelve silencio manteniendo + abierto el enlace HFP. +*/ +static uint32_t outgoing_audio_callback(uint8_t *buf, uint32_t len) +{ + if (buf == nullptr || len == 0 || !audio_connected) { + return 0; + } + + if (speaker_clear_requested) { + drain_speaker_buffer_from_reader(buf, len); + speaker_clear_requested = false; + } + + if (!playback_enabled || speaker_buffer == nullptr) { + memset(buf, 0, len); + return len; + } + + const size_t received = xStreamBufferReceive(speaker_buffer, buf, len, 0); + if (received < len) { + memset(buf + received, 0, len - received); + } + + return len; +} + +/* ============================================================ + CONEXION HFP + ============================================================ */ + +static void request_slc_connect(bool force) +{ + if (!hfp_ready || slc_connected || slc_connecting) { + return; + } + + const uint32_t now = millis(); + if (!force && (uint32_t)(now - last_slc_attempt_ms) < INTERCOM_SLC_RETRY_MS) { + return; + } + + last_slc_attempt_ms = now; + slc_connecting = true; + +#if PILOT_DEBUG_SERIAL + Serial.print("Conectando intercom HFP: "); + print_intercom_mac(); + Serial.println(); +#endif + + const esp_err_t err = esp_hf_ag_slc_connect(intercom_addr); + if (err != ESP_OK) { + slc_connecting = false; + } + print_esp_result("esp_hf_ag_slc_connect", err); +} + +static void start_fake_call() +{ + if (!slc_connected || call_active) { + return; + } + + call_active = true; + const esp_err_t err = esp_hf_ag_out_call( + intercom_addr, + 1, + 0, + ESP_HF_CALL_STATUS_CALL_IN_PROGRESS, + ESP_HF_CALL_SETUP_STATUS_IDLE, + test_number, + ESP_HF_CALL_ADDR_TYPE_UNKNOWN + ); + + print_esp_result("esp_hf_ag_out_call", err); + audio_open_at_ms = millis() + INTERCOM_AUDIO_OPEN_DELAY_MS; +} + +static void request_audio_connect(bool force) +{ + if (!slc_connected || audio_connected) { + return; + } + + const uint32_t now = millis(); + if (!force && audio_connecting && + (uint32_t)(now - last_audio_attempt_ms) < INTERCOM_AUDIO_RETRY_MS) { + return; + } + + last_audio_attempt_ms = now; + audio_connecting = true; + + const esp_err_t err = esp_hf_ag_audio_connect(intercom_addr); + if (err != ESP_OK) { + audio_connecting = false; + } + print_esp_result("esp_hf_ag_audio_connect", err); +} + +/* ============================================================ + RESPUESTAS HFP BASICAS + ============================================================ */ + +static void send_indicator_state(esp_bd_addr_t addr) +{ + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_CALL, + call_active ? ESP_HF_CALL_STATUS_CALL_IN_PROGRESS : ESP_HF_CALL_STATUS_NO_CALLS); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_CALLSETUP, ESP_HF_CALL_SETUP_STATUS_IDLE); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_SERVICE, ESP_HF_NETWORK_STATE_AVAILABLE); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_SIGNAL, 5); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_ROAM, ESP_HF_ROAMING_STATUS_INACTIVE); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_BATTCHG, 5); + esp_hf_ag_ciev_report(addr, ESP_HF_IND_TYPE_CALLHELD, ESP_HF_CALL_HELD_STATUS_NONE); +} + +static void answer_current_call(esp_bd_addr_t addr) +{ + call_active = true; + print_esp_result( + "esp_hf_ag_answer_call", + esp_hf_ag_answer_call( + addr, + 1, + 0, + ESP_HF_CALL_STATUS_CALL_IN_PROGRESS, + ESP_HF_CALL_SETUP_STATUS_IDLE, + test_number, + ESP_HF_CALL_ADDR_TYPE_UNKNOWN + ) + ); + audio_open_at_ms = millis() + INTERCOM_AUDIO_OPEN_DELAY_MS; +} + +static void gap_callback(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) +{ + switch (event) { + case ESP_BT_GAP_AUTH_CMPL_EVT: +#if PILOT_DEBUG_SERIAL + Serial.println(param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS + ? "Intercom emparejado correctamente" + : "ERROR emparejando el intercom"); +#endif + break; + + case ESP_BT_GAP_CFM_REQ_EVT: + esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); + break; + + case ESP_BT_GAP_PIN_REQ_EVT: { + esp_bt_pin_code_t pin = {'0', '0', '0', '0'}; + esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin); + break; + } + + default: + break; + } +} + +static void hfp_callback(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) +{ + switch (event) { + case ESP_HF_PROF_STATE_EVT: + hfp_ready = (param->prof_stat.state == ESP_HF_INIT_SUCCESS || + param->prof_stat.state == ESP_HF_INIT_ALREADY); + if (hfp_ready) { + request_slc_connect(true); + } + break; + + case ESP_HF_CONNECTION_STATE_EVT: { + const esp_hf_connection_state_t state = param->conn_stat.state; + slc_connected = (state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED); + slc_connecting = (state == ESP_HF_CONNECTION_STATE_CONNECTING || + state == ESP_HF_CONNECTION_STATE_CONNECTED); + + if (state == ESP_HF_CONNECTION_STATE_DISCONNECTED) { + slc_connected = false; + slc_connecting = false; + audio_connected = false; + audio_connecting = false; + call_active = false; + call_start_at_ms = 0; + audio_open_at_ms = 0; + microphone_enabled = false; + speaker_clear_requested = true; + stop_hfp_audio_timer(); +#if PILOT_DEBUG_SERIAL + Serial.println("Intercom desconectado. Se reintentara automaticamente."); +#endif + } else if (slc_connected) { + slc_connecting = false; +#if PILOT_DEBUG_SERIAL + Serial.println("Intercom HFP conectado"); +#endif + esp_hf_ag_volume_control(intercom_addr, ESP_HF_VOLUME_CONTROL_TARGET_SPK, 12); + esp_hf_ag_volume_control(intercom_addr, ESP_HF_VOLUME_CONTROL_TARGET_MIC, 15); + call_start_at_ms = millis() + INTERCOM_CALL_DELAY_MS; + } + break; + } + + case ESP_HF_AUDIO_STATE_EVT: { + const esp_hf_audio_state_t state = param->audio_stat.state; + audio_connecting = (state == ESP_HF_AUDIO_STATE_CONNECTING); + audio_connected = (state == ESP_HF_AUDIO_STATE_CONNECTED || + state == ESP_HF_AUDIO_STATE_CONNECTED_MSBC); + codec_msbc = (state == ESP_HF_AUDIO_STATE_CONNECTED_MSBC); + + if (audio_connected) { + audio_connecting = false; + downsample_phase = false; + speaker_clear_requested = true; + esp_hf_ag_register_data_callback(incoming_audio_callback, outgoing_audio_callback); + start_hfp_audio_timer(); +#if PILOT_DEBUG_SERIAL + Serial.printf("Audio del intercom conectado: %s\n", + codec_msbc ? "mSBC 16 kHz" : "CVSD 8 kHz"); +#endif + } else if (state == ESP_HF_AUDIO_STATE_DISCONNECTED) { + audio_connecting = false; + stop_hfp_audio_timer(); +#if PILOT_DEBUG_SERIAL + Serial.println("Audio del intercom desconectado"); +#endif + } + break; + } + + case ESP_HF_IND_UPDATE_EVT: + send_indicator_state(param->ind_upd.remote_addr); + break; + + case ESP_HF_CIND_RESPONSE_EVT: + esp_hf_ag_cind_response( + param->cind_rep.remote_addr, + call_active ? ESP_HF_CALL_STATUS_CALL_IN_PROGRESS : ESP_HF_CALL_STATUS_NO_CALLS, + ESP_HF_CALL_SETUP_STATUS_IDLE, + ESP_HF_NETWORK_STATE_AVAILABLE, + 5, + ESP_HF_ROAMING_STATUS_INACTIVE, + 5, + ESP_HF_CALL_HELD_STATUS_NONE + ); + break; + + case ESP_HF_COPS_RESPONSE_EVT: { + static char operator_name[] = "FormulaGades"; + esp_hf_ag_cops_response(param->cops_rep.remote_addr, operator_name); + break; + } + + case ESP_HF_CLCC_RESPONSE_EVT: + if (call_active) { + esp_hf_ag_clcc_response( + param->clcc_rep.remote_addr, + 1, + ESP_HF_CURRENT_CALL_DIRECTION_OUTGOING, + ESP_HF_CURRENT_CALL_STATUS_ACTIVE, + ESP_HF_CURRENT_CALL_MODE_VOICE, + ESP_HF_CURRENT_CALL_MPTY_TYPE_SINGLE, + test_number, + ESP_HF_CALL_ADDR_TYPE_UNKNOWN + ); + } + esp_hf_ag_clcc_response( + param->clcc_rep.remote_addr, + 0, + ESP_HF_CURRENT_CALL_DIRECTION_OUTGOING, + ESP_HF_CURRENT_CALL_STATUS_ACTIVE, + ESP_HF_CURRENT_CALL_MODE_VOICE, + ESP_HF_CURRENT_CALL_MPTY_TYPE_SINGLE, + test_number, + ESP_HF_CALL_ADDR_TYPE_UNKNOWN + ); + break; + + case ESP_HF_CNUM_RESPONSE_EVT: + esp_hf_ag_cnum_response( + param->cnum_rep.remote_addr, + test_number, + 129, + ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE + ); + break; + + case ESP_HF_ATA_RESPONSE_EVT: + answer_current_call(param->ata_rep.remote_addr); + break; + + case ESP_HF_CHUP_RESPONSE_EVT: + call_active = false; + audio_connected = false; + audio_connecting = false; + stop_hfp_audio_timer(); + break; + + case ESP_HF_DIAL_EVT: + esp_hf_ag_cmee_send( + param->out_call.remote_addr, + ESP_HF_AT_RESPONSE_CODE_OK, + ESP_HF_CME_AG_FAILURE + ); + answer_current_call(param->out_call.remote_addr); + break; + + case ESP_HF_UNAT_RESPONSE_EVT: { + // El V6 Pro+ envia +SUGCODEC=1. Hay que responder OK para completar SLC. + static char ok_response[] = "OK"; + esp_hf_ag_unknown_at_send(param->unat_rep.remote_addr, ok_response); + break; + } + + default: + break; + } +} + +static bool init_bluetooth() +{ + if (mic_buffer == nullptr) { + mic_buffer = xStreamBufferCreate(INTERCOM_MIC_BUFFER_BYTES, 1); + } + if (speaker_buffer == nullptr) { + speaker_buffer = xStreamBufferCreate(INTERCOM_SPEAKER_BUFFER_BYTES, 1); + } + + if (mic_buffer == nullptr || speaker_buffer == nullptr) { +#if PILOT_DEBUG_SERIAL + Serial.println("ERROR creando buffers de audio Bluetooth"); +#endif + return false; + } + + if (!btStarted() && !btStartMode(BT_MODE_CLASSIC_BT)) { +#if PILOT_DEBUG_SERIAL + Serial.println("ERROR iniciando Bluetooth Classic"); +#endif + return false; + } + + if (esp_bredr_tx_power_set(ESP_PWR_LVL_P9, ESP_PWR_LVL_P9) != ESP_OK) { +#if PILOT_DEBUG_SERIAL + Serial.println("ERROR configurando Bluetooth Classic a maxima potencia"); +#endif + return false; + } + + esp_bluedroid_status_t status = esp_bluedroid_get_status(); + if (status == ESP_BLUEDROID_STATUS_UNINITIALIZED) { + if (esp_bluedroid_init() != ESP_OK) { + return false; + } + } + + status = esp_bluedroid_get_status(); + if (status != ESP_BLUEDROID_STATUS_ENABLED) { + if (esp_bluedroid_enable() != ESP_OK) { + return false; + } + } + + if (esp_bt_gap_register_callback(gap_callback) != ESP_OK) { + return false; + } + + esp_bt_io_cap_t io_capability = ESP_BT_IO_CAP_NONE; + esp_bt_gap_set_security_param(ESP_BT_SP_IOCAP_MODE, &io_capability, sizeof(io_capability)); + + esp_bt_pin_code_t unused_pin = {0}; + esp_bt_gap_set_pin(ESP_BT_PIN_TYPE_VARIABLE, 0, unused_pin); + esp_bt_dev_set_device_name(INTERCOM_BT_NAME); + + esp_bt_cod_t cod = {}; + cod.major = ESP_BT_COD_MAJOR_DEV_PHONE; + cod.minor = 0x00; + cod.service = ESP_BT_COD_SRVC_AUDIO | ESP_BT_COD_SRVC_TELEPHONY; + esp_bt_gap_set_cod(cod, ESP_BT_SET_COD_ALL); + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + + if (esp_bredr_sco_datapath_set(ESP_SCO_DATA_PATH_HCI) != ESP_OK) { + return false; + } + if (esp_hf_ag_register_callback(hfp_callback) != ESP_OK) { + return false; + } + if (esp_hf_ag_register_data_callback(incoming_audio_callback, outgoing_audio_callback) != ESP_OK) { + return false; + } + if (esp_hf_ag_init() != ESP_OK) { + return false; + } + + return true; +} + +/* ============================================================ + API USADA POR RADIO_PILOTO + ============================================================ */ + +bool audio_init() +{ + playback_enabled = false; + speaker_clear_requested = true; + microphone_enabled = false; + +#if PILOT_DEBUG_SERIAL + Serial.print("Intercom configurado: "); + print_intercom_mac(); + Serial.println(); +#endif + + return init_bluetooth(); +} + +void audio_process() +{ + const uint32_t now = millis(); + + if (hfp_ready && !slc_connected) { + request_slc_connect(false); + } + + if (slc_connected && call_start_at_ms != 0 && + (int32_t)(now - call_start_at_ms) >= 0) { + call_start_at_ms = 0; + start_fake_call(); + } + + if (slc_connected && call_active && audio_open_at_ms != 0 && + (int32_t)(now - audio_open_at_ms) >= 0) { + audio_open_at_ms = 0; + request_audio_connect(true); + } + + if (slc_connected && call_active && !audio_connected && + (uint32_t)(now - last_audio_attempt_ms) >= INTERCOM_AUDIO_RETRY_MS) { + request_audio_connect(false); + } +} + +void audio_set_microphone_enabled(bool enabled) +{ + microphone_enabled = false; + drain_microphone_buffer(); + downsample_phase = false; + microphone_enabled = enabled; +} + +bool audio_capture_frame(const int8_t **out_audio, uint16_t *out_len) +{ + if (out_audio == nullptr || out_len == nullptr || mic_buffer == nullptr || + !microphone_enabled || !audio_connected) { + return false; + } + + size_t total = 0; + const uint32_t started = millis(); + + while (total < AUDIO_SAMPLES_PER_BLOCK) { + if (!microphone_enabled || !audio_connected) { + return false; + } + + const size_t received = xStreamBufferReceive( + mic_buffer, + mic_frame + total, + AUDIO_SAMPLES_PER_BLOCK - total, + pdMS_TO_TICKS(20) + ); + + total += received; + + if ((uint32_t)(millis() - started) >= INTERCOM_MIC_FRAME_TIMEOUT_MS) { + return false; + } + } + + *out_audio = mic_frame; + *out_len = AUDIO_SAMPLES_PER_BLOCK; + return true; +} + +void audio_play_frame_s8(const int8_t *audio, uint16_t len) +{ + if (audio == nullptr || len == 0 || speaker_buffer == nullptr || + !playback_enabled || !audio_connected) { + return; + } + + if (len > AUDIO_MAX_PAYLOAD) { + len = AUDIO_MAX_PAYLOAD; + } + + const size_t required_bytes = (size_t)len * sizeof(int16_t) * (codec_msbc ? 2U : 1U); + if (xStreamBufferSpacesAvailable(speaker_buffer) < required_bytes) { + return; + } + + constexpr uint16_t INPUT_CHUNK = 160; + int16_t converted[INPUT_CHUNK * 2]; + + uint16_t position = 0; + while (position < len) { + uint16_t chunk = (uint16_t)(len - position); + if (chunk > INPUT_CHUNK) { + chunk = INPUT_CHUNK; + } + + size_t output_samples = 0; + for (uint16_t i = 0; i < chunk; ++i) { + const int16_t sample = (int16_t)((int32_t)audio[position + i] * 256); + converted[output_samples++] = sample; + + if (codec_msbc) { + converted[output_samples++] = sample; + } + } + + const size_t bytes = output_samples * sizeof(int16_t); + const size_t written = xStreamBufferSend( + speaker_buffer, + reinterpret_cast(converted), + bytes, + 0 + ); + + if (written != bytes) { + return; + } + + position = (uint16_t)(position + chunk); + } +} + +void audio_request_playback_stop() +{ + playback_enabled = false; + speaker_clear_requested = true; +} + +void audio_resume_playback() +{ + playback_enabled = true; +} + +void audio_cut_playback() +{ + playback_enabled = false; + speaker_clear_requested = true; +} diff --git a/Radio/Radio_piloto/audio.hpp b/Radio/Radio_piloto/audio.hpp new file mode 100644 index 0000000..23719c7 --- /dev/null +++ b/Radio/Radio_piloto/audio.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +bool audio_init(); +void audio_process(); + +void audio_set_microphone_enabled(bool enabled); +bool audio_capture_frame(const int8_t **out_audio, uint16_t *out_len); + +void audio_play_frame_s8(const int8_t *audio, uint16_t len); +void audio_request_playback_stop(); +void audio_resume_playback(); +void audio_cut_playback(); diff --git a/Radio/Radio_piloto/config.hpp b/Radio/Radio_piloto/config.hpp new file mode 100644 index 0000000..0ee6457 --- /dev/null +++ b/Radio/Radio_piloto/config.hpp @@ -0,0 +1,87 @@ +#pragma once + +#include + +/* ============================================================ + AUDIO DE LA RADIO + + El protocolo de radio sigue usando audio mono de 8 bits a 8 kHz. + El intercom negocia normalmente mSBC a 16 kHz; audio.cpp hace la + conversión sencilla 16 kHz <-> 8 kHz sin aplicar filtros. + ============================================================ */ + +#define AUDIO_SAMPLE_RATE 8000 +#define AUDIO_BLOCK_MS 200 +#define AUDIO_SAMPLES_PER_BLOCK ((AUDIO_SAMPLE_RATE * AUDIO_BLOCK_MS) / 1000) +#define AUDIO_MAX_PAYLOAD AUDIO_SAMPLES_PER_BLOCK + +/* ============================================================ + INTERCOM BLUETOOTH HFP + + ESP32-A1S = Audio Gateway (como un teléfono) + V6 Pro+ = manos libres HFP + ============================================================ */ + +#define INTERCOM_BT_NAME "FORMULA_GADES_HFP" +#define INTERCOM_BT_MAC {0x10, 0xDC, 0xB6, 0x74, 0x2D, 0x23} +#define INTERCOM_SLC_RETRY_MS 5000 +#define INTERCOM_AUDIO_RETRY_MS 3000 +#define INTERCOM_CALL_DELAY_MS 1200 +#define INTERCOM_AUDIO_OPEN_DELAY_MS 600 +#define INTERCOM_MIC_BUFFER_BYTES 6400 +#define INTERCOM_SPEAKER_BUFFER_BYTES 32768 +#define INTERCOM_CVSD_TRIGGER_US 4000 +#define INTERCOM_MSBC_TRIGGER_US 7500 +#define INTERCOM_MIC_FRAME_TIMEOUT_MS 500 + +/* ============================================================ + PTT CON EL BOTON KEY2 DE LA ESP32-AUDIO-KIT + + Switch 1 (IO13-KEY2): ON + Switch 2 (IO13-DATA3): OFF + Switch 4 (IO13-MTCK): OFF + ============================================================ */ + +#define PTT_BUTTON_GPIO GPIO_NUM_13 +#define PTT_BUTTON_ACTIVE_LEVEL LOW +#define PTT_DEBOUNCE_MS 25 +#define PTT_BUTTON_DEBUG 0 + +/* ============================================================ + UART CON EL ESP32-WROOM-32U INTERMEDIARIO + + Audio Kit GPIO23 (TX) -> WROOM-U GPIO16 (RX) + Audio Kit GPIO22 (RX) <- WROOM-U GPIO17 (TX) + GND Audio Kit <-> GND WROOM-U + ============================================================ */ + +#define PILOT_UART_PORT 2 +#define PILOT_UART_BAUD 460800 +#define PILOT_UART_RX_GPIO 22 +#define PILOT_UART_TX_GPIO 23 +#define PILOT_UART_RX_BUFFER_SIZE 8192 +#define PILOT_UART_PACKET_QUEUE_SIZE 32 +#define PILOT_UART_TASK_STACK 4096 +#define PILOT_UART_TASK_PRIORITY 4 +#define PILOT_UART_TASK_CORE 1 +#define PILOT_UART_PARSER_TIMEOUT_MS 120 +#define PILOT_UART_WRITE_TIMEOUT_MS 120 + +#define PILOT_TX_TASK_STACK 6144 +#define PILOT_TX_TASK_PRIORITY 3 +#define PILOT_TX_TASK_CORE 1 + +#define RADIO_AUDIO_CHUNK 200 +#define RADIO_PACKET_HEADER_LEN 11 +#define RADIO_PACKET_MAX_LEN (RADIO_PACKET_HEADER_LEN + RADIO_AUDIO_CHUNK) +#define RADIO_REASSEMBLY_TIMEOUT_MS 600 +#define BOX_AUDIO_AUTOSTART_GUARD_MS 150 + +#define RADIO_AUDIO_MAGIC_1 0xE5 +#define RADIO_AUDIO_MAGIC_2 0x5E +#define RADIO_CONTROL_MAGIC_1 0xE5 +#define RADIO_CONTROL_MAGIC_2 0x5F +#define RADIO_CONTROL_COMMAND_BOX_PTT 0x01 +#define RADIO_CONTROL_PACKET_LEN 4 + +#define PILOT_DEBUG_SERIAL 1 diff --git a/Radio/Radio_piloto/ptt.cpp b/Radio/Radio_piloto/ptt.cpp new file mode 100644 index 0000000..8bb5e73 --- /dev/null +++ b/Radio/Radio_piloto/ptt.cpp @@ -0,0 +1,62 @@ +#include "ptt.hpp" +#include "config.hpp" + +#include + +static bool stable_pressed = false; +static bool last_raw_pressed = false; +static uint32_t last_raw_change_ms = 0; + +bool ptt_init() +{ + // KEY2 no lleva resistencia pull-up externa, por lo que activamos + // la pull-up interna. Al pulsar KEY2, GPIO13 queda conectado a GND. + pinMode(PTT_BUTTON_GPIO, INPUT_PULLUP); + delay(10); + + last_raw_pressed = + (digitalRead(PTT_BUTTON_GPIO) == PTT_BUTTON_ACTIVE_LEVEL); + stable_pressed = last_raw_pressed; + last_raw_change_ms = millis(); + +#if PILOT_DEBUG_SERIAL + Serial.println("PTT configurado en KEY2 (GPIO13, activo a nivel LOW)"); + Serial.println("DIP: 1=ON, 2=OFF y 4=OFF para usar KEY2 sin conflictos"); +#endif + + return true; +} + +bool ptt_is_pressed() +{ + const bool raw_pressed = + (digitalRead(PTT_BUTTON_GPIO) == PTT_BUTTON_ACTIVE_LEVEL); + + // Reinicia el temporizador cada vez que cambia la lectura instantanea. + if (raw_pressed != last_raw_pressed) { + last_raw_pressed = raw_pressed; + last_raw_change_ms = millis(); + } + + // Solo acepta el nuevo estado cuando se mantiene estable el tiempo + // indicado. Esto elimina los rebotes mecanicos del pulsador. + if (stable_pressed != last_raw_pressed && + (uint32_t)(millis() - last_raw_change_ms) >= PTT_DEBOUNCE_MS) { + stable_pressed = last_raw_pressed; + +#if PILOT_DEBUG_SERIAL + Serial.println(stable_pressed + ? "PTT KEY2 ACTIVADO" + : "PTT KEY2 DESACTIVADO"); +#endif + } + +#if PTT_BUTTON_DEBUG + Serial.print("KEY2 raw="); + Serial.print(raw_pressed ? "PULSADO" : "LIBRE"); + Serial.print(" estable="); + Serial.println(stable_pressed ? "PULSADO" : "LIBRE"); +#endif + + return stable_pressed; +} diff --git a/Radio/Radio_piloto/ptt.hpp b/Radio/Radio_piloto/ptt.hpp new file mode 100644 index 0000000..551fc12 --- /dev/null +++ b/Radio/Radio_piloto/ptt.hpp @@ -0,0 +1,4 @@ +#pragma once + +bool ptt_init(); +bool ptt_is_pressed(); diff --git a/Radio/Radio_piloto/uart_audio.cpp b/Radio/Radio_piloto/uart_audio.cpp new file mode 100644 index 0000000..dcd1920 --- /dev/null +++ b/Radio/Radio_piloto/uart_audio.cpp @@ -0,0 +1,679 @@ +#include "uart_audio.hpp" +#include "audio.hpp" +#include "config.hpp" + +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" + +struct __attribute__((packed)) AudioWirePacket { + uint8_t magic1; + uint8_t magic2; + uint8_t frame_seq; + uint8_t chunk_index; + uint8_t chunk_total; + uint16_t frame_len; + uint16_t offset; + uint16_t chunk_len; + int8_t audio[RADIO_AUDIO_CHUNK]; +}; + +struct UartRxItem { + uint32_t epoch; + uint16_t packet_len; + uint8_t packet[RADIO_PACKET_MAX_LEN]; +}; + +static constexpr size_t AUDIO_HEADER_SIZE = offsetof(AudioWirePacket, audio); +static constexpr uint8_t MAX_AUDIO_CHUNKS = + (AUDIO_MAX_PAYLOAD + RADIO_AUDIO_CHUNK - 1) / RADIO_AUDIO_CHUNK; + +static HardwareSerial PilotUart(PILOT_UART_PORT); +static QueueHandle_t rx_packet_queue = nullptr; +static TaskHandle_t rx_task_handle = nullptr; + +static portMUX_TYPE state_mux = portMUX_INITIALIZER_UNLOCKED; +static volatile bool box_ptt_active = false; +static volatile bool box_stop_pending = false; +static volatile uint32_t box_stream_epoch = 0; +static volatile uint32_t box_control_version = 0; +static volatile uint32_t dropped_uart_packets = 0; +static volatile uint32_t box_last_stop_ms = 0; + +static volatile uint32_t debug_control_start = 0; +static volatile uint32_t debug_control_stop = 0; +static volatile uint32_t debug_audio_packets = 0; +static volatile uint32_t debug_reassembled_frames = 0; +static volatile uint32_t debug_audio_autostarts = 0; +static volatile uint32_t debug_guard_drops = 0; + +static int8_t reassembly_buffer[AUDIO_MAX_PAYLOAD]; +static bool chunk_received[MAX_AUDIO_CHUNKS]; +static bool reassembly_active = false; +static uint8_t reassembly_seq = 0; +static uint8_t reassembly_total_chunks = 0; +static uint8_t reassembly_received_chunks = 0; +static uint16_t reassembly_frame_len = 0; +static uint32_t reassembly_epoch = 0; +static uint32_t reassembly_started_ms = 0; + +static uint16_t read_le_u16(const uint8_t *p) +{ + return (uint16_t)p[0] | ((uint16_t)p[1] << 8); +} + +static bool audio_packet_valid(const uint8_t *data, uint16_t len) +{ + if (data == nullptr || len < RADIO_PACKET_HEADER_LEN || len > RADIO_PACKET_MAX_LEN) { + return false; + } + + if (data[0] != RADIO_AUDIO_MAGIC_1 || data[1] != RADIO_AUDIO_MAGIC_2) { + return false; + } + + const uint8_t chunk_index = data[3]; + const uint8_t chunk_total = data[4]; + const uint16_t frame_len = read_le_u16(&data[5]); + const uint16_t offset = read_le_u16(&data[7]); + const uint16_t chunk_len = read_le_u16(&data[9]); + + if (chunk_total == 0 || chunk_total > MAX_AUDIO_CHUNKS) { + return false; + } + + if (chunk_index >= chunk_total) { + return false; + } + + if (frame_len == 0 || frame_len > AUDIO_MAX_PAYLOAD) { + return false; + } + + if (chunk_len == 0 || chunk_len > RADIO_AUDIO_CHUNK) { + return false; + } + + if ((uint32_t)offset + chunk_len > frame_len) { + return false; + } + + return len == RADIO_PACKET_HEADER_LEN + chunk_len; +} + +static bool control_packet_valid(const uint8_t *data, uint16_t len) +{ + return data != nullptr && + len == RADIO_CONTROL_PACKET_LEN && + data[0] == RADIO_CONTROL_MAGIC_1 && + data[1] == RADIO_CONTROL_MAGIC_2 && + data[2] == RADIO_CONTROL_COMMAND_BOX_PTT && + (data[3] == 0 || data[3] == 1); +} + +static void snapshot_control_state( + bool *active, + bool *stop_pending, + uint32_t *epoch, + uint32_t *version) +{ + portENTER_CRITICAL(&state_mux); + if (active != nullptr) { + *active = box_ptt_active; + } + if (stop_pending != nullptr) { + *stop_pending = box_stop_pending; + } + if (epoch != nullptr) { + *epoch = box_stream_epoch; + } + if (version != nullptr) { + *version = box_control_version; + } + portEXIT_CRITICAL(&state_mux); +} + +static void handle_control_packet(const uint8_t *packet) +{ + const bool start_requested = packet[3] != 0; + const uint32_t now = millis(); + bool started = false; + bool stop_registered = false; + + portENTER_CRITICAL(&state_mux); + + if (start_requested) { + // Los START periódicos son latidos. No cambian el epoch si el stream ya + // está activo. También cancelan un cierre pendiente si vuelve a pulsarse. + if (!box_ptt_active) { + box_ptt_active = true; + ++box_stream_epoch; + ++box_control_version; + started = true; + } + box_stop_pending = false; + } else { + box_last_stop_ms = now; + if (box_ptt_active && !box_stop_pending) { + // No cortar todavía: todos los paquetes anteriores al STOP ya están + // en la cola UART y deben reconstruirse/reproducirse primero. + box_stop_pending = true; + stop_registered = true; + } + } + + portEXIT_CRITICAL(&state_mux); + + if (started) { + ++debug_control_start; + audio_resume_playback(); + } + + if (stop_registered) { + ++debug_control_stop; + } +} + +static void enqueue_audio_packet(const uint8_t *packet, uint16_t len) +{ + if (rx_packet_queue == nullptr || !audio_packet_valid(packet, len)) { + return; + } + + bool active = false; + bool stop_pending = false; + uint32_t epoch = 0; + snapshot_control_state(&active, &stop_pending, &epoch, nullptr); + + if (stop_pending) { + ++debug_guard_drops; + return; + } + + if (!active) { + const uint32_t now = millis(); + uint32_t last_stop = 0; + + portENTER_CRITICAL(&state_mux); + last_stop = box_last_stop_ms; + portEXIT_CRITICAL(&state_mux); + + // Si acaba de llegar STOP, estos pueden ser fragmentos atrasados y se + // descartan. Pasado el margen, un paquete de audio válido puede recuperar + // por sí solo un START perdido o un reinicio del Audio Kit. + if ((uint32_t)(now - last_stop) < BOX_AUDIO_AUTOSTART_GUARD_MS) { + ++debug_guard_drops; + return; + } + + portENTER_CRITICAL(&state_mux); + if (!box_ptt_active) { + box_ptt_active = true; + box_stop_pending = false; + ++box_stream_epoch; + ++box_control_version; + ++debug_audio_autostarts; + } + active = box_ptt_active; + epoch = box_stream_epoch; + portEXIT_CRITICAL(&state_mux); + + if (active) { + audio_resume_playback(); + } + } + + ++debug_audio_packets; + + UartRxItem item = {}; + item.epoch = epoch; + item.packet_len = len; + memcpy(item.packet, packet, len); + + if (xQueueSend(rx_packet_queue, &item, 0) != pdTRUE) { + // Mantener audio reciente es preferible a acumular retraso. Si la cola + // se llena, eliminamos el paquete más antiguo e insertamos el nuevo. + UartRxItem discarded = {}; + xQueueReceive(rx_packet_queue, &discarded, 0); + + if (xQueueSend(rx_packet_queue, &item, 0) != pdTRUE) { + ++dropped_uart_packets; + } + } +} + +static void uart_rx_task(void *parameter) +{ + (void)parameter; + + enum ParserState { + WAIT_MAGIC_1, + WAIT_MAGIC_2, + READ_AUDIO_HEADER, + READ_AUDIO_BODY, + READ_CONTROL + }; + + ParserState state = WAIT_MAGIC_1; + uint8_t packet[RADIO_PACKET_MAX_LEN] = {}; + size_t index = 0; + uint16_t expected_audio_len = 0; + uint32_t last_byte_ms = millis(); + + auto reset_parser = [&]() { + state = WAIT_MAGIC_1; + index = 0; + expected_audio_len = 0; + }; + + for (;;) { + bool read_anything = false; + + while (PilotUart.available() > 0) { + const int value = PilotUart.read(); + if (value < 0) { + break; + } + + read_anything = true; + const uint8_t b = (uint8_t)value; + const uint32_t now = millis(); + + if (state != WAIT_MAGIC_1 && + (uint32_t)(now - last_byte_ms) > PILOT_UART_PARSER_TIMEOUT_MS) { + reset_parser(); + } + last_byte_ms = now; + + switch (state) { + case WAIT_MAGIC_1: + if (b == RADIO_AUDIO_MAGIC_1) { + packet[0] = b; + index = 1; + state = WAIT_MAGIC_2; + } + break; + + case WAIT_MAGIC_2: + if (b == RADIO_AUDIO_MAGIC_2) { + packet[1] = b; + index = 2; + state = READ_AUDIO_HEADER; + } else if (b == RADIO_CONTROL_MAGIC_2) { + packet[1] = b; + index = 2; + state = READ_CONTROL; + } else if (b == RADIO_AUDIO_MAGIC_1) { + packet[0] = b; + index = 1; + } else { + reset_parser(); + } + break; + + case READ_CONTROL: + if (index >= sizeof(packet)) { + reset_parser(); + break; + } + + packet[index++] = b; + if (index >= RADIO_CONTROL_PACKET_LEN) { + if (control_packet_valid(packet, (uint16_t)index)) { + handle_control_packet(packet); + } + reset_parser(); + } + break; + + case READ_AUDIO_HEADER: + if (index >= sizeof(packet)) { + reset_parser(); + break; + } + + packet[index++] = b; + if (index >= RADIO_PACKET_HEADER_LEN) { + const uint16_t frame_len = read_le_u16(&packet[5]); + const uint16_t offset = read_le_u16(&packet[7]); + expected_audio_len = read_le_u16(&packet[9]); + + if (packet[4] == 0 || packet[4] > MAX_AUDIO_CHUNKS || + packet[3] >= packet[4] || + frame_len == 0 || frame_len > AUDIO_MAX_PAYLOAD || + expected_audio_len == 0 || expected_audio_len > RADIO_AUDIO_CHUNK || + (uint32_t)offset + expected_audio_len > frame_len) { + reset_parser(); + break; + } + + state = READ_AUDIO_BODY; + } + break; + + case READ_AUDIO_BODY: + if (index >= sizeof(packet)) { + reset_parser(); + break; + } + + packet[index++] = b; + if (index >= RADIO_PACKET_HEADER_LEN + expected_audio_len) { + enqueue_audio_packet(packet, (uint16_t)index); + reset_parser(); + } + break; + } + } + + if (!read_anything) { + vTaskDelay(pdMS_TO_TICKS(1)); + } else { + taskYIELD(); + } + } +} + +static bool uart_write_all(const uint8_t *data, size_t len) +{ + if (data == nullptr || len == 0) { + return false; + } + + size_t sent = 0; + const uint32_t started = millis(); + + while (sent < len) { + const size_t written = PilotUart.write(data + sent, len - sent); + sent += written; + + if (sent >= len) { + return true; + } + + if ((uint32_t)(millis() - started) >= PILOT_UART_WRITE_TIMEOUT_MS) { + return false; + } + + delay(0); + } + + return true; +} + +static void reset_reassembly(uint8_t seq, uint8_t total_chunks, uint16_t frame_len, uint32_t epoch) +{ + reassembly_active = true; + reassembly_seq = seq; + reassembly_total_chunks = total_chunks; + reassembly_received_chunks = 0; + reassembly_frame_len = frame_len; + reassembly_epoch = epoch; + reassembly_started_ms = millis(); + memset(chunk_received, 0, sizeof(chunk_received)); +} + +bool uart_audio_init() +{ + rx_packet_queue = xQueueCreate( + PILOT_UART_PACKET_QUEUE_SIZE, + sizeof(UartRxItem) + ); + + if (rx_packet_queue == nullptr) { +#if PILOT_DEBUG_SERIAL + Serial.println("ERROR: no se pudo crear la cola UART de audio"); +#endif + return false; + } + + // Debe configurarse antes de begin(), según la API HardwareSerial del ESP32. + PilotUart.setRxBufferSize(PILOT_UART_RX_BUFFER_SIZE); + PilotUart.begin( + PILOT_UART_BAUD, + SERIAL_8N1, + PILOT_UART_RX_GPIO, + PILOT_UART_TX_GPIO + ); + + const BaseType_t task_result = xTaskCreatePinnedToCore( + uart_rx_task, + "pilot_uart_rx", + PILOT_UART_TASK_STACK, + nullptr, + PILOT_UART_TASK_PRIORITY, + &rx_task_handle, + PILOT_UART_TASK_CORE + ); + + if (task_result != pdPASS) { +#if PILOT_DEBUG_SERIAL + Serial.println("ERROR: no se pudo crear la tarea UART"); +#endif + rx_task_handle = nullptr; + return false; + } + +#if PILOT_DEBUG_SERIAL + Serial.println("UART con intermediario iniciada"); + Serial.printf("Baudios: %d | RX GPIO%d | TX GPIO%d\n", + PILOT_UART_BAUD, + PILOT_UART_RX_GPIO, + PILOT_UART_TX_GPIO); +#endif + + return true; +} + +bool uart_send_audio(uint8_t frame_seq, const int8_t *audio_data, uint16_t audio_len) +{ + if (audio_data == nullptr || audio_len == 0 || audio_len > AUDIO_MAX_PAYLOAD) { + return false; + } + + const uint8_t total_chunks = + (uint8_t)((audio_len + RADIO_AUDIO_CHUNK - 1) / RADIO_AUDIO_CHUNK); + + for (uint8_t chunk_index = 0; chunk_index < total_chunks; ++chunk_index) { + const uint16_t offset = (uint16_t)chunk_index * RADIO_AUDIO_CHUNK; + const uint16_t remaining = (uint16_t)(audio_len - offset); + const uint16_t chunk_len = remaining > RADIO_AUDIO_CHUNK + ? RADIO_AUDIO_CHUNK + : remaining; + + AudioWirePacket packet = {}; + packet.magic1 = RADIO_AUDIO_MAGIC_1; + packet.magic2 = RADIO_AUDIO_MAGIC_2; + packet.frame_seq = frame_seq; + packet.chunk_index = chunk_index; + packet.chunk_total = total_chunks; + packet.frame_len = audio_len; + packet.offset = offset; + packet.chunk_len = chunk_len; + memcpy(packet.audio, audio_data + offset, chunk_len); + + const size_t packet_size = AUDIO_HEADER_SIZE + chunk_len; + if (!uart_write_all(reinterpret_cast(&packet), packet_size)) { +#if PILOT_DEBUG_SERIAL + Serial.printf("ERROR UART enviando fragmento %u/%u\n", + (unsigned)chunk_index, + (unsigned)total_chunks); +#endif + return false; + } + } + + return true; +} + +void uart_discard_received_audio() +{ + if (rx_packet_queue != nullptr) { + UartRxItem discarded = {}; + while (xQueueReceive(rx_packet_queue, &discarded, 0) == pdTRUE) { + } + } + + reassembly_active = false; + reassembly_received_chunks = 0; + memset(chunk_received, 0, sizeof(chunk_received)); +} + +static bool finalize_box_stop_if_drained() +{ + if (rx_packet_queue == nullptr || uxQueueMessagesWaiting(rx_packet_queue) != 0 || reassembly_active) { + return false; + } + + bool changed = false; + + portENTER_CRITICAL(&state_mux); + if (box_stop_pending && box_ptt_active) { + box_stop_pending = false; + box_ptt_active = false; + ++box_stream_epoch; + ++box_control_version; + changed = true; + } + portEXIT_CRITICAL(&state_mux); + + return changed; +} + +bool uart_box_ptt_active() +{ + bool active = false; + snapshot_control_state(&active, nullptr, nullptr, nullptr); + return active; +} + +void uart_process_received_audio(bool reproduce) +{ + static uint32_t processed_control_version = 0; + + bool active = false; + uint32_t current_epoch = 0; + uint32_t current_version = 0; + snapshot_control_state(&active, nullptr, ¤t_epoch, ¤t_version); + + if (current_version != processed_control_version) { + processed_control_version = current_version; + reassembly_active = false; + reassembly_received_chunks = 0; + memset(chunk_received, 0, sizeof(chunk_received)); + + if (!active) { + uart_discard_received_audio(); + // El último frame ya se escribió al I2S. Se solicita el cierre sin + // vaciarlo, y el silencio final se añade tras el timeout normal. + audio_request_playback_stop(); + } else if (reproduce) { + audio_resume_playback(); + } + } + + if (!reproduce || !active) { + uart_discard_received_audio(); + return; + } + + if (reassembly_active && + (uint32_t)(millis() - reassembly_started_ms) > RADIO_REASSEMBLY_TIMEOUT_MS) { + reassembly_active = false; + } + + UartRxItem item = {}; + while (rx_packet_queue != nullptr && + xQueueReceive(rx_packet_queue, &item, 0) == pdTRUE) { + + snapshot_control_state(&active, nullptr, ¤t_epoch, nullptr); + + if (!active || item.epoch != current_epoch) { + continue; + } + + if (!audio_packet_valid(item.packet, item.packet_len)) { + continue; + } + + AudioWirePacket packet = {}; + memcpy(&packet, item.packet, item.packet_len); + + if (!reassembly_active || + reassembly_epoch != item.epoch || + packet.frame_seq != reassembly_seq || + packet.chunk_total != reassembly_total_chunks || + packet.frame_len != reassembly_frame_len) { + reset_reassembly( + packet.frame_seq, + packet.chunk_total, + packet.frame_len, + item.epoch + ); + } + + if (!chunk_received[packet.chunk_index]) { + memcpy( + reassembly_buffer + packet.offset, + packet.audio, + packet.chunk_len + ); + chunk_received[packet.chunk_index] = true; + ++reassembly_received_chunks; + } + + if (reassembly_received_chunks >= reassembly_total_chunks) { + ++debug_reassembled_frames; + audio_play_frame_s8(reassembly_buffer, reassembly_frame_len); + reassembly_active = false; + } + } + + // STOP se aplica únicamente cuando ya no queda ningún paquete ni un frame + // incompleto. Así los auriculares reproducen el final completo del mensaje. + if (finalize_box_stop_if_drained()) { + audio_request_playback_stop(); + } +} + +void uart_audio_debug_report() +{ +#if PILOT_DEBUG_SERIAL + static uint32_t last_report_ms = 0; + const uint32_t now = millis(); + + if ((uint32_t)(now - last_report_ms) < 1000) { + return; + } + last_report_ms = now; + + bool active = false; + bool stop_pending = false; + uint32_t epoch = 0; + uint32_t version = 0; + snapshot_control_state(&active, &stop_pending, &epoch, &version); + + const UBaseType_t queued = + rx_packet_queue != nullptr ? uxQueueMessagesWaiting(rx_packet_queue) : 0; + + Serial.printf( + "PILOTO BOX->INTERCOM: PTT=%s cierre_pendiente=%s ctrlON=%lu ctrlOFF=%lu paquetes=%lu frames=%lu autoSTART=%lu guard=%lu cola=%u drop=%lu epoch=%lu version=%lu\n", + active ? "ON" : "OFF", + stop_pending ? "SI" : "NO", + (unsigned long)debug_control_start, + (unsigned long)debug_control_stop, + (unsigned long)debug_audio_packets, + (unsigned long)debug_reassembled_frames, + (unsigned long)debug_audio_autostarts, + (unsigned long)debug_guard_drops, + (unsigned int)queued, + (unsigned long)dropped_uart_packets, + (unsigned long)epoch, + (unsigned long)version + ); +#endif +} diff --git a/Radio/Radio_piloto/uart_audio.hpp b/Radio/Radio_piloto/uart_audio.hpp new file mode 100644 index 0000000..ba7ab04 --- /dev/null +++ b/Radio/Radio_piloto/uart_audio.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +bool uart_audio_init(); +bool uart_send_audio(uint8_t frame_seq, const int8_t *audio_data, uint16_t audio_len); +void uart_process_received_audio(bool reproduce); +void uart_discard_received_audio(); +bool uart_box_ptt_active(); +void uart_audio_debug_report(); diff --git a/Radio/Radio_receptor/Radio_receptor.ino b/Radio/Radio_receptor/Radio_receptor.ino new file mode 100644 index 0000000..6a42627 --- /dev/null +++ b/Radio/Radio_receptor/Radio_receptor.ino @@ -0,0 +1,50 @@ +#include +#include "espnow.hpp" + +void setup() +{ + // UART USB con el PC. + // IMPORTANTE: tiene que coincidir con el baudrate del programa de Windows. + // Buffer grande para que no se pierdan bytes cuando el PC envia audio por UART. + Serial.setRxBufferSize(4096); + Serial.begin(115200); + delay(1000); + +#if DEBUG_SERIAL + Serial.println(); + Serial.println("================================"); + Serial.println(" Puente UART <-> ESP-NOW LR"); + Serial.println("================================"); +#endif + + if (!init_espnow_puente_bidir()) { +#if DEBUG_SERIAL + Serial.println("FALLO: no se pudo iniciar ESP-NOW bidireccional"); +#endif + while (true) { + delay(1000); + } + } + +#if DEBUG_SERIAL + Serial.println("Puente listo: PC <-> UART <-> ESP-NOW LR"); +#endif +} + +void loop() +{ + static bool pilot_first = true; + + // Cada funcion procesa un numero limitado de paquetes. Ademas se alterna + // el orden para que ninguno de los dos sentidos monopolice el loop. + if (pilot_first) { + procesar_espnow_y_enviar_pc(); + procesar_uart_y_enviar_espnow(); + } else { + procesar_uart_y_enviar_espnow(); + procesar_espnow_y_enviar_pc(); + } + + pilot_first = !pilot_first; + delay(0); +} diff --git a/Radio/Radio_receptor/espnow.cpp b/Radio/Radio_receptor/espnow.cpp new file mode 100644 index 0000000..9d3fe46 --- /dev/null +++ b/Radio/Radio_receptor/espnow.cpp @@ -0,0 +1,439 @@ +#include "espnow.hpp" + +#include +#include +#include +#include + +#define ESPNOW_CHANNEL 1 + +// Potencia en cuartos de dBm: 84 = 21 dBm teorico. + // OJO: no todos los ESP32/modulos llegan a 21 dBm; si el driver no lo acepta, lo limita/falla. + // Con antenas externas hay que respetar la potencia EIRP legal del evento/pais. +#define ESPNOW_TX_POWER_QDBM 84 + +// MAC WiFi STA FIJA del ESP32-WROOM-32U INTERMEDIARIO del piloto. +// CAMBIAR OBLIGATORIAMENTE por la MAC que imprime el intermediario. +// Ejemplo: 7C:DF:A1:12:34:56 -> {0x7C, 0xDF, 0xA1, 0x12, 0x34, 0x56} +static const uint8_t ESPNOW_PEER_INTERMEDIARIO_MAC[6] = { + 0x28, 0x05, 0xA5, 0xE1, 0xCF, 0x90 +}; + +static volatile bool espnow_send_busy = false; +static volatile bool espnow_last_send_ok = false; + +#define ESPNOW_SEND_RETRIES 3 +#define ESPNOW_SEND_TIMEOUT_MS 35 + +/* ========================= + COLA ESP-NOW RX -> PC + ========================= */ + +// IMPORTANTE: +// No conviene hacer Serial.write() dentro del callback de ESP-NOW. A 115200 baudios, +// escribir un chunk de ~211 bytes puede bloquear unos 18 ms. Eso puede hacer que se +// pierdan paquetes ESP-NOW que llegan justo despues. Por eso el callback solo copia +// el paquete a esta cola y el loop() lo manda al PC. +#define ESPNOW_RX_QUEUE_SIZE 64 + +static uint8_t rx_queue[ESPNOW_RX_QUEUE_SIZE][ESPNOW_PACKET_MAX_LEN]; +static uint16_t rx_queue_len[ESPNOW_RX_QUEUE_SIZE]; +static volatile uint8_t rx_queue_head = 0; +static volatile uint8_t rx_queue_tail = 0; +static volatile uint32_t rx_queue_dropped = 0; + +static uint16_t read_le_u16(const uint8_t* p) +{ + return (uint16_t)p[0] | ((uint16_t)p[1] << 8); +} + +static bool mac_is_zero(const uint8_t* mac) +{ + static const uint8_t zero[6] = {0, 0, 0, 0, 0, 0}; + return memcmp(mac, zero, 6) == 0; +} + +static bool paquete_audio_valido(const uint8_t* data, int len) +{ + if (data == nullptr || len < ESPNOW_PACKET_HEADER_LEN || len > ESPNOW_PACKET_MAX_LEN) { + return false; + } + + if (data[0] != 0xE5 || data[1] != 0x5E) { + return false; + } + + uint8_t chunk_index = data[3]; + uint8_t chunk_total = data[4]; + uint16_t frame_len = read_le_u16(&data[5]); + uint16_t offset = read_le_u16(&data[7]); + uint16_t chunk_len = read_le_u16(&data[9]); + + if (chunk_total == 0 || chunk_total > 16) { + return false; + } + + if (chunk_index >= chunk_total) { + return false; + } + + if (frame_len == 0 || frame_len > 2000) { + return false; + } + + if (chunk_len == 0 || chunk_len > ESPNOW_AUDIO_CHUNK) { + return false; + } + + if ((uint32_t)offset + (uint32_t)chunk_len > (uint32_t)frame_len) { + return false; + } + + if (len != (int)ESPNOW_PACKET_HEADER_LEN + (int)chunk_len) { + return false; + } + + return true; +} + +static bool paquete_control_valido(const uint8_t* data, int len) +{ + return data != nullptr && + len == RADIO_CONTROL_PACKET_LEN && + data[0] == RADIO_CONTROL_MAGIC_1 && + data[1] == RADIO_CONTROL_MAGIC_2 && + data[2] == RADIO_CONTROL_COMMAND_BOX_PTT && + (data[3] == 0 || data[3] == 1); +} + +static bool paquete_radio_valido(const uint8_t* data, int len) +{ + return paquete_audio_valido(data, len) || paquete_control_valido(data, len); +} + +static bool ensure_peer_registered(const uint8_t* mac) +{ + if (mac == nullptr || mac_is_zero(mac)) { + return false; + } + + if (esp_now_is_peer_exist(mac)) { + return true; + } + + esp_now_peer_info_t peerInfo = {}; + memcpy(peerInfo.peer_addr, mac, 6); + peerInfo.channel = ESPNOW_CHANNEL; + peerInfo.ifidx = WIFI_IF_STA; + peerInfo.encrypt = false; + + return esp_now_add_peer(&peerInfo) == ESP_OK; +} + +// Arduino-ESP32 3.x usa esta firma para el callback de envio. +// Antes era: const uint8_t* mac_addr. +static void on_espnow_sent(const wifi_tx_info_t* tx_info, esp_now_send_status_t status) +{ + (void)tx_info; + espnow_last_send_ok = (status == ESP_NOW_SEND_SUCCESS); + espnow_send_busy = false; +} + +// ESP-NOW -> cola -> UART/USB -> PC +static void on_espnow_recv(const esp_now_recv_info_t* info, const uint8_t* data, int len) +{ + if (!paquete_audio_valido(data, len)) { + return; + } + + // Configuracion de peer fija: ignorar paquetes que no vengan del WROOM-U intermediario. + if (info == nullptr || info->src_addr == nullptr || + memcmp(info->src_addr, ESPNOW_PEER_INTERMEDIARIO_MAC, 6) != 0) { + return; + } + + uint8_t next_head = (uint8_t)((rx_queue_head + 1) % ESPNOW_RX_QUEUE_SIZE); + + if (next_head == rx_queue_tail) { + rx_queue_dropped++; + return; + } + + memcpy(rx_queue[rx_queue_head], data, len); + rx_queue_len[rx_queue_head] = (uint16_t)len; + rx_queue_head = next_head; +} + +static bool pop_espnow_rx_packet(uint8_t* out_packet, uint16_t* out_len) +{ + if (rx_queue_tail == rx_queue_head) { + return false; + } + + uint8_t index = rx_queue_tail; + + memcpy(out_packet, rx_queue[index], rx_queue_len[index]); + *out_len = rx_queue_len[index]; + + rx_queue_tail = (uint8_t)((rx_queue_tail + 1) % ESPNOW_RX_QUEUE_SIZE); + return true; +} + +static bool enviar_paquete_espnow(const uint8_t* data, size_t len) +{ + if (!paquete_radio_valido(data, (int)len)) { + return false; + } + + if (!ensure_peer_registered(ESPNOW_PEER_INTERMEDIARIO_MAC)) { + return false; + } + + // Reintentos cortos: a larga distancia algun paquete puede fallar. + // No reintentamos infinito para no meter retraso enorme al audio. + for (uint8_t intento = 0; intento < ESPNOW_SEND_RETRIES; intento++) { + + uint32_t inicio_busy = millis(); + while (espnow_send_busy && (millis() - inicio_busy) < ESPNOW_SEND_TIMEOUT_MS) { + delay(1); + } + + if (espnow_send_busy) { + espnow_send_busy = false; + } + + espnow_last_send_ok = false; + espnow_send_busy = true; + + esp_err_t err = esp_now_send(ESPNOW_PEER_INTERMEDIARIO_MAC, data, len); + + if (err != ESP_OK) { + espnow_send_busy = false; +#if DEBUG_SERIAL + Serial.print("ERROR esp_now_send: "); + Serial.println((int)err); +#endif + delay(1); + continue; + } + + uint32_t inicio_ack = millis(); + while (espnow_send_busy && (millis() - inicio_ack) < ESPNOW_SEND_TIMEOUT_MS) { + delay(1); + } + + if (!espnow_send_busy && espnow_last_send_ok) { + return true; + } + + delay(1); + } + + return false; +} + +bool init_espnow_puente_bidir() +{ + // 1. Modo WiFi Station para poder usar ESP-NOW. + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + WiFi.setSleep(false); + + // 2. Sin ahorro de energia para reducir latencia/cortes. + esp_wifi_set_ps(WIFI_PS_NONE); + + // 3. Potencia de transmision alta. + esp_wifi_set_max_tx_power(ESPNOW_TX_POWER_QDBM); + + // 4. Activar protocolos WiFi, incluido Long Range. + esp_wifi_set_protocol( + WIFI_IF_STA, + WIFI_PROTOCOL_11B | + WIFI_PROTOCOL_11G | + WIFI_PROTOCOL_11N | + WIFI_PROTOCOL_LR + ); + + // 5. Fijar canal. El otro ESP-NOW tiene que usar el mismo canal. + esp_wifi_set_channel(ESPNOW_CHANNEL, WIFI_SECOND_CHAN_NONE); + + // 6. Iniciar ESP-NOW. + if (esp_now_init() != ESP_OK) { +#if DEBUG_SERIAL + Serial.println("ERROR: no se pudo iniciar ESP-NOW"); +#endif + return false; + } + + // 7. Callback de envio: libera la bandera espnow_send_busy. + if (esp_now_register_send_cb(on_espnow_sent) != ESP_OK) { +#if DEBUG_SERIAL + Serial.println("ERROR: no se pudo registrar callback de envio ESP-NOW"); +#endif + return false; + } + + // 8. Callback de recepcion: ESP-NOW -> cola. El loop lo manda al PC. + if (esp_now_register_recv_cb(on_espnow_recv) != ESP_OK) { +#if DEBUG_SERIAL + Serial.println("ERROR: no se pudo registrar callback de recepcion ESP-NOW"); +#endif + return false; + } + + // 9. Registrar la MAC fija del WROOM-U intermediario. + if (!ensure_peer_registered(ESPNOW_PEER_INTERMEDIARIO_MAC)) { +#if DEBUG_SERIAL + Serial.println("ERROR: configura ESPNOW_PEER_INTERMEDIARIO_MAC con la MAC real del WROOM-U"); +#endif + return false; + } + +#if DEBUG_SERIAL + int8_t txPower = 0; + esp_wifi_get_max_tx_power(&txPower); + + Serial.println("ESP-NOW puente bidireccional iniciado correctamente"); + Serial.print("MAC: "); + Serial.println(WiFi.macAddress()); + Serial.print("Canal ESP-NOW: "); + Serial.println(ESPNOW_CHANNEL); + Serial.print("Potencia TX configurada: "); + Serial.print(txPower * 0.25f); + Serial.println(" dBm aprox"); +#endif + + return true; +} + +// ESP-NOW -> UART/USB -> PC. Se llama desde loop(), no desde el callback. +void procesar_espnow_y_enviar_pc() +{ + static uint8_t packet[ESPNOW_PACKET_MAX_LEN]; + uint16_t len = 0; + uint8_t processed = 0; + + while (processed < MAX_ESPNOW_TO_PC_PACKETS_PER_PASS && + pop_espnow_rx_packet(packet, &len)) { + Serial.write(packet, len); + ++processed; + } +} + +// UART/USB -> ESP-NOW +// Lee paquetes binarios que vienen del programa de Windows y los manda por ESP-NOW LR. +void procesar_uart_y_enviar_espnow() +{ + enum EstadoParser { + ESPERANDO_MAGIC_1, + ESPERANDO_MAGIC_2, + LEYENDO_CABECERA, + LEYENDO_AUDIO, + LEYENDO_CONTROL + }; + + static EstadoParser estado = ESPERANDO_MAGIC_1; + static uint8_t packet[ESPNOW_PACKET_MAX_LEN]; + static size_t index = 0; + static uint16_t chunk_len = 0; + uint8_t processed_packets = 0; + + auto reset_parser = [&]() { + index = 0; + chunk_len = 0; + estado = ESPERANDO_MAGIC_1; + }; + + while (Serial.available() > 0) { + uint8_t b = (uint8_t)Serial.read(); + + switch (estado) { + case ESPERANDO_MAGIC_1: + if (b == RADIO_CONTROL_MAGIC_1) { + packet[0] = b; + index = 1; + estado = ESPERANDO_MAGIC_2; + } + break; + + case ESPERANDO_MAGIC_2: + if (b == 0x5E) { + packet[1] = b; + index = 2; + estado = LEYENDO_CABECERA; + } else if (b == RADIO_CONTROL_MAGIC_2) { + packet[1] = b; + index = 2; + estado = LEYENDO_CONTROL; + } else if (b == RADIO_CONTROL_MAGIC_1) { + // Puede ser el inicio real de otro paquete. + packet[0] = b; + index = 1; + } else { + reset_parser(); + } + break; + + case LEYENDO_CONTROL: + packet[index++] = b; + + if (index >= RADIO_CONTROL_PACKET_LEN) { + if (paquete_control_valido(packet, (int)index)) { + enviar_paquete_espnow(packet, index); + } + reset_parser(); + + ++processed_packets; + if (processed_packets >= MAX_PC_TO_ESPNOW_PACKETS_PER_PASS) { + return; + } + } + break; + + case LEYENDO_CABECERA: + packet[index++] = b; + + if (index >= ESPNOW_PACKET_HEADER_LEN) { + uint16_t frame_len = read_le_u16(&packet[5]); + uint16_t offset = read_le_u16(&packet[7]); + chunk_len = read_le_u16(&packet[9]); + + bool cabecera_ok = true; + + if (chunk_len == 0 || chunk_len > ESPNOW_AUDIO_CHUNK) { + cabecera_ok = false; + } + + if (frame_len == 0 || frame_len > 2000) { + cabecera_ok = false; + } + + if ((uint32_t)offset + (uint32_t)chunk_len > (uint32_t)frame_len) { + cabecera_ok = false; + } + + if (!cabecera_ok) { + reset_parser(); + break; + } + + estado = LEYENDO_AUDIO; + } + break; + + case LEYENDO_AUDIO: + packet[index++] = b; + + if (index >= (size_t)ESPNOW_PACKET_HEADER_LEN + chunk_len) { + enviar_paquete_espnow(packet, index); + reset_parser(); + + ++processed_packets; + if (processed_packets >= MAX_PC_TO_ESPNOW_PACKETS_PER_PASS) { + return; + } + } + break; + } + } +} diff --git a/Radio/Radio_receptor/espnow.hpp b/Radio/Radio_receptor/espnow.hpp new file mode 100644 index 0000000..e2cdd01 --- /dev/null +++ b/Radio/Radio_receptor/espnow.hpp @@ -0,0 +1,53 @@ +#ifndef ESPNOW_HPP +#define ESPNOW_HPP + +#include + +// Ponlo a 1 solo para depurar. +// Para audio real por UART es mejor dejarlo en 0 para no mezclar texto con datos binarios. +#define DEBUG_SERIAL 0 + +#define ESPNOW_AUDIO_CHUNK 200 +#define ESPNOW_PACKET_HEADER_LEN 11 +#define ESPNOW_PACKET_MAX_LEN (ESPNOW_PACKET_HEADER_LEN + ESPNOW_AUDIO_CHUNK) + +#define RADIO_CONTROL_MAGIC_1 0xE5 +#define RADIO_CONTROL_MAGIC_2 0x5F +#define RADIO_CONTROL_COMMAND_BOX_PTT 0x01 +#define RADIO_CONTROL_PACKET_LEN 4 + +/* Reparto justo del loop entre PC -> piloto y piloto -> PC. */ +#define MAX_ESPNOW_TO_PC_PACKETS_PER_PASS 2 +#define MAX_PC_TO_ESPNOW_PACKETS_PER_PASS 2 + +// Formato del paquete: +// 0: magic1 0xE5 +// 1: magic2 0x5E +// 2: frame_seq +// 3: chunk_index +// 4: chunk_total +// 5-6: frame_len little endian +// 7-8: offset little endian +// 9-10: chunk_len little endian +// 11... audio signed 8-bit + +typedef struct __attribute__((packed)) { + uint8_t magic1; // 0xE5 + uint8_t magic2; // 0x5E + + uint8_t frame_seq; + uint8_t chunk_index; + uint8_t chunk_total; + + uint16_t frame_len; + uint16_t offset; + uint16_t chunk_len; + + int8_t audio[ESPNOW_AUDIO_CHUNK]; +} AudioNowPacket; + +bool init_espnow_puente_bidir(); +void procesar_uart_y_enviar_espnow(); +void procesar_espnow_y_enviar_pc(); + +#endif