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