Stephane@161: /* Stephane@161: * This file is part of the libCEC(R) library. Stephane@161: * Stephane@161: * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. Stephane@161: * libCEC(R) is an original work, containing original code. Stephane@161: * Stephane@161: * libCEC(R) is a trademark of Pulse-Eight Limited. Stephane@161: * Stephane@161: * This program is dual-licensed; you can redistribute it and/or modify Stephane@161: * it under the terms of the GNU General Public License as published by Stephane@161: * the Free Software Foundation; either version 2 of the License, or Stephane@161: * (at your option) any later version. Stephane@161: * Stephane@161: * This program is distributed in the hope that it will be useful, Stephane@161: * but WITHOUT ANY WARRANTY; without even the implied warranty of Stephane@161: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Stephane@161: * GNU General Public License for more details. Stephane@161: * Stephane@161: * You should have received a copy of the GNU General Public License Stephane@161: * along with this program; if not, write to the Free Software Stephane@161: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Stephane@161: * Stephane@161: * Stephane@161: * Alternatively, you can license this library under a commercial license, Stephane@161: * please contact Pulse-Eight Licensing for more information. Stephane@161: * Stephane@161: * For more information contact: Stephane@161: * Pulse-Eight Licensing Stephane@161: * http://www.pulse-eight.com/ Stephane@161: * http://www.pulse-eight.net/ Stephane@161: */ Stephane@161: Stephane@161: using System; Stephane@161: using System.Text; Stephane@161: using CecSharp; Stephane@161: Stephane@161: namespace Cec Stephane@161: { Stephane@161: class Client : CecCallbackMethods Stephane@161: { StephaneLenclud@167: /// StephaneLenclud@167: /// StephaneLenclud@167: /// StephaneLenclud@167: /// StephaneLenclud@167: /// StephaneLenclud@167: public Client(string aDeviceName, byte aHdmiPort) Stephane@161: { Stephane@161: Config = new LibCECConfiguration(); Stephane@161: Config.DeviceTypes.Types[0] = CecDeviceType.Tv; StephaneLenclud@167: Config.DeviceName = aDeviceName; StephaneLenclud@167: Config.HDMIPort = aHdmiPort; Stephane@161: //Config.ClientVersion = LibCECConfiguration.CurrentVersion; Stephane@161: Config.SetCallbacks(this); Stephane@161: LogLevel = (int)CecLogLevel.All; Stephane@161: StephaneLenclud@167: iLib = new LibCecSharp(Config); StephaneLenclud@167: iLib.InitVideoStandalone(); Stephane@161: Stephane@161: //Console.WriteLine("CEC Parser created - libCEC version " + Lib.VersionToString(Config.ServerVersion)); Stephane@161: Console.WriteLine("CEC Parser created - libCEC version " + Config.ServerVersion); Stephane@161: } Stephane@161: Stephane@161: public override int ReceiveCommand(CecCommand command) Stephane@161: { Stephane@161: return 1; Stephane@161: } Stephane@161: Stephane@161: public override int ReceiveKeypress(CecKeypress key) Stephane@161: { Stephane@161: return 1; Stephane@161: } Stephane@161: Stephane@161: public override int ReceiveLogMessage(CecLogMessage message) Stephane@161: { Stephane@161: if (((int)message.Level & LogLevel) == (int)message.Level) Stephane@161: { Stephane@161: string strLevel = ""; Stephane@161: switch (message.Level) Stephane@161: { Stephane@161: case CecLogLevel.Error: Stephane@161: strLevel = "ERROR: "; Stephane@161: break; Stephane@161: case CecLogLevel.Warning: Stephane@161: strLevel = "WARNING: "; Stephane@161: break; Stephane@161: case CecLogLevel.Notice: Stephane@161: strLevel = "NOTICE: "; Stephane@161: break; Stephane@161: case CecLogLevel.Traffic: Stephane@161: strLevel = "TRAFFIC: "; Stephane@161: break; Stephane@161: case CecLogLevel.Debug: Stephane@161: strLevel = "DEBUG: "; Stephane@161: break; Stephane@161: default: Stephane@161: break; Stephane@161: } Stephane@161: string strLog = string.Format("{0} {1,16} {2}", strLevel, message.Time, message.Message); Stephane@161: Console.WriteLine(strLog); Stephane@161: } Stephane@161: return 1; Stephane@161: } Stephane@161: Stephane@161: /// Stephane@161: /// Stephane@161: /// Stephane@161: /// Stephane@161: /// Stephane@161: public bool Connect(int timeout) Stephane@161: { StephaneLenclud@167: CecAdapter[] adapters = iLib.FindAdapters(string.Empty); Stephane@161: if (adapters.Length > 0) Stephane@161: return Connect(adapters[0].ComPort, timeout); Stephane@161: else Stephane@161: { Stephane@161: Console.WriteLine("Did not find any CEC adapters"); Stephane@161: return false; Stephane@161: } Stephane@161: } Stephane@161: Stephane@161: public bool Connect(string port, int timeout) Stephane@161: { StephaneLenclud@167: return iLib.Open(port, timeout); Stephane@161: } Stephane@161: Stephane@161: public void Close() Stephane@161: { StephaneLenclud@167: iLib.Close(); Stephane@161: } Stephane@161: Stephane@161: public void ListDevices() Stephane@161: { Stephane@161: int iAdapter = 0; StephaneLenclud@167: foreach (CecAdapter adapter in iLib.FindAdapters(string.Empty)) Stephane@161: { Stephane@161: Console.WriteLine("Adapter: " + iAdapter++); Stephane@161: Console.WriteLine("Path: " + adapter.Path); Stephane@161: Console.WriteLine("Com port: " + adapter.ComPort); Stephane@161: } Stephane@161: } Stephane@161: Stephane@161: void ShowConsoleHelp() Stephane@161: { Stephane@161: Console.WriteLine( Stephane@161: "================================================================================" + Environment.NewLine + Stephane@161: "Available commands:" + Environment.NewLine + Stephane@161: Environment.NewLine + Stephane@161: "[tx] {bytes} transfer bytes over the CEC line." + Environment.NewLine + Stephane@161: "[txn] {bytes} transfer bytes but don't wait for transmission ACK." + Environment.NewLine + Stephane@161: "[on] {address} power on the device with the given logical address." + Environment.NewLine + Stephane@161: "[standby] {address} put the device with the given address in standby mode." + Environment.NewLine + Stephane@161: "[la] {logical_address} change the logical address of the CEC adapter." + Environment.NewLine + Stephane@161: "[pa] {physical_address} change the physical address of the CEC adapter." + Environment.NewLine + Stephane@161: "[osd] {addr} {string} set OSD message on the specified device." + Environment.NewLine + Stephane@161: "[ver] {addr} get the CEC version of the specified device." + Environment.NewLine + Stephane@161: "[ven] {addr} get the vendor ID of the specified device." + Environment.NewLine + Stephane@161: "[lang] {addr} get the menu language of the specified device." + Environment.NewLine + Stephane@161: "[pow] {addr} get the power status of the specified device." + Environment.NewLine + Stephane@161: "[poll] {addr} poll the specified device." + Environment.NewLine + Stephane@161: "[scan] scan the CEC bus and display device info" + Environment.NewLine + Stephane@161: "[mon] {1|0} enable or disable CEC bus monitoring." + Environment.NewLine + Stephane@161: "[log] {1 - 31} change the log level. see cectypes.h for values." + Environment.NewLine + Stephane@161: "[ping] send a ping command to the CEC adapter." + Environment.NewLine + Stephane@161: "[bl] to let the adapter enter the bootloader, to upgrade" + Environment.NewLine + Stephane@161: " the flash rom." + Environment.NewLine + Stephane@161: "[r] reconnect to the CEC adapter." + Environment.NewLine + Stephane@161: "[h] or [help] show this help." + Environment.NewLine + Stephane@161: "[q] or [quit] to quit the CEC test client and switch off all" + Environment.NewLine + Stephane@161: " connected CEC devices." + Environment.NewLine + Stephane@161: "================================================================================"); Stephane@161: } Stephane@161: Stephane@161: public void MainLoop() Stephane@161: { Stephane@161: bool bContinue = true; Stephane@161: string command; Stephane@161: while (bContinue) Stephane@161: { Stephane@161: Console.WriteLine("waiting for input"); Stephane@161: Stephane@161: command = Console.ReadLine(); Stephane@161: if (command != null && command.Length == 0) Stephane@161: continue; Stephane@161: string[] splitCommand = command.Split(' '); Stephane@161: if (splitCommand[0] == "tx" || splitCommand[0] == "txn") Stephane@161: { Stephane@161: CecCommand bytes = new CecCommand(); Stephane@161: for (int iPtr = 1; iPtr < splitCommand.Length; iPtr++) Stephane@161: { Stephane@161: bytes.PushBack(byte.Parse(splitCommand[iPtr], System.Globalization.NumberStyles.HexNumber)); Stephane@161: } Stephane@161: Stephane@161: if (command == "txn") Stephane@161: bytes.TransmitTimeout = 0; Stephane@161: StephaneLenclud@167: iLib.Transmit(bytes); Stephane@161: } Stephane@161: else if (splitCommand[0] == "on") Stephane@161: { Stephane@161: if (splitCommand.Length > 1) StephaneLenclud@167: iLib.PowerOnDevices((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); Stephane@161: else StephaneLenclud@167: iLib.PowerOnDevices(CecLogicalAddress.Broadcast); Stephane@161: } Stephane@161: else if (splitCommand[0] == "standby") Stephane@161: { Stephane@161: if (splitCommand.Length > 1) StephaneLenclud@167: iLib.StandbyDevices((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); Stephane@161: else StephaneLenclud@167: iLib.StandbyDevices(CecLogicalAddress.Broadcast); Stephane@161: } Stephane@161: else if (splitCommand[0] == "poll") Stephane@161: { Stephane@161: bool bSent = false; Stephane@161: if (splitCommand.Length > 1) StephaneLenclud@167: bSent = iLib.PollDevice((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); Stephane@161: else StephaneLenclud@167: bSent = iLib.PollDevice(CecLogicalAddress.Broadcast); Stephane@161: if (bSent) Stephane@161: Console.WriteLine("POLL message sent"); Stephane@161: else Stephane@161: Console.WriteLine("POLL message not sent"); Stephane@161: } Stephane@161: else if (splitCommand[0] == "la") Stephane@161: { Stephane@161: if (splitCommand.Length > 1) StephaneLenclud@167: iLib.SetLogicalAddress((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); Stephane@161: } Stephane@161: else if (splitCommand[0] == "pa") Stephane@161: { Stephane@161: if (splitCommand.Length > 1) StephaneLenclud@167: iLib.SetPhysicalAddress(ushort.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); Stephane@161: } Stephane@161: else if (splitCommand[0] == "osd") Stephane@161: { Stephane@161: if (splitCommand.Length > 2) Stephane@161: { Stephane@161: StringBuilder osdString = new StringBuilder(); Stephane@161: for (int iPtr = 1; iPtr < splitCommand.Length; iPtr++) Stephane@161: { Stephane@161: osdString.Append(splitCommand[iPtr]); Stephane@161: if (iPtr != splitCommand.Length - 1) Stephane@161: osdString.Append(" "); Stephane@161: } StephaneLenclud@167: iLib.SetOSDString((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber), CecDisplayControl.DisplayForDefaultTime, osdString.ToString()); Stephane@161: } Stephane@161: } Stephane@161: else if (splitCommand[0] == "ping") Stephane@161: { StephaneLenclud@167: iLib.PingAdapter(); Stephane@161: } Stephane@161: else if (splitCommand[0] == "mon") Stephane@161: { Stephane@161: bool enable = splitCommand.Length > 1 ? splitCommand[1] == "1" : false; StephaneLenclud@167: iLib.SwitchMonitoring(enable); Stephane@161: } Stephane@161: else if (splitCommand[0] == "bl") Stephane@161: { StephaneLenclud@167: iLib.StartBootloader(); Stephane@161: } Stephane@161: else if (splitCommand[0] == "lang") Stephane@161: { Stephane@161: if (splitCommand.Length > 1) Stephane@161: { StephaneLenclud@167: string language = iLib.GetDeviceMenuLanguage((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); Stephane@161: Console.WriteLine("Menu language: " + language); Stephane@161: } Stephane@161: } Stephane@161: else if (splitCommand[0] == "ven") Stephane@161: { Stephane@161: if (splitCommand.Length > 1) Stephane@161: { StephaneLenclud@167: CecVendorId vendor = iLib.GetDeviceVendorId((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); StephaneLenclud@167: Console.WriteLine("Vendor ID: " + iLib.ToString(vendor)); Stephane@161: } Stephane@161: } Stephane@161: else if (splitCommand[0] == "ver") Stephane@161: { Stephane@161: if (splitCommand.Length > 1) Stephane@161: { StephaneLenclud@167: CecVersion version = iLib.GetDeviceCecVersion((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); StephaneLenclud@167: Console.WriteLine("CEC version: " + iLib.ToString(version)); Stephane@161: } Stephane@161: } Stephane@161: else if (splitCommand[0] == "pow") Stephane@161: { Stephane@161: if (splitCommand.Length > 1) Stephane@161: { StephaneLenclud@167: CecPowerStatus power = iLib.GetDevicePowerStatus((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber)); StephaneLenclud@167: Console.WriteLine("power status: " + iLib.ToString(power)); Stephane@161: } Stephane@161: } Stephane@161: else if (splitCommand[0] == "r") Stephane@161: { Stephane@161: Console.WriteLine("closing the connection"); StephaneLenclud@167: iLib.Close(); Stephane@161: Stephane@161: Console.WriteLine("opening a new connection"); Stephane@161: Connect(10000); Stephane@161: Stephane@161: Console.WriteLine("setting active source"); StephaneLenclud@167: iLib.SetActiveSource(CecDeviceType.PlaybackDevice); Stephane@161: } Stephane@161: else if (splitCommand[0] == "scan") Stephane@161: { Stephane@161: StringBuilder output = new StringBuilder(); Stephane@161: output.AppendLine("CEC bus information"); Stephane@161: output.AppendLine("==================="); StephaneLenclud@167: CecLogicalAddresses addresses = iLib.GetActiveDevices(); Stephane@161: for (int iPtr = 0; iPtr < addresses.Addresses.Length; iPtr++) Stephane@161: { Stephane@161: CecLogicalAddress address = (CecLogicalAddress)iPtr; Stephane@161: if (!addresses.IsSet(address)) Stephane@161: continue; Stephane@161: StephaneLenclud@167: CecVendorId iVendorId = iLib.GetDeviceVendorId(address); StephaneLenclud@167: bool bActive = iLib.IsActiveDevice(address); StephaneLenclud@167: ushort iPhysicalAddress = iLib.GetDevicePhysicalAddress(address); Stephane@161: string strAddr = "todo: fixme"; //Lib.PhysicalAddressToString(iPhysicalAddress); StephaneLenclud@167: CecVersion iCecVersion = iLib.GetDeviceCecVersion(address); StephaneLenclud@167: CecPowerStatus power = iLib.GetDevicePowerStatus(address); StephaneLenclud@167: string osdName = iLib.GetDeviceOSDName(address); StephaneLenclud@167: string lang = iLib.GetDeviceMenuLanguage(address); Stephane@161: StephaneLenclud@167: output.AppendLine("device #" + iPtr + ": " + iLib.ToString(address)); Stephane@161: output.AppendLine("address: " + strAddr); Stephane@161: output.AppendLine("active source: " + (bActive ? "yes" : "no")); StephaneLenclud@167: output.AppendLine("vendor: " + iLib.ToString(iVendorId)); Stephane@161: output.AppendLine("osd string: " + osdName); StephaneLenclud@167: output.AppendLine("CEC version: " + iLib.ToString(iCecVersion)); StephaneLenclud@167: output.AppendLine("power status: " + iLib.ToString(power)); Stephane@161: if (!string.IsNullOrEmpty(lang)) Stephane@161: output.AppendLine("language: " + lang); Stephane@161: output.AppendLine(""); Stephane@161: } Stephane@161: Console.WriteLine(output.ToString()); Stephane@161: } Stephane@161: else if (splitCommand[0] == "h" || splitCommand[0] == "help") Stephane@161: ShowConsoleHelp(); Stephane@161: else if (splitCommand[0] == "q" || splitCommand[0] == "quit") Stephane@161: bContinue = false; Stephane@161: else if (splitCommand[0] == "log" && splitCommand.Length > 1) Stephane@161: LogLevel = int.Parse(splitCommand[1]); Stephane@161: } Stephane@161: } Stephane@161: StephaneLenclud@167: /// TODO: remove that Stephane@161: static void Main(string[] args) Stephane@161: { StephaneLenclud@167: Client p = new Client("CEC",2); Stephane@161: if (p.Connect(10000)) Stephane@161: { Stephane@161: p.MainLoop(); Stephane@161: } Stephane@161: else Stephane@161: { Stephane@161: Console.WriteLine("Could not open a connection to the CEC adapter"); Stephane@161: } Stephane@161: } Stephane@161: Stephane@161: /// StephaneLenclud@167: /// Provide direct access to CEC library Stephane@161: /// StephaneLenclud@167: public LibCecSharp Lib Stephane@161: { StephaneLenclud@167: get StephaneLenclud@167: { StephaneLenclud@167: return iLib; StephaneLenclud@167: } Stephane@161: } Stephane@161: Stephane@161: /// Stephane@161: /// Stephane@161: /// Stephane@161: private int LogLevel; StephaneLenclud@167: /// StephaneLenclud@167: /// StephaneLenclud@167: /// StephaneLenclud@167: private LibCecSharp iLib; StephaneLenclud@167: /// StephaneLenclud@167: /// StephaneLenclud@167: /// Stephane@161: private LibCECConfiguration Config; Stephane@161: } Stephane@161: }