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