Commit | Line | Data |
---|---|---|
f017f3c4 LOK |
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.Globalization; | |
35 | using System.IO; | |
36 | using System.Text; | |
37 | using System.Windows.Forms; | |
38 | using System.Xml; | |
39 | using CecSharp; | |
40 | using LibCECTray.Properties; | |
41 | using LibCECTray.settings; | |
42 | ||
43 | namespace LibCECTray.controller.applications.@internal | |
44 | { | |
45 | internal class XBMCController : ApplicationController | |
46 | { | |
47 | public XBMCController(CECSettings settings) : | |
48 | base(settings, | |
49 | Resources.application_xbmc, | |
50 | "XBMC", | |
51 | "XBMC.exe", | |
52 | Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\XBMC") | |
53 | { | |
54 | IsInternal = true; | |
55 | AutoStartApplication.Value = false; | |
56 | ControlApplication.Value = false; | |
57 | ||
58 | LoadXMLConfiguration(); | |
f4729954 LOK |
59 | |
60 | ApplicationRunningChanged += RunningChanged; | |
61 | } | |
62 | ||
63 | static void RunningChanged(bool running) | |
64 | { | |
65 | if (running) | |
66 | { | |
67 | // XBMC is running, close the application, or we'll block communication | |
68 | Application.Exit(); | |
69 | } | |
f017f3c4 LOK |
70 | } |
71 | ||
72 | public override ApplicationAction DefaultValue(CecKeypress key) | |
73 | { | |
74 | return null; | |
75 | } | |
76 | ||
77 | public override ControllerTabPage UiControl | |
78 | { | |
79 | get { return UIControlInternal ?? (UIControlInternal = new XBMCControllerUI(this)); } | |
80 | } | |
81 | ||
82 | public bool LoadXMLConfiguration() | |
49689754 | 83 | { |
5156a42c LOK |
84 | var xbmcDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\XBMC\userdata\peripheral_data"; |
85 | return LoadXMLConfiguration(xbmcDir + string.Format(@"\usb_{0:X}_{1:X}.xml", Program.Instance.Controller.AdapterVendorId, Program.Instance.Controller.AdapterProductId)) || | |
86 | LoadXMLConfiguration(xbmcDir + @"\usb_2548_1001.xml") || | |
87 | LoadXMLConfiguration(xbmcDir + @"\usb_2548_1002.xml"); | |
88 | } | |
8768aeca | 89 | |
5156a42c LOK |
90 | public bool LoadXMLConfiguration(string filename) |
91 | { | |
92 | bool gotConfig = false; | |
93 | if (File.Exists(filename)) | |
f017f3c4 | 94 | { |
5156a42c | 95 | XmlTextReader reader = new XmlTextReader(filename); |
f017f3c4 LOK |
96 | while (reader.Read()) |
97 | { | |
98 | gotConfig = true; | |
99 | switch (reader.NodeType) | |
100 | { | |
101 | case XmlNodeType.Element: | |
102 | if (reader.Name.ToLower() == "setting") | |
103 | { | |
104 | string name = string.Empty; | |
105 | string value = string.Empty; | |
106 | ||
107 | while (reader.MoveToNextAttribute()) | |
108 | { | |
109 | if (reader.Name.ToLower().Equals("id")) | |
110 | name = reader.Value.ToLower(); | |
111 | if (reader.Name.ToLower().Equals("value")) | |
112 | value = reader.Value; | |
113 | } | |
114 | ||
115 | switch (name) | |
116 | { | |
117 | case "cec_hdmi_port": | |
118 | { | |
119 | byte iPort; | |
120 | if (byte.TryParse(value, out iPort)) | |
121 | Settings.HDMIPort.Value = iPort; | |
122 | } | |
123 | break; | |
124 | case "connected_device": | |
125 | { | |
1b09c8f6 LOK |
126 | int iDevice; |
127 | if (int.TryParse(value, out iDevice)) | |
128 | Settings.ConnectedDevice.Value = iDevice == 36038 ? CecLogicalAddress.AudioSystem : CecLogicalAddress.Tv; | |
f017f3c4 LOK |
129 | } |
130 | break; | |
131 | case "cec_power_on_startup": | |
132 | if (value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes")) | |
133 | { | |
134 | Settings.ActivateSource.Value = true; | |
135 | Settings.WakeDevices.Value.Set(CecLogicalAddress.Tv); | |
136 | } | |
137 | break; | |
138 | case "cec_power_off_shutdown": | |
139 | if (value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes")) | |
140 | Settings.PowerOffDevices.Value.Set(CecLogicalAddress.Broadcast); | |
141 | break; | |
142 | case "cec_standby_screensaver": | |
143 | StandbyScreensaver.Value = value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes"); | |
144 | break; | |
145 | case "standby_pc_on_tv_standby": | |
146 | PowerOffOnStandby.Value = value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes"); | |
147 | break; | |
148 | case "use_tv_menu_language": | |
149 | UseTVLanguage.Value = value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes"); | |
150 | break; | |
151 | // 1.5.0+ settings | |
152 | case "physical_address": | |
153 | { | |
154 | ushort physicalAddress; | |
155 | if (ushort.TryParse(value, NumberStyles.AllowHexSpecifier, null, out physicalAddress)) | |
156 | Settings.PhysicalAddress.Value = physicalAddress; | |
157 | } | |
158 | break; | |
159 | case "device_type": | |
160 | { | |
161 | ushort iType; | |
162 | if (ushort.TryParse(value, out iType)) | |
163 | Settings.DeviceType.Value = (CecDeviceType)iType; | |
164 | } | |
165 | break; | |
166 | case "tv_vendor": | |
167 | { | |
168 | UInt64 iVendor; | |
169 | if (UInt64.TryParse(value, out iVendor)) | |
170 | Settings.TVVendor.Value = (CecVendorId)iVendor; | |
171 | } | |
172 | break; | |
1b09c8f6 LOK |
173 | case "wake_device": |
174 | { | |
175 | int iWakeDevices; | |
176 | if (int.TryParse(value, out iWakeDevices)) | |
177 | { | |
178 | Settings.WakeDevices.Value.Clear(); | |
179 | switch (iWakeDevices) | |
180 | { | |
181 | case 36037: | |
182 | Settings.WakeDevices.Value.Set(CecLogicalAddress.Tv); | |
183 | break; | |
184 | case 36038: | |
185 | Settings.WakeDevices.Value.Set(CecLogicalAddress.AudioSystem); | |
186 | break; | |
187 | case 36039: | |
188 | Settings.WakeDevices.Value.Set(CecLogicalAddress.Tv); | |
189 | Settings.WakeDevices.Value.Set(CecLogicalAddress.AudioSystem); | |
190 | break; | |
191 | } | |
192 | } | |
193 | } | |
194 | break; | |
195 | case "wake_devices_advanced": | |
f017f3c4 LOK |
196 | { |
197 | Settings.WakeDevices.Value.Clear(); | |
198 | string[] split = value.Split(new[] { ' ' }); | |
199 | foreach (string dev in split) | |
200 | { | |
201 | byte iLogicalAddress; | |
202 | if (byte.TryParse(dev, out iLogicalAddress)) | |
203 | Settings.WakeDevices.Value.Set((CecLogicalAddress)iLogicalAddress); | |
204 | } | |
205 | } | |
206 | break; | |
207 | case "standby_devices": | |
1b09c8f6 LOK |
208 | { |
209 | int iStandbyDevices; | |
210 | if (int.TryParse(value, out iStandbyDevices)) | |
211 | { | |
212 | Settings.PowerOffDevices.Value.Clear(); | |
213 | switch (iStandbyDevices) | |
214 | { | |
215 | case 36037: | |
216 | Settings.PowerOffDevices.Value.Set(CecLogicalAddress.Tv); | |
217 | break; | |
218 | case 36038: | |
219 | Settings.PowerOffDevices.Value.Set(CecLogicalAddress.AudioSystem); | |
220 | break; | |
221 | case 36039: | |
222 | Settings.PowerOffDevices.Value.Set(CecLogicalAddress.Tv); | |
223 | Settings.PowerOffDevices.Value.Set(CecLogicalAddress.AudioSystem); | |
224 | break; | |
225 | } | |
226 | } | |
227 | } | |
228 | break; | |
229 | case "standby_devices_advanced": | |
f017f3c4 LOK |
230 | { |
231 | Settings.PowerOffDevices.Value.Clear(); | |
232 | string[] split = value.Split(new[] { ' ' }); | |
233 | foreach (string dev in split) | |
234 | { | |
235 | byte iLogicalAddress; | |
236 | if (byte.TryParse(dev, out iLogicalAddress)) | |
237 | Settings.PowerOffDevices.Value.Set((CecLogicalAddress)iLogicalAddress); | |
238 | } | |
239 | } | |
240 | break; | |
241 | case "enabled": | |
242 | break; | |
243 | case "port": | |
244 | //TODO | |
245 | break; | |
246 | // 1.5.1 settings | |
247 | case "send_inactive_source": | |
248 | SendInactiveSource.Value = value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes"); | |
249 | break; | |
1b09c8f6 LOK |
250 | // 1.9.0+ settings |
251 | case "pause_playback_on_deactivate": | |
252 | PausePlaybackOnDeactivate.Value = value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes"); | |
253 | break; | |
f017f3c4 LOK |
254 | } |
255 | } | |
256 | break; | |
257 | } | |
258 | } | |
259 | } | |
260 | return gotConfig; | |
261 | } | |
262 | ||
1b09c8f6 LOK |
263 | static bool HasAdvancedDeviceIdSet(CecLogicalAddresses addresses) |
264 | { | |
265 | foreach (var val in addresses.Addresses) | |
266 | if (val != CecLogicalAddress.Tv && val != CecLogicalAddress.AudioSystem) | |
267 | return true; | |
268 | return false; | |
269 | } | |
270 | ||
f017f3c4 LOK |
271 | public void SaveXMLConfiguration() |
272 | { | |
273 | Settings.Persist(); | |
274 | ||
5156a42c LOK |
275 | var xbmcDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\XBMC\userdata\peripheral_data"; |
276 | if (!Directory.Exists(xbmcDir)) | |
277 | Directory.CreateDirectory(xbmcDir); | |
278 | ||
279 | if (!Directory.Exists(xbmcDir)) | |
280 | { | |
281 | // couldn't create directory | |
282 | MessageBox.Show(string.Format(Resources.could_not_create_directory, xbmcDir), Resources.error, | |
283 | MessageBoxButtons.OK, MessageBoxIcon.Error); | |
284 | return; | |
285 | } | |
f017f3c4 LOK |
286 | |
287 | SaveFileDialog dialog = new SaveFileDialog | |
5156a42c | 288 | { |
f017f3c4 | 289 | Title = Resources.store_settings_where, |
5156a42c LOK |
290 | InitialDirectory = xbmcDir, |
291 | FileName = string.Format("usb_{0:X}_{1:X}.xml", Program.Instance.Controller.AdapterVendorId, Program.Instance.Controller.AdapterProductId), | |
f017f3c4 LOK |
292 | Filter = Resources.xml_file_filter, |
293 | FilterIndex = 1 | |
294 | }; | |
295 | if (dialog.ShowDialog() != DialogResult.OK) return; | |
296 | ||
297 | FileStream fs = null; | |
298 | string error = string.Empty; | |
299 | try | |
300 | { | |
301 | fs = (FileStream)dialog.OpenFile(); | |
302 | } | |
303 | catch (Exception ex) | |
304 | { | |
305 | error = ex.Message; | |
306 | } | |
307 | if (fs == null) | |
308 | { | |
309 | MessageBox.Show(string.Format(Resources.cannot_open_file, dialog.FileName) + (error.Length > 0 ? ": " + error : string.Empty), Resources.app_name, MessageBoxButtons.OK, MessageBoxIcon.Error); | |
310 | } | |
311 | else | |
312 | { | |
313 | StreamWriter writer = new StreamWriter(fs); | |
314 | StringBuilder output = new StringBuilder(); | |
315 | output.AppendLine("<settings>"); | |
316 | output.AppendLine("<setting id=\"cec_hdmi_port\" value=\"" + Settings.HDMIPort.Value + "\" />"); | |
1b09c8f6 | 317 | output.AppendLine("<setting id=\"connected_device\" value=\"" + (Settings.ConnectedDevice.Value == CecLogicalAddress.AudioSystem ? 36038 : 36037) + "\" />"); |
f017f3c4 LOK |
318 | output.AppendLine("<setting id=\"cec_power_on_startup\" value=\"" + (Settings.ActivateSource.Value ? 1 : 0) + "\" />"); |
319 | output.AppendLine("<setting id=\"cec_power_off_shutdown\" value=\"" + (Settings.PowerOffDevices.Value.IsSet(CecLogicalAddress.Broadcast) ? 1 : 0) + "\" />"); | |
320 | output.AppendLine("<setting id=\"cec_standby_screensaver\" value=\"" + (StandbyScreensaver.Value ? 1 : 0) + "\" />"); | |
321 | output.AppendLine("<setting id=\"standby_pc_on_tv_standby\" value=\"" + (PowerOffOnStandby.Value ? 1 : 0) + "\" />"); | |
322 | output.AppendLine("<setting id=\"use_tv_menu_language\" value=\"" + (UseTVLanguage.Value ? 1 : 0) + "\" />"); | |
323 | output.AppendLine("<setting id=\"enabled\" value=\"1\" />"); | |
324 | output.AppendLine("<setting id=\"port\" value=\"\" />"); | |
325 | ||
326 | // only supported by 1.5.0+ clients | |
327 | output.AppendLine("<!-- the following lines are only supported by v1.5.0+ clients -->"); | |
328 | output.AppendLine("<setting id=\"activate_source\" value=\"" + (Settings.ActivateSource.Value ? 1 : 0) + "\" />"); | |
329 | output.AppendLine("<setting id=\"physical_address\" value=\"" + string.Format("{0,4:X}", Settings.OverridePhysicalAddress.Value ? Settings.PhysicalAddress.Value : 0).Trim() + "\" />"); | |
330 | output.AppendLine("<setting id=\"device_type\" value=\"" + (int)Settings.DeviceType.Value + "\" />"); | |
331 | output.AppendLine("<setting id=\"tv_vendor\" value=\"" + string.Format("{0,6:X}", Settings.OverrideTVVendor.Value ? (int)Settings.TVVendor.Value : 0).Trim() + "\" />"); | |
332 | ||
1b09c8f6 LOK |
333 | if (HasAdvancedDeviceIdSet(Settings.WakeDevices.Value)) |
334 | { | |
335 | output.Append("<setting id=\"wake_devices_advanced\" value=\""); | |
336 | StringBuilder strWakeDevices = new StringBuilder(); | |
337 | foreach (CecLogicalAddress addr in Settings.WakeDevices.Value.Addresses) | |
338 | if (addr != CecLogicalAddress.Unknown) | |
339 | strWakeDevices.Append(" " + (int)addr); | |
340 | output.Append(strWakeDevices.ToString().Trim()); | |
341 | output.AppendLine("\" />"); | |
342 | } | |
343 | ||
344 | if (Settings.WakeDevices.Value.IsSet(CecLogicalAddress.Tv) && | |
345 | Settings.WakeDevices.Value.IsSet(CecLogicalAddress.AudioSystem)) | |
346 | output.Append("<setting id=\"wake_devices\" value=\"36039\">"); | |
347 | else if (Settings.WakeDevices.Value.IsSet(CecLogicalAddress.Tv)) | |
348 | output.Append("<setting id=\"wake_devices\" value=\"36037\">"); | |
349 | else if (Settings.WakeDevices.Value.IsSet(CecLogicalAddress.AudioSystem)) | |
350 | output.Append("<setting id=\"wake_devices\" value=\"36038\">"); | |
351 | else | |
352 | output.Append("<setting id=\"wake_devices\" value=\"231\">"); | |
353 | ||
354 | if (HasAdvancedDeviceIdSet(Settings.PowerOffDevices.Value)) | |
355 | { | |
356 | output.Append("<setting id=\"standby_devices_advanced\" value=\""); | |
357 | StringBuilder strSleepDevices = new StringBuilder(); | |
358 | foreach (CecLogicalAddress addr in Settings.PowerOffDevices.Value.Addresses) | |
359 | if (addr != CecLogicalAddress.Unknown) | |
360 | strSleepDevices.Append(" " + (int) addr); | |
361 | output.Append(strSleepDevices.ToString().Trim()); | |
362 | output.AppendLine("\" />"); | |
363 | } | |
f017f3c4 | 364 | |
1b09c8f6 LOK |
365 | if (Settings.PowerOffDevices.Value.IsSet(CecLogicalAddress.Tv) && |
366 | Settings.PowerOffDevices.Value.IsSet(CecLogicalAddress.AudioSystem)) | |
367 | output.Append("<setting id=\"standby_devices\" value=\"36039\">"); | |
368 | else if (Settings.PowerOffDevices.Value.IsSet(CecLogicalAddress.Tv)) | |
369 | output.Append("<setting id=\"standby_devices\" value=\"36037\">"); | |
370 | else if (Settings.PowerOffDevices.Value.IsSet(CecLogicalAddress.AudioSystem)) | |
371 | output.Append("<setting id=\"standby_devices\" value=\"36038\">"); | |
372 | else | |
373 | output.Append("<setting id=\"standby_devices\" value=\"231\">"); | |
f017f3c4 LOK |
374 | |
375 | // only supported by 1.5.1+ clients | |
376 | output.AppendLine("<!-- the following lines are only supported by v1.5.1+ clients -->"); | |
9c72728b | 377 | output.AppendLine("<setting id=\"send_inactive_source\" value=\"" + (SendInactiveSource.Value ? 1 : 0) + "\" />"); |
f017f3c4 | 378 | |
1b09c8f6 LOK |
379 | // only supported by 1.9.0+ clients |
380 | output.AppendLine("<setting id=\"pause_playback_on_deactivate\" value=\"" + (PausePlaybackOnDeactivate.Value ? 1 : 0) + "\" />"); | |
381 | ||
f017f3c4 LOK |
382 | output.AppendLine("</settings>"); |
383 | writer.Write(output.ToString()); | |
384 | writer.Close(); | |
385 | fs.Close(); | |
386 | fs.Dispose(); | |
387 | MessageBox.Show(Resources.settings_stored, Resources.app_name, MessageBoxButtons.OK, MessageBoxIcon.Information); | |
388 | } | |
389 | } | |
390 | ||
391 | public CECSettingBool UseTVLanguage | |
392 | { | |
393 | get | |
394 | { | |
395 | if (!Settings.ContainsKey(ProcessName + "_use_tv_language")) | |
396 | { | |
397 | CECSettingBool setting = new CECSettingBool(ProcessName + "_use_tv_language", Resources.app_use_tv_language, true, null); | |
398 | Settings.Load(setting); | |
399 | Settings[ProcessName + "_use_tv_language"] = setting; | |
400 | } | |
401 | return Settings[ProcessName + "_use_tv_language"].AsSettingBool; | |
402 | } | |
403 | } | |
404 | ||
405 | public CECSettingBool StandbyScreensaver | |
406 | { | |
407 | get | |
408 | { | |
409 | if (!Settings.ContainsKey(ProcessName + "_standby_screensaver")) | |
410 | { | |
411 | CECSettingBool setting = new CECSettingBool(ProcessName + "_standby_screensaver", Resources.app_standby_screensaver, true, null); | |
412 | Settings.Load(setting); | |
413 | Settings[ProcessName + "_standby_screensaver"] = setting; | |
414 | } | |
415 | return Settings[ProcessName + "_standby_screensaver"].AsSettingBool; | |
416 | } | |
417 | } | |
418 | ||
419 | public CECSettingBool ActivateSource | |
420 | { | |
421 | get | |
422 | { | |
423 | if (!Settings.ContainsKey(ProcessName + "_activate_source")) | |
424 | { | |
425 | CECSettingBool setting = new CECSettingBool(ProcessName + "_activate_source", Resources.global_activate_source, true, null); | |
426 | Settings.Load(setting); | |
427 | Settings[ProcessName + "_activate_source"] = setting; | |
428 | } | |
429 | return Settings[ProcessName + "_activate_source"].AsSettingBool; | |
430 | } | |
431 | } | |
432 | ||
433 | public CECSettingBool PowerOffOnStandby | |
434 | { | |
435 | get | |
436 | { | |
437 | if (!Settings.ContainsKey(ProcessName + "_standby_on_tv_standby")) | |
438 | { | |
439 | CECSettingBool setting = new CECSettingBool(ProcessName + "_standby_on_tv_standby", Resources.app_standby_on_tv_standby, true, null); | |
440 | Settings.Load(setting); | |
441 | Settings[ProcessName + "_standby_on_tv_standby"] = setting; | |
442 | } | |
443 | return Settings[ProcessName + "_standby_on_tv_standby"].AsSettingBool; | |
444 | } | |
445 | } | |
446 | ||
447 | public CECSettingBool SendInactiveSource | |
448 | { | |
449 | get | |
450 | { | |
451 | if (!Settings.ContainsKey(ProcessName + "_send_inactive_source")) | |
452 | { | |
453 | CECSettingBool setting = new CECSettingBool(ProcessName + "_send_inactive_source", Resources.app_send_inactive_source, true, null); | |
454 | Settings.Load(setting); | |
455 | Settings[ProcessName + "_send_inactive_source"] = setting; | |
456 | } | |
457 | return Settings[ProcessName + "_send_inactive_source"].AsSettingBool; | |
458 | } | |
459 | } | |
1b09c8f6 LOK |
460 | |
461 | public CECSettingBool PausePlaybackOnDeactivate | |
462 | { | |
463 | get | |
464 | { | |
465 | if (!Settings.ContainsKey(ProcessName + "_pause_playback_on_deactivate")) | |
466 | { | |
467 | CECSettingBool setting = new CECSettingBool(ProcessName + "_pause_playback_on_deactivate", Resources.app_pause_playback_on_deactivate, true, null); | |
468 | Settings.Load(setting); | |
469 | Settings[ProcessName + "_pause_playback_on_deactivate"] = setting; | |
470 | } | |
471 | return Settings[ProcessName + "_pause_playback_on_deactivate"].AsSettingBool; | |
472 | } | |
473 | } | |
f017f3c4 LOK |
474 | } |
475 | } |