LibCecTray: power management
[deb_libcec.git] / src / LibCecTray / ui / CECTray.cs
1 /*
2 * This file is part of the libCEC(R) library.
3 *
4 * libCEC(R) is Copyright (C) 2011-2013 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.Windows.Forms;
35 using CecSharp;
36 using System.IO;
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
44 namespace LibCECTray.ui
45 {
46 /// <summary>
47 /// The tab pages in this application
48 /// </summary>
49 internal enum ConfigTab
50 {
51 Configuration,
52 KeyConfiguration,
53 Tester,
54 Log,
55 WMC,
56 XBMC
57 }
58
59 /// <summary>
60 /// Main LibCecTray GUI
61 /// </summary>
62 partial class CECTray : AsyncForm
63 {
64 public CECTray()
65 {
66 Text = Resources.app_name;
67 InitializeComponent();
68 VisibleChanged += delegate
69 {
70 if (!Visible)
71 OnHide();
72 else
73 OnShow();
74 };
75 SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(OnPowerModeChanged);
76 SystemEvents.SessionEnding += new SessionEndingEventHandler(OnSessionEnding);
77 }
78
79 public void OnSessionEnding(object sender, SessionEndingEventArgs e)
80 {
81 Controller.Close();
82 }
83
84 public void OnPowerModeChanged(Object sender, PowerModeChangedEventArgs e)
85 {
86 switch (e.Mode)
87 {
88 case PowerModes.Resume:
89 Controller.Initialise();
90 break;
91 case PowerModes.Suspend:
92 Controller.Close();
93 break;
94 case PowerModes.StatusChange:
95 break;
96 }
97 }
98
99 public override sealed string Text
100 {
101 get { return base.Text; }
102 set { base.Text = value; }
103 }
104
105 public void Initialise()
106 {
107 Controller.Initialise();
108 }
109
110 protected override void Dispose(bool disposing)
111 {
112 Hide();
113 if (disposing)
114 {
115 Controller.Close();
116 }
117 if (disposing && (components != null))
118 {
119 components.Dispose();
120 }
121 base.Dispose(disposing);
122 }
123
124 #region Configuration tab
125 /// <summary>
126 /// Replaces the gui controls by the ones that are bound to the settings.
127 /// 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
128 /// </summary>
129 public void InitialiseSettingsComponent(CECSettings settings)
130 {
131 settings.WakeDevices.ReplaceControls(this, Configuration.Controls, lWakeDevices, cbWakeDevices);
132 settings.PowerOffDevices.ReplaceControls(this, Configuration.Controls, lPowerOff, cbPowerOffDevices);
133 settings.OverridePhysicalAddress.ReplaceControls(this, Configuration.Controls, cbOverrideAddress);
134 settings.OverrideTVVendor.ReplaceControls(this, Configuration.Controls, cbVendorOverride);
135 settings.PhysicalAddress.ReplaceControls(this, Configuration.Controls, tbPhysicalAddress);
136 settings.HDMIPort.ReplaceControls(this, Configuration.Controls, lPortNumber, cbPortNumber);
137 settings.ConnectedDevice.ReplaceControls(this, Configuration.Controls, lConnectedDevice, cbConnectedDevice);
138 settings.ActivateSource.ReplaceControls(this, Configuration.Controls, cbActivateSource);
139 settings.DeviceType.ReplaceControls(this, Configuration.Controls, lDeviceType, cbDeviceType);
140 settings.TVVendor.ReplaceControls(this, Configuration.Controls, cbVendorId);
141 settings.StartHidden.ReplaceControls(this, Configuration.Controls, cbStartMinimised);
142 }
143
144 private void BSaveClick(object sender, EventArgs e)
145 {
146 Controller.PersistSettings();
147 }
148
149 private void BReloadConfigClick(object sender, EventArgs e)
150 {
151 Controller.ResetDefaultSettings();
152 }
153 #endregion
154
155 #region CEC Tester tab
156 delegate void SetActiveDevicesCallback(string[] activeDevices);
157 public void SetActiveDevices(string[] activeDevices)
158 {
159 if (cbCommandDestination.InvokeRequired)
160 {
161 SetActiveDevicesCallback d = SetActiveDevices;
162 try
163 {
164 Invoke(d, new object[] { activeDevices });
165 }
166 catch (Exception) { }
167 }
168 else
169 {
170 cbCommandDestination.Items.Clear();
171 foreach (string item in activeDevices)
172 cbCommandDestination.Items.Add(item);
173 }
174 }
175
176 delegate CecLogicalAddress GetTargetDeviceCallback();
177 private CecLogicalAddress GetTargetDevice()
178 {
179 if (cbCommandDestination.InvokeRequired)
180 {
181 GetTargetDeviceCallback d = GetTargetDevice;
182 CecLogicalAddress retval = CecLogicalAddress.Unknown;
183 try
184 {
185 retval = (CecLogicalAddress)Invoke(d, new object[] { });
186 }
187 catch (Exception) { }
188 return retval;
189 }
190
191 return CECSettingLogicalAddresses.GetLogicalAddressFromString(cbCommandDestination.Text);
192 }
193
194 private void BSendImageViewOnClick(object sender, EventArgs e)
195 {
196 Controller.CECActions.SendImageViewOn(GetTargetDevice());
197 }
198
199 private void BStandbyClick(object sender, EventArgs e)
200 {
201 Controller.CECActions.SendStandby(GetTargetDevice());
202 }
203
204 private void BScanClick(object sender, EventArgs e)
205 {
206 Controller.CECActions.ShowDeviceInfo(GetTargetDevice());
207 }
208
209 private void BActivateSourceClick(object sender, EventArgs e)
210 {
211 Controller.CECActions.ActivateSource(GetTargetDevice());
212 }
213
214 private void CbCommandDestinationSelectedIndexChanged(object sender, EventArgs e)
215 {
216 bool enableVolumeButtons = (GetTargetDevice() == CecLogicalAddress.AudioSystem);
217 bVolUp.Enabled = enableVolumeButtons;
218 bVolDown.Enabled = enableVolumeButtons;
219 bMute.Enabled = enableVolumeButtons;
220 bActivateSource.Enabled = (GetTargetDevice() != CecLogicalAddress.Broadcast);
221 bScan.Enabled = (GetTargetDevice() != CecLogicalAddress.Broadcast);
222 }
223
224 private void BVolUpClick(object sender, EventArgs e)
225 {
226 Controller.Lib.VolumeUp(true);
227 }
228
229 private void BVolDownClick(object sender, EventArgs e)
230 {
231 Controller.Lib.VolumeDown(true);
232 }
233
234 private void BMuteClick(object sender, EventArgs e)
235 {
236 Controller.Lib.MuteAudio(true);
237 }
238
239 private void BRescanDevicesClick(object sender, EventArgs e)
240 {
241 Controller.CECActions.RescanDevices();
242 }
243 #endregion
244
245 #region Log tab
246 delegate void UpdateLogCallback();
247 private void UpdateLog()
248 {
249 if (tbLog.InvokeRequired)
250 {
251 UpdateLogCallback d = UpdateLog;
252 try
253 {
254 Invoke(d, new object[] { });
255 }
256 catch (Exception) { }
257 }
258 else
259 {
260 tbLog.Text = _log;
261 tbLog.Select(tbLog.Text.Length, 0);
262 tbLog.ScrollToCaret();
263 }
264 }
265
266 public void AddLogMessage(CecLogMessage message)
267 {
268 string strLevel = "";
269 bool display = false;
270 switch (message.Level)
271 {
272 case CecLogLevel.Error:
273 strLevel = "ERROR: ";
274 display = cbLogError.Checked;
275 break;
276 case CecLogLevel.Warning:
277 strLevel = "WARNING: ";
278 display = cbLogWarning.Checked;
279 break;
280 case CecLogLevel.Notice:
281 strLevel = "NOTICE: ";
282 display = cbLogNotice.Checked;
283 break;
284 case CecLogLevel.Traffic:
285 strLevel = "TRAFFIC: ";
286 display = cbLogTraffic.Checked;
287 break;
288 case CecLogLevel.Debug:
289 strLevel = "DEBUG: ";
290 display = cbLogDebug.Checked;
291 break;
292 }
293
294 if (display)
295 {
296 string strLog = string.Format("{0} {1,16} {2}", strLevel, message.Time, message.Message) + Environment.NewLine;
297 AddLogMessage(strLog);
298 }
299 }
300
301 public void AddLogMessage(string message)
302 {
303 _log += message;
304
305 if (_selectedTab == ConfigTab.Log)
306 UpdateLog();
307 }
308
309 private void BClearLogClick(object sender, EventArgs e)
310 {
311 _log = string.Empty;
312 UpdateLog();
313 }
314
315 private void BSaveLogClick(object sender, EventArgs e)
316 {
317 SaveFileDialog dialog = new SaveFileDialog
318 {
319 Title = Resources.where_do_you_want_to_store_the_log,
320 InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
321 FileName = Resources.cec_log_filename,
322 Filter = Resources.cec_log_filter,
323 FilterIndex = 1
324 };
325
326 if (dialog.ShowDialog() == DialogResult.OK)
327 {
328 FileStream fs = (FileStream)dialog.OpenFile();
329 if (!fs.CanWrite)
330 {
331 MessageBox.Show(string.Format(Resources.cannot_open_for_writing, dialog.FileName), Resources.app_name, MessageBoxButtons.OK, MessageBoxIcon.Error);
332 }
333 else
334 {
335 StreamWriter writer = new StreamWriter(fs);
336 writer.Write(_log);
337 writer.Close();
338 fs.Close();
339 fs.Dispose();
340 MessageBox.Show(string.Format(Resources.log_stored_as, dialog.FileName), Resources.app_name, MessageBoxButtons.OK, MessageBoxIcon.Information);
341 }
342 }
343 }
344 #endregion
345
346 #region Tray icon and window controls
347 private void HideToolStripMenuItemClick(object sender, EventArgs e)
348 {
349 ShowHideToggle();
350 }
351
352 private void CloseToolStripMenuItemClick(object sender, EventArgs e)
353 {
354 Dispose();
355 }
356
357 private void AboutToolStripMenuItemClick(object sender, EventArgs e)
358 {
359 (new About(Controller.LibServerVersion, Controller.LibClientVersion, Controller.LibInfo)).ShowDialog();
360 }
361
362 private void AdvancedModeToolStripMenuItemClick(object sender, EventArgs e)
363 {
364 Controller.Settings.AdvancedMode.Value = !advancedModeToolStripMenuItem.Checked;
365 ShowHideAdvanced(!advancedModeToolStripMenuItem.Checked);
366 }
367
368 private void BCancelClick(object sender, EventArgs e)
369 {
370 Dispose();
371 }
372
373 private void TrayIconClick(object sender, EventArgs e)
374 {
375 if (e is MouseEventArgs && (e as MouseEventArgs).Button == MouseButtons.Left)
376 ShowHideToggle();
377 }
378
379 public void OnHide()
380 {
381 ShowInTaskbar = false;
382 Visible = false;
383 tsMenuShowHide.Text = Resources.show;
384 }
385
386 public void OnShow()
387 {
388 ShowInTaskbar = true;
389 WindowState = FormWindowState.Normal;
390 Activate();
391 tsMenuShowHide.Text = Resources.hide;
392 }
393
394 private void ShowHideToggle()
395 {
396 if (Visible && WindowState != FormWindowState.Minimized)
397 {
398 Controller.Settings.StartHidden.Value = true;
399 Hide();
400 }
401 else
402 {
403 Controller.Settings.StartHidden.Value = false;
404 Show();
405 }
406 }
407
408 private void TsMenuCloseClick(object sender, EventArgs e)
409 {
410 Dispose();
411 }
412
413 private void CECTrayResize(object sender, EventArgs e)
414 {
415 if (WindowState == FormWindowState.Minimized)
416 Hide();
417 else
418 Show();
419 }
420
421 private void TsMenuShowHideClick(object sender, EventArgs e)
422 {
423 ShowHideToggle();
424 }
425
426 public void ShowHideAdvanced(bool setTo)
427 {
428 if (setTo)
429 {
430 tsAdvanced.Checked = true;
431 advancedModeToolStripMenuItem.Checked = true;
432 SuspendLayout();
433 if (!tabPanel.Controls.Contains(tbTestCommands))
434 TabControls.Add(tbTestCommands);
435 if (!tabPanel.Controls.Contains(LogOutput))
436 TabControls.Add(LogOutput);
437 ResumeLayout();
438 }
439 else
440 {
441 tsAdvanced.Checked = false;
442 advancedModeToolStripMenuItem.Checked = false;
443 SuspendLayout();
444 tabPanel.Controls.Remove(tbTestCommands);
445 tabPanel.Controls.Remove(LogOutput);
446 ResumeLayout();
447 }
448 }
449
450 private void TsAdvancedClick(object sender, EventArgs e)
451 {
452 Controller.Settings.AdvancedMode.Value = !tsAdvanced.Checked;
453 ShowHideAdvanced(!tsAdvanced.Checked);
454 }
455
456 public void SetStatusText(string status)
457 {
458 SetControlText(lStatus, status);
459 }
460
461 public void SetProgressBar(int progress, bool visible)
462 {
463 SetControlVisible(pProgress, visible);
464 SetProgressValue(pProgress, progress);
465 }
466
467 public void SetControlsEnabled(bool val)
468 {
469 //main tab
470 SetControlEnabled(bClose, val);
471 SetControlEnabled(bSaveConfig, val);
472 SetControlEnabled(bReloadConfig, val);
473
474 //tester tab
475 SetControlEnabled(bRescanDevices, val);
476 SetControlEnabled(bSendImageViewOn, val);
477 SetControlEnabled(bStandby, val);
478 SetControlEnabled(bActivateSource, val);
479 SetControlEnabled(bScan, val);
480
481 bool enableVolumeButtons = (GetTargetDevice() == CecLogicalAddress.AudioSystem) && val;
482 SetControlEnabled(bVolUp, enableVolumeButtons);
483 SetControlEnabled(bVolDown, enableVolumeButtons);
484 SetControlEnabled(bMute, enableVolumeButtons);
485 }
486
487 private void TabControl1SelectedIndexChanged(object sender, EventArgs e)
488 {
489 switch (tabPanel.TabPages[tabPanel.SelectedIndex].Name)
490 {
491 case "tbTestCommands":
492 _selectedTab = ConfigTab.Tester;
493 break;
494 case "LogOutput":
495 _selectedTab = ConfigTab.Log;
496 UpdateLog();
497 break;
498 default:
499 _selectedTab = ConfigTab.Configuration;
500 break;
501 }
502 }
503 #endregion
504
505 #region Class members
506 private ConfigTab _selectedTab = ConfigTab.Configuration;
507 private string _log = string.Empty;
508 private CECController _controller;
509 public CECController Controller
510 {
511 get
512 {
513 return _controller ?? (_controller = new CECController(this));
514 }
515 }
516 public Control.ControlCollection TabControls
517 {
518 get { return tabPanel.Controls; }
519 }
520 public string SelectedTabName
521 {
522 get { return GetSelectedTabName(tabPanel, tabPanel.TabPages); }
523 }
524 #endregion
525
526 private void AddNewApplicationToolStripMenuItemClick(object sender, EventArgs e)
527 {
528 ConfigureApplication appConfig = new ConfigureApplication(Controller.Settings, Controller);
529 Controller.DisplayDialog(appConfig, false);
530 }
531 }
532 }