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