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