Server/CecClient.cs
author StephaneLenclud
Fri, 22 Jul 2016 18:19:49 +0200
changeset 209 fef4ca058087
parent 206 33be8cb90c57
child 214 4961ede27e0a
permissions -rw-r--r--
Prototype for event and action framework.
     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 '{5}' from {0} to {1} - Ack: {2} Eom: {3} OpcodeSet: {4} 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             string scanRes = "";
   306             scanRes += "CEC bus information\n";
   307             scanRes += "===================\n";
   308             CecLogicalAddresses addresses = Lib.GetActiveDevices();
   309             for (int iPtr = 0; iPtr < addresses.Addresses.Length; iPtr++)
   310             {
   311                 CecLogicalAddress address = (CecLogicalAddress) iPtr;
   312                 if (!addresses.IsSet(address))
   313                     continue;
   314 
   315                 CecVendorId iVendorId = Lib.GetDeviceVendorId(address);
   316                 bool bActive = Lib.IsActiveDevice(address);
   317                 ushort iPhysicalAddress = Lib.GetDevicePhysicalAddress(address);
   318                 string strAddr = Lib.PhysicalAddressToString(iPhysicalAddress);
   319                 CecVersion iCecVersion = Lib.GetDeviceCecVersion(address);
   320                 CecPowerStatus power = Lib.GetDevicePowerStatus(address);
   321                 string osdName = Lib.GetDeviceOSDName(address);
   322                 string lang = Lib.GetDeviceMenuLanguage(address);
   323 
   324                 scanRes += "device #" + iPtr + ": " + Lib.ToString(address) + "\n";
   325                 scanRes += "address:       " + strAddr + "\n";
   326                 scanRes += "active source: " + (bActive ? "yes" : "no") + "\n";
   327                 scanRes += "vendor:        " + Lib.ToString(iVendorId) + "\n";
   328                 scanRes += "osd string:    " + osdName + "\n";
   329                 scanRes += "CEC version:   " + Lib.ToString(iCecVersion) + "\n";
   330                 scanRes += "power status:  " + Lib.ToString(power) + "\n";
   331                 if (!string.IsNullOrEmpty(lang))
   332                     scanRes += "language:      " + lang + "\n";
   333                 scanRes += "===================" + "\n";
   334             }
   335 
   336             Console.Write(scanRes);
   337         }
   338 
   339         public void ListAdapters()
   340         {
   341             int iAdapter = 0;
   342             foreach (CecAdapter adapter in iLib.FindAdapters(string.Empty))
   343             {
   344                 Console.WriteLine("Adapter:    " + iAdapter++);
   345                 Console.WriteLine("Path:         " + adapter.Path);
   346                 Console.WriteLine("Com port: " + adapter.ComPort);
   347             }
   348         }
   349 
   350         void ShowConsoleHelp()
   351         {
   352             Console.WriteLine(
   353                 "================================================================================" + Environment.NewLine +
   354                 "Available commands:" + Environment.NewLine +
   355                 Environment.NewLine +
   356                 "[tx] {bytes}                            transfer bytes over the CEC line." + Environment.NewLine +
   357                 "[txn] {bytes}                         transfer bytes but don't wait for transmission ACK." + Environment.NewLine +
   358                 "[on] {address}                        power on the device with the given logical address." + Environment.NewLine +
   359                 "[standby] {address}             put the device with the given address in standby mode." + Environment.NewLine +
   360                 "[la] {logical_address}        change the logical address of the CEC adapter." + Environment.NewLine +
   361                 "[pa] {physical_address}     change the physical address of the CEC adapter." + Environment.NewLine +
   362                 "[osd] {addr} {string}         set OSD message on the specified device." + Environment.NewLine +
   363                 "[ver] {addr}                            get the CEC version of the specified device." + Environment.NewLine +
   364                 "[ven] {addr}                            get the vendor ID of the specified device." + Environment.NewLine +
   365                 "[lang] {addr}                         get the menu language of the specified device." + Environment.NewLine +
   366                 "[pow] {addr}                            get the power status of the specified device." + Environment.NewLine +
   367                 "[poll] {addr}                         poll the specified device." + Environment.NewLine +
   368                 "[scan]                                        scan the CEC bus and display device info" + Environment.NewLine +
   369                 "[mon] {1|0}                             enable or disable CEC bus monitoring." + Environment.NewLine +
   370                 "[log] {1 - 31}                        change the log level. see cectypes.h for values." + Environment.NewLine +
   371                 "[ping]                                        send a ping command to the CEC adapter." + Environment.NewLine +
   372                 "[bl]                                            to let the adapter enter the bootloader, to upgrade" + Environment.NewLine +
   373                 "                                                    the flash rom." + Environment.NewLine +
   374                 "[r]                                             reconnect to the CEC adapter." + Environment.NewLine +
   375                 "[h] or [help]                         show this help." + Environment.NewLine +
   376                 "[q] or [quit]                         to quit the CEC test client and switch off all" + Environment.NewLine +
   377                 "                                                    connected CEC devices." + Environment.NewLine +
   378                 "================================================================================");
   379         }
   380 
   381         public void MainLoop()
   382         {
   383             bool bContinue = true;
   384             string command;
   385             while (bContinue)
   386             {
   387                 Console.WriteLine("waiting for input");
   388 
   389                 command = Console.ReadLine();
   390                 if (command != null && command.Length == 0)
   391                     continue;
   392                 string[] splitCommand = command.Split(' ');
   393                 if (splitCommand[0] == "tx" || splitCommand[0] == "txn")
   394                 {
   395                     CecCommand bytes = new CecCommand();
   396                     for (int iPtr = 1; iPtr < splitCommand.Length; iPtr++)
   397                     {
   398                         bytes.PushBack(byte.Parse(splitCommand[iPtr], System.Globalization.NumberStyles.HexNumber));
   399                     }
   400 
   401                     if (command == "txn")
   402                         bytes.TransmitTimeout = 0;
   403 
   404                     iLib.Transmit(bytes);
   405                 }
   406                 else if (splitCommand[0] == "on")
   407                 {
   408                     if (splitCommand.Length > 1)
   409                         iLib.PowerOnDevices((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   410                     else
   411                         iLib.PowerOnDevices(CecLogicalAddress.Broadcast);
   412                 }
   413                 else if (splitCommand[0] == "standby")
   414                 {
   415                     if (splitCommand.Length > 1)
   416                         iLib.StandbyDevices((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   417                     else
   418                         iLib.StandbyDevices(CecLogicalAddress.Broadcast);
   419                 }
   420                 else if (splitCommand[0] == "poll")
   421                 {
   422                     bool bSent = false;
   423                     if (splitCommand.Length > 1)
   424                         bSent = iLib.PollDevice((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   425                     else
   426                         bSent = iLib.PollDevice(CecLogicalAddress.Broadcast);
   427                     if (bSent)
   428                         Console.WriteLine("POLL message sent");
   429                     else
   430                         Console.WriteLine("POLL message not sent");
   431                 }
   432                 else if (splitCommand[0] == "la")
   433                 {
   434                     if (splitCommand.Length > 1)
   435                         iLib.SetLogicalAddress((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   436                 }
   437                 else if (splitCommand[0] == "pa")
   438                 {
   439                     if (splitCommand.Length > 1)
   440                         iLib.SetPhysicalAddress(ushort.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   441                 }
   442                 else if (splitCommand[0] == "osd")
   443                 {
   444                     if (splitCommand.Length > 2)
   445                     {
   446                         StringBuilder osdString = new StringBuilder();
   447                         for (int iPtr = 1; iPtr < splitCommand.Length; iPtr++)
   448                         {
   449                             osdString.Append(splitCommand[iPtr]);
   450                             if (iPtr != splitCommand.Length - 1)
   451                                 osdString.Append(" ");
   452                         }
   453                         iLib.SetOSDString((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber), CecDisplayControl.DisplayForDefaultTime, osdString.ToString());
   454                     }
   455                 }
   456                 else if (splitCommand[0] == "ping")
   457                 {
   458                     iLib.PingAdapter();
   459                 }
   460                 else if (splitCommand[0] == "mon")
   461                 {
   462                     bool enable = splitCommand.Length > 1 ? splitCommand[1] == "1" : false;
   463                     iLib.SwitchMonitoring(enable);
   464                 }
   465                 else if (splitCommand[0] == "bl")
   466                 {
   467                     iLib.StartBootloader();
   468                 }
   469                 else if (splitCommand[0] == "lang")
   470                 {
   471                     if (splitCommand.Length > 1)
   472                     {
   473                         string language = iLib.GetDeviceMenuLanguage((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   474                         Console.WriteLine("Menu language: " + language);
   475                     }
   476                 }
   477                 else if (splitCommand[0] == "ven")
   478                 {
   479                     if (splitCommand.Length > 1)
   480                     {
   481                         CecVendorId vendor = iLib.GetDeviceVendorId((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   482                         Console.WriteLine("Vendor ID: " + iLib.ToString(vendor));
   483                     }
   484                 }
   485                 else if (splitCommand[0] == "ver")
   486                 {
   487                     if (splitCommand.Length > 1)
   488                     {
   489                         CecVersion version = iLib.GetDeviceCecVersion((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   490                         Console.WriteLine("CEC version: " + iLib.ToString(version));
   491                     }
   492                 }
   493                 else if (splitCommand[0] == "pow")
   494                 {
   495                     if (splitCommand.Length > 1)
   496                     {
   497                         CecPowerStatus power = iLib.GetDevicePowerStatus((CecLogicalAddress)byte.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
   498                         Console.WriteLine("power status: " + iLib.ToString(power));
   499                     }
   500                 }
   501                 else if (splitCommand[0] == "r")
   502                 {
   503                     Console.WriteLine("closing the connection");
   504                     iLib.Close();
   505 
   506                     Console.WriteLine("opening a new connection");
   507                     Connect(10000);
   508 
   509                     Console.WriteLine("setting active source");
   510                     iLib.SetActiveSource(CecDeviceType.PlaybackDevice);
   511                 }
   512                 else if (splitCommand[0] == "scan")
   513                 {
   514                     StringBuilder output = new StringBuilder();
   515                     output.AppendLine("CEC bus information");
   516                     output.AppendLine("===================");
   517                     CecLogicalAddresses addresses = iLib.GetActiveDevices();
   518                     for (int iPtr = 0; iPtr < addresses.Addresses.Length; iPtr++)
   519                     {
   520                         CecLogicalAddress address = (CecLogicalAddress)iPtr;
   521                         if (!addresses.IsSet(address))
   522                             continue;
   523 
   524                         CecVendorId iVendorId = iLib.GetDeviceVendorId(address);
   525                         bool bActive = iLib.IsActiveDevice(address);
   526                         ushort iPhysicalAddress = iLib.GetDevicePhysicalAddress(address);
   527                         string strAddr = "todo: fixme"; //Lib.PhysicalAddressToString(iPhysicalAddress);
   528                         CecVersion iCecVersion = iLib.GetDeviceCecVersion(address);
   529                         CecPowerStatus power = iLib.GetDevicePowerStatus(address);
   530                         string osdName = iLib.GetDeviceOSDName(address);
   531                         string lang = iLib.GetDeviceMenuLanguage(address);
   532 
   533                         output.AppendLine("device #" + iPtr + ": " + iLib.ToString(address));
   534                         output.AppendLine("address:             " + strAddr);
   535                         output.AppendLine("active source: " + (bActive ? "yes" : "no"));
   536                         output.AppendLine("vendor:                " + iLib.ToString(iVendorId));
   537                         output.AppendLine("osd string:        " + osdName);
   538                         output.AppendLine("CEC version:     " + iLib.ToString(iCecVersion));
   539                         output.AppendLine("power status:    " + iLib.ToString(power));
   540                         if (!string.IsNullOrEmpty(lang))
   541                             output.AppendLine("language:            " + lang);
   542                         output.AppendLine("");
   543                     }
   544                     Console.WriteLine(output.ToString());
   545                 }
   546                 else if (splitCommand[0] == "h" || splitCommand[0] == "help")
   547                     ShowConsoleHelp();
   548                 else if (splitCommand[0] == "q" || splitCommand[0] == "quit")
   549                     bContinue = false;
   550                 else if (splitCommand[0] == "log" && splitCommand.Length > 1)
   551                     LogLevel = int.Parse(splitCommand[1]);                
   552             }
   553         }
   554        
   555 
   556     }
   557 }