1 #pragma once
2 /*
3  * This file is part of the libCEC(R) library.
4  *
5  * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited.  All rights reserved.
6  * libCEC(R) is an original work, containing original code.
7  *
8  * libCEC(R) is a trademark of Pulse-Eight Limited.
9  *
10  * This program is dual-licensed; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  *
24  *
25  * Alternatively, you can license this library under a commercial license,
26  * please contact Pulse-Eight Licensing for more information.
27  *
28  * For more information contact:
29  * Pulse-Eight Licensing       <license@pulse-eight.com>
30  *     http://www.pulse-eight.com/
31  *     http://www.pulse-eight.net/
32  */
33 
34 #include "cecc.h"
35 
36 #include <stdio.h>
37 #if defined(_WIN32) || defined(_WIN64)
38 #include <windows.h>
39 #include <conio.h>
40 typedef HINSTANCE libcecc_lib_instance_t;
41 #else
42 #include <dlfcn.h>
43 typedef void* libcecc_lib_instance_t;
44 #ifndef CDECL
45 #define CDECL
46 #endif
47 #endif
48 
49 static libcecc_lib_instance_t libcecc_load_library(const char* strLib);
50 static void libcecc_close_library(libcecc_lib_instance_t lib);
51 static void* libcecc_resolve(void* lib, const char* name);
52 
53 #define _libcecc_resolve(lib, tar, name, method) \
54   do { \
55     tar = (method) libcecc_resolve(lib, name); \
56     if (tar == NULL) \
57     { \
58       libcecc_close_library(lib); \
59       return -1; \
60     } \
61   } while(0)
62 
63 typedef struct {
64   libcec_connection_t                 connection;
65   libcecc_lib_instance_t              lib_instance;
66   void                                (CDECL *destroy)(libcec_connection_t connection);
67   int                                 (CDECL *open)(libcec_connection_t connection, const char* strPort, uint32_t iTimeout);
68   void                                (CDECL *close)(libcec_connection_t connection);
69   void                                (CDECL *clear_configuration)(CEC_NAMESPACE libcec_configuration* configuration);
70   int                                 (CDECL *enable_callbacks)(libcec_connection_t connection, void* cbParam, CEC_NAMESPACE ICECCallbacks* callbacks);
71   int8_t                              (CDECL *find_adapters)(libcec_connection_t connection, CEC_NAMESPACE cec_adapter* deviceList, uint8_t iBufSize, const char* strDevicePath);
72   int                                 (CDECL *ping_adapters)(libcec_connection_t connection);
73   int                                 (CDECL *start_bootloader)(libcec_connection_t connection);
74   int                                 (CDECL *power_on_devices)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address address);
75   int                                 (CDECL *standby_devices)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address address);
76   int                                 (CDECL *set_active_source)(libcec_connection_t connection, CEC_NAMESPACE cec_device_type type);
77   int                                 (CDECL *set_deck_control_mode)(libcec_connection_t connection, CEC_NAMESPACE cec_deck_control_mode mode, int bSendUpdate);
78   int                                 (CDECL *set_deck_info)(libcec_connection_t connection, CEC_NAMESPACE cec_deck_info info, int bSendUpdate);
79   int                                 (CDECL *set_inactive_view)(libcec_connection_t connection);
80   int                                 (CDECL *set_menu_state)(libcec_connection_t connection, CEC_NAMESPACE cec_menu_state state, int bSendUpdate);
81   int                                 (CDECL *transmit)(libcec_connection_t connection, const CEC_NAMESPACE cec_command* data);
82   int                                 (CDECL *set_logical_address)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
83   int                                 (CDECL *set_physical_address)(libcec_connection_t connection, uint16_t iPhysicalAddress);
84   int                                 (CDECL *set_osd_string)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress, CEC_NAMESPACE cec_display_control duration, const char* strMessage);
85   int                                 (CDECL *switch_monitoring)(libcec_connection_t connection, int bEnable);
86   CEC_NAMESPACE cec_version           (CDECL *get_device_cec_version)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
87   int                                 (CDECL *get_device_menu_language)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress, CEC_NAMESPACE cec_menu_language language);
88   uint64_t                            (CDECL *get_device_vendor_id)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
89   uint16_t                            (CDECL *get_device_physical_address)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
90   CEC_NAMESPACE cec_logical_address   (CDECL *get_active_source)(libcec_connection_t connection);
91   int                                 (CDECL *is_active_source)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iAddress);
92   CEC_NAMESPACE cec_power_status      (CDECL *get_device_power_status)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
93   int                                 (CDECL *poll_device)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
94   CEC_NAMESPACE cec_logical_addresses (CDECL *get_active_devices)(libcec_connection_t connection);
95   int                                 (CDECL *is_active_device)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address address);
96   int                                 (CDECL *is_active_device_type)(libcec_connection_t connection, CEC_NAMESPACE cec_device_type type);
97   int                                 (CDECL *set_hdmi_port)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address baseDevice, uint8_t iPort);
98   int                                 (CDECL *volume_up)(libcec_connection_t connection, int bSendRelease);
99   int                                 (CDECL *volume_down)(libcec_connection_t connection, int bSendRelease);
100   int                                 (CDECL *mute_audio)(libcec_connection_t connection, int bSendRelease);
101   int                                 (CDECL *send_keypress)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iDestination, CEC_NAMESPACE cec_user_control_code key, int bWait);
102   int                                 (CDECL *send_key_release)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iDestination, int bWait);
103   int                                 (CDECL *get_device_osd_name)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iAddress, CEC_NAMESPACE cec_osd_name name);
104   int                                 (CDECL *set_stream_path_logical)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iAddress);
105   int                                 (CDECL *set_stream_path_physical)(libcec_connection_t connection, uint16_t iPhysicalAddress);
106   CEC_NAMESPACE cec_logical_addresses (CDECL *get_logical_addresses)(libcec_connection_t connection);
107   int                                 (CDECL *get_current_configuration)(libcec_connection_t connection, CEC_NAMESPACE libcec_configuration* configuration);
108   int                                 (CDECL *can_persist_configuration)(libcec_connection_t connection);
109   int                                 (CDECL *persist_configuration)(libcec_connection_t connection, CEC_NAMESPACE libcec_configuration* configuration);
110   int                                 (CDECL *set_configuration)(libcec_connection_t connection, const CEC_NAMESPACE libcec_configuration* configuration);
111   void                                (CDECL *rescan_devices)(libcec_connection_t connection);
112   int                                 (CDECL *is_libcec_active_source)(libcec_connection_t connection);
113   int                                 (CDECL *get_device_information)(libcec_connection_t connection, const char* strPort, CEC_NAMESPACE libcec_configuration* config, uint32_t iTimeoutMs);
114   const char*                         (CDECL *get_lib_info)(libcec_connection_t connection);
115   void                                (CDECL *init_video_standalone)(libcec_connection_t connection);
116   uint16_t                            (CDECL *get_adapter_vendor_id)(libcec_connection_t connection);
117   uint16_t                            (CDECL *get_adapter_product_id)(libcec_connection_t connection);
118   uint8_t                             (CDECL *audio_toggle_mute)(libcec_connection_t connection);
119   uint8_t                             (CDECL *audio_mute)(libcec_connection_t connection);
120   uint8_t                             (CDECL *audio_unmute)(libcec_connection_t connection);
121   uint8_t                             (CDECL *audio_get_status)(libcec_connection_t connection);
122   int8_t                              (CDECL *detect_adapters)(libcec_connection_t connection, CEC_NAMESPACE cec_adapter_descriptor* deviceList, uint8_t iBufSize, const char* strDevicePath, int bQuickScan);
123   void                                (CDECL *menu_state_to_string)(const CEC_NAMESPACE cec_menu_state state, char* buf, size_t bufsize);
124   void                                (CDECL *cec_version_to_string)(const CEC_NAMESPACE cec_version version, char* buf, size_t bufsize);
125   void                                (CDECL *power_status_to_string)(const CEC_NAMESPACE cec_power_status status, char* buf, size_t bufsize);
126   void                                (CDECL *logical_address_to_string)(const CEC_NAMESPACE cec_logical_address address, char* buf, size_t bufsize);
127   void                                (CDECL *deck_control_mode_to_string)(const CEC_NAMESPACE cec_deck_control_mode mode, char* buf, size_t bufsize);
128   void                                (CDECL *deck_status_to_string)(const CEC_NAMESPACE cec_deck_info status, char* buf, size_t bufsize);
129   void                                (CDECL *opcode_to_string)(const CEC_NAMESPACE cec_opcode opcode, char* buf, size_t bufsize);
130   void                                (CDECL *system_audio_status_to_string)(const CEC_NAMESPACE cec_system_audio_status mode, char* buf, size_t bufsize);
131   void                                (CDECL *audio_status_to_string)(const CEC_NAMESPACE cec_audio_status status, char* buf, size_t bufsize);
132   void                                (CDECL *vendor_id_to_string)(const CEC_NAMESPACE cec_vendor_id vendor, char* buf, size_t bufsize);
133   void                                (CDECL *user_control_key_to_string)(const CEC_NAMESPACE cec_user_control_code key, char* buf, size_t bufsize);
134   void                                (CDECL *adapter_type_to_string)(const CEC_NAMESPACE cec_adapter_type type, char* buf, size_t bufsize);
135   void                                (CDECL *version_to_string)(uint32_t version, char* buf, size_t bufsize);
136 } libcec_interface_t;
137 
libcecc_resolve_all(void * lib,libcec_interface_t * iface)138 static int libcecc_resolve_all(void* lib, libcec_interface_t* iface)
139 {
140   if (!lib || !iface)
141     return -1;
142 
143   _libcecc_resolve(lib, iface->destroy,                       "libcec_destroy",                       void(CDECL *)(libcec_connection_t));
144   _libcecc_resolve(lib, iface->open,                          "libcec_open",                          int(CDECL *)(libcec_connection_t, const char*, uint32_t));
145   _libcecc_resolve(lib, iface->close,                         "libcec_close",                         void(CDECL *)(libcec_connection_t));
146   _libcecc_resolve(lib, iface->clear_configuration,           "libcec_clear_configuration",           void(CDECL *)(CEC_NAMESPACE libcec_configuration*));
147   _libcecc_resolve(lib, iface->enable_callbacks,              "libcec_enable_callbacks",              int(CDECL *)(libcec_connection_t, void*, CEC_NAMESPACE ICECCallbacks*));
148   _libcecc_resolve(lib, iface->find_adapters,                 "libcec_find_adapters",                 int8_t(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_adapter*, uint8_t, const char*));
149   _libcecc_resolve(lib, iface->ping_adapters,                 "libcec_ping_adapters",                 int(CDECL *)(libcec_connection_t));
150   _libcecc_resolve(lib, iface->start_bootloader,              "libcec_start_bootloader",              int(CDECL *)(libcec_connection_t));
151   _libcecc_resolve(lib, iface->power_on_devices,              "libcec_power_on_devices",              int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
152   _libcecc_resolve(lib, iface->standby_devices,               "libcec_standby_devices",               int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
153   _libcecc_resolve(lib, iface->set_active_source,             "libcec_set_active_source",             int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_device_type));
154   _libcecc_resolve(lib, iface->set_deck_control_mode,         "libcec_set_deck_control_mode",         int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_deck_control_mode, int));
155   _libcecc_resolve(lib, iface->set_deck_info,                 "libcec_set_deck_info",                 int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_deck_info, int));
156   _libcecc_resolve(lib, iface->set_inactive_view,             "libcec_set_inactive_view",             int(CDECL *)(libcec_connection_t));
157   _libcecc_resolve(lib, iface->set_menu_state,                "libcec_set_menu_state",                int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_menu_state, int));
158   _libcecc_resolve(lib, iface->transmit,                      "libcec_transmit",                      int(CDECL *)(libcec_connection_t, const CEC_NAMESPACE cec_command*));
159   _libcecc_resolve(lib, iface->set_logical_address,           "libcec_set_logical_address",           int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
160   _libcecc_resolve(lib, iface->set_physical_address,          "libcec_set_physical_address",          int(CDECL *)(libcec_connection_t, uint16_t));
161   _libcecc_resolve(lib, iface->set_osd_string,                "libcec_set_osd_string",                int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, CEC_NAMESPACE cec_display_control, const char*));
162   _libcecc_resolve(lib, iface->switch_monitoring,             "libcec_switch_monitoring",             int(CDECL *)(libcec_connection_t, int));
163   _libcecc_resolve(lib, iface->get_device_cec_version,        "libcec_get_device_cec_version",        CEC_NAMESPACE cec_version(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
164   _libcecc_resolve(lib, iface->get_device_menu_language,      "libcec_get_device_menu_language",      int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, CEC_NAMESPACE cec_menu_language));
165   _libcecc_resolve(lib, iface->get_device_vendor_id,          "libcec_get_device_vendor_id",          uint64_t(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
166   _libcecc_resolve(lib, iface->get_device_physical_address,   "libcec_get_device_physical_address",   uint16_t(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
167   _libcecc_resolve(lib, iface->get_active_source,             "libcec_get_active_source",             CEC_NAMESPACE cec_logical_address(CDECL *)(libcec_connection_t));
168   _libcecc_resolve(lib, iface->is_active_source,              "libcec_is_active_source",              int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
169   _libcecc_resolve(lib, iface->get_device_power_status,       "libcec_get_device_power_status",       CEC_NAMESPACE cec_power_status(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
170   _libcecc_resolve(lib, iface->poll_device,                   "libcec_poll_device",                   int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
171   _libcecc_resolve(lib, iface->get_active_devices,            "libcec_get_active_devices",            CEC_NAMESPACE cec_logical_addresses(CDECL *)(libcec_connection_t));
172   _libcecc_resolve(lib, iface->is_active_device,              "libcec_is_active_device",              int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
173   _libcecc_resolve(lib, iface->is_active_device_type,         "libcec_is_active_device_type",         int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_device_type));
174   _libcecc_resolve(lib, iface->set_hdmi_port,                 "libcec_set_hdmi_port",                 int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, uint8_t));
175   _libcecc_resolve(lib, iface->volume_up,                     "libcec_volume_up",                     int(CDECL *)(libcec_connection_t, int));
176   _libcecc_resolve(lib, iface->volume_down,                   "libcec_volume_down",                   int(CDECL *)(libcec_connection_t, int));
177   _libcecc_resolve(lib, iface->mute_audio,                    "libcec_mute_audio",                    int(CDECL *)(libcec_connection_t, int));
178   _libcecc_resolve(lib, iface->send_keypress,                 "libcec_send_keypress",                 int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, CEC_NAMESPACE cec_user_control_code, int));
179   _libcecc_resolve(lib, iface->send_key_release,              "libcec_send_key_release",              int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, int));
180   _libcecc_resolve(lib, iface->get_device_osd_name,           "libcec_get_device_osd_name",           int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, CEC_NAMESPACE cec_osd_name));
181   _libcecc_resolve(lib, iface->set_stream_path_logical,       "libcec_set_stream_path_logical",       int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
182   _libcecc_resolve(lib, iface->set_stream_path_physical,      "libcec_set_stream_path_physical",      int(CDECL *)(libcec_connection_t, uint16_t));
183   _libcecc_resolve(lib, iface->get_logical_addresses,         "libcec_get_logical_addresses",         CEC_NAMESPACE cec_logical_addresses(CDECL *)(libcec_connection_t));
184   _libcecc_resolve(lib, iface->get_current_configuration,     "libcec_get_current_configuration",     int(CDECL *)(libcec_connection_t, CEC_NAMESPACE libcec_configuration*));
185   _libcecc_resolve(lib, iface->can_persist_configuration,     "libcec_can_persist_configuration",     int(CDECL *)(libcec_connection_t));
186   _libcecc_resolve(lib, iface->persist_configuration,         "libcec_persist_configuration",         int(CDECL *)(libcec_connection_t, CEC_NAMESPACE libcec_configuration*));
187   _libcecc_resolve(lib, iface->set_configuration,             "libcec_set_configuration",             int(CDECL *)(libcec_connection_t, const CEC_NAMESPACE libcec_configuration*));
188   _libcecc_resolve(lib, iface->rescan_devices,                "libcec_rescan_devices",                void(CDECL *)(libcec_connection_t));
189   _libcecc_resolve(lib, iface->is_libcec_active_source,       "libcec_is_libcec_active_source",       int(CDECL *)(libcec_connection_t));
190   _libcecc_resolve(lib, iface->get_device_information,        "libcec_get_device_information",        int(CDECL *)(libcec_connection_t, const char*, CEC_NAMESPACE libcec_configuration*, uint32_t));
191   _libcecc_resolve(lib, iface->get_lib_info,                  "libcec_get_lib_info",                  const char*(CDECL *)(libcec_connection_t));
192   _libcecc_resolve(lib, iface->init_video_standalone,         "libcec_init_video_standalone",         void(CDECL *)(libcec_connection_t));
193   _libcecc_resolve(lib, iface->get_adapter_vendor_id,         "libcec_get_adapter_vendor_id",         uint16_t(CDECL *)(libcec_connection_t));
194   _libcecc_resolve(lib, iface->get_adapter_product_id,        "libcec_get_adapter_product_id",        uint16_t(CDECL *)(libcec_connection_t));
195   _libcecc_resolve(lib, iface->audio_toggle_mute,             "libcec_audio_toggle_mute",             uint8_t(CDECL *)(libcec_connection_t));
196   _libcecc_resolve(lib, iface->audio_mute,                    "libcec_audio_mute",                    uint8_t(CDECL *)(libcec_connection_t));
197   _libcecc_resolve(lib, iface->audio_unmute,                  "libcec_audio_unmute",                  uint8_t(CDECL *)(libcec_connection_t));
198   _libcecc_resolve(lib, iface->audio_get_status,              "libcec_audio_get_status",              uint8_t(CDECL *)(libcec_connection_t));
199   _libcecc_resolve(lib, iface->detect_adapters,               "libcec_detect_adapters",               int8_t(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_adapter_descriptor*, uint8_t, const char*, int));
200   _libcecc_resolve(lib, iface->menu_state_to_string,          "libcec_menu_state_to_string",          void(CDECL *)(const CEC_NAMESPACE cec_menu_state, char*, size_t));
201   _libcecc_resolve(lib, iface->cec_version_to_string,         "libcec_cec_version_to_string",         void(CDECL *)(const CEC_NAMESPACE cec_version, char*, size_t));
202   _libcecc_resolve(lib, iface->power_status_to_string,        "libcec_power_status_to_string",        void(CDECL *)(const CEC_NAMESPACE cec_power_status, char*, size_t));
203   _libcecc_resolve(lib, iface->logical_address_to_string,     "libcec_logical_address_to_string",     void(CDECL *)(const CEC_NAMESPACE cec_logical_address, char*, size_t));
204   _libcecc_resolve(lib, iface->deck_control_mode_to_string,   "libcec_deck_control_mode_to_string",   void(CDECL *)(const CEC_NAMESPACE cec_deck_control_mode, char*, size_t));
205   _libcecc_resolve(lib, iface->deck_status_to_string,         "libcec_deck_status_to_string",         void(CDECL *)(const CEC_NAMESPACE cec_deck_info, char*, size_t));
206   _libcecc_resolve(lib, iface->opcode_to_string,              "libcec_opcode_to_string",              void(CDECL *)(const CEC_NAMESPACE cec_opcode, char*, size_t));
207   _libcecc_resolve(lib, iface->system_audio_status_to_string, "libcec_system_audio_status_to_string", void(CDECL *)(const CEC_NAMESPACE cec_system_audio_status, char*, size_t));
208   _libcecc_resolve(lib, iface->audio_status_to_string,        "libcec_audio_status_to_string",        void(CDECL *)(const CEC_NAMESPACE cec_audio_status, char*, size_t));
209   _libcecc_resolve(lib, iface->vendor_id_to_string,           "libcec_vendor_id_to_string",           void(CDECL *)(const CEC_NAMESPACE cec_vendor_id, char*, size_t));
210   _libcecc_resolve(lib, iface->user_control_key_to_string,    "libcec_user_control_key_to_string",    void(CDECL *)(const CEC_NAMESPACE cec_user_control_code, char*, size_t));
211   _libcecc_resolve(lib, iface->adapter_type_to_string,        "libcec_adapter_type_to_string",        void(CDECL *)(const CEC_NAMESPACE cec_adapter_type, char*, size_t));
212   _libcecc_resolve(lib, iface->version_to_string,             "libcec_version_to_string",             void(CDECL *)(uint32_t, char*, size_t));
213 
214   return 1;
215 }
216 
libcecc_load_library(const char * strLib)217 static libcecc_lib_instance_t libcecc_load_library(const char* strLib)
218 {
219   libcecc_lib_instance_t lib;
220 #if defined(_WIN32) || defined(_WIN64)
221   lib = LoadLibrary(strLib ? strLib : "cec.dll");
222   if (lib == NULL)
223     printf("failed to load cec.dll\n");
224 #else
225   #if defined(__APPLE__)
226     lib =  dlopen(strLib ? strLib : "libcec." CEC_LIB_VERSION_MAJOR_STR ".dylib", RTLD_LAZY);
227   #else
228     lib = dlopen(strLib ? strLib : "libcec.so." CEC_LIB_VERSION_MAJOR_STR, RTLD_LAZY);
229   #endif
230   if (lib == NULL)
231     printf("%s\n", dlerror());
232 #endif
233   return lib;
234 }
235 
libcecc_close_library(libcecc_lib_instance_t lib)236 static void libcecc_close_library(libcecc_lib_instance_t lib)
237 {
238 #if defined(_WIN32) || defined(_WIN64)
239   FreeLibrary(lib);
240 #else
241   dlclose(lib);
242 #endif
243 }
244 
libcecc_resolve(void * lib,const char * name)245 static void* libcecc_resolve(void* lib, const char* name)
246 {
247 #if defined(_WIN32) || defined(_WIN64)
248   return GetProcAddress(lib, name);
249 #else
250   return dlsym(lib, name);
251 #endif
252 }
253 
libcecc_reset_configuration(CEC_NAMESPACE libcec_configuration * configuration)254 void libcecc_reset_configuration(CEC_NAMESPACE libcec_configuration* configuration)
255 {
256   void(CDECL * _clear_configuration)(CEC_NAMESPACE libcec_configuration*);
257   libcecc_lib_instance_t lib;
258 
259   memset(configuration, 0, sizeof(CEC_NAMESPACE libcec_configuration));
260   lib = libcecc_load_library(NULL);
261   if (lib == NULL)
262     return;
263 
264   _clear_configuration = (void(CDECL *)(CEC_NAMESPACE libcec_configuration*)) libcecc_resolve(lib, "libcec_clear_configuration");
265   if (_clear_configuration)
266     _clear_configuration(configuration);
267 
268   libcecc_close_library(lib);
269 }
270 
271 /*!
272  * @brief Create a new libCEC instance.
273  * @param configuration The configuration to pass to libCEC
274  * @param strLib The name of and/or path to libCEC
275  * @return 1 when loaded, 0 if libCEC failed to initialise, -1 if methods failed to be resolved
276  */
libcecc_initialise(CEC_NAMESPACE libcec_configuration * configuration,libcec_interface_t * iface,const char * strLib)277 int libcecc_initialise(CEC_NAMESPACE libcec_configuration* configuration, libcec_interface_t* iface, const char* strLib)
278 {
279   void* (CDECL *_cec_initialise)(CEC_NAMESPACE libcec_configuration*);
280 
281   libcecc_lib_instance_t lib;
282   lib = libcecc_load_library(strLib);
283   if (lib == NULL)
284     return -1;
285 
286   _libcecc_resolve(lib, _cec_initialise, "libcec_initialise", void* (CDECL *)(CEC_NAMESPACE libcec_configuration*));
287 
288   iface->lib_instance = lib;
289   iface->connection   = _cec_initialise(configuration);
290 
291   return iface->connection ?
292       libcecc_resolve_all(lib, iface) :
293       0;
294 }
295 
296 /*!
297  * @brief Destroy an instance of libCEC.
298  * @param device The instance to destroy.
299  */
libcecc_destroy(libcec_interface_t * iface)300 void libcecc_destroy(libcec_interface_t* iface)
301 {
302   if (iface->destroy)
303     iface->destroy(iface->connection);
304   libcecc_close_library(iface->lib_instance);
305   memset(iface, 0, sizeof(libcec_interface_t));
306 }
307