e82bce0c3279c020e2594a83d0e047d28dbbcc20
[deb_libcec.git] / src / LibCecTray / controller / CECController.cs
1 /*
2 * This file is part of the libCEC(R) library.
3 *
4 * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved.
5 * libCEC(R) is an original work, containing original code.
6 *
7 * libCEC(R) is a trademark of Pulse-Eight Limited.
8 *
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.
13 *
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.
18 *
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.
22 *
23 *
24 * Alternatively, you can license this library under a commercial license,
25 * please contact Pulse-Eight Licensing for more information.
26 *
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/
31 */
32
33 using System;
34 using System.Collections.Generic;
35 using System.Windows.Forms;
36 using CecSharp;
37 using LibCECTray.Properties;
38 using LibCECTray.controller.applications;
39 using LibCECTray.settings;
40 using LibCECTray.ui;
41
42 namespace LibCECTray.controller
43 {
44 internal class CECController : CecCallbackMethods
45 {
46 public CECController(CECTray gui)
47 {
48 _gui = gui;
49 CECActions = new Actions(this);
50
51 InitialiseGui();
52
53 Settings.SettingChanged += OnSettingChanged;
54 }
55
56 #region Settings
57 /// <summary>
58 /// Called when a setting changed
59 /// </summary>
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)
64 {
65 if (setting.KeyName == CECSettings.KeyHDMIPort)
66 {
67 CECSettingByte byteSetting = setting as CECSettingByte;
68 if (byteSetting != null)
69 {
70 if (!Settings.OverridePhysicalAddress.Value)
71 Config.HDMIPort = byteSetting.Value;
72 CECActions.SetConnectedDevice(Settings.ConnectedDevice.Value, byteSetting.Value);
73 }
74 }
75 else if (setting.KeyName == CECSettings.KeyConnectedToHDMIDevice)
76 {
77 CECSettingLogicalAddress laSetting = setting as CECSettingLogicalAddress;
78 if (laSetting != null)
79 {
80 if (!Settings.OverridePhysicalAddress.Value)
81 Config.BaseDevice = laSetting.Value;
82 CECActions.SetConnectedDevice(laSetting.Value, Settings.HDMIPort.Value);
83 }
84 }
85 else if (setting.KeyName == CECSettings.KeyPhysicalAddress)
86 {
87 CECSettingUShort ushortSetting = setting as CECSettingUShort;
88 if (ushortSetting != null && Settings.OverridePhysicalAddress.Value && Config.PhysicalAddress != ushortSetting.Value)
89 {
90 Config.PhysicalAddress = ushortSetting.Value;
91 CECActions.SetPhysicalAddress(ushortSetting.Value);
92 }
93 }
94 else if (setting.KeyName == CECSettings.KeyOverridePhysicalAddress)
95 {
96 CECSettingBool boolSetting = setting as CECSettingBool;
97 if (boolSetting != null)
98 {
99 Settings.PhysicalAddress.Enabled = boolSetting.Value;
100 Settings.HDMIPort.Enabled = !boolSetting.Value;
101 Settings.ConnectedDevice.Enabled = !boolSetting.Value;
102 if (boolSetting.Value)
103 {
104 Config.BaseDevice = Settings.ConnectedDevice.Value;
105 Config.HDMIPort = 0;
106 Config.PhysicalAddress = Settings.PhysicalAddress.Value;
107 }
108 else
109 {
110 Config.BaseDevice = Settings.ConnectedDevice.Value;
111 Config.HDMIPort = Settings.HDMIPort.Value;
112 Config.PhysicalAddress = 0xFFFF;
113 }
114 }
115 }
116 else if (setting.KeyName == CECSettings.KeyDeviceType)
117 {
118 CECSettingDeviceType dtSetting = setting as CECSettingDeviceType;
119 if (dtSetting != null)
120 {
121 if (dtSetting.Value != Config.DeviceTypes.Types[0] && Settings.OverrideTVVendor.Value)
122 {
123 Config.DeviceTypes.Types[0] = dtSetting.Value;
124 if (!_deviceChangeWarningDisplayed)
125 {
126 _deviceChangeWarningDisplayed = true;
127 MessageBox.Show(Resources.device_type_changed, Resources.app_name, MessageBoxButtons.OK,
128 MessageBoxIcon.Warning);
129 }
130 }
131 }
132 }
133 else if (setting.KeyName == CECSettings.KeyOverrideTVVendor)
134 {
135 CECSettingBool boolSetting = setting as CECSettingBool;
136 if (boolSetting != null)
137 {
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;
141 }
142 }
143 else if (setting.KeyName == CECSettings.KeyActivateSource)
144 {
145 CECSettingBool boolSetting = setting as CECSettingBool;
146 if (boolSetting != null)
147 Config.ActivateSource = boolSetting.Value;
148 }
149 else if (setting.KeyName == CECSettings.KeyTVVendor)
150 {
151 CECSettingVendorId vendorSetting = setting as CECSettingVendorId;
152 if (vendorSetting != null && Settings.OverrideTVVendor.Value)
153 Config.TvVendor = vendorSetting.Value;
154 }
155 else if (setting.KeyName == CECSettings.KeyWakeDevices)
156 {
157 CECSettingLogicalAddresses laSetting = setting as CECSettingLogicalAddresses;
158 if (laSetting != null)
159 Config.WakeDevices = laSetting.Value;
160 }
161 else if (setting.KeyName == CECSettings.KeyPowerOffDevices)
162 {
163 CECSettingLogicalAddresses laSetting = setting as CECSettingLogicalAddresses;
164 if (laSetting != null)
165 Config.PowerOffDevices = laSetting.Value;
166 }
167 }
168
169 /// <summary>
170 /// Persist all known settings in the registry
171 /// </summary>
172 public void PersistSettings()
173 {
174 /* save settings in the eeprom */
175 Lib.SetConfiguration(Config);
176 Lib.PersistConfiguration(Config);
177
178 /* and in the registry */
179 Settings.Persist();
180 }
181
182 /// <summary>
183 /// Reset all settings to their default values
184 /// </summary>
185 public void ResetDefaultSettings()
186 {
187 SetControlsEnabled(false);
188 _gui.ShowHideAdvanced(false);
189
190 CECActions.SuppressUpdates = true;
191 Settings.SetDefaultValues();
192 _config = null;
193 Lib.SetConfiguration(Config);
194 CECActions.SuppressUpdates = false;
195
196 _gui.ShowHideAdvanced(Settings.AdvancedMode.Value);
197 SetControlsEnabled(true);
198 }
199 #endregion
200
201 /// <summary>
202 /// Opens a connection to libCEC and register known applications
203 /// </summary>
204 public void Initialise()
205 {
206 CECActions.ConnectToDevice(Config);
207 Applications.Initialise(this);
208 }
209
210 /// <summary>
211 /// Closes the connection to libCEC
212 /// </summary>
213 public void Close()
214 {
215 Lib.DisableCallbacks();
216 Lib.StandbyDevices(CecLogicalAddress.Broadcast);
217 Lib.Close();
218 }
219
220 /// <summary>
221 /// Register a new application controller, which will add a new tab for the application
222 /// </summary>
223 /// <param name="app">The new application to register</param>
224 /// <returns>True when registered, false otherwise</returns>
225 public bool RegisterApplication(ApplicationController app)
226 {
227 if (_applications.Contains(app)) return false;
228 _applications.Add(app);
229
230 _gui.SuspendLayout();
231 _gui.TabControls.Add(app.UiControl);
232 _gui.ResumeLayout();
233
234 app.Initialise();
235
236 return true;
237 }
238
239 #region GUI controls
240 /// <summary>
241 /// Initialises the UI
242 /// </summary>
243 private void InitialiseGui()
244 {
245 _gui.SuspendLayout();
246 _gui.InitialiseSettingsComponent(Settings);
247
248 // add the controller tabs to the gui
249 foreach (var ui in ApplicationUIs)
250 _gui.TabControls.Add(ui);
251
252 // enable/disable advanced mode
253 _gui.ShowHideAdvanced(Settings.AdvancedMode.Value);
254
255 _gui.ResumeLayout();
256 }
257
258 /// <summary>
259 /// Display a dialog
260 /// </summary>
261 /// <param name="control">The dialog to display</param>
262 /// <param name="modal">True when modal</param>
263 public void DisplayDialog(Form control, bool modal)
264 {
265 _gui.DisplayDialog(control, modal);
266 }
267
268 /// <summary>
269 /// Changes the status text of this window
270 /// </summary>
271 /// <param name="status">The new status text</param>
272 public void SetStatusText(string status)
273 {
274 _gui.SetStatusText(status);
275 }
276
277 /// <summary>
278 /// Changes the progress bar value
279 /// </summary>
280 /// <param name="progress">The new progress percentage</param>
281 /// <param name="visible">True to make the bar visible, false otherwise</param>
282 public void SetProgressBar(int progress, bool visible)
283 {
284 _gui.SetProgressBar(progress, visible);
285 }
286
287 /// <summary>
288 /// Enable/disable all controls
289 /// </summary>
290 /// <param name="val">True to enable, false to disable</param>
291 public void SetControlsEnabled(bool val)
292 {
293 Settings.Enabled = val;
294 foreach (var app in _applications)
295 app.UiControl.SetEnabled(val);
296 _gui.SetControlsEnabled(val);
297 }
298
299 /// <summary>
300 /// (re)check the logical addresses of the active devices on the bus
301 /// </summary>
302 public void CheckActiveDevices()
303 {
304 var activeDevices = Lib.GetActiveDevices();
305 List<string> deviceList = new List<string>();
306 foreach (var activeDevice in activeDevices.Addresses)
307 {
308 if (activeDevice != CecLogicalAddress.Unknown)
309 deviceList.Add(string.Format("{0,1:X} : {1}", (int)activeDevice, Lib.ToString(activeDevice)));
310 }
311 deviceList.Add(string.Format("{0,1:X} : {1}", (int)CecLogicalAddress.Broadcast, Lib.ToString(CecLogicalAddress.Broadcast)));
312
313 _gui.SetActiveDevices(deviceList.ToArray());
314 }
315
316 /// <summary>
317 /// Show/hide the taskbar entry
318 /// </summary>
319 /// <param name="val">True to show, false to hide</param>
320 public void SetShowInTaskbar(bool val)
321 {
322 _gui.SetShowInTaskbar(val);
323 }
324
325 /// <summary>
326 /// Show or hide this window
327 /// </summary>
328 /// <param name="val">True to show, false to hide</param>
329 public void Hide(bool val)
330 {
331 _gui.SafeHide(val);
332 }
333 #endregion
334
335 #region Callbacks called by libCEC
336 public override int ReceiveCommand(CecCommand command)
337 {
338 return 0;
339 }
340
341 public override int ReceiveKeypress(CecKeypress key)
342 {
343 foreach (var app in _applications)
344 {
345 bool keySent = app.SendKey(key, app.UiName == _gui.SelectedTabName);
346
347 if (keySent)
348 {
349 string strLog = string.Format("sent key '{0}' to '{1}'", (int) key.Keycode, app.UiName) + Environment.NewLine;
350 _gui.AddLogMessage(strLog);
351 break;
352 }
353 }
354
355 return 1;
356 }
357
358 public override int ReceiveLogMessage(CecLogMessage message)
359 {
360 _gui.AddLogMessage(message);
361 return 1;
362 }
363
364 public override int ConfigurationChanged(LibCECConfiguration config)
365 {
366 Settings.PhysicalAddress.Value = Config.PhysicalAddress;
367 Settings.ConnectedDevice.Value = Config.BaseDevice == CecLogicalAddress.AudioSystem ? CecLogicalAddress.AudioSystem : CecLogicalAddress.Tv;
368 Settings.HDMIPort.Value = Config.HDMIPort;
369 Settings.WakeDevices.Value = Config.WakeDevices;
370 Settings.PowerOffDevices.Value = Config.PowerOffDevices;
371 Settings.ActivateSource.Value = Config.ActivateSource;
372 Settings.DeviceType.Value = config.DeviceTypes.Types[0];
373
374 if (config.TvVendor != CecVendorId.Unknown)
375 {
376 Settings.OverrideTVVendor.Value = true;
377 Settings.TVVendor.Value = config.TvVendor;
378 }
379 else
380 {
381 Settings.OverrideTVVendor.Value = false;
382 }
383
384 _gui.SetControlText(_gui, Resources.app_name + " - libCEC " + Lib.ToString(Config.ServerVersion));
385
386 CECActions.UpdatePhysicalAddress();
387 return 1;
388 }
389
390 public override void SourceActivated(CecLogicalAddress logicalAddress, bool activated)
391 {
392 if (!activated)
393 return;
394
395 foreach (var app in _applications)
396 {
397 if (app.AutoStartApplication.Value)
398 app.Start(false);
399 }
400 }
401 #endregion
402
403 #region Members
404 /// <summary>
405 /// List of tab pages for each application that the UI supports
406 /// </summary>
407 public List<ControllerTabPage> ApplicationUIs
408 {
409 get
410 {
411 List<ControllerTabPage> retVal = new List<ControllerTabPage>();
412 foreach (var app in _applications)
413 retVal.Add(app.UiControl);
414 return retVal;
415 }
416 }
417
418 /// <summary>
419 /// List of application controllers that the UI supports
420 /// </summary>
421 private readonly List<ApplicationController> _applications = new List<ApplicationController>();
422
423 /// <summary>
424 /// Settings that are persisted in the registry (when not using the default value)
425 /// </summary>
426 public CECSettings Settings
427 {
428 get { return _settings ?? (_settings = new CECSettings(OnSettingChanged)); }
429 }
430 private CECSettings _settings;
431
432 /// <summary>
433 /// libCEC configuration for the application
434 /// </summary>
435 private LibCECConfiguration Config
436 {
437 get
438 {
439 if (_config == null)
440 {
441 _config = new LibCECConfiguration { DeviceName = "CEC Tray", ClientVersion = CecClientVersion.Version2_1_0 };
442 _config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice;
443 _config.SetCallbacks(this);
444
445 if (Settings.OverridePhysicalAddress.Value)
446 {
447 _config.PhysicalAddress = Settings.PhysicalAddress.Value;
448 _config.HDMIPort = 0;
449 _config.BaseDevice = CecLogicalAddress.Unknown;
450 }
451 else
452 {
453 _config.PhysicalAddress = 0;
454 _config.HDMIPort = Settings.HDMIPort.Value;
455 _config.BaseDevice = Settings.ConnectedDevice.Value;
456 }
457 _config.ActivateSource = Settings.ActivateSource.Value;
458 _config.DeviceTypes.Types[0] = Settings.DeviceType.Value;
459 if (Settings.OverrideTVVendor.Value)
460 _config.TvVendor = Settings.TVVendor.Value;
461 _config.WakeDevices = Settings.WakeDevices.Value;
462 _config.PowerOffDevices = Settings.PowerOffDevices.Value;
463 }
464 return _config;
465 }
466 }
467 private LibCECConfiguration _config;
468
469 /// <summary>
470 /// Get build info from libCEC
471 /// </summary>
472 public string LibInfo
473 {
474 get { return Lib.GetLibInfo(); }
475 }
476
477 /// <summary>
478 /// libCEC API version
479 /// </summary>
480 public string LibServerVersion
481 {
482 get { return Lib.ToString(Config.ServerVersion); }
483 }
484
485 /// <summary>
486 /// libCEC client API version
487 /// </summary>
488 public string LibClientVersion
489 {
490 get { return Lib.ToString(Config.ClientVersion); }
491 }
492
493 /// <summary>
494 /// Get the usb vendor id
495 /// </summary>
496 public ushort AdapterVendorId
497 {
498 get { return Lib.GetAdapterVendorId(); }
499 }
500
501 /// <summary>
502 /// Get the usb product id
503 /// </summary>
504 public ushort AdapterProductId
505 {
506 get { return Lib.GetAdapterProductId(); }
507 }
508
509
510 /// <summary>
511 /// libCEC
512 /// </summary>
513 public LibCecSharp Lib
514 {
515 get { return _lib ?? (_lib = new LibCecSharp(Config)); }
516 }
517 private LibCecSharp _lib;
518
519 private readonly CECTray _gui;
520 public Actions CECActions;
521 private bool _deviceChangeWarningDisplayed;
522
523 #endregion
524 }
525 }