using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using CSCore; using CSCore.Codecs.WAV; using CSCore.SoundIn; using CSCore.SoundOut; using Mono.Zeroconf; namespace SoundBeam { /*using (WasapiCapture capture = new WasapiLoopbackCapture()) { //if nessesary, you can choose a device here //to do so, simply set the device property of the capture to any MMDevice //to choose a device, take a look at the sample here: http://cscore.codeplex.com/ //initialize the selected device for recording capture.Initialize(); capture.DataAvailable += OnCaptureDataAvailable; //create a wavewriter to write the data to using (WaveWriter w = new WaveWriter("dump.wav", capture.WaveFormat)) { //setup an eventhandler to receive the recorded data capture.DataAvailable += (s, a) => { //save the recorded audio w.Write(a.Data, a.Offset, a.ByteCount); }; //start recording capture.Start(); Console.ReadKey(); //stop recording capture.Stop(); } }*/ public partial class Form1 : Form { private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource(); private static readonly TcpServer TcpServer = new TcpServer("0.0.0.0", 9000); private static readonly WasapiCapture WasapiCapture = new WasapiCapture(); private static readonly RegisterService SoundBeamRegisterService = new RegisterService(); private static readonly ServiceBrowser SoundBeamServiceBrowser = new ServiceBrowser(); private static readonly Dictionary WasapiOut = new Dictionary(); private static readonly BindingList DiscoveredServersBindingList = new BindingList(); private static readonly BindingSource DiscoveredServersBindingSource = new BindingSource(DiscoveredServersBindingList, null); public Form1() { InitializeComponent(); // Set the tool strip combo box binding. sendToolStripComboBox.ComboBox.DisplayMember = "Hostname"; sendToolStripComboBox.ComboBox.ValueMember = "Hostname"; sendToolStripComboBox.ComboBox.DataSource = DiscoveredServersBindingSource; sendToolStripComboBox.ComboBox.BindingContext = this.BindingContext; // Register local service. SoundBeamRegisterService.Name = "SoundBeam Audio Sink"; SoundBeamRegisterService.RegType = "_soundbeam._tcp"; SoundBeamRegisterService.Port = 9000; SoundBeamRegisterService.UPort = 9000; SoundBeamRegisterService.ReplyDomain = "local."; SoundBeamRegisterService.Response += OnRegisterServiceResponse; SoundBeamRegisterService.Register(); // Browse for services. SoundBeamServiceBrowser.ServiceAdded += OnSoundBeamServiceBrowserServiceAdded; SoundBeamServiceBrowser.Browse(0, AddressProtocol.Any, "_soundbeam._tcp", "local."); } /// /// 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)) { TcpServer.Dispose(); WasapiCapture.Dispose(); SoundBeamRegisterService.Dispose(); SoundBeamServiceBrowser.Dispose(); components.Dispose(); } base.Dispose(disposing); } private void OnTcpServerClientConnected(object sender, TcpClientConnectedEventArgs args) { WasapiOut.Add(args.TcpClient, new WasapiOut()); using (var waveReader = new WaveFileReader(args.TcpClient.GetStream())) { WasapiOut[args.TcpClient].Initialize(waveReader); WasapiOut[args.TcpClient].Play(); } } private void OnSoundBeamServiceBrowserServiceAdded(object o, ServiceBrowseEventArgs args) { if (args?.Service == null) return; args.Service.Resolved += OnSoundBeamServiceResolved; args.Service.Resolve(); } private void OnSoundBeamServiceResolved(object o, ServiceResolvedEventArgs args) { if (args?.Service == null) return; args.Service.Resolved -= OnSoundBeamServiceResolved; // Do not add already added servers. if (DiscoveredServersBindingList.Any(server => string.Equals(server.Hostname, args.Service.HostTarget, StringComparison.OrdinalIgnoreCase) && server.Port == args.Service.Port)) return; Invoke((Action) (() => { DiscoveredServersBindingList.Add(new DiscoveredServer(args.Service.HostTarget, args.Service.Port)); })); } private void OnRegisterServiceResponse(object o, RegisterServiceEventArgs args) { if (args.IsRegistered) { notifyIcon1.ShowBalloonTip(250, "SoundBeam Audio Sink Registered", "Bonjour service registered successfully.", ToolTipIcon.Info); return; } notifyIcon1.ShowBalloonTip(250, "SoundBeam Sink Failed to Register", "Failed to register SoundBeam sink with bonjour.", ToolTipIcon.Error); } private void OnCaptureDataAvailable(object sender, DataAvailableEventArgs args) { // Send data to destination. } private void OnReceiveToolStripMenuItemCheckedChanged(object sender, EventArgs e) { switch (((ToolStripMenuItem) sender).Checked) { case true: // Listen for TCP connections. TcpServer.ClientConnected += OnTcpServerClientConnected; TcpServer.Start(); break; default: TcpServer.ClientConnected -= OnTcpServerClientConnected; TcpServer.Stop(); break; } } private void OnSendToolStripMenuItemCheckedChanged(object sender, EventArgs e) { } private void OnQuitToolStripMenuItemClick(object sender, EventArgs e) { Dispose(true); Application.Exit(); } private void OnFormLoad(object sender, EventArgs e) { } } }