# HG changeset patch # User StephaneLenclud # Date 1423412822 -3600 # Node ID 57b1c6507bd72b0825b66c34158f677d7070bc4d # Parent 1b6de6f9b7c6817e46883bae90cb76cc9d6b940d Adding 'Audio' tab. Volume indicator of MDM16AA display now working. Adding server side dependency on NAudio. It was decided to have a server side dependency so that we could implement new fields control such as: * Volume indicator * Mute indicator * Spectrum visualizer * Meter visualizer * Fancy visualizer diff -r 1b6de6f9b7c6 -r 57b1c6507bd7 Server/MainForm.Designer.cs --- a/Server/MainForm.Designer.cs Sat Feb 07 21:16:33 2015 +0100 +++ b/Server/MainForm.Designer.cs Sun Feb 08 17:27:02 2015 +0100 @@ -90,6 +90,8 @@ this.checkBoxMinimizeToTray = new System.Windows.Forms.CheckBox(); this.checkBoxAutoStart = new System.Windows.Forms.CheckBox(); this.buttonUpdate = new System.Windows.Forms.Button(); + this.tabPageAudio = new System.Windows.Forms.TabPage(); + this.trackBarMasterVolume = new System.Windows.Forms.TrackBar(); this.labelFontWidth = new System.Windows.Forms.Label(); this.labelFontHeight = new System.Windows.Forms.Label(); this.pictureBoxDemo = new System.Windows.Forms.PictureBox(); @@ -103,6 +105,8 @@ this.tabControl.SuspendLayout(); this.tabPageDesign.SuspendLayout(); this.tabPageApp.SuspendLayout(); + this.tabPageAudio.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarMasterVolume)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBoxDemo)).BeginInit(); this.SuspendLayout(); // @@ -504,6 +508,7 @@ this.tabControl.Controls.Add(this.tabPageClients); this.tabControl.Controls.Add(this.tabPageDesign); this.tabControl.Controls.Add(this.tabPageApp); + this.tabControl.Controls.Add(this.tabPageAudio); this.tabControl.Location = new System.Drawing.Point(12, 139); this.tabControl.Name = "tabControl"; this.tabControl.SelectedIndex = 0; @@ -683,6 +688,31 @@ this.buttonUpdate.UseVisualStyleBackColor = true; this.buttonUpdate.Click += new System.EventHandler(this.buttonUpdate_Click); // + // tabPageAudio + // + this.tabPageAudio.Controls.Add(this.trackBarMasterVolume); + this.tabPageAudio.Location = new System.Drawing.Point(4, 22); + this.tabPageAudio.Name = "tabPageAudio"; + this.tabPageAudio.Padding = new System.Windows.Forms.Padding(3); + this.tabPageAudio.Size = new System.Drawing.Size(592, 242); + this.tabPageAudio.TabIndex = 5; + this.tabPageAudio.Text = "Audio"; + this.tabPageAudio.UseVisualStyleBackColor = true; + // + // trackBarMasterVolume + // + this.trackBarMasterVolume.BackColor = System.Drawing.SystemColors.Window; + this.trackBarMasterVolume.Location = new System.Drawing.Point(541, 6); + this.trackBarMasterVolume.Maximum = 100; + this.trackBarMasterVolume.Name = "trackBarMasterVolume"; + this.trackBarMasterVolume.Orientation = System.Windows.Forms.Orientation.Vertical; + this.trackBarMasterVolume.Size = new System.Drawing.Size(45, 230); + this.trackBarMasterVolume.TabIndex = 0; + this.trackBarMasterVolume.TickFrequency = 10; + this.trackBarMasterVolume.TickStyle = System.Windows.Forms.TickStyle.Both; + this.toolTip.SetToolTip(this.trackBarMasterVolume, "Master Volume"); + this.trackBarMasterVolume.Scroll += new System.EventHandler(this.trackBarMasterVolume_Scroll); + // // labelFontWidth // this.labelFontWidth.AutoSize = true; @@ -743,6 +773,9 @@ this.tabPageDesign.PerformLayout(); this.tabPageApp.ResumeLayout(false); this.tabPageApp.PerformLayout(); + this.tabPageAudio.ResumeLayout(false); + this.tabPageAudio.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarMasterVolume)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBoxDemo)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -806,6 +839,8 @@ private System.Windows.Forms.Label labelScrollingSpeed; private System.Windows.Forms.MaskedTextBox maskedTextBoxScrollingSpeed; private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.TabPage tabPageAudio; + private System.Windows.Forms.TrackBar trackBarMasterVolume; } } diff -r 1b6de6f9b7c6 -r 57b1c6507bd7 Server/MainForm.cs --- a/Server/MainForm.cs Sat Feb 07 21:16:33 2015 +0100 +++ b/Server/MainForm.cs Sun Feb 08 17:27:02 2015 +0100 @@ -15,6 +15,10 @@ using System.Diagnostics; using System.Deployment.Application; using System.Reflection; +//NAudio +using NAudio.CoreAudioApi; +using NAudio.CoreAudioApi.Interfaces; +using System.Runtime.InteropServices; // using SharpDisplayClient; using SharpDisplay; @@ -31,12 +35,13 @@ public delegate void SetFieldsDelegate(string SessionId, System.Collections.Generic.IList aFields); public delegate void SetLayoutDelegate(string SessionId, TableLayout aLayout); public delegate void SetClientNameDelegate(string aSessionId, string aName); + public delegate void PlainUpdateDelegate(); /// /// Our Display manager main form /// - public partial class MainForm : Form + public partial class MainForm : Form, IMMNotificationClient { DateTime LastTickTime; Display iDisplay; @@ -56,6 +61,10 @@ CoordinateTranslationDelegate iScreenX; //Function pointer for pixel Y coordinate intercept CoordinateTranslationDelegate iScreenY; + //NAudio + private MMDeviceEnumerator iMultiMediaDeviceEnumerator; + private MMDevice iMultiMediaDevice; + /// /// Manage run when Windows startup option @@ -121,6 +130,12 @@ this.Text += " - development"; } + //NAudio + iMultiMediaDeviceEnumerator = new MMDeviceEnumerator(); + iMultiMediaDeviceEnumerator.RegisterEndpointNotificationCallback(this); + + UpdateAudioDeviceAndMasterVolumeThreadSafe(); + //Setup notification icon SetupTrayIcon(); @@ -167,10 +182,13 @@ //Initiate asynchronous request iDisplay.RequestFirmwareRevision(); + // + UpdateMasterVolumeThreadSafe(); + #if DEBUG //Testing icon in debug, no arm done if icon not supported //iDisplay.SetIconStatus(Display.TMiniDisplayIconType.EMiniDisplayIconRecording, 0, 1); - iDisplay.SetAllIconsStatus(2); + //iDisplay.SetAllIconsStatus(2); #endif } @@ -184,6 +202,135 @@ //Our display was just closed, update our UI consequently UpdateStatus(); } + + /// + /// Receive volume change notification and reflect changes on our slider. + /// + /// + public void OnVolumeNotificationThreadSafe(AudioVolumeNotificationData data) + { + UpdateMasterVolumeThreadSafe(); + } + + /// + /// Update master volume when user moves our slider. + /// + /// + /// + private void trackBarMasterVolume_Scroll(object sender, EventArgs e) + { + iMultiMediaDevice.AudioEndpointVolume.MasterVolumeLevelScalar = trackBarMasterVolume.Value / 100.0f; + } + + /// + /// Device State Changed + /// + public void OnDeviceStateChanged([MarshalAs(UnmanagedType.LPWStr)] string deviceId, [MarshalAs(UnmanagedType.I4)] DeviceState newState){} + + /// + /// Device Added + /// + public void OnDeviceAdded([MarshalAs(UnmanagedType.LPWStr)] string pwstrDeviceId) { } + + /// + /// Device Removed + /// + public void OnDeviceRemoved([MarshalAs(UnmanagedType.LPWStr)] string deviceId) { } + + /// + /// Default Device Changed + /// + public void OnDefaultDeviceChanged(DataFlow flow, Role role, [MarshalAs(UnmanagedType.LPWStr)] string defaultDeviceId) + { + if (role == Role.Multimedia && flow == DataFlow.Render) + { + UpdateAudioDeviceAndMasterVolumeThreadSafe(); + } + } + + /// + /// Property Value Changed + /// + /// + /// + public void OnPropertyValueChanged([MarshalAs(UnmanagedType.LPWStr)] string pwstrDeviceId, PropertyKey key){} + + + + + /// + /// + /// + private void UpdateMasterVolumeThreadSafe() + { + if (this.InvokeRequired) + { + //Not in the proper thread, invoke ourselves + PlainUpdateDelegate d = new PlainUpdateDelegate(UpdateMasterVolumeThreadSafe); + this.Invoke(d, new object[] { }); + return; + } + + float volumeLevelScalar = iMultiMediaDevice.AudioEndpointVolume.MasterVolumeLevelScalar; + trackBarMasterVolume.Value = Convert.ToInt32(volumeLevelScalar * 100); + + //TODO: Check our display device too + if (iDisplay.IsOpen()) + { + int volumeIconCount = iDisplay.IconCount(Display.TMiniDisplayIconType.EMiniDisplayIconVolume); + if (volumeIconCount > 0) + { + int currentVolume = Convert.ToInt32(volumeLevelScalar * volumeIconCount); + for (int i = 0; i < volumeIconCount; i++) + { + if (i < currentVolume) + { + iDisplay.SetIconStatus(Display.TMiniDisplayIconType.EMiniDisplayIconVolume, i, 10); + } + else + { + iDisplay.SetIconStatus(Display.TMiniDisplayIconType.EMiniDisplayIconVolume, i, 0); + } + } + } + } + + } + + /// + /// + /// + private void UpdateAudioDeviceAndMasterVolumeThreadSafe() + { + if (this.InvokeRequired) + { + //Not in the proper thread, invoke ourselves + PlainUpdateDelegate d = new PlainUpdateDelegate(UpdateAudioDeviceAndMasterVolumeThreadSafe); + this.Invoke(d, new object[] { }); + return; + } + + //We are in the correct thread just go ahead. + try + { + //Get our master volume + iMultiMediaDevice = iMultiMediaDeviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); + //Show our volume in our track bar + UpdateMasterVolumeThreadSafe(); + + //Register to get volume modifications + iMultiMediaDevice.AudioEndpointVolume.OnVolumeNotification += OnVolumeNotificationThreadSafe; + // + trackBarMasterVolume.Enabled = true; + } + catch (Exception ex) + { + Debug.WriteLine("Exception thrown in UpdateAudioDeviceAndMasterVolume"); + Debug.WriteLine(ex.ToString()); + //Something went wrong S/PDIF device ca throw exception I guess + trackBarMasterVolume.Enabled = false; + } + } /// /// diff -r 1b6de6f9b7c6 -r 57b1c6507bd7 Server/SharpDisplayManager.csproj --- a/Server/SharpDisplayManager.csproj Sat Feb 07 21:16:33 2015 +0100 +++ b/Server/SharpDisplayManager.csproj Sun Feb 08 17:27:02 2015 +0100 @@ -106,6 +106,9 @@ + + ..\packages\NAudio.1.7.2\lib\net35\NAudio.dll + @@ -169,6 +172,7 @@ Designer + SettingsSingleFileGenerator Settings.Designer.cs diff -r 1b6de6f9b7c6 -r 57b1c6507bd7 Server/packages.config --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Server/packages.config Sun Feb 08 17:27:02 2015 +0100 @@ -0,0 +1,4 @@ + + + + \ No newline at end of file