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.Collections.Generic;
35 using System.Windows.Forms;
37 using LibCECTray.Properties;
38 using LibCECTray.controller.applications;
39 using LibCECTray.settings;
42 namespace LibCECTray.controller
44 internal class CECController : CecCallbackMethods
46 public CECController(CECTray gui)
49 CECActions = new Actions(this);
53 Settings.SettingChanged += OnSettingChanged;
58 /// Called when a setting changed
60 /// <param name="setting">The setting that changed</param>
61 /// <param name="oldValue">The old value</param>
62 /// <param name="newValue">The new value</param>
63 private void OnSettingChanged(CECSetting setting, object oldValue, object newValue)
65 if (setting.KeyName == CECSettings.KeyHDMIPort)
67 CECSettingByte byteSetting = setting as CECSettingByte;
68 if (byteSetting != null)
70 if (!Settings.OverridePhysicalAddress.Value)
71 Config.HDMIPort = byteSetting.Value;
72 CECActions.SetConnectedDevice(Settings.ConnectedDevice.Value, byteSetting.Value);
75 else if (setting.KeyName == CECSettings.KeyConnectedToHDMIDevice)
77 CECSettingLogicalAddress laSetting = setting as CECSettingLogicalAddress;
78 if (laSetting != null)
80 if (!Settings.OverridePhysicalAddress.Value)
81 Config.BaseDevice = laSetting.Value;
82 CECActions.SetConnectedDevice(laSetting.Value, Settings.HDMIPort.Value);
85 else if (setting.KeyName == CECSettings.KeyPhysicalAddress)
87 CECSettingUShort ushortSetting = setting as CECSettingUShort;
88 if (ushortSetting != null && Settings.OverridePhysicalAddress.Value && Config.PhysicalAddress != ushortSetting.Value)
90 Config.PhysicalAddress = ushortSetting.Value;
91 CECActions.SetPhysicalAddress(ushortSetting.Value);
94 else if (setting.KeyName == CECSettings.KeyOverridePhysicalAddress)
96 CECSettingBool boolSetting = setting as CECSettingBool;
97 if (boolSetting != null)
99 Settings.PhysicalAddress.Enabled = boolSetting.Value;
100 Settings.HDMIPort.Enabled = !boolSetting.Value;
101 Settings.ConnectedDevice.Enabled = !boolSetting.Value;
102 if (boolSetting.Value)
104 Config.BaseDevice = Settings.ConnectedDevice.Value;
106 Config.PhysicalAddress = Settings.PhysicalAddress.Value;
110 Config.BaseDevice = Settings.ConnectedDevice.Value;
111 Config.HDMIPort = Settings.HDMIPort.Value;
112 Config.PhysicalAddress = 0xFFFF;
116 else if (setting.KeyName == CECSettings.KeyDeviceType)
118 CECSettingDeviceType dtSetting = setting as CECSettingDeviceType;
119 if (dtSetting != null)
121 if (dtSetting.Value != Config.DeviceTypes.Types[0] && Settings.OverrideTVVendor.Value)
123 Config.DeviceTypes.Types[0] = dtSetting.Value;
124 if (!_deviceChangeWarningDisplayed)
126 _deviceChangeWarningDisplayed = true;
127 MessageBox.Show(Resources.device_type_changed, Resources.app_name, MessageBoxButtons.OK,
128 MessageBoxIcon.Warning);
133 else if (setting.KeyName == CECSettings.KeyOverrideTVVendor)
135 CECSettingBool boolSetting = setting as CECSettingBool;
136 if (boolSetting != null)
138 Settings.TVVendor.Enabled = boolSetting.Value;
139 Settings.TVVendor.Value = boolSetting.Value ? Lib.GetDeviceVendorId(CecLogicalAddress.Tv) : CecVendorId.Unknown;
140 Config.TvVendor = boolSetting.Value ? Settings.TVVendor.Value : CecVendorId.Unknown;
143 else if (setting.KeyName == CECSettings.KeyActivateSource)
145 CECSettingBool boolSetting = setting as CECSettingBool;
146 if (boolSetting != null)
147 Config.ActivateSource = boolSetting.Value;
149 else if (setting.KeyName == CECSettings.KeyTVVendor)
151 CECSettingVendorId vendorSetting = setting as CECSettingVendorId;
152 if (vendorSetting != null && Settings.OverrideTVVendor.Value)
153 Config.TvVendor = vendorSetting.Value;
155 else if (setting.KeyName == CECSettings.KeyWakeDevices)
157 CECSettingLogicalAddresses laSetting = setting as CECSettingLogicalAddresses;
158 if (laSetting != null)
159 Config.WakeDevices = laSetting.Value;
161 else if (setting.KeyName == CECSettings.KeyPowerOffDevices)
163 CECSettingLogicalAddresses laSetting = setting as CECSettingLogicalAddresses;
164 if (laSetting != null)
165 Config.PowerOffDevices = laSetting.Value;
170 /// Persist all known settings in the registry
172 public void PersistSettings()
174 /* save settings in the eeprom */
175 Lib.SetConfiguration(Config);
176 Lib.PersistConfiguration(Config);
178 /* and in the registry */
183 /// Reset all settings to their default values
185 public void ResetDefaultSettings()
187 SetControlsEnabled(false);
188 _gui.ShowHideAdvanced(false);
190 CECActions.SuppressUpdates = true;
191 Settings.SetDefaultValues();
193 Lib.SetConfiguration(Config);
194 CECActions.SuppressUpdates = false;
196 _gui.ShowHideAdvanced(Settings.AdvancedMode.Value);
197 SetControlsEnabled(true);
202 /// Opens a connection to libCEC and register known applications
204 public void Initialise()
211 CECActions.ConnectToDevice(Config);
212 Applications.Initialise(this);
216 /// Closes the connection to libCEC
220 Lib.DisableCallbacks();
221 Lib.StandbyDevices(CecLogicalAddress.Broadcast);
223 _initialised = false;
227 /// Register a new application controller, which will add a new tab for the application
229 /// <param name="app">The new application to register</param>
230 /// <returns>True when registered, false otherwise</returns>
231 public bool RegisterApplication(ApplicationController app)
233 if (_applications.Contains(app)) return false;
234 _applications.Add(app);
236 _gui.SuspendLayout();
237 _gui.TabControls.Add(app.UiControl);
247 /// Initialises the UI
249 private void InitialiseGui()
251 _gui.SuspendLayout();
252 _gui.InitialiseSettingsComponent(Settings);
254 // add the controller tabs to the gui
255 foreach (var ui in ApplicationUIs)
256 _gui.TabControls.Add(ui);
258 // enable/disable advanced mode
259 _gui.ShowHideAdvanced(Settings.AdvancedMode.Value);
267 /// <param name="control">The dialog to display</param>
268 /// <param name="modal">True when modal</param>
269 public void DisplayDialog(Form control, bool modal)
271 _gui.DisplayDialog(control, modal);
275 /// Changes the status text of this window
277 /// <param name="status">The new status text</param>
278 public void SetStatusText(string status)
280 _gui.SetStatusText(status);
284 /// Changes the progress bar value
286 /// <param name="progress">The new progress percentage</param>
287 /// <param name="visible">True to make the bar visible, false otherwise</param>
288 public void SetProgressBar(int progress, bool visible)
290 _gui.SetProgressBar(progress, visible);
294 /// Enable/disable all controls
296 /// <param name="val">True to enable, false to disable</param>
297 public void SetControlsEnabled(bool val)
299 Settings.Enabled = val;
300 foreach (var app in _applications)
301 app.UiControl.SetEnabled(val);
302 _gui.SetControlsEnabled(val);
306 /// (re)check the logical addresses of the active devices on the bus
308 public void CheckActiveDevices()
310 var activeDevices = Lib.GetActiveDevices();
311 List<string> deviceList = new List<string>();
312 foreach (var activeDevice in activeDevices.Addresses)
314 if (activeDevice != CecLogicalAddress.Unknown)
315 deviceList.Add(string.Format("{0,1:X} : {1}", (int)activeDevice, Lib.ToString(activeDevice)));
317 deviceList.Add(string.Format("{0,1:X} : {1}", (int)CecLogicalAddress.Broadcast, Lib.ToString(CecLogicalAddress.Broadcast)));
319 _gui.SetActiveDevices(deviceList.ToArray());
323 /// Show/hide the taskbar entry
325 /// <param name="val">True to show, false to hide</param>
326 public void SetShowInTaskbar(bool val)
328 _gui.SetShowInTaskbar(val);
332 /// Show or hide this window
334 /// <param name="val">True to show, false to hide</param>
335 public void Hide(bool val)
341 #region Callbacks called by libCEC
342 public override int ReceiveCommand(CecCommand command)
347 public override int ReceiveKeypress(CecKeypress key)
349 foreach (var app in _applications)
351 bool keySent = app.SendKey(key, app.UiName == _gui.SelectedTabName);
355 string strLog = string.Format("sent key '{0}' to '{1}'", (int) key.Keycode, app.UiName) + Environment.NewLine;
356 _gui.AddLogMessage(strLog);
364 public override int ReceiveLogMessage(CecLogMessage message)
366 _gui.AddLogMessage(message);
370 public override int ReceiveAlert(CecAlert alert, CecParameter data)
374 case CecAlert.ServiceDevice:
375 MessageBox.Show(Resources.alert_service_device, Resources.cec_alert, MessageBoxButtons.OK, MessageBoxIcon.Warning);
377 case CecAlert.ConnectionLost:
378 MessageBox.Show(Resources.alert_connection_lost, Resources.cec_alert, MessageBoxButtons.OK, MessageBoxIcon.Warning);
380 case CecAlert.PermissionError:
381 MessageBox.Show(Resources.alert_permission_error, Resources.cec_alert, MessageBoxButtons.OK, MessageBoxIcon.Warning);
383 case CecAlert.PortBusy:
384 MessageBox.Show(Resources.alert_port_busy, Resources.cec_alert, MessageBoxButtons.OK, MessageBoxIcon.Warning);
386 case CecAlert.PhysicalAddressError:
387 MessageBox.Show(Resources.alert_physical_address_error, Resources.cec_alert, MessageBoxButtons.OK, MessageBoxIcon.Warning);
389 case CecAlert.TVPollFailed:
390 MessageBox.Show(Resources.alert_tv_poll_failed, Resources.cec_alert, MessageBoxButtons.OK, MessageBoxIcon.Warning);
396 public override int ConfigurationChanged(LibCECConfiguration config)
398 Settings.PhysicalAddress.Value = Config.PhysicalAddress;
399 Settings.ConnectedDevice.Value = Config.BaseDevice == CecLogicalAddress.AudioSystem ? CecLogicalAddress.AudioSystem : CecLogicalAddress.Tv;
400 Settings.HDMIPort.Value = Config.HDMIPort;
401 Settings.WakeDevices.Value = Config.WakeDevices;
402 Settings.PowerOffDevices.Value = Config.PowerOffDevices;
403 Settings.ActivateSource.Value = Config.ActivateSource;
404 Settings.DeviceType.Value = config.DeviceTypes.Types[0];
406 if (config.TvVendor != CecVendorId.Unknown)
408 Settings.OverrideTVVendor.Value = true;
409 Settings.TVVendor.Value = config.TvVendor;
413 Settings.OverrideTVVendor.Value = false;
416 _gui.SetControlText(_gui, Resources.app_name + " - libCEC " + Lib.ToString(Config.ServerVersion));
418 CECActions.UpdatePhysicalAddress();
422 public override void SourceActivated(CecLogicalAddress logicalAddress, bool activated)
427 foreach (var app in _applications)
429 if (app.AutoStartApplication.Value)
437 /// List of tab pages for each application that the UI supports
439 public List<ControllerTabPage> ApplicationUIs
443 List<ControllerTabPage> retVal = new List<ControllerTabPage>();
444 foreach (var app in _applications)
445 retVal.Add(app.UiControl);
451 /// List of application controllers that the UI supports
453 private readonly List<ApplicationController> _applications = new List<ApplicationController>();
456 /// Settings that are persisted in the registry (when not using the default value)
458 public CECSettings Settings
460 get { return _settings ?? (_settings = new CECSettings(OnSettingChanged)); }
462 private CECSettings _settings;
465 /// libCEC configuration for the application
467 private LibCECConfiguration Config
473 _config = new LibCECConfiguration { DeviceName = "CEC Tray", ClientVersion = CecClientVersion.CurrentVersion };
474 _config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice;
475 _config.SetCallbacks(this);
477 if (Settings.OverridePhysicalAddress.Value)
479 _config.PhysicalAddress = Settings.PhysicalAddress.Value;
480 _config.HDMIPort = 0;
481 _config.BaseDevice = CecLogicalAddress.Unknown;
485 _config.PhysicalAddress = 0;
486 _config.HDMIPort = Settings.HDMIPort.Value;
487 _config.BaseDevice = Settings.ConnectedDevice.Value;
489 _config.ActivateSource = Settings.ActivateSource.Value;
490 _config.DeviceTypes.Types[0] = Settings.DeviceType.Value;
491 if (Settings.OverrideTVVendor.Value)
492 _config.TvVendor = Settings.TVVendor.Value;
493 _config.WakeDevices = Settings.WakeDevices.Value;
494 _config.PowerOffDevices = Settings.PowerOffDevices.Value;
499 private LibCECConfiguration _config;
502 /// Get build info from libCEC
504 public string LibInfo
506 get { return Lib.GetLibInfo(); }
510 /// libCEC API version
512 public string LibServerVersion
514 get { return Lib.ToString(Config.ServerVersion); }
518 /// libCEC client API version
520 public string LibClientVersion
522 get { return Lib.ToString(Config.ClientVersion); }
526 /// Get the usb vendor id
528 public ushort AdapterVendorId
530 get { return Lib.GetAdapterVendorId(); }
534 /// Get the usb product id
536 public ushort AdapterProductId
538 get { return Lib.GetAdapterProductId(); }
545 public LibCecSharp Lib
547 get { return _lib ?? (_lib = new LibCecSharp(Config)); }
549 private LibCecSharp _lib;
551 private readonly CECTray _gui;
552 public Actions CECActions;
553 private bool _deviceChangeWarningDisplayed;
554 private bool _initialised;