Server/CecClient.cs
author StephaneLenclud
Thu, 25 Aug 2016 00:42:09 +0200
changeset 253 2dae7a163fff
parent 214 4961ede27e0a
permissions -rw-r--r--
Published v1.0.0.0
Updating Harmony library to v0.4.0 for keep alive support.
Improved logs mechanism.
Stephane@161
     1
/*
Stephane@161
     2
 * This file is part of the libCEC(R) library.
Stephane@161
     3
 *
Stephane@161
     4
 * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited.    All rights reserved.
Stephane@161
     5
 * libCEC(R) is an original work, containing original code.
Stephane@161
     6
 *
Stephane@161
     7
 * libCEC(R) is a trademark of Pulse-Eight Limited.
Stephane@161
     8
 *
Stephane@161
     9
 * This program is dual-licensed; you can redistribute it and/or modify
Stephane@161
    10
 * it under the terms of the GNU General Public License as published by
Stephane@161
    11
 * the Free Software Foundation; either version 2 of the License, or
Stephane@161
    12
 * (at your option) any later version.
Stephane@161
    13
 *
Stephane@161
    14
 * This program is distributed in the hope that it will be useful,
Stephane@161
    15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Stephane@161
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
Stephane@161
    17
 * GNU General Public License for more details.
Stephane@161
    18
 *
Stephane@161
    19
 * You should have received a copy of the GNU General Public License
Stephane@161
    20
 * along with this program; if not, write to the Free Software
Stephane@161
    21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Stephane@161
    22
 *
Stephane@161
    23
 *
Stephane@161
    24
 * Alternatively, you can license this library under a commercial license,
Stephane@161
    25
 * please contact Pulse-Eight Licensing for more information.
Stephane@161
    26
 *
Stephane@161
    27
 * For more information contact:
Stephane@161
    28
 * Pulse-Eight Licensing             <license@pulse-eight.com>
Stephane@161
    29
 *         http://www.pulse-eight.com/
Stephane@161
    30
 *         http://www.pulse-eight.net/
Stephane@161
    31
 */
Stephane@161
    32
Stephane@161
    33
using System;
Stephane@161
    34
using System.Text;
Stephane@161
    35
using CecSharp;
Stephane@202
    36
using System.Threading;
StephaneLenclud@253
    37
using System.Diagnostics;
Stephane@161
    38
Stephane@161
    39
