Server/CecClient.cs
author StephaneLenclud
Tue, 19 Jul 2016 15:43:04 +0200
changeset 206 33be8cb90c57
parent 203 ce63ebb51da4
child 207 ca469451f8e6
permissions -rw-r--r--
Logs with time stamp.
CEC logs level configurable from UI.
     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 
    33 using System;
    34 using System.Text;
    35 using CecSharp;
    36 using System.Threading;
    37 
    38 namespace Cec
    39 {
    40     class Client : CecCallbackMethods
    41     {
    42         /// <summary>
    43         /// Provide direct access to CEC library
    44         /// </summary>
    45         public LibCecSharp Lib
    46         {
    47             get
    48             {
    49                 return iLib;
    50             }
    51         }
    52 
    53         /// <summary>
    54         /// 
    55         /// </summary>
    56         public int LogLevel = (int)CecLogLevel.Notice;
    57 
    58         /// <summary>
    59         /// 
    60         /// </summary>
    61         public bool FilterOutPollLogs = true;
    62 
    63         /// <summary>
    64         /// 
    65         /// </summary>
    66         private LibCecSharp iLib;
    67         /// <summary>
    68         /// 
    69         /// </summary>
    70         private LibCECConfiguration Config;
    71 
    72         /// <summary>
    73         /// 
    74         /// </summary>
    75         private bool iConnected;
    76 
    77         /// <summary>
    78         /// 
    79         /// </summary>
    80         /// <param name="aDeviceName"></param>
    81         /// <param name="aHdmiPort"></param>
    82         public Client(string aDeviceName, byte aHdmiPort, CecDeviceType aDeviceType = CecDeviceType.PlaybackDevice)
    83         {
    84             Config = new LibCECConfiguration();
    85             Config.DeviceTypes.Types[0] = aDeviceType;
    86             Config.DeviceName = aDeviceName;
    87             Config.HDMIPort = aHdmiPort;
    88             //Config.ClientVersion = LibCECConfiguration.CurrentVersion;
    89             Config.SetCallbacks(this);
    90 
    91             iLib = new LibCecSharp(Config);
    92             iLib.InitVideoStandalone();
    93 
    94             //Console.WriteLine("CEC Parser created - libCEC version " + Lib.VersionToString(Config.ServerVersion));
    95             Console.WriteLine("CEC Parser created - libCEC version " + Config.ServerVersion);
    96         }
    97 
    98 
    99         /// <summary>
   100         /// 
   101         /// </summary>
   102         /// <param name="alert"></param>
   103         /// <param name="data"></param>
   104         /// <returns></returns>
   105         public override int ReceiveAlert(CecAlert alert, CecParameter data)
   106         {
   107             string log = "CEC alert: " + alert.ToString();
   108             if (data != null && data.Type == CecParameterType.ParameterTypeString)
   109             {
   110                 log += " " + data.Data;
   111             }
   112 
   113             Console.WriteLine(log);
   114 
   115             Close();
   116             //Try reconnect
   117             Connect(1000);
   118             return 1;
   119         }
   120 
   121         /// <summary>
   122         /// 
   123         /// </summary>
   124         /// <param name="newVal"></param>
   125         /// <returns></returns>
   126         public override int ReceiveMenuStateChange(CecMenuState newVal)
   127         {
   128             Console.WriteLine("CEC menu state changed to: " + iLib.ToString(newVal));
   129             return 1;
   130         }
   131 
   132         /// <summary>
   133         /// 
   134         /// </summary>
   135         /// <param name="logicalAddress"></param>
   136         /// <param name="activated"></param>
   137         public override void SourceActivated(CecLogicalAddress logicalAddress, bool activated)
   138         {
   139             Console.WriteLine("CEC source activated: " + iLib.ToString(logicalAddress) + "/" + activated.ToString() );
   140             return;
   141         }
   142 
   143         public override int ReceiveCommand(CecCommand command)
   144         {
   145             Console.WriteLine(string.Format("CEC command Src:{0} Dst:{1} Ack: {2} Eom: {3} OpcodeSet: {4} Opcode: {5} Timeout: {6}",
   146                 iLib.ToString(command.Initiator),
   147                 iLib.ToString(command.Destination),
   148                 command.Ack.ToString(),
   149                 command.Eom.ToString(),
   150                 command.OpcodeSet.ToString(),
   151                 iLib.ToString(command.Opcode),
   152                 command.TransmitTimeout.ToString()
   153                 ));
   154             return 1;
   155         }
   156 
   157         public override int ReceiveKeypress(CecKeypress key)
   158         {
   159             Console.WriteLine(string.Format("CEC keypress: {0} Duration:{1} Empty: {2}",
   160                 key.Keycode.ToString(), key.Duration.ToString(), key.Empty.ToString()));
   161             return 1;
   162         }
   163 
   164         public override int ReceiveLogMessage(CecLogMessage message)
   165         {
   166             if (((int)message.Level & LogLevel) == (int)message.Level)
   167             {
   168                 string strLevel = "";
   169                 switch (message.Level)
   170                 {
   171                     case CecLogLevel.Error:
   172                         strLevel = "ERROR: ";
   173                         break;
   174                     case CecLogLevel.Warning:
   175                         strLevel = "WARNING: ";
   176                         break;
   177                     case CecLogLevel.Notice:
   178                         strLevel = "NOTICE: ";
   179                         break;
   180                     case CecLogLevel.Traffic:
   181                         strLevel = "TRAFFIC: ";
   182                         break;
   183                     case CecLogLevel.Debug:
   184                         strLevel = "DEBUG: ";
   185                         if (message.Message.IndexOf("POLL") != -1 && FilterOutPollLogs)
   186                         {
   187                             //We have an option to prevent spamming with poll debug logs
   188                             return 1;
   189                         }
   190                         break;
   191                     default:
   192                         break;
   193                 }
   194                 string strLog = string.Format("{0} {1} {2}", strLevel, message.Time, message.Message);
   195                 Console.WriteLine(strLog);
   196                 
   197             }
   198             return 1;
   199         }
   200 
   201         /// <summary>
   202         /// 
   203         /// </summary>
   204         /// <param name="timeout"></param>
   205         /// <returns></returns>
   206         public bool Connect(int timeout)
   207         {
   208             Close();         
   209             CecAdapter[] adapters = iLib.FindAdapters(string.Empty);
   210             if (adapters.Length > 0)
   211             {
   212                 Connect(adapters[0].ComPort, timeout);                
   213             }                
   214             else
   215             {
   216                 Console.WriteLine("CEC did not find any adapters");
   217             }
   218 
   219             return iConnected;
   220         }
   221 
   222         public bool Connect(string port, int timeout)
   223         {
   224             Close();
   225             iConnected = iLib.Open(port, timeout);
   226             if (iConnected)
   227             {
   228                 Scan();
   229                 //TestSendKey();
   230             }
   231             return iConnected;
   232         }
   233 
   234         public void Close()
   235         {            
   236             iLib.Close();
   237             iConnected = false;
   238         }
   239 
   240 
   241         public void TestSendKey()
   242         {
   243             //SetupMenu: opens option menu
   244             //RootMenu: opens Android home menu
   245             //ContentsMenu: nop
   246             //FavoriteMenu: nop
   247 
   248             //Philips TopMenu = 16
   249             //Philips PopupMenu = 17
   250 
   251             //bool res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.DisplayInformation, true);
   252             //Thread.Sleep(3000); //Wait few seconds for menu to open
   253                                 //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.SetupMenu, true);
   254 
   255             for (int i = 0; i < 256; i++)
   256             {
   257                 //Thread.Sleep(100);
   258                 //res = iLib.SendKeyRelease(CecLogicalAddress.Tv, true);
   259                 //Thread.Sleep(100);
   260                 switch ((CecUserControlCode)i)
   261                 {
   262                     case CecUserControlCode.Power:
   263                     case CecUserControlCode.PowerOffFunction:
   264                     case CecUserControlCode.PowerOnFunction:
   265                     case CecUserControlCode.PowerToggleFunction:
   266                     case CecUserControlCode.ElectronicProgramGuide:
   267                     case CecUserControlCode.InputSelect:
   268                     case CecUserControlCode.RootMenu:
   269 
   270                         break;
   271 
   272                     default:
   273                         Console.WriteLine(i.ToString());
   274                         Thread.Sleep(1000);
   275                         iLib.SendKeypress(CecLogicalAddress.Tv, (CecUserControlCode)i, true);
   276                         
   277                         break;
   278 
   279                 }
   280                 
   281                 //
   282             }
   283 
   284 
   285             for (int i=0;i<7;i++)
   286             {
   287                 //Thread.Sleep(100);
   288                 //res = iLib.SendKeyRelease(CecLogicalAddress.Tv, true);
   289                 //Thread.Sleep(100);
   290                 //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.Down, true);
   291                 //
   292             }
   293 
   294             //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.Select, true);
   295 
   296             //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.Select, true);
   297             //res = iLib.SendKeyRelease(CecLogicalAddress.Tv, true);
   298         }
   299 
   300         /// <summary>
   301         /// 
   302         /// </summary>
   303         public void Scan()
   304         {
   305             Console.WriteLine("CEC bus information");
   306             Console.WriteLine("===================");
   307             CecLogicalAddresses addresses = Lib.GetActiveDevices();
   308             for (int iPtr = 0; iPtr < addresses.Addresses.Length; iPtr++)
   309             {
   310                 CecLogicalAddress address = (CecLogicalAddress) iPtr;
   311                 if (!addresses.IsSet(address))
   312                     continue;
   313 
   314                 CecVendorId iVendorId = Lib.GetDeviceVendorId(address);
   315                 bool bActive = Lib.IsActiveDevice(address);
   316                 ushort iPhysicalAddress = Lib.GetDevicePhysicalAddress(address);
   317                 string strAddr = Lib.PhysicalAddressToString(iPhysicalAddress);
   318                 CecVersion iCecVersion = Lib.GetDeviceCecVersion(address);
   319                 CecPowerStatus power = Lib.GetDevicePowerStatus(address);
   320                 string osdName = Lib.GetDeviceOSDName(address);
   321                 string lang = Lib.GetDeviceMenuLanguage(address);
   322 
   323                 Console.WriteLine("device #" + iPtr + ": " + Lib.ToString(address));
   324                 Console.WriteLine("address:       " + strAddr);
   325                 Console.WriteLine("active source: " + (bActive ? "yes" : "no"));
   326                 Console.WriteLine("vendor:        " + Lib.ToString(iVendorId));
   327                 Console.WriteLine("osd string:    " + osdName);
   328                 Console.WriteLine("CEC version:   " + Lib.ToString(iCecVersion));
   329                 Console.WriteLine("power status:  " + Lib.ToString(power));
   330                 if (!string.IsNullOrEmpty(lang))
   331                     Console.WriteLine("language:      " + lang);
   332                 Console.WriteLine("");
   333             }
   334         }
   335 
   336         public void ListAdapters()
   337         {
   338             int iAdapter = 0;
   339             foreach (CecAdapter adapter in iLib.FindAdapters(string.Empty))
   340             {
   341                 Console.WriteLine("Adapter:    " + iAdapter++);
   342                 Console.WriteLine("Path:         " + adapter.Path);
   343                 Console.WriteLine("Com port: " + adapter.ComPort);
   344             }
   345         }
   346 
   347         void ShowConsoleHelp()
   348         {
   349             Console.WriteLine(
   350                 "================================================================================" + Environment.NewLine +
   351                 "Available commands:" + Environment.NewLine +
   352                 Environment.NewLine +
   353                 "[tx] {bytes}                            transfer bytes over the CEC line." + Environment.NewLine +
   354                 "[txn] {bytes}                         transfer bytes but don't wait for transmission ACK." + Environment.NewLine +
   355                 "[on] {address}                        power on the device with the given logical address." + Environment.NewLine +
   356                 "[standby] {address}             put the device with the given address in standby mode." + Environment.NewLine +
   357                 "[la] {logical_address}        change the logical address of the CEC adapter." + Environment.NewLine +
   358                 "[pa] {physical_address}     change the physical address of the CEC adapter." + Environment.NewLine +
   359                 "[osd] {addr} {string}         set OSD message on the specified device." + Environment.NewLine +
   360                 "[ver] {addr}                            get the CEC version of the specified device." + Environment.NewLine +
   361                 "[ven] {addr}                            get the vendor ID of the specified device." + Environment.NewLine +
   362                 "[lang] {addr}                         get the menu language of the specified device." + Environment.NewLine +
   363                 "[pow] {addr}                            get the power status of the specified device." + Environment.NewLine +
   364                 "[poll] {addr}                         poll the specified device." + Environment.NewLine +
   365                 "[scan]                                        scan the CEC bus and display device info" + Environment.NewLine +
   366                 "[mon] {1|0}                             enable or disable CEC bus monitoring." + Environment.NewLine +
   367                 "[log] {1 - 31}                        change the log level. see cectypes.h for values." + Environment.NewLine +
   368                 "[ping]                                        send a ping command to the CEC adapter." + Environment.NewLine +
   369                 "[bl]                                            to let the adapter enter the bootloader, to upgrade" + Environment.NewLine +
   370                 "                                                    the flash rom." + Environment.NewLine +
   371                 "[r]                                             reconnect to the CEC adapter." + Environment.NewLine +
   372                 "[h] or [help]                         show this help." + Environment.NewLine +
   373                 "[q] or [quit]                         to quit the CEC test client and switch off all" + Environment.NewLine +
   374                 "                                                    connected CEC devices." + Environment.NewLine +
   375                 "================================================================================");
   376         }
   377 
   378         public void MainLoop()
   379         {
   380             bool bContinue = true;
   381             string command;
   382             while (bContinue)
   383             {
   384                 Console.WriteLine("waiting for input");
   385 
   386                 command = Console.ReadLine();
   387                 if (command != null && command.Length == 0)
   388                     continue;
   389                 string[] splitCommand = command.Split(' ');
   390                 if (splitCommand[0] == "tx" || splitCommand[0] == "txn")
   391                 {
   392                     CecCommand bytes = new CecCommand();
   393                     for (int iPtr = 1; iPtr < splitCommand.Length; iPtr++)
   394                     {
   395                         bytes.PushBack(byte.Parse(splitCommand[iPtr], System.Globalization.NumberStyles.HexNumber));
   396                     }
   397 
   398                     if (command == "txn")
   399                         bytes.TransmitTimeout = 0;
   400 
   401                     iLib.Transmit(bytes);
   402                 }
   403                 else if (splitCommand[0] == "on")
   404                 {
   405                     if (splitCommand.Length > 1)
   406                         iLib.PowerOnDevices((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   407                     else
   408                         iLib.PowerOnDevices(CecLogicalAddress.Broadcast);
   409                 }
   410                 else if (splitCommand[0] == "standby")
   411                 {
   412                     if (splitCommand.Length > 1)
   413                         iLib.StandbyDevices((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   414                     else
   415                         iLib.StandbyDevices(CecLogicalAddress.Broadcast);
   416                 }
   417                 else if (splitCommand[0] == "poll")
   418                 {
   419                     bool bSent = false;
   420                     if (splitCommand.Length > 1)
   421                         bSent = iLib.PollDevice((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   422                     else
   423                         bSent = iLib.PollDevice(CecLogicalAddress.Broadcast);
   424                     if (bSent)
   425                         Console.WriteLine("POLL message sent");
   426                     else
   427                         Console.WriteLine("POLL message not sent");
   428                 }
   429                 else if (splitCommand[0] == "la")
   430                 {
   431                     if (splitCommand.Length > 1)
   432                         iLib.SetLogicalAddress((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   433                 }
   434                 else if (splitCommand[0] == "pa")
   435                 {
   436                     if (splitCommand.Length > 1)
   437                         iLib.SetPhysicalAddress(ushort.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   438                 }
   439                 else if (splitCommand[0] == "osd")
   440                 {
   441                     if (splitCommand.Length > 2)
   442                     {
   443                         StringBuilder osdString = new StringBuilder();
   444                         for (int iPtr = 1; iPtr < splitCommand.Length; iPtr++)
   445                         {
   446                             osdString.Append(splitCommand[iPtr]);
   447                             if (iPtr != splitCommand.Length - 1)
   448                                 osdString.Append(" ");
   449                         }
   450                         iLib.SetOSDString((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber), CecDisplayControl.DisplayForDefaultTime, osdString.ToString());
   451                     }
   452                 }
   453                 else if (splitCommand[0] == "ping")
   454                 {
   455                     iLib.PingAdapter();
   456                 }
   457                 else if (splitCommand[0] == "mon")
   458                 {
   459                     bool enable = splitCommand.Length > 1 ? splitCommand[1] == "1" : false;
   460                     iLib.SwitchMonitoring(enable);
   461                 }
   462                 else if (splitCommand[0] == "bl")
   463                 {
   464                     iLib.StartBootloader();
   465                 }
   466                 else if (splitCommand[0] == "lang")
   467                 {
   468                     if (splitCommand.Length > 1)
   469                     {
   470                         string language = iLib.GetDeviceMenuLanguage((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   471                         Console.WriteLine("Menu language: " + language);
   472                     }
   473                 }
   474                 else if (splitCommand[0] == "ven")
   475                 {
   476                     if (splitCommand.Length > 1)
   477                     {
   478                         CecVendorId vendor = iLib.GetDeviceVendorId((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   479                         Console.WriteLine("Vendor ID: " + iLib.ToString(vendor));
   480                     }
   481                 }
   482                 else if (splitCommand[0] == "ver")
   483                 {
   484                     if (splitCommand.Length > 1)
   485                     {
   486                         CecVersion version = iLib.GetDeviceCecVersion((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   487                         Console.WriteLine("CEC version: " + iLib.ToString(version));
   488                     }
   489                 }
   490                 else if (splitCommand[0] == "pow")
   491                 {
   492                     if (splitCommand.Length > 1)
   493                     {
   494                         CecPowerStatus power = iLib.GetDevicePowerStatus((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   495                         Console.WriteLine("power status: " + iLib.ToString(power));
   496                     }
   497                 }
   498                 else if (splitCommand[0] == "r")
   499                 {
   500                     Console.WriteLine("closing the connection");
   501                     iLib.Close();
   502 
   503                     Console.WriteLine("opening a new connection");
   504                     Connect(10000);
   505 
   506                     Console.WriteLine("setting active source");
   507                     iLib.SetActiveSource(CecDeviceType.PlaybackDevice);
   508                 }
   509                 else if (splitCommand[0] == "scan")
   510                 {
   511                     StringBuilder output = new StringBuilder();
   512                     output.AppendLine("CEC bus information");
   513                     output.AppendLine("===================");
   514                     CecLogicalAddresses addresses = iLib.GetActiveDevices();
   515                     for (int iPtr = 0; iPtr < addresses.Addresses.Length; iPtr++)
   516                     {
   517                         CecLogicalAddress address = (CecLogicalAddress)iPtr;
   518                         if (!addresses.IsSet(address))
   519                             continue;
   520 
   521                         CecVendorId iVendorId = iLib.GetDeviceVendorId(address);
   522                         bool bActive = iLib.IsActiveDevice(address);
   523                         ushort iPhysicalAddress = iLib.GetDevicePhysicalAddress(address);
   524                         string strAddr = "todo: fixme"; //Lib.PhysicalAddressToString(iPhysicalAddress);
   525                         CecVersion iCecVersion = iLib.GetDeviceCecVersion(address);
   526                         CecPowerStatus power = iLib.GetDevicePowerStatus(address);
   527                         string osdName = iLib.GetDeviceOSDName(address);
   528                         string lang = iLib.GetDeviceMenuLanguage(address);
   529 
   530                         output.AppendLine("device #" + iPtr + ": " + iLib.ToString(address));
   531                         output.AppendLine("address:             " + strAddr);
   532                         output.AppendLine("active source: " + (bActive ? "yes" : "no"));
   533                         output.AppendLine("vendor:                " + iLib.ToString(iVendorId));
   534                         output.AppendLine("osd string:        " + osdName);
   535                         output.AppendLine("CEC version:     " + iLib.ToString(iCecVersion));
   536                         output.AppendLine("power status:    " + iLib.ToString(power));
   537                         if (!string.IsNullOrEmpty(lang))
   538                             output.AppendLine("language:            " + lang);
   539                         output.AppendLine("");
   540                     }
   541                     Console.WriteLine(output.ToString());
   542                 }
   543                 else if (splitCommand[0] == "h" || splitCommand[0] == "help")
   544                     ShowConsoleHelp();
   545                 else if (splitCommand[0] == "q" || splitCommand[0] == "quit")
   546                     bContinue = false;
   547                 else if (splitCommand[0] == "log" && splitCommand.Length > 1)
   548                     LogLevel = int.Parse(splitCommand[1]);                
   549             }
   550         }
   551        
   552 
   553     }
   554 }