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@202: using System.Threading; StephaneLenclud@253: using System.Diagnostics; Stephane@161: Stephane@161: namespace Cec Stephane@161: { Stephane@161: class Client : CecCallbackMethods Stephane@161: { StephaneLenclud@167: /// StephaneLenclud@214: /// Enable public static access StephaneLenclud@214: /// StephaneLenclud@214: public static Client Static; StephaneLenclud@214: StephaneLenclud@214: /// StephaneLenclud@206: /// Provide direct access to CEC library StephaneLenclud@206: /// StephaneLenclud@206: public LibCecSharp Lib StephaneLenclud@206: { StephaneLenclud@206: get StephaneLenclud@206: { StephaneLenclud@206: return iLib; StephaneLenclud@206: } StephaneLenclud@206: } StephaneLenclud@206: StephaneLenclud@206: /// StephaneLenclud@206: /// StephaneLenclud@206: /// StephaneLenclud@206: public int LogLevel = (int)CecLogLevel.Notice; StephaneLenclud@206: StephaneLenclud@206: /// StephaneLenclud@206: /// StephaneLenclud@206: /// StephaneLenclud@206: public bool FilterOutPollLogs = true; StephaneLenclud@206: StephaneLenclud@206: /// StephaneLenclud@206: /// StephaneLenclud@206: /// StephaneLenclud@206: private LibCecSharp iLib; StephaneLenclud@206: /// StephaneLenclud@206: /// StephaneLenclud@206: /// StephaneLenclud@206: private LibCECConfiguration Config; StephaneLenclud@206: StephaneLenclud@206: /// StephaneLenclud@206: /// StephaneLenclud@206: /// StephaneLenclud@206: private bool iConnected; StephaneLenclud@206: StephaneLenclud@206: /// StephaneLenclud@167: /// StephaneLenclud@167: /// StephaneLenclud@167: /// StephaneLenclud@167: /// StephaneLenclud@206: public Client(string aDeviceName, byte aHdmiPort, CecDeviceType aDeviceType = CecDeviceType.PlaybackDevice) Stephane@161: { Stephane@161: Config = new LibCECConfiguration(); Stephane@203: Config.DeviceTypes.Types[0] = aDeviceType; StephaneLenclud@167: Config.DeviceName = aDeviceName; StephaneLenclud@167: Config.HDMIPort = aHdmiPort; Stephane@161: //Config.ClientVersion = LibCECConfiguration.CurrentVersion; Stephane@161: Config.SetCallbacks(this); Stephane@161: StephaneLenclud@167: iLib = new LibCecSharp(Config); StephaneLenclud@167: iLib.InitVideoStandalone(); Stephane@161: StephaneLenclud@214: if (Static != null) StephaneLenclud@214: { StephaneLenclud@253: Trace.WriteLine("WARNING: CEC client static already exists"); StephaneLenclud@214: } StephaneLenclud@214: else StephaneLenclud@214: { StephaneLenclud@214: Static = this; StephaneLenclud@214: } StephaneLenclud@214: StephaneLenclud@214: StephaneLenclud@253: //Trace.WriteLine("CEC Parser created - libCEC version " + Lib.VersionToString(Config.ServerVersion)); StephaneLenclud@253: Trace.WriteLine("INFO: CEC Parser created - libCEC version " + Config.ServerVersion); Stephane@161: } Stephane@161: Stephane@200: StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// Stephane@202: public override int ReceiveAlert(CecAlert alert, CecParameter data) Stephane@200: { StephaneLenclud@201: string log = "CEC alert: " + alert.ToString(); StephaneLenclud@201: if (data != null && data.Type == CecParameterType.ParameterTypeString) StephaneLenclud@201: { StephaneLenclud@201: log += " " + data.Data; StephaneLenclud@201: } StephaneLenclud@201: StephaneLenclud@253: Trace.WriteLine(log); StephaneLenclud@201: StephaneLenclud@201: Close(); StephaneLenclud@201: //Try reconnect StephaneLenclud@214: Open(1000); Stephane@200: return 1; Stephane@200: } Stephane@200: StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// Stephane@202: public override int ReceiveMenuStateChange(CecMenuState newVal) Stephane@200: { StephaneLenclud@253: Trace.WriteLine("CEC menu state changed to: " + iLib.ToString(newVal)); Stephane@200: return 1; Stephane@200: } Stephane@200: StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// Stephane@202: public override void SourceActivated(CecLogicalAddress logicalAddress, bool activated) Stephane@200: { StephaneLenclud@253: Trace.WriteLine("CEC source activated: " + iLib.ToString(logicalAddress) + "/" + activated.ToString() ); Stephane@200: return; Stephane@200: } Stephane@200: Stephane@161: public override int ReceiveCommand(CecCommand command) Stephane@161: { StephaneLenclud@253: Trace.WriteLine(string.Format("CEC command '{5}' from {0} to {1} - Ack: {2} Eom: {3} OpcodeSet: {4} Timeout: {6}", StephaneLenclud@201: iLib.ToString(command.Initiator), StephaneLenclud@201: iLib.ToString(command.Destination), StephaneLenclud@201: command.Ack.ToString(), StephaneLenclud@201: command.Eom.ToString(), StephaneLenclud@201: command.OpcodeSet.ToString(), StephaneLenclud@201: iLib.ToString(command.Opcode), StephaneLenclud@201: command.TransmitTimeout.ToString() StephaneLenclud@201: )); Stephane@161: return 1; Stephane@161: } Stephane@161: Stephane@161: public override int ReceiveKeypress(CecKeypress key) Stephane@161: { StephaneLenclud@253: Trace.WriteLine(string.Format("CEC keypress: {0} Duration:{1} Empty: {2}", StephaneLenclud@201: key.Keycode.ToString(), key.Duration.ToString(), key.Empty.ToString())); 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@202: strLevel = "ERROR: "; Stephane@161: break; Stephane@161: case CecLogLevel.Warning: Stephane@161: strLevel = "WARNING: "; Stephane@161: break; Stephane@161: case CecLogLevel.Notice: Stephane@202: strLevel = "NOTICE: "; Stephane@161: break; Stephane@161: case CecLogLevel.Traffic: Stephane@161: strLevel = "TRAFFIC: "; Stephane@161: break; Stephane@161: case CecLogLevel.Debug: Stephane@202: strLevel = "DEBUG: "; StephaneLenclud@206: if (message.Message.IndexOf("POLL") != -1 && FilterOutPollLogs) StephaneLenclud@206: { StephaneLenclud@206: //We have an option to prevent spamming with poll debug logs StephaneLenclud@206: return 1; StephaneLenclud@206: } Stephane@161: break; Stephane@161: default: Stephane@161: break; Stephane@161: } Stephane@202: string strLog = string.Format("{0} {1} {2}", strLevel, message.Time, message.Message); StephaneLenclud@253: Trace.WriteLine(strLog); StephaneLenclud@201: Stephane@161: } Stephane@161: return 1; Stephane@161: } Stephane@161: Stephane@161: /// Stephane@161: /// Stephane@161: /// Stephane@161: /// Stephane@161: /// StephaneLenclud@214: public bool Open(int timeout) Stephane@161: { StephaneLenclud@201: Close(); StephaneLenclud@167: CecAdapter[] adapters = iLib.FindAdapters(string.Empty); Stephane@161: if (adapters.Length > 0) StephaneLenclud@201: { StephaneLenclud@214: Open(adapters[0].ComPort, timeout); StephaneLenclud@201: } Stephane@161: else Stephane@161: { StephaneLenclud@253: Trace.WriteLine("CEC did not find any adapters"); Stephane@161: } StephaneLenclud@201: StephaneLenclud@201: return iConnected; Stephane@161: } Stephane@161: StephaneLenclud@214: public bool Open(string port, int timeout) Stephane@161: { StephaneLenclud@201: Close(); StephaneLenclud@201: iConnected = iLib.Open(port, timeout); StephaneLenclud@201: return iConnected; Stephane@161: } Stephane@161: Stephane@161: public void Close() StephaneLenclud@201: { StephaneLenclud@167: iLib.Close(); StephaneLenclud@201: iConnected = false; Stephane@161: } Stephane@161: Stephane@202: Stephane@202: public void TestSendKey() Stephane@202: { Stephane@202: //SetupMenu: opens option menu Stephane@202: //RootMenu: opens Android home menu Stephane@202: //ContentsMenu: nop Stephane@202: //FavoriteMenu: nop Stephane@202: Stephane@202: //Philips TopMenu = 16 Stephane@202: //Philips PopupMenu = 17 Stephane@202: Stephane@202: //bool res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.DisplayInformation, true); Stephane@202: //Thread.Sleep(3000); //Wait few seconds for menu to open Stephane@202: //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.SetupMenu, true); Stephane@202: Stephane@202: for (int i = 0; i < 256; i++) Stephane@202: { Stephane@202: //Thread.Sleep(100); Stephane@202: //res = iLib.SendKeyRelease(CecLogicalAddress.Tv, true); Stephane@202: //Thread.Sleep(100); Stephane@202: switch ((CecUserControlCode)i) Stephane@202: { Stephane@202: case CecUserControlCode.Power: Stephane@202: case CecUserControlCode.PowerOffFunction: Stephane@202: case CecUserControlCode.PowerOnFunction: Stephane@202: case CecUserControlCode.PowerToggleFunction: Stephane@202: case CecUserControlCode.ElectronicProgramGuide: Stephane@202: case CecUserControlCode.InputSelect: Stephane@202: case CecUserControlCode.RootMenu: Stephane@202: Stephane@202: break; Stephane@202: Stephane@202: default: StephaneLenclud@253: Trace.WriteLine(i.ToString()); Stephane@202: Thread.Sleep(1000); Stephane@202: iLib.SendKeypress(CecLogicalAddress.Tv, (CecUserControlCode)i, true); Stephane@202: Stephane@202: break; Stephane@202: Stephane@202: } Stephane@202: Stephane@202: // Stephane@202: } Stephane@202: Stephane@202: Stephane@202: for (int i=0;i<7;i++) Stephane@202: { Stephane@202: //Thread.Sleep(100); Stephane@202: //res = iLib.SendKeyRelease(CecLogicalAddress.Tv, true); Stephane@202: //Thread.Sleep(100); Stephane@202: //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.Down, true); Stephane@202: // Stephane@202: } Stephane@202: Stephane@202: //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.Select, true); Stephane@202: Stephane@202: //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.Select, true); Stephane@202: //res = iLib.SendKeyRelease(CecLogicalAddress.Tv, true); Stephane@202: } Stephane@202: StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: /// StephaneLenclud@201: public void Scan() StephaneLenclud@201: { Stephane@207: string scanRes = ""; Stephane@207: scanRes += "CEC bus information\n"; Stephane@207: scanRes += "===================\n"; StephaneLenclud@201: CecLogicalAddresses addresses = Lib.GetActiveDevices(); StephaneLenclud@201: for (int iPtr = 0; iPtr < addresses.Addresses.Length; iPtr++) StephaneLenclud@201: { StephaneLenclud@201: CecLogicalAddress address = (CecLogicalAddress) iPtr; StephaneLenclud@201: if (!addresses.IsSet(address)) StephaneLenclud@201: continue; StephaneLenclud@201: StephaneLenclud@201: CecVendorId iVendorId = Lib.GetDeviceVendorId(address); StephaneLenclud@201: bool bActive = Lib.IsActiveDevice(address); StephaneLenclud@201: ushort iPhysicalAddress = Lib.GetDevicePhysicalAddress(address); StephaneLenclud@201: string strAddr = Lib.PhysicalAddressToString(iPhysicalAddress); StephaneLenclud@201: CecVersion iCecVersion = Lib.GetDeviceCecVersion(address); StephaneLenclud@201: CecPowerStatus power = Lib.GetDevicePowerStatus(address); StephaneLenclud@201: string osdName = Lib.GetDeviceOSDName(address); StephaneLenclud@201: string lang = Lib.GetDeviceMenuLanguage(address); StephaneLenclud@201: Stephane@207: scanRes += "device #" + iPtr + ": " + Lib.ToString(address) + "\n"; Stephane@207: scanRes += "address: " + strAddr + "\n"; Stephane@207: scanRes += "active source: " + (bActive ? "yes" : "no") + "\n"; Stephane@207: scanRes += "vendor: " + Lib.ToString(iVendorId) + "\n"; Stephane@207: scanRes += "osd string: " + osdName + "\n"; Stephane@207: scanRes += "CEC version: " + Lib.ToString(iCecVersion) + "\n"; Stephane@207: scanRes += "power status: " + Lib.ToString(power) + "\n"; StephaneLenclud@201: if (!string.IsNullOrEmpty(lang)) Stephane@207: scanRes += "language: " + lang + "\n"; Stephane@207: scanRes += "===================" + "\n"; StephaneLenclud@201: } Stephane@207: StephaneLenclud@253: Trace.Write(scanRes); StephaneLenclud@201: } StephaneLenclud@201: StephaneLenclud@201: public void ListAdapters() Stephane@161: { Stephane@161: int iAdapter = 0; StephaneLenclud@167: foreach (CecAdapter adapter in iLib.FindAdapters(string.Empty)) Stephane@161: { StephaneLenclud@253: Trace.WriteLine("Adapter: " + iAdapter++); StephaneLenclud@253: Trace.WriteLine("Path: " + adapter.Path); StephaneLenclud@253: Trace.WriteLine("Com port: " + adapter.ComPort); Stephane@161: } Stephane@161: } Stephane@203: Stephane@161: Stephane@161: } Stephane@161: }