namespace Cec
Stephane@161
    40
{
Stephane@161
    41
    class Client : CecCallbackMethods
Stephane@161
    42
    {
StephaneLenclud@167
    43
        /// <summary>
StephaneLenclud@214
    44
        /// Enable public static access
StephaneLenclud@214
    45
        /// </summary>
StephaneLenclud@214
    46
        public static Client Static;
StephaneLenclud@214
    47
StephaneLenclud@214
    48
        /// <summary>
StephaneLenclud@206
    49
        /// Provide direct access to CEC library
StephaneLenclud@206
    50
        /// </summary>
StephaneLenclud@206
    51
        public LibCecSharp Lib
StephaneLenclud@206
    52
        {
StephaneLenclud@206
    53
            get
StephaneLenclud@206
    54
            {
StephaneLenclud@206
    55
                return iLib;
StephaneLenclud@206
    56
            }
StephaneLenclud@206
    57
        }
StephaneLenclud@206
    58
StephaneLenclud@206
    59
        /// <summary>
StephaneLenclud@206
    60
        /// 
StephaneLenclud@206
    61
        /// </summary>
StephaneLenclud@206
    62
        public int LogLevel = (int)CecLogLevel.Notice;
StephaneLenclud@206
    63
StephaneLenclud@206
    64
        /// <summary>
StephaneLenclud@206
    65
        /// 
StephaneLenclud@206
    66
        /// </summary>
StephaneLenclud@206
    67
        public bool FilterOutPollLogs = true;
StephaneLenclud@206
    68
StephaneLenclud@206
    69
        /// <summary>
StephaneLenclud@206
    70
        /// 
StephaneLenclud@206
    71
        /// </summary>
StephaneLenclud@206
    72
        private LibCecSharp iLib;
StephaneLenclud@206
    73
        /// <summary>
StephaneLenclud@206
    74
        /// 
StephaneLenclud@206
    75
        /// </summary>
StephaneLenclud@206
    76
        private LibCECConfiguration Config;
StephaneLenclud@206
    77
StephaneLenclud@206
    78
        /// <summary>
StephaneLenclud@206
    79
        /// 
StephaneLenclud@206
    80
        /// </summary>
StephaneLenclud@206
    81
        private bool iConnected;
StephaneLenclud@206
    82
StephaneLenclud@206
    83
        /// <summary>
StephaneLenclud@167
    84
        /// 
StephaneLenclud@167
    85
        /// </summary>
StephaneLenclud@167
    86
        /// <param name="aDeviceName"></param>
StephaneLenclud@167
    87
        /// <param name="aHdmiPort"></param>
StephaneLenclud@206
    88
        public Client(string aDeviceName, byte aHdmiPort, CecDeviceType aDeviceType = CecDeviceType.PlaybackDevice)
Stephane@161
    89
        {
Stephane@161
    90
            Config = new LibCECConfiguration();
Stephane@203
    91
            Config.DeviceTypes.Types[0] = aDeviceType;
StephaneLenclud@167
    92
            Config.DeviceName = aDeviceName;
StephaneLenclud@167
    93
            Config.HDMIPort = aHdmiPort;
Stephane@161
    94
            //Config.ClientVersion = LibCECConfiguration.CurrentVersion;
Stephane@161
    95
            Config.SetCallbacks(this);
Stephane@161
    96
StephaneLenclud@167
    97
            iLib = new LibCecSharp(Config);
StephaneLenclud@167
    98
            iLib.InitVideoStandalone();
Stephane@161
    99
StephaneLenclud@214
   100
            if (Static != null)
StephaneLenclud@214
   101
            {
StephaneLenclud@253
   102
                Trace.WriteLine("WARNING: CEC client static already exists");
StephaneLenclud@214
   103
            }
StephaneLenclud@214
   104
            else
StephaneLenclud@214
   105
            {
StephaneLenclud@214
   106
                Static = this;
StephaneLenclud@214
   107
            }
StephaneLenclud@214
   108
            
StephaneLenclud@214
   109
StephaneLenclud@253
   110
            //Trace.WriteLine("CEC Parser created - libCEC version " + Lib.VersionToString(Config.ServerVersion));
StephaneLenclud@253
   111
            Trace.WriteLine("INFO: CEC Parser created - libCEC version " + Config.ServerVersion);
Stephane@161
   112
        }
Stephane@161
   113
Stephane@200
   114
StephaneLenclud@201
   115
        /// <summary>
StephaneLenclud@201
   116
        /// 
StephaneLenclud@201
   117
        /// </summary>
StephaneLenclud@201
   118
        /// <param name="alert"></param>
StephaneLenclud@201
   119
        /// <param name="data"></param>
StephaneLenclud@201
   120
        /// <returns></returns>
Stephane@202
   121
        public override int ReceiveAlert(CecAlert alert, CecParameter data)
Stephane@200
   122
        {
StephaneLenclud@201
   123
            string log = "CEC alert: " + alert.ToString();
StephaneLenclud@201
   124
            if (data != null && data.Type == CecParameterType.ParameterTypeString)
StephaneLenclud@201
   125
            {
StephaneLenclud@201
   126
                log += " " + data.Data;
StephaneLenclud@201
   127
            }
StephaneLenclud@201
   128
StephaneLenclud@253
   129
            Trace.WriteLine(log);
StephaneLenclud@201
   130
StephaneLenclud@201
   131
            Close();
StephaneLenclud@201
   132
            //Try reconnect
StephaneLenclud@214
   133
            Open(1000);
Stephane@200
   134
            return 1;
Stephane@200
   135
        }
Stephane@200
   136
StephaneLenclud@201
   137
        /// <summary>
StephaneLenclud@201
   138
        /// 
StephaneLenclud@201
   139
        /// </summary>
StephaneLenclud@201
   140
        /// <param name="newVal"></param>
StephaneLenclud@201
   141
        /// <returns></returns>
Stephane@202
   142
        public override int ReceiveMenuStateChange(CecMenuState newVal)
Stephane@200
   143
        {
StephaneLenclud@253
   144
            Trace.WriteLine("CEC menu state changed to: " + iLib.ToString(newVal));
Stephane@200
   145
            return 1;
Stephane@200
   146
        }
Stephane@200
   147
StephaneLenclud@201
   148
        /// <summary>
StephaneLenclud@201
   149
        /// 
StephaneLenclud@201
   150
        /// </summary>
StephaneLenclud@201
   151
        /// <param name="logicalAddress"></param>
StephaneLenclud@201
   152
        /// <param name="activated"></param>
Stephane@202
   153
        public override void SourceActivated(CecLogicalAddress logicalAddress, bool activated)
Stephane@200
   154
        {
StephaneLenclud@253
   155
            Trace.WriteLine("CEC source activated: " + iLib.ToString(logicalAddress) + "/" + activated.ToString() );
Stephane@200
   156
            return;
Stephane@200
   157
        }
Stephane@200
   158
Stephane@161
   159
        public override int ReceiveCommand(CecCommand command)
Stephane@161
   160
        {
StephaneLenclud@253
   161
            Trace.WriteLine(string.Format("CEC command '{5}' from {0} to {1} - Ack: {2} Eom: {3} OpcodeSet: {4} Timeout: {6}",
StephaneLenclud@201
   162
                iLib.ToString(command.Initiator),
StephaneLenclud@201
   163
                iLib.ToString(command.Destination),
StephaneLenclud@201
   164
                command.Ack.ToString(),
StephaneLenclud@201
   165
                command.Eom.ToString(),
StephaneLenclud@201
   166
                command.OpcodeSet.ToString(),
StephaneLenclud@201
   167
                iLib.ToString(command.Opcode),
StephaneLenclud@201
   168
                command.TransmitTimeout.ToString()
StephaneLenclud@201
   169
                ));
Stephane@161
   170
            return 1;
Stephane@161
   171
        }
Stephane@161
   172
Stephane@161
   173
        public override int ReceiveKeypress(CecKeypress key)
Stephane@161
   174
        {
StephaneLenclud@253
   175
            Trace.WriteLine(string.Format("CEC keypress: {0} Duration:{1} Empty: {2}",
StephaneLenclud@201
   176
                key.Keycode.ToString(), key.Duration.ToString(), key.Empty.ToString()));
Stephane@161
   177
            return 1;
Stephane@161
   178
        }
Stephane@161
   179
Stephane@161
   180
        public override int ReceiveLogMessage(CecLogMessage message)
Stephane@161
   181
        {
Stephane@161
   182
            if (((int)message.Level & LogLevel) == (int)message.Level)
Stephane@161
   183
            {
Stephane@161
   184
                string strLevel = "";
Stephane@161
   185
                switch (message.Level)
Stephane@161
   186
                {
Stephane@161
   187
                    case CecLogLevel.Error:
Stephane@202
   188
                        strLevel = "ERROR: ";
Stephane@161
   189
                        break;
Stephane@161
   190
                    case CecLogLevel.Warning:
Stephane@161
   191
                        strLevel = "WARNING: ";
Stephane@161
   192
                        break;
Stephane@161
   193
                    case CecLogLevel.Notice:
Stephane@202
   194
                        strLevel = "NOTICE: ";
Stephane@161
   195
                        break;
Stephane@161
   196
                    case CecLogLevel.Traffic:
Stephane@161
   197
                        strLevel = "TRAFFIC: ";
Stephane@161
   198
                        break;
Stephane@161
   199
                    case CecLogLevel.Debug:
Stephane@202
   200
                        strLevel = "DEBUG: ";
StephaneLenclud@206
   201
                        if (message.Message.IndexOf("POLL") != -1 && FilterOutPollLogs)
StephaneLenclud@206
   202
                        {
StephaneLenclud@206
   203
                            //We have an option to prevent spamming with poll debug logs
StephaneLenclud@206
   204
                            return 1;
StephaneLenclud@206
   205
                        }
Stephane@161
   206
                        break;
Stephane@161
   207
                    default:
Stephane@161
   208
                        break;
Stephane@161
   209
                }
Stephane@202
   210
                string strLog = string.Format("{0} {1} {2}", strLevel, message.Time, message.Message);
StephaneLenclud@253
   211
                Trace.WriteLine(strLog);
StephaneLenclud@201
   212
                
Stephane@161
   213
            }
Stephane@161
   214
            return 1;
Stephane@161
   215
        }
Stephane@161
   216
Stephane@161
   217
        /// <summary>
Stephane@161
   218
        /// 
Stephane@161
   219
        /// </summary>
Stephane@161
   220
        /// <param name="timeout"></param>
Stephane@161
   221
        /// <returns></returns>
StephaneLenclud@214
   222
        public bool Open(int timeout)
Stephane@161
   223
        {
StephaneLenclud@201
   224
            Close();         
StephaneLenclud@167
   225
            CecAdapter[] adapters = iLib.FindAdapters(string.Empty);
Stephane@161
   226
            if (adapters.Length > 0)
StephaneLenclud@201
   227
            {
StephaneLenclud@214
   228
                Open(adapters[0].ComPort, timeout);                
StephaneLenclud@201
   229
            }                
Stephane@161
   230
            else
Stephane@161
   231
            {
StephaneLenclud@253
   232
                Trace.WriteLine("CEC did not find any adapters");
Stephane@161
   233
            }
StephaneLenclud@201
   234
StephaneLenclud@201
   235
            return iConnected;
Stephane@161
   236
        }
Stephane@161
   237
StephaneLenclud@214
   238
        public bool Open(string port, int timeout)
Stephane@161
   239
        {
StephaneLenclud@201
   240
            Close();
StephaneLenclud@201
   241
            iConnected = iLib.Open(port, timeout);
StephaneLenclud@201
   242
            return iConnected;
Stephane@161
   243
        }
Stephane@161
   244
Stephane@161
   245
        public void Close()
StephaneLenclud@201
   246
        {            
StephaneLenclud@167
   247
            iLib.Close();
StephaneLenclud@201
   248
            iConnected = false;
Stephane@161
   249
        }
Stephane@161
   250
Stephane@202
   251
Stephane@202
   252
        public void TestSendKey()
Stephane@202
   253
        {
Stephane@202
   254
            //SetupMenu: opens option menu
Stephane@202
   255
            //RootMenu: opens Android home menu
Stephane@202
   256
            //ContentsMenu: nop
Stephane@202
   257
            //FavoriteMenu: nop
Stephane@202
   258
Stephane@202
   259
            //Philips TopMenu = 16
Stephane@202
   260
            //Philips PopupMenu = 17
Stephane@202
   261
Stephane@202
   262
            //bool res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.DisplayInformation, true);
Stephane@202
   263
            //Thread.Sleep(3000); //Wait few seconds for menu to open
Stephane@202
   264
                                //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.SetupMenu, true);
Stephane@202
   265
Stephane@202
   266
            for (int i = 0; i < 256; i++)
Stephane@202
   267
            {
Stephane@202
   268
                //Thread.Sleep(100);
Stephane@202
   269
                //res = iLib.SendKeyRelease(CecLogicalAddress.Tv, true);
Stephane@202
   270
                //Thread.Sleep(100);
Stephane@202
   271
                switch ((CecUserControlCode)i)
Stephane@202
   272
                {
Stephane@202
   273
                    case CecUserControlCode.Power:
Stephane@202
   274
                    case CecUserControlCode.PowerOffFunction:
Stephane@202
   275
                    case CecUserControlCode.PowerOnFunction:
Stephane@202
   276
                    case CecUserControlCode.PowerToggleFunction:
Stephane@202
   277
                    case CecUserControlCode.ElectronicProgramGuide:
Stephane@202
   278
                    case CecUserControlCode.InputSelect:
Stephane@202
   279
                    case CecUserControlCode.RootMenu:
Stephane@202
   280
Stephane@202
   281
                        break;
Stephane@202
   282
Stephane@202
   283
                    default:
StephaneLenclud@253
   284
                        Trace.WriteLine(i.ToString());
Stephane@202
   285
                        Thread.Sleep(1000);
Stephane@202
   286
                        iLib.SendKeypress(CecLogicalAddress.Tv, (CecUserControlCode)i, true);
Stephane@202
   287
                        
Stephane@202
   288
                        break;
Stephane@202
   289
Stephane@202
   290
                }
Stephane@202
   291
                
Stephane@202
   292
                //
Stephane@202
   293
            }
Stephane@202
   294
Stephane@202
   295
Stephane@202
   296
            for (int i=0;i<7;i++)
Stephane@202
   297
            {
Stephane@202
   298
                //Thread.Sleep(100);
Stephane@202
   299
                //res = iLib.SendKeyRelease(CecLogicalAddress.Tv, true);
Stephane@202
   300
                //Thread.Sleep(100);
Stephane@202
   301
                //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.Down, true);
Stephane@202
   302
                //
Stephane@202
   303
            }
Stephane@202
   304
Stephane@202
   305
            //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.Select, true);
Stephane@202
   306
Stephane@202
   307
            //res = iLib.SendKeypress(CecLogicalAddress.Tv, CecUserControlCode.Select, true);
Stephane@202
   308
            //res = iLib.SendKeyRelease(CecLogicalAddress.Tv, true);
Stephane@202
   309
        }
Stephane@202
   310
StephaneLenclud@201
   311
        /// <summary>
StephaneLenclud@201
   312
        /// 
StephaneLenclud@201
   313
        /// </summary>
StephaneLenclud@201
   314
        public void Scan()
StephaneLenclud@201
   315
        {
Stephane@207
   316
            string scanRes = "";
Stephane@207
   317
            scanRes += "CEC bus information\n";
Stephane@207
   318
            scanRes += "===================\n";
StephaneLenclud@201
   319
            CecLogicalAddresses addresses = Lib.GetActiveDevices();
StephaneLenclud@201
   320
            for (int iPtr = 0; iPtr < addresses.Addresses.Length; iPtr++)
StephaneLenclud@201
   321
            {
StephaneLenclud@201
   322
                CecLogicalAddress address = (CecLogicalAddress) iPtr;
StephaneLenclud@201
   323
                if (!addresses.IsSet(address))
StephaneLenclud@201
   324
                    continue;
StephaneLenclud@201
   325
StephaneLenclud@201
   326
                CecVendorId iVendorId = Lib.GetDeviceVendorId(address);
StephaneLenclud@201
   327
                bool bActive = Lib.IsActiveDevice(address);
StephaneLenclud@201
   328
                ushort iPhysicalAddress = Lib.GetDevicePhysicalAddress(address);
StephaneLenclud@201
   329
                string strAddr = Lib.PhysicalAddressToString(iPhysicalAddress);
StephaneLenclud@201
   330
                CecVersion iCecVersion = Lib.GetDeviceCecVersion(address);
StephaneLenclud@201
   331
                CecPowerStatus power = Lib.GetDevicePowerStatus(address);
StephaneLenclud@201
   332
                string osdName = Lib.GetDeviceOSDName(address);
StephaneLenclud@201
   333
                string lang = Lib.GetDeviceMenuLanguage(address);
StephaneLenclud@201
   334
Stephane@207
   335
                scanRes += "device #" + iPtr + ": " + Lib.ToString(address) + "\n";
Stephane@207
   336
                scanRes += "address:       " + strAddr + "\n";
Stephane@207
   337
                scanRes += "active source: " + (bActive ? "yes" : "no") + "\n";
Stephane@207
   338
                scanRes += "vendor:        " + Lib.ToString(iVendorId) + "\n";
Stephane@207
   339
                scanRes += "osd string:    " + osdName + "\n";
Stephane@207
   340
                scanRes += "CEC version:   " + Lib.ToString(iCecVersion) + "\n";
Stephane@207
   341
                scanRes += "power status:  " + Lib.ToString(power) + "\n";
StephaneLenclud@201
   342
                if (!string.IsNullOrEmpty(lang))
Stephane@207
   343
                    scanRes += "language:      " + lang + "\n";
Stephane@207
   344
                scanRes += "===================" + "\n";
StephaneLenclud@201
   345
            }
Stephane@207
   346
StephaneLenclud@253
   347
            Trace.Write(scanRes);
StephaneLenclud@201
   348
        }
StephaneLenclud@201
   349
StephaneLenclud@201
   350
        public void ListAdapters()
Stephane@161
   351
        {
Stephane@161
   352
            int iAdapter = 0;
StephaneLenclud@167
   353
            foreach (CecAdapter adapter in iLib.FindAdapters(string.Empty))
Stephane@161
   354
            {
StephaneLenclud@253
   355
                Trace.WriteLine("Adapter:    " + iAdapter++);
StephaneLenclud@253
   356
                Trace.WriteLine("Path:         " + adapter.Path);
StephaneLenclud@253
   357
                Trace.WriteLine("Com port: " + adapter.ComPort);
Stephane@161
   358
            }
Stephane@161
   359
        }
Stephane@203
   360
       
Stephane@161
   361
Stephane@161
   362
    }
Stephane@161
   363
}