(view source code of audioendpoints.cs as plain text)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using NAudio.CoreAudioApi;
using NAudio.Wave;
namespace RobvanderWoude
{
internal class AudioEndPoints
{
static readonly string progver = "2.00";
#region Global Variables
static bool bgcolors = true;
static bool fgcolors = false;
static bool helprequested = false;
static bool stereo = true;
static DataGridView datagrid;
static readonly Dictionary<DeviceState, Color> foregroundcolors = new Dictionary<DeviceState, Color>
{
[DeviceState.Active] = Color.Green,
[DeviceState.Disabled] = Color.Orange,
[DeviceState.NotPresent] = Color.SlateGray,
[DeviceState.Unplugged] = Color.Red
};
static readonly Dictionary<DeviceState, Color> backgroundcolors = new Dictionary<DeviceState, Color>
{
[DeviceState.Active] = Color.LightGreen,
[DeviceState.Disabled] = Color.Yellow,
[DeviceState.NotPresent] = Color.LightGray,
[DeviceState.Unplugged] = Color.Red
};
static Dictionary<int, AudioEndPoint> audioendpoints;
static Form form;
static int interval = 0;
static Timer timer = new Timer( );
static WaveIn recorder;
#endregion Global Variables
[STAThread]
static int Main( string[] args )
{
#region Parse Command Line
foreach ( string arg in args )
{
string[] kvp = arg.Split( ":=".ToCharArray( ), 2 );
string key = kvp[0].ToUpper( );
string val = ( kvp.Length == 2 ? kvp[1] : string.Empty );
switch ( key )
{
case "/?":
return ShowHelp( true );
case "/B":
bgcolors = false;
fgcolors = false;
break;
case "/F":
bgcolors = false;
fgcolors = true;
break;
case "/M":
stereo = false;
break;
case "/R":
interval = 1;
if ( string.IsNullOrWhiteSpace( val ) )
{
if ( !int.TryParse( val, out interval ) )
{
interval = 1;
}
}
if ( interval < 0 )
{
interval = 1;
}
timer.Interval = interval * 1000;
timer.Tick += Timer_Tick;
timer.Start( );
break;
default:
return ShowHelp( true );
}
}
#endregion Parse Command Line
Application.EnableVisualStyles( );
form = new Form
{
BackColor = Color.White,
Font = new Font( FontFamily.GenericSansSerif, 12 ),
Size = new Size( 1380, 840 ),
StartPosition = FormStartPosition.CenterScreen,
Text = "AudioEndPoints.exe, \u00A0 Version " + progver + " \u00A0?\u00A0 \u00A0 Copyright \u00A9 2025 Rob van der Woude",
Visible = true
};
form.FormClosing += Form_FormClosing;
audioendpoints = new Dictionary<int, AudioEndPoint>( );
recorder = new WaveIn( );
recorder.StartRecording( );
SetupDataGrid( );
PopulateDataGrid( );
while ( form.Enabled )
{
Application.DoEvents( );
}
return 0;
}
private static void Datagrid_KeyUp( object sender, KeyEventArgs e )
{
if ( e.KeyCode == Keys.F1 )
{
ShowHelp( false );
}
if ( e.KeyCode == Keys.F5 )
{
RefreshDataGrid( );
}
if ( e.KeyCode == Keys.Escape )
{
form.Close( );
}
if ( e.Control && e.KeyCode == Keys.P )
{
PrintDataGrid( );
}
if ( e.Control && e.KeyCode == Keys.S )
{
string filename = string.Format( "AudioEndPoints.{0}.{1}.txt", Environment.GetEnvironmentVariable( "COMPUTERNAME" ), DateTime.Now.ToString( "yyyy-MM-dd_HHmmss" ) );
string outfile = Path.Combine( Environment.CurrentDirectory, filename );
SaveDataGrid( outfile );
MessageBox.Show( "Saved as \"" + filename + "\" in folder \"" + Path.GetDirectoryName( outfile ) + "\"", "File Saved", MessageBoxButtons.OK, MessageBoxIcon.Information );
}
}
private static void Datagrid_SortCompare( object sender, DataGridViewSortCompareEventArgs e )
{
if ( e.Column.Index == 0 )
{
e.SortResult = int.Parse( e.CellValue1.ToString( ) ).CompareTo( int.Parse( e.CellValue2.ToString( ) ) );
e.Handled = true; // skip the default sorting
}
}
private static void Form_FormClosing( object sender, FormClosingEventArgs e )
{
try
{
timer.Stop( );
}
catch { }
try
{
recorder.StopRecording( );
}
catch { }
if ( helprequested )
{
ShowHelp( true );
}
form.Enabled = false;
}
private static void Timer_Tick( object sender, EventArgs e )
{
RefreshDataGrid( );
}
private static void InventoryAudioEndPoints( )
{
MMDeviceEnumerator enumerator = new MMDeviceEnumerator( );
int index = 0;
foreach ( MMDevice endpoint in enumerator.EnumerateAudioEndPoints( DataFlow.All, DeviceState.All ) )
{
AudioEndPoint audioendpoint = new AudioEndPoint
{
Index = index,
InOut = endpoint.DataFlow,
Name = endpoint.FriendlyName,
State = endpoint.State,
ID = endpoint.ID,
};
if ( audioendpoint.State == DeviceState.Active )
{
audioendpoint.MasterVolumeLevelScalar = endpoint.AudioEndpointVolume.MasterVolumeLevelScalar;
audioendpoint.MasterPeakValue = endpoint.AudioMeterInformation.MasterPeakValue;
audioendpoint.PeakValues = endpoint.AudioMeterInformation.PeakValues;
}
else
{
audioendpoint.MasterVolumeLevelScalar = 0f;
audioendpoint.MasterPeakValue = 0f;
audioendpoint.PeakValues = null;
}
audioendpoints[index] = audioendpoint;
index++;
}
}
private static void PopulateDataGrid( )
{
InventoryAudioEndPoints( );
foreach ( AudioEndPoint endpoint in audioendpoints.Values )
{
PopulateDataGridRow( endpoint );
}
for ( int i = 0; i < datagrid.ColumnCount; i++ )
{
if ( i == datagrid.ColumnCount - 1 )
{
datagrid.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
else
{
datagrid.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
}
}
private static void PopulateDataGridRow( AudioEndPoint endpoint )
{
string[] line;
if ( stereo )
{
line = new string[] { endpoint.Index.ToString( ), ( endpoint.InOut == DataFlow.Capture ? "IN" : "OUT" ), endpoint.Name, endpoint.State.ToString( ), endpoint.ID, endpoint.GetVolume( ), endpoint.GetPeakLevel( 0 ), endpoint.GetPeakLevel( 1 ) };
}
else
{
line = new string[] { endpoint.Index.ToString( ), ( endpoint.InOut == DataFlow.Capture ? "IN" : "OUT" ), endpoint.Name, endpoint.State.ToString( ), endpoint.ID, endpoint.GetVolume( ), endpoint.GetPeakLevel( -1 ) };
}
int row;
if ( endpoint.Index < datagrid.Rows.Count - 1 )
{
row = endpoint.Index;
datagrid.Rows[row].SetValues( line );
}
else
{
row = datagrid.Rows.Count - 1;
datagrid.Rows.Add( line );
}
if ( bgcolors )
{
datagrid.Rows[row].DefaultCellStyle.BackColor = backgroundcolors[endpoint.State];
}
if ( fgcolors )
{
datagrid.Rows[row].DefaultCellStyle.ForeColor = foregroundcolors[endpoint.State];
}
}
private static void PrintDataGrid( )
{
string printout = Path.GetTempFileName( );
SaveDataGrid( printout );
ProcessStartInfo psi = new ProcessStartInfo
{
UseShellExecute = false,
Arguments = string.Format( "/p \"{0}\"", printout ),
FileName = "notepad.exe"
};
Process proc = Process.Start( psi );
proc.WaitForExit( );
File.Delete( printout );
}
private static void RefreshDataGrid( )
{
PopulateDataGrid( );
}
private static void SaveDataGrid( string outfile )
{
// line out colums
int[] cw;
if ( stereo )
{
cw = new int[] { 5, 6, 0, 0, 0, 6, 6, 6 };
}
else
{
cw = new int[] { 5, 6, 0, 0, 0, 6, 4 };
}
for ( int i = 0; i < datagrid.Columns.Count; i++ )
{
for ( int j = 0; j < datagrid.Rows.Count; j++ )
{
if ( datagrid.Rows[j].Cells[i].Value != null && datagrid.Rows[j].Cells[i].Value.ToString( ).Length > cw[i] )
{
cw[i] = datagrid.Rows[j].Cells[i].Value.ToString( ).Length;
}
}
}
// format printout
List<string> lines = new List<string>( );
string linetemplate;
if ( stereo )
{
linetemplate = "{0,-" + cw[0] + "} {1,-" + cw[1] + "} {2,-" + cw[2] + "} {3,-" + cw[3] + "} {4,-" + cw[4] + "} {5," + cw[5] + "} {6," + cw[6] + "} {7," + cw[7] + "}";
}
else
{
linetemplate = "{0,-" + cw[0] + "} {1,-" + cw[1] + "} {2,-" + cw[2] + "} {3,-" + cw[3] + "} {4,-" + cw[4] + "} {5," + cw[5] + "} {6," + cw[6] + "}";
}
// header
var cols = datagrid.Columns;
string headerline;
if ( stereo )
{
headerline = string.Format( linetemplate, cols[0].HeaderText, cols[1].HeaderText.Replace( "\u00A0", "" ), cols[2].HeaderText, cols[3].HeaderText, cols[4].HeaderText, cols[5].HeaderText, cols[6].HeaderText, cols[7].HeaderText );
}
else
{
headerline = string.Format( linetemplate, cols[0].HeaderText, cols[1].HeaderText.Replace( "\u00A0", "" ), cols[2].HeaderText, cols[3].HeaderText, cols[4].HeaderText, cols[5].HeaderText, cols[6].HeaderText );
}
lines.Add( headerline );
// rows
for ( int i = 0; i < datagrid.Rows.Count; i++ )
{
var cells = datagrid.Rows[i].Cells;
string line;
if ( stereo )
{
line = string.Format( linetemplate, cells[0].Value, cells[1].Value, cells[2].Value, cells[3].Value, cells[4].Value, cells[5].Value, cells[6].Value, cells[7].Value );
}
else
{
line = string.Format( linetemplate, cells[0].Value, cells[1].Value, cells[2].Value, cells[3].Value, cells[4].Value, cells[5].Value, cells[6].Value );
}
lines.Add( line );
}
using ( StreamWriter print = new StreamWriter( outfile ) )
{
for ( int i = 0; i < lines.Count; i++ )
{
print.WriteLine( lines[i] );
}
}
}
private static void SetupDataGrid( )
{
datagrid = new DataGridView
{
Location = new Point( 0, 0 ),
Size = new Size( 1200, 250 ),
AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders,
ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single,
CellBorderStyle = DataGridViewCellBorderStyle.Single,
GridColor = Color.Black,
RowHeadersVisible = false,
SelectionMode = DataGridViewSelectionMode.FullRowSelect,
MultiSelect = false,
Dock = DockStyle.Fill
};
if ( stereo )
{
datagrid.ColumnCount = 8;
}
else
{
datagrid.ColumnCount = 7;
form.Width -= 85;
}
datagrid.ColumnHeadersDefaultCellStyle.BackColor = Color.Navy;
datagrid.ColumnHeadersDefaultCellStyle.ForeColor = Color.White;
datagrid.ColumnHeadersDefaultCellStyle.Font = new Font( FontFamily.GenericSansSerif, 12, FontStyle.Bold );
datagrid.Columns[0].Name = "Index";
datagrid.Columns[1].Name = "In\u00A0/\u00A0Out";
datagrid.Columns[2].Name = "Name";
datagrid.Columns[3].Name = "Status";
datagrid.Columns[4].Name = "ID";
datagrid.Columns[5].Name = "Volume";
datagrid.Columns[5].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
if ( stereo )
{
datagrid.Columns[6].Name = "Peak\u00A0L";
datagrid.Columns[6].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
datagrid.Columns[7].Name = "Peak\u00A0R";
datagrid.Columns[7].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
}
else
{
datagrid.Columns[6].Name = "Peak";
datagrid.Columns[6].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
}
datagrid.KeyUp += Datagrid_KeyUp;
datagrid.SortCompare += Datagrid_SortCompare;
form.Controls.Add( datagrid );
datagrid.Focus( );
}
private static int ShowHelp( bool cli = false )
{
string message = string.Format( "\nAudioEndPoints.exe, Version {0}\n", progver );
message += "List the local computer's audio endpoints\n\n";
message += "Usage:\tAudioEndPoints.exe\t[ /? ] [ /F | /B ] [ /M ] [ /R[:nn] ]\n\n";
message += "Where:\t \t/? \tdisplay this help text and exit\n";
message += " \t \t/F \tuse status dependent\n";
message += " \t \t \tFOREGROUND colors,\n";
message += " \t \t/B \tuse BLACK and WHITE,\n";
message += " \t \t \tdefault is status dependent\n";
message += " \t \t \tBACKGROUND colors\n";
message += " \t \t/M \tpeak levels for L and R combined,\n";
message += " \t \t \tdefault is separate peak levels\n";
message += " \t \t/R[:nn]\trefresh values every nn seconds,\n";
message += " \t \t \tdefault interval is 1 second\n\n";
message += "Click on ANY column header to sort the table by that column.\n";
message += "Note that the table's sort order will be reset to its default at\n";
message += "every refresh, be it by pressing F5 or by specifying a refresh\n";
message += "interval with the /R command line switch.\n";
message += "You can edit all cells, if you like.\n\n";
message += "Keys: \tCtrl+C will copy the SELECTED LINE to the clipboard,\n";
message += " \tCtrl+P will print the list,\n";
message += " \tCtrl+S will save it in a text file,\n";
message += " \tF1 will show this help text,\n";
message += " \tF5 will refresh volume and peak level values,\n";
message += " \tEscape will abort the program.\n\n";
message += "Credits:\tTo access audio endpoints, this program uses\n";
message += " \tNAudio created by Mark Heath:\n";
message += " \thttps://github.com/naudio/NAudio\n";
message += " \tVolume reading based on code by Mike de Klerk:\n";
message += " \thttps://stackoverflow.com/a/12534584\n\n";
message += "Written by Rob van der Woude\n";
message += "https://www.robvanderwoude.com\n";
if ( cli )
{
Console.Error.WriteLine( message );
Environment.Exit( -1 );
Application.Exit( );
}
else
{
helprequested = true;
MessageBox.Show( message, "AudioEndPoints.exe, \u00A0 Version " + progver );
}
return -1;
}
}
public class AudioEndPoint
{
public int Index
{
get; set;
}
public DataFlow InOut
{
get; set;
}
public string Name
{
get; set;
}
public DeviceState State
{
get; set;
}
public string ID
{
get; set;
}
public float MasterVolumeLevelScalar
{
get; set;
}
public float MasterPeakValue
{
get; set;
}
public AudioMeterInformationChannels PeakValues
{
get; set;
}
public string GetVolume( )
{
if ( State == DeviceState.Active )
{
return string.Format( "{0} %", (int)( MasterVolumeLevelScalar * 100 ) );
}
else
{
return string.Empty;
}
}
public string GetPeakLevel( int channel = -1 )
{
if ( State == DeviceState.Active )
{
switch ( channel )
{
case 0:
return string.Format( "{0} %", (int)( 100 * float.Parse( PeakValues[0].ToString( ) ) ) );
case 1:
return string.Format( "{0} %", (int)( 100 * float.Parse( PeakValues[1].ToString( ) ) ) );
default:
return string.Format( "{0} %", (int)( 100 * MasterPeakValue ) );
}
}
else
{
return string.Empty;
}
}
}
}
page last modified: 2024-04-16; loaded in 0.0096 seconds