Commit | Line | Data |
---|---|---|
61f3c2ad LOK |
1 | /* |
2 | * This file is part of the libCEC(R) library. | |
3 | * | |
4 | * libCEC(R) is Copyright (C) 2011 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; | |
61f3c2ad | 35 | using System.Text; |
4ef3b314 | 36 | using CecSharp; |
61f3c2ad LOK |
37 | |
38 | namespace CecSharpClient | |
39 | { | |
dd4ace4f | 40 | class CecSharpClient : CecCallbackMethods |
61f3c2ad LOK |
41 | { |
42 | public CecSharpClient() | |
43 | { | |
7f7414d5 LOK |
44 | Config = new LibCECConfiguration(); |
45 | Config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice; | |
46 | Config.DeviceName = "CEC Tester"; | |
47 | Config.ClientVersion = CecClientVersion.Version1_5_0; | |
48 | Config.SetCallbacks(this); | |
49 | LogLevel = (int)CecLogLevel.All; | |
61f3c2ad | 50 | |
7f7414d5 | 51 | Lib = new LibCecSharp(Config); |
61f3c2ad LOK |
52 | |
53 | Console.WriteLine("CEC Parser created - libcec version " + Lib.GetLibVersionMajor() + "." + Lib.GetLibVersionMinor()); | |
54 | } | |
55 | ||
dd4ace4f LOK |
56 | public override int ReceiveCommand(CecCommand command) |
57 | { | |
58 | return 1; | |
59 | } | |
60 | ||
61 | public override int ReceiveKeypress(CecKeypress key) | |
62 | { | |
63 | return 1; | |
64 | } | |
65 | ||
66 | public override int ReceiveLogMessage(CecLogMessage message) | |
67 | { | |
68 | if (((int)message.Level & LogLevel) == (int)message.Level) | |
69 | { | |
70 | string strLevel = ""; | |
71 | switch (message.Level) | |
72 | { | |
73 | case CecLogLevel.Error: | |
74 | strLevel = "ERROR: "; | |
75 | break; | |
76 | case CecLogLevel.Warning: | |
77 | strLevel = "WARNING: "; | |
78 | break; | |
79 | case CecLogLevel.Notice: | |
80 | strLevel = "NOTICE: "; | |
81 | break; | |
82 | case CecLogLevel.Traffic: | |
83 | strLevel = "TRAFFIC: "; | |
84 | break; | |
85 | case CecLogLevel.Debug: | |
86 | strLevel = "DEBUG: "; | |
87 | break; | |
88 | default: | |
89 | break; | |
90 | } | |
91 | string strLog = string.Format("{0} {1,16} {2}", strLevel, message.Time, message.Message); | |
92 | Console.WriteLine(strLog); | |
93 | } | |
94 | return 1; | |
95 | } | |
96 | ||
61f3c2ad LOK |
97 | void FlushLog() |
98 | { | |
99 | CecLogMessage message = Lib.GetNextLogMessage(); | |
100 | bool bGotMessage = !message.Empty; | |
101 | while (bGotMessage) | |
102 | { | |
103 | if (((int)message.Level & LogLevel) == (int)message.Level) | |
104 | { | |
105 | string strLevel = ""; | |
106 | switch (message.Level) | |
107 | { | |
108 | case CecLogLevel.Error: | |
109 | strLevel = "ERROR: "; | |
110 | break; | |
111 | case CecLogLevel.Warning: | |
112 | strLevel = "WARNING: "; | |
113 | break; | |
114 | case CecLogLevel.Notice: | |
115 | strLevel = "NOTICE: "; | |
116 | break; | |
117 | case CecLogLevel.Traffic: | |
118 | strLevel = "TRAFFIC: "; | |
119 | break; | |
120 | case CecLogLevel.Debug: | |
121 | strLevel = "DEBUG: "; | |
122 | break; | |
123 | default: | |
124 | break; | |
125 | } | |
126 | string strLog = string.Format("{0} {1,16} {2}", strLevel, message.Time, message.Message); | |
127 | Console.WriteLine(strLog); | |
128 | } | |
129 | ||
130 | message = Lib.GetNextLogMessage(); | |
131 | bGotMessage = !message.Empty; | |
132 | } | |
133 | } | |
134 | ||
135 | public bool Connect(int timeout) | |
136 | { | |
137 | CecAdapter[] adapters = Lib.FindAdapters(string.Empty); | |
138 | if (adapters.Length > 0) | |
139 | return Connect(adapters[0].ComPort, timeout); | |
140 | else | |
141 | { | |
142 | Console.WriteLine("Did not find any CEC adapters"); | |
143 | return false; | |
144 | } | |
145 | } | |
146 | ||
147 | public bool Connect(string port, int timeout) | |
148 | { | |
149 | return Lib.Open(port, timeout); | |
150 | } | |
151 | ||
152 | public void Close() | |
153 | { | |
154 | Lib.Close(); | |
155 | } | |
156 | ||
157 | public void ListDevices() | |
158 | { | |
159 | int iAdapter = 0; | |
160 | foreach (CecAdapter adapter in Lib.FindAdapters(string.Empty)) | |
161 | { | |
162 | Console.WriteLine("Adapter: " + iAdapter++); | |
163 | Console.WriteLine("Path: " + adapter.Path); | |
164 | Console.WriteLine("Com port: " + adapter.ComPort); | |
165 | } | |
166 | } | |
167 | ||
168 | void ShowConsoleHelp() | |
169 | { | |
170 | Console.WriteLine( | |
171 | "================================================================================" + System.Environment.NewLine + | |
172 | "Available commands:" + System.Environment.NewLine + | |
173 | System.Environment.NewLine + | |
8d4c47d9 LOK |
174 | "[tx] {bytes} transfer bytes over the CEC line." + System.Environment.NewLine + |
175 | "[txn] {bytes} transfer bytes but don't wait for transmission ACK." + System.Environment.NewLine + | |
176 | "[on] {address} power on the device with the given logical address." + System.Environment.NewLine + | |
177 | "[standby] {address} put the device with the given address in standby mode." + System.Environment.NewLine + | |
178 | "[la] {logical_address} change the logical address of the CEC adapter." + System.Environment.NewLine + | |
179 | "[pa] {physical_address} change the physical address of the CEC adapter." + System.Environment.NewLine + | |
180 | "[osd] {addr} {string} set OSD message on the specified device." + System.Environment.NewLine + | |
181 | "[ver] {addr} get the CEC version of the specified device." + System.Environment.NewLine + | |
182 | "[ven] {addr} get the vendor ID of the specified device." + System.Environment.NewLine + | |
183 | "[lang] {addr} get the menu language of the specified device." + System.Environment.NewLine + | |
184 | "[pow] {addr} get the power status of the specified device." + System.Environment.NewLine + | |
185 | "[poll] {addr} poll the specified device." + System.Environment.NewLine + | |
186 | "[scan] scan the CEC bus and display device info" + System.Environment.NewLine + | |
61f3c2ad LOK |
187 | "[mon] {1|0} enable or disable CEC bus monitoring." + System.Environment.NewLine + |
188 | "[log] {1 - 31} change the log level. see cectypes.h for values." + System.Environment.NewLine + | |
61f3c2ad LOK |
189 | "[ping] send a ping command to the CEC adapter." + System.Environment.NewLine + |
190 | "[bl] to let the adapter enter the bootloader, to upgrade" + System.Environment.NewLine + | |
191 | " the flash rom." + System.Environment.NewLine + | |
192 | "[r] reconnect to the CEC adapter." + System.Environment.NewLine + | |
193 | "[h] or [help] show this help." + System.Environment.NewLine + | |
194 | "[q] or [quit] to quit the CEC test client and switch off all" + System.Environment.NewLine + | |
195 | " connected CEC devices." + System.Environment.NewLine + | |
196 | "================================================================================"); | |
197 | } | |
198 | ||
199 | public void MainLoop() | |
200 | { | |
dd4ace4f | 201 | Lib.PowerOnDevices(CecLogicalAddress.Tv); |
61f3c2ad | 202 | Lib.SetActiveSource(CecDeviceType.PlaybackDevice); |
61f3c2ad LOK |
203 | |
204 | bool bContinue = true; | |
205 | string command; | |
206 | while (bContinue) | |
207 | { | |
208 | Console.WriteLine("waiting for input"); | |
209 | ||
210 | command = Console.ReadLine(); | |
211 | if (command.Length == 0) | |
212 | continue; | |
213 | string[] splitCommand = command.Split(' '); | |
214 | if (splitCommand[0] == "tx" || splitCommand[0] == "txn") | |
215 | { | |
216 | CecCommand bytes = new CecCommand(); | |
217 | for (int iPtr = 1; iPtr < splitCommand.Length; iPtr++) | |
218 | { | |
219 | bytes.PushBack(byte.Parse(splitCommand[iPtr], System.Globalization.NumberStyles.HexNumber)); | |
220 | } | |
221 | ||
222 | if (command == "txn") | |
223 | bytes.TransmitTimeout = 0; | |
224 | ||
225 | Lib.Transmit(bytes); | |
226 | } | |
227 | else if (splitCommand[0] == "on") | |
228 | { | |
229 | if (splitCommand.Length > 1) | |
230 | Lib.PowerOnDevices((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); | |
231 | else | |
232 | Lib.PowerOnDevices(CecLogicalAddress.Broadcast); | |
233 | } | |
234 | else if (splitCommand[0] == "standby") | |
235 | { | |
236 | if (splitCommand.Length > 1) | |
237 | Lib.StandbyDevices((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); | |
238 | else | |
239 | Lib.StandbyDevices(CecLogicalAddress.Broadcast); | |
240 | } | |
241 | else if (splitCommand[0] == "poll") | |
242 | { | |
243 | bool bSent = false; | |
244 | if (splitCommand.Length > 1) | |
245 | bSent = Lib.PollDevice((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); | |
246 | else | |
247 | bSent = Lib.PollDevice(CecLogicalAddress.Broadcast); | |
248 | if (bSent) | |
249 | Console.WriteLine("POLL message sent"); | |
250 | else | |
251 | Console.WriteLine("POLL message not sent"); | |
252 | } | |
253 | else if (splitCommand[0] == "la") | |
254 | { | |
255 | if (splitCommand.Length > 1) | |
256 | Lib.SetLogicalAddress((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); | |
257 | } | |
258 | else if (splitCommand[0] == "pa") | |
259 | { | |
260 | if (splitCommand.Length > 1) | |
006b76b9 | 261 | Lib.SetPhysicalAddress(ushort.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); |
61f3c2ad LOK |
262 | } |
263 | else if (splitCommand[0] == "osd") | |
264 | { | |
265 | if (splitCommand.Length > 2) | |
266 | { | |
267 | StringBuilder osdString = new StringBuilder(); | |
268 | for (int iPtr = 1; iPtr < splitCommand.Length; iPtr++) | |
269 | { | |
270 | osdString.Append(splitCommand[iPtr]); | |
271 | if (iPtr != splitCommand.Length - 1) | |
272 | osdString.Append(" "); | |
273 | } | |
274 | Lib.SetOSDString((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber), CecDisplayControl.DisplayForDefaultTime, osdString.ToString()); | |
275 | } | |
276 | } | |
277 | else if (splitCommand[0] == "ping") | |
278 | { | |
279 | Lib.PingAdapter(); | |
280 | } | |
281 | else if (splitCommand[0] == "mon") | |
282 | { | |
283 | bool enable = splitCommand.Length > 1 ? splitCommand[1] == "1" : false; | |
284 | Lib.SwitchMonitoring(enable); | |
285 | } | |
286 | else if (splitCommand[0] == "bl") | |
287 | { | |
288 | Lib.StartBootloader(); | |
289 | } | |
290 | else if (splitCommand[0] == "lang") | |
291 | { | |
292 | if (splitCommand.Length > 1) | |
293 | { | |
294 | string language = Lib.GetDeviceMenuLanguage((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); | |
295 | Console.WriteLine("Menu language: " + language); | |
296 | } | |
297 | } | |
298 | else if (splitCommand[0] == "ven") | |
299 | { | |
300 | if (splitCommand.Length > 1) | |
301 | { | |
8d4c47d9 LOK |
302 | CecVendorId vendor = Lib.GetDeviceVendorId((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); |
303 | Console.WriteLine("Vendor ID: " + Lib.ToString(vendor)); | |
61f3c2ad LOK |
304 | } |
305 | } | |
306 | else if (splitCommand[0] == "ver") | |
307 | { | |
308 | if (splitCommand.Length > 1) | |
309 | { | |
310 | CecVersion version = Lib.GetDeviceCecVersion((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); | |
8d4c47d9 | 311 | Console.WriteLine("CEC version: " + Lib.ToString(version)); |
61f3c2ad LOK |
312 | } |
313 | } | |
314 | else if (splitCommand[0] == "pow") | |
315 | { | |
316 | if (splitCommand.Length > 1) | |
317 | { | |
318 | CecPowerStatus power = Lib.GetDevicePowerStatus((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); | |
8d4c47d9 | 319 | Console.WriteLine("power status: " + Lib.ToString(power)); |
61f3c2ad LOK |
320 | } |
321 | } | |
322 | else if (splitCommand[0] == "r") | |
323 | { | |
324 | Console.WriteLine("closing the connection"); | |
325 | Lib.Close(); | |
61f3c2ad LOK |
326 | |
327 | Console.WriteLine("opening a new connection"); | |
328 | Connect(10000); | |
61f3c2ad LOK |
329 | |
330 | Console.WriteLine("setting active source"); | |
331 | Lib.SetActiveSource(CecDeviceType.PlaybackDevice); | |
332 | } | |
8d4c47d9 LOK |
333 | else if (splitCommand[0] == "scan") |
334 | { | |
335 | Console.WriteLine("CEC bus information"); | |
336 | Console.WriteLine("==================="); | |
337 | CecLogicalAddresses addresses = Lib.GetActiveDevices(); | |
4d760b54 | 338 | for (int iPtr = 0; iPtr < addresses.Addresses.Length; iPtr++) |
8d4c47d9 LOK |
339 | { |
340 | CecLogicalAddress address = (CecLogicalAddress)iPtr; | |
341 | if (!addresses.IsSet(address)) | |
342 | continue; | |
343 | ||
344 | CecVendorId iVendorId = Lib.GetDeviceVendorId(address); | |
345 | bool bActive = Lib.IsActiveDevice(address); | |
346 | ushort iPhysicalAddress = Lib.GetDevicePhysicalAddress(address); | |
347 | string strAddr = string.Format("{0,4:X}", iPhysicalAddress); | |
348 | CecVersion iCecVersion = Lib.GetDeviceCecVersion(address); | |
349 | CecPowerStatus power = Lib.GetDevicePowerStatus(address); | |
350 | string osdName = Lib.GetDeviceOSDName(address); | |
351 | string lang = Lib.GetDeviceMenuLanguage(address); | |
352 | ||
353 | StringBuilder output = new StringBuilder(); | |
354 | output.AppendLine("device #" + iPtr + ": " + Lib.ToString(address)); | |
355 | output.AppendLine("address: " + strAddr); | |
356 | output.AppendLine("active source: " + (bActive ? "yes" : "no")); | |
357 | output.AppendLine("vendor: " + Lib.ToString(iVendorId)); | |
358 | output.AppendLine("osd string: " + osdName); | |
359 | output.AppendLine("CEC version: " + Lib.ToString(iCecVersion)); | |
360 | output.AppendLine("power status: " + Lib.ToString(power)); | |
361 | if (!string.IsNullOrEmpty(lang)) | |
362 | output.AppendLine("language: " + lang); | |
363 | ||
364 | Console.WriteLine(output.ToString()); | |
365 | } | |
366 | } | |
61f3c2ad LOK |
367 | else if (splitCommand[0] == "h" || splitCommand[0] == "help") |
368 | ShowConsoleHelp(); | |
369 | else if (splitCommand[0] == "q" || splitCommand[0] == "quit") | |
370 | bContinue = false; | |
371 | else if (splitCommand[0] == "log" && splitCommand.Length > 1) | |
8d4c47d9 | 372 | LogLevel = int.Parse(splitCommand[1]); |
61f3c2ad LOK |
373 | } |
374 | } | |
375 | ||
376 | static void Main(string[] args) | |
377 | { | |
378 | CecSharpClient p = new CecSharpClient(); | |
379 | if (p.Connect(10000)) | |
380 | { | |
381 | p.MainLoop(); | |
382 | } | |
383 | else | |
384 | { | |
385 | Console.WriteLine("Could not open a connection to the CEC adapter"); | |
386 | } | |
61f3c2ad LOK |
387 | } |
388 | ||
7f7414d5 LOK |
389 | private int LogLevel; |
390 | private LibCecSharp Lib; | |
391 | private LibCECConfiguration Config; | |
61f3c2ad LOK |
392 | } |
393 | } |