2 * This file is part of the libCEC(R) library.
4 * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
5 * libCEC(R) is an original work, containing original code.
7 * libCEC(R) is a trademark of Pulse-Eight Limited.
9 * This program is dual-licensed; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * Alternatively, you can license this library under a commercial license,
25 * please contact Pulse-Eight Licensing for more information.
27 * For more information contact:
28 * Pulse-Eight Licensing <license@pulse-eight.com>
29 * http://www.pulse-eight.com/
30 * http://www.pulse-eight.net/
34 using System.Windows.Forms;
37 using LibCECTray.Properties;
38 using LibCECTray.controller;
39 using LibCECTray.controller.applications;
40 using LibCECTray.settings;
41 using Microsoft.Win32;
42 using System.Security.Permissions;
43 using System.Runtime.InteropServices;
45 namespace LibCECTray.ui
48 /// The tab pages in this application
50 internal enum ConfigTab
61 /// Main LibCecTray GUI
63 partial class CECTray : AsyncForm
67 Text = Resources.app_name;
68 InitializeComponent();
69 VisibleChanged += delegate
77 SystemEvents.SessionEnding += new SessionEndingEventHandler(OnSessionEnding);
80 public void OnSessionEnding(object sender, SessionEndingEventArgs e)
85 #region Power state change window messages
86 private const int WM_POWERBROADCAST = 0x0218;
87 private const int PBT_APMSUSPEND = 0x0004;
88 private const int PBT_APMRESUMESUSPEND = 0x0007;
89 private const int PBT_APMRESUMECRITICAL = 0x0006;
90 private const int PBT_APMRESUMEAUTOMATIC = 0x0012;
91 private const int PBT_POWERSETTINGCHANGE = 0x8013;
92 private static Guid GUID_SYSTEM_AWAYMODE = new Guid("98a7f580-01f7-48aa-9c0f-44352c29e5c0");
94 [StructLayout(LayoutKind.Sequential, Pack = 4)]
95 internal struct POWERBROADCAST_SETTING
97 public Guid PowerSetting;
98 public uint DataLength;
104 /// Check for power state changes, and pass up when it's something we don't care about
106 /// <param name="msg">The incoming window message</param>
107 protected override void WndProc(ref Message msg)
109 if (msg.Msg == WM_POWERBROADCAST)
111 switch (msg.WParam.ToInt32())
117 case PBT_APMRESUMESUSPEND:
118 case PBT_APMRESUMECRITICAL:
119 case PBT_APMRESUMEAUTOMATIC:
123 case PBT_POWERSETTINGCHANGE:
125 POWERBROADCAST_SETTING pwr = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(msg.LParam, typeof(POWERBROADCAST_SETTING));
126 if (pwr.PowerSetting == GUID_SYSTEM_AWAYMODE && pwr.DataLength == Marshal.SizeOf(typeof(Int32)))
131 // do _not_ wake the pc when away mode is deactivated
148 // pass up when not handled
149 base.WndProc(ref msg);
152 private void OnWake()
154 Controller.Initialise();
157 private void OnSleep()
162 public override sealed string Text
164 get { return base.Text; }
165 set { base.Text = value; }
168 public void Initialise()
170 Controller.Initialise();
173 protected override void Dispose(bool disposing)
180 if (disposing && (components != null))
182 components.Dispose();
184 base.Dispose(disposing);
187 #region Configuration tab
189 /// Replaces the gui controls by the ones that are bound to the settings.
190 /// this is a fugly way to do it, but the gui designer doesn't allow us to ref CECSettings, since it uses symbols from LibCecSharp
192 public void InitialiseSettingsComponent(CECSettings settings)
194 settings.WakeDevices.ReplaceControls(this, Configuration.Controls, lWakeDevices, cbWakeDevices);
195 settings.PowerOffDevices.ReplaceControls(this, Configuration.Controls, lPowerOff, cbPowerOffDevices);
196 settings.OverridePhysicalAddress.ReplaceControls(this, Configuration.Controls, cbOverrideAddress);
197 settings.OverrideTVVendor.ReplaceControls(this, Configuration.Controls, cbVendorOverride);
198 settings.PhysicalAddress.ReplaceControls(this, Configuration.Controls, tbPhysicalAddress);
199 settings.HDMIPort.ReplaceControls(this, Configuration.Controls, lPortNumber, cbPortNumber);
200 settings.ConnectedDevice.ReplaceControls(this, Configuration.Controls, lConnectedDevice, cbConnectedDevice);
201 settings.ActivateSource.ReplaceControls(this, Configuration.Controls, cbActivateSource);
202 settings.DeviceType.ReplaceControls(this, Configuration.Controls, lDeviceType, cbDeviceType);
203 settings.TVVendor.ReplaceControls(this, Configuration.Controls, cbVendorId);
204 settings.StartHidden.ReplaceControls(this, Configuration.Controls, cbStartMinimised);
207 private void BSaveClick(object sender, EventArgs e)
209 Controller.PersistSettings();
212 private void BReloadConfigClick(object sender, EventArgs e)
214 Controller.ResetDefaultSettings();
218 #region CEC Tester tab
219 delegate void SetActiveDevicesCallback(string[] activeDevices);
220 public void SetActiveDevices(string[] activeDevices)
222 if (cbCommandDestination.InvokeRequired)
224 SetActiveDevicesCallback d = SetActiveDevices;
227 Invoke(d, new object[] { activeDevices });
229 catch (Exception) { }
233 cbCommandDestination.Items.Clear();
234 foreach (string item in activeDevices)
235 cbCommandDestination.Items.Add(item);
239 delegate CecLogicalAddress GetTargetDeviceCallback();
240 private CecLogicalAddress GetTargetDevice()
242 if (cbCommandDestination.InvokeRequired)
244 GetTargetDeviceCallback d = GetTargetDevice;
245 CecLogicalAddress retval = CecLogicalAddress.Unknown;
248 retval = (CecLogicalAddress)Invoke(d, new object[] { });
250 catch (Exception) { }
254 return CECSettingLogicalAddresses.GetLogicalAddressFromString(cbCommandDestination.Text);
257 private void BSendImageViewOnClick(object sender, EventArgs e)
259 Controller.CECActions.SendImageViewOn(GetTargetDevice());
262 private void BStandbyClick(object sender, EventArgs e)
264 Controller.CECActions.SendStandby(GetTargetDevice());
267 private void BScanClick(object sender, EventArgs e)
269 Controller.CECActions.ShowDeviceInfo(GetTargetDevice());
272 private void BActivateSourceClick(object sender, EventArgs e)
274 Controller.CECActions.ActivateSource(GetTargetDevice());
277 private void CbCommandDestinationSelectedIndexChanged(object sender, EventArgs e)
279 bool enableVolumeButtons = (GetTargetDevice() == CecLogicalAddress.AudioSystem);
280 bVolUp.Enabled = enableVolumeButtons;
281 bVolDown.Enabled = enableVolumeButtons;
282 bMute.Enabled = enableVolumeButtons;
283 bActivateSource.Enabled = (GetTargetDevice() != CecLogicalAddress.Broadcast);
284 bScan.Enabled = (GetTargetDevice() != CecLogicalAddress.Broadcast);
287 private void BVolUpClick(object sender, EventArgs e)
289 Controller.Lib.VolumeUp(true);
292 private void BVolDownClick(object sender, EventArgs e)
294 Controller.Lib.VolumeDown(true);
297 private void BMuteClick(object sender, EventArgs e)
299 Controller.Lib.MuteAudio(true);
302 private void BRescanDevicesClick(object sender, EventArgs e)
304 Controller.CECActions.RescanDevices();
309 delegate void UpdateLogCallback();
310 private void UpdateLog()
312 if (tbLog.InvokeRequired)
314 UpdateLogCallback d = UpdateLog;
317 Invoke(d, new object[] { });
319 catch (Exception) { }
324 tbLog.Select(tbLog.Text.Length, 0);
325 tbLog.ScrollToCaret();
329 public void AddLogMessage(CecLogMessage message)
331 string strLevel = "";
332 bool display = false;
333 switch (message.Level)
335 case CecLogLevel.Error:
336 strLevel = "ERROR: ";
337 display = cbLogError.Checked;
339 case CecLogLevel.Warning:
340 strLevel = "WARNING: ";
341 display = cbLogWarning.Checked;
343 case CecLogLevel.Notice:
344 strLevel = "NOTICE: ";
345 display = cbLogNotice.Checked;
347 case CecLogLevel.Traffic:
348 strLevel = "TRAFFIC: ";
349 display = cbLogTraffic.Checked;
351 case CecLogLevel.Debug:
352 strLevel = "DEBUG: ";
353 display = cbLogDebug.Checked;
359 string strLog = string.Format("{0} {1,16} {2}", strLevel, message.Time, message.Message) + Environment.NewLine;
360 AddLogMessage(strLog);
364 public void AddLogMessage(string message)
368 if (_selectedTab == ConfigTab.Log)
372 private void BClearLogClick(object sender, EventArgs e)
378 private void BSaveLogClick(object sender, EventArgs e)
380 SaveFileDialog dialog = new SaveFileDialog
382 Title = Resources.where_do_you_want_to_store_the_log,
383 InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
384 FileName = Resources.cec_log_filename,
385 Filter = Resources.cec_log_filter,
389 if (dialog.ShowDialog() == DialogResult.OK)
391 FileStream fs = (FileStream)dialog.OpenFile();
394 MessageBox.Show(string.Format(Resources.cannot_open_for_writing, dialog.FileName), Resources.app_name, MessageBoxButtons.OK, MessageBoxIcon.Error);
398 StreamWriter writer = new StreamWriter(fs);
403 MessageBox.Show(string.Format(Resources.log_stored_as, dialog.FileName), Resources.app_name, MessageBoxButtons.OK, MessageBoxIcon.Information);
409 #region Tray icon and window controls
410 private void HideToolStripMenuItemClick(object sender, EventArgs e)
415 private void CloseToolStripMenuItemClick(object sender, EventArgs e)
420 private void AboutToolStripMenuItemClick(object sender, EventArgs e)
422 (new About(Controller.LibServerVersion, Controller.LibClientVersion, Controller.LibInfo)).ShowDialog();
425 private void AdvancedModeToolStripMenuItemClick(object sender, EventArgs e)
427 Controller.Settings.AdvancedMode.Value = !advancedModeToolStripMenuItem.Checked;
428 ShowHideAdvanced(!advancedModeToolStripMenuItem.Checked);
431 private void BCancelClick(object sender, EventArgs e)
436 private void TrayIconClick(object sender, EventArgs e)
438 if (e is MouseEventArgs && (e as MouseEventArgs).Button == MouseButtons.Left)
444 ShowInTaskbar = false;
446 tsMenuShowHide.Text = Resources.show;
451 ShowInTaskbar = true;
452 WindowState = FormWindowState.Normal;
454 tsMenuShowHide.Text = Resources.hide;
457 private void ShowHideToggle()
459 if (Visible && WindowState != FormWindowState.Minimized)
461 Controller.Settings.StartHidden.Value = true;
466 Controller.Settings.StartHidden.Value = false;
471 private void TsMenuCloseClick(object sender, EventArgs e)
476 private void CECTrayResize(object sender, EventArgs e)
478 if (WindowState == FormWindowState.Minimized)
484 private void TsMenuShowHideClick(object sender, EventArgs e)
489 public void ShowHideAdvanced(bool setTo)
493 tsAdvanced.Checked = true;
494 advancedModeToolStripMenuItem.Checked = true;
496 if (!tabPanel.Controls.Contains(tbTestCommands))
497 TabControls.Add(tbTestCommands);
498 if (!tabPanel.Controls.Contains(LogOutput))
499 TabControls.Add(LogOutput);
504 tsAdvanced.Checked = false;
505 advancedModeToolStripMenuItem.Checked = false;
507 tabPanel.Controls.Remove(tbTestCommands);
508 tabPanel.Controls.Remove(LogOutput);
513 private void TsAdvancedClick(object sender, EventArgs e)
515 Controller.Settings.AdvancedMode.Value = !tsAdvanced.Checked;
516 ShowHideAdvanced(!tsAdvanced.Checked);
519 public void SetStatusText(string status)
521 SetControlText(lStatus, status);
524 public void SetProgressBar(int progress, bool visible)
526 SetControlVisible(pProgress, visible);
527 SetProgressValue(pProgress, progress);
530 public void SetControlsEnabled(bool val)
533 SetControlEnabled(bClose, val);
534 SetControlEnabled(bSaveConfig, val);
535 SetControlEnabled(bReloadConfig, val);
538 SetControlEnabled(bRescanDevices, val);
539 SetControlEnabled(bSendImageViewOn, val);
540 SetControlEnabled(bStandby, val);
541 SetControlEnabled(bActivateSource, val);
542 SetControlEnabled(bScan, val);
544 bool enableVolumeButtons = (GetTargetDevice() == CecLogicalAddress.AudioSystem) && val;
545 SetControlEnabled(bVolUp, enableVolumeButtons);
546 SetControlEnabled(bVolDown, enableVolumeButtons);
547 SetControlEnabled(bMute, enableVolumeButtons);
550 private void TabControl1SelectedIndexChanged(object sender, EventArgs e)
552 switch (tabPanel.TabPages[tabPanel.SelectedIndex].Name)
554 case "tbTestCommands":
555 _selectedTab = ConfigTab.Tester;
558 _selectedTab = ConfigTab.Log;
562 _selectedTab = ConfigTab.Configuration;
568 #region Class members
569 private ConfigTab _selectedTab = ConfigTab.Configuration;
570 private string _log = string.Empty;
571 private CECController _controller;
572 public CECController Controller
576 return _controller ?? (_controller = new CECController(this));
579 public Control.ControlCollection TabControls
581 get { return tabPanel.Controls; }
583 public string SelectedTabName
585 get { return GetSelectedTabName(tabPanel, tabPanel.TabPages); }
589 private void AddNewApplicationToolStripMenuItemClick(object sender, EventArgs e)
591 ConfigureApplication appConfig = new ConfigureApplication(Controller.Settings, Controller);
592 Controller.DisplayDialog(appConfig, false);