#pragma once /* * Copyright (C) 2005-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, see * . * */ #include #include #include #include #include #include #include #ifdef _WIN32 // windows #include "dlfcn-win32.h" #define ADDON_DLL "\\library.xbmc.addon\\libXBMC_addon" ADDON_HELPER_EXT #define ADDON_HELPER_EXT ".dll" #else #if defined(__APPLE__) // osx #if defined(__POWERPC__) #define ADDON_HELPER_ARCH "powerpc-osx" #elif defined(__arm__) #define ADDON_HELPER_ARCH "arm-osx" #elif defined(__x86_64__) #define ADDON_HELPER_ARCH "x86-osx" #else #define ADDON_HELPER_ARCH "x86-osx" #endif #else // linux #if defined(__x86_64__) #define ADDON_HELPER_ARCH "x86_64-linux" #elif defined(_POWERPC) #define ADDON_HELPER_ARCH "powerpc-linux" #elif defined(_POWERPC64) #define ADDON_HELPER_ARCH "powerpc64-linux" #elif defined(__ARMEL__) #define ADDON_HELPER_ARCH "arm" #elif defined(_MIPSEL) #define ADDON_HELPER_ARCH "mipsel-linux" #else #define ADDON_HELPER_ARCH "i486-linux" #endif #endif #include // linux+osx #define ADDON_HELPER_EXT ".so" #define ADDON_DLL_NAME "libXBMC_addon-" ADDON_HELPER_ARCH ADDON_HELPER_EXT #define ADDON_DLL "/library.xbmc.addon/" ADDON_DLL_NAME #endif #if defined(ANDROID) #include #endif #ifdef LOG_DEBUG #undef LOG_DEBUG #endif #ifdef LOG_INFO #undef LOG_INFO #endif #ifdef LOG_NOTICE #undef LOG_NOTICE #endif #ifdef LOG_ERROR #undef LOG_ERROR #endif namespace ADDON { typedef enum addon_log { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_ERROR } addon_log_t; typedef enum queue_msg { QUEUE_INFO, QUEUE_WARNING, QUEUE_ERROR } queue_msg_t; class CHelper_libXBMC_addon { public: CHelper_libXBMC_addon() { m_libXBMC_addon = NULL; m_Handle = NULL; } ~CHelper_libXBMC_addon() { if (m_libXBMC_addon) { XBMC_unregister_me(m_Handle, m_Callbacks); dlclose(m_libXBMC_addon); } } bool RegisterMe(void *Handle) { m_Handle = Handle; std::string libBasePath; libBasePath = ((cb_array*)m_Handle)->libPath; libBasePath += ADDON_DLL; #if defined(ANDROID) struct stat st; if(stat(libBasePath.c_str(),&st) != 0) { std::string tempbin = getenv("XBMC_ANDROID_LIBS"); libBasePath = tempbin + "/" + ADDON_DLL_NAME; } #endif m_libXBMC_addon = dlopen(libBasePath.c_str(), RTLD_LAZY); if (m_libXBMC_addon == NULL) { fprintf(stderr, "Unable to load %s\n", dlerror()); return false; } XBMC_register_me = (void* (*)(void *HANDLE)) dlsym(m_libXBMC_addon, "XBMC_register_me"); if (XBMC_register_me == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_unregister_me = (void (*)(void* HANDLE, void* CB)) dlsym(m_libXBMC_addon, "XBMC_unregister_me"); if (XBMC_unregister_me == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_log = (void (*)(void* HANDLE, void* CB, const addon_log_t loglevel, const char *msg)) dlsym(m_libXBMC_addon, "XBMC_log"); if (XBMC_log == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_get_setting = (bool (*)(void* HANDLE, void* CB, const char* settingName, void *settingValue)) dlsym(m_libXBMC_addon, "XBMC_get_setting"); if (XBMC_get_setting == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_queue_notification = (void (*)(void* HANDLE, void* CB, const queue_msg_t loglevel, const char *msg)) dlsym(m_libXBMC_addon, "XBMC_queue_notification"); if (XBMC_queue_notification == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_wake_on_lan = (bool (*)(void* HANDLE, void *CB, const char *mac)) dlsym(m_libXBMC_addon, "XBMC_wake_on_lan"); if (XBMC_wake_on_lan == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_unknown_to_utf8 = (char* (*)(void* HANDLE, void* CB, const char* str)) dlsym(m_libXBMC_addon, "XBMC_unknown_to_utf8"); if (XBMC_unknown_to_utf8 == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_get_localized_string = (char* (*)(void* HANDLE, void* CB, int dwCode)) dlsym(m_libXBMC_addon, "XBMC_get_localized_string"); if (XBMC_get_localized_string == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_free_string = (void (*)(void* HANDLE, void* CB, char* str)) dlsym(m_libXBMC_addon, "XBMC_free_string"); if (XBMC_free_string == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_get_dvd_menu_language = (char* (*)(void* HANDLE, void* CB)) dlsym(m_libXBMC_addon, "XBMC_get_dvd_menu_language"); if (XBMC_get_dvd_menu_language == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_open_file = (void* (*)(void* HANDLE, void* CB, const char* strFileName, unsigned int flags)) dlsym(m_libXBMC_addon, "XBMC_open_file"); if (XBMC_open_file == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_open_file_for_write = (void* (*)(void* HANDLE, void* CB, const char* strFileName, bool bOverWrite)) dlsym(m_libXBMC_addon, "XBMC_open_file_for_write"); if (XBMC_open_file_for_write == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_read_file = (unsigned int (*)(void* HANDLE, void* CB, void* file, void* lpBuf, int64_t uiBufSize)) dlsym(m_libXBMC_addon, "XBMC_read_file"); if (XBMC_read_file == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_read_file_string = (bool (*)(void* HANDLE, void* CB, void* file, char *szLine, int iLineLength)) dlsym(m_libXBMC_addon, "XBMC_read_file_string"); if (XBMC_read_file_string == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_write_file = (int (*)(void* HANDLE, void* CB, void* file, const void* lpBuf, int64_t uiBufSize)) dlsym(m_libXBMC_addon, "XBMC_write_file"); if (XBMC_write_file == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_flush_file = (void (*)(void* HANDLE, void* CB, void* file)) dlsym(m_libXBMC_addon, "XBMC_flush_file"); if (XBMC_flush_file == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_seek_file = (int64_t (*)(void* HANDLE, void* CB, void* file, int64_t iFilePosition, int iWhence)) dlsym(m_libXBMC_addon, "XBMC_seek_file"); if (XBMC_seek_file == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_truncate_file = (int (*)(void* HANDLE, void* CB, void* file, int64_t iSize)) dlsym(m_libXBMC_addon, "XBMC_truncate_file"); if (XBMC_truncate_file == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_get_file_position = (int64_t (*)(void* HANDLE, void* CB, void* file)) dlsym(m_libXBMC_addon, "XBMC_get_file_position"); if (XBMC_get_file_position == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_get_file_length = (int64_t (*)(void* HANDLE, void* CB, void* file)) dlsym(m_libXBMC_addon, "XBMC_get_file_length"); if (XBMC_get_file_length == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_close_file = (void (*)(void* HANDLE, void* CB, void* file)) dlsym(m_libXBMC_addon, "XBMC_close_file"); if (XBMC_close_file == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_get_file_chunk_size = (int (*)(void* HANDLE, void* CB, void* file)) dlsym(m_libXBMC_addon, "XBMC_get_file_chunk_size"); if (XBMC_get_file_chunk_size == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_file_exists = (bool (*)(void* HANDLE, void* CB, const char *strFileName, bool bUseCache)) dlsym(m_libXBMC_addon, "XBMC_file_exists"); if (XBMC_file_exists == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_stat_file = (int (*)(void* HANDLE, void* CB, const char *strFileName, struct __stat64* buffer)) dlsym(m_libXBMC_addon, "XBMC_stat_file"); if (XBMC_stat_file == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_delete_file = (bool (*)(void* HANDLE, void* CB, const char *strFileName)) dlsym(m_libXBMC_addon, "XBMC_delete_file"); if (XBMC_delete_file == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_can_open_directory = (bool (*)(void* HANDLE, void* CB, const char* strURL)) dlsym(m_libXBMC_addon, "XBMC_can_open_directory"); if (XBMC_can_open_directory == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_create_directory = (bool (*)(void* HANDLE, void* CB, const char* strPath)) dlsym(m_libXBMC_addon, "XBMC_create_directory"); if (XBMC_create_directory == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_directory_exists = (bool (*)(void* HANDLE, void* CB, const char* strPath)) dlsym(m_libXBMC_addon, "XBMC_directory_exists"); if (XBMC_directory_exists == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } XBMC_remove_directory = (bool (*)(void* HANDLE, void* CB, const char* strPath)) dlsym(m_libXBMC_addon, "XBMC_remove_directory"); if (XBMC_remove_directory == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } m_Callbacks = XBMC_register_me(m_Handle); return m_Callbacks != NULL; } /*! * @brief Add a message to XBMC's log. * @param loglevel The log level of the message. * @param format The format of the message to pass to XBMC. */ void Log(const addon_log_t loglevel, const char *format, ... ) { char buffer[16384]; va_list args; va_start (args, format); vsprintf (buffer, format, args); va_end (args); return XBMC_log(m_Handle, m_Callbacks, loglevel, buffer); } /*! * @brief Get a settings value for this add-on. * @param settingName The name of the setting to get. * @param settingValue The value. * @return True if the settings was fetched successfully, false otherwise. */ bool GetSetting(const char* settingName, void *settingValue) { return XBMC_get_setting(m_Handle, m_Callbacks, settingName, settingValue); } /*! * @brief Queue a notification in the GUI. * @param type The message type. * @param format The format of the message to pass to display in XBMC. */ void QueueNotification(const queue_msg_t type, const char *format, ... ) { char buffer[16384]; va_list args; va_start (args, format); vsprintf (buffer, format, args); va_end (args); return XBMC_queue_notification(m_Handle, m_Callbacks, type, buffer); } /*! * @brief Send WakeOnLan magic packet. * @param mac Network address of the host to wake. * @return True if the magic packet was successfully sent, false otherwise. */ bool WakeOnLan(const char* mac) { return XBMC_wake_on_lan(m_Handle, m_Callbacks, mac); } /*! * @brief Translate a string with an unknown encoding to UTF8. * @param str The string to translate. * @return The string translated to UTF8. Must be freed by calling FreeString() when done. */ char* UnknownToUTF8(const char* str) { return XBMC_unknown_to_utf8(m_Handle, m_Callbacks, str); } /*! * @brief Get a localised message. * @param dwCode The code of the message to get. * @return The message. Must be freed by calling FreeString() when done. */ char* GetLocalizedString(int dwCode) { return XBMC_get_localized_string(m_Handle, m_Callbacks, dwCode); } /*! * @brief Get the DVD menu language. * @return The language. Must be freed by calling FreeString() when done. */ char* GetDVDMenuLanguage() { return XBMC_get_dvd_menu_language(m_Handle, m_Callbacks); } /*! * @brief Free the memory used by str * @param str The string to free */ void FreeString(char* str) { return XBMC_free_string(m_Handle, m_Callbacks, str); } /*! * @brief Open the file with filename via XBMC's CFile. Needs to be closed by calling CloseFile() when done. * @param strFileName The filename to open. * @param flags The flags to pass. Documented in XBMC's File.h * @return A handle for the file, or NULL if it couldn't be opened. */ void* OpenFile(const char* strFileName, unsigned int flags) { return XBMC_open_file(m_Handle, m_Callbacks, strFileName, flags); } /*! * @brief Open the file with filename via XBMC's CFile in write mode. Needs to be closed by calling CloseFile() when done. * @param strFileName The filename to open. * @param bOverWrite True to overwrite, false otherwise. * @return A handle for the file, or NULL if it couldn't be opened. */ void* OpenFileForWrite(const char* strFileName, bool bOverWrite) { return XBMC_open_file_for_write(m_Handle, m_Callbacks, strFileName, bOverWrite); } /*! * @brief Read from an open file. * @param file The file handle to read from. * @param lpBuf The buffer to store the data in. * @param uiBufSize The size of the buffer. * @return Number of bytes read. */ unsigned int ReadFile(void* file, void* lpBuf, int64_t uiBufSize) { return XBMC_read_file(m_Handle, m_Callbacks, file, lpBuf, uiBufSize); } /*! * @brief Read a string from an open file. * @param file The file handle to read from. * @param szLine The buffer to store the data in. * @param iLineLength The size of the buffer. * @return True when a line was read, false otherwise. */ bool ReadFileString(void* file, char *szLine, int iLineLength) { return XBMC_read_file_string(m_Handle, m_Callbacks, file, szLine, iLineLength); } /*! * @brief Write to a file opened in write mode. * @param file The file handle to write to. * @param lpBuf The data to write. * @param uiBufSize Size of the data to write. * @return The number of bytes read. */ int WriteFile(void* file, const void* lpBuf, int64_t uiBufSize) { return XBMC_write_file(m_Handle, m_Callbacks, file, lpBuf, uiBufSize); } /*! * @brief Flush buffered data. * @param file The file handle to flush the data for. */ void FlushFile(void* file) { return XBMC_flush_file(m_Handle, m_Callbacks, file); } /*! * @brief Seek in an open file. * @param file The file handle to see in. * @param iFilePosition The new position. * @param iWhence Seek argument. See stdio.h for possible values. * @return The new position. */ int64_t SeekFile(void* file, int64_t iFilePosition, int iWhence) { return XBMC_seek_file(m_Handle, m_Callbacks, file, iFilePosition, iWhence); } /*! * @brief Truncate a file to the requested size. * @param file The file handle to truncate. * @param iSize The new max size. * @return New size? */ int TruncateFile(void* file, int64_t iSize) { return XBMC_truncate_file(m_Handle, m_Callbacks, file, iSize); } /*! * @brief The current position in an open file. * @param file The file handle to get the position for. * @return The requested position. */ int64_t GetFilePosition(void* file) { return XBMC_get_file_position(m_Handle, m_Callbacks, file); } /*! * @brief Get the file size of an open file. * @param file The file to get the size for. * @return The requested size. */ int64_t GetFileLength(void* file) { return XBMC_get_file_length(m_Handle, m_Callbacks, file); } /*! * @brief Close an open file. * @param file The file handle to close. */ void CloseFile(void* file) { return XBMC_close_file(m_Handle, m_Callbacks, file); } /*! * @brief Get the chunk size for an open file. * @param file the file handle to get the size for. * @return The requested size. */ int GetFileChunkSize(void* file) { return XBMC_get_file_chunk_size(m_Handle, m_Callbacks, file); } /*! * @brief Check if a file exists. * @param strFileName The filename to check. * @param bUseCache Check in file cache. * @return true if the file exists false otherwise. */ bool FileExists(const char *strFileName, bool bUseCache) { return XBMC_file_exists(m_Handle, m_Callbacks, strFileName, bUseCache); } /*! * @brief Reads file status. * @param strFileName The filename to read the status from. * @param buffer The file status is written into this buffer. * @return The file status was successfully read. */ int StatFile(const char *strFileName, struct __stat64* buffer) { return XBMC_stat_file(m_Handle, m_Callbacks, strFileName, buffer); } /*! * @brief Deletes a file. * @param strFileName The filename to delete. * @return The file was successfully deleted. */ bool DeleteFile(const char *strFileName) { return XBMC_delete_file(m_Handle, m_Callbacks, strFileName); } /*! * @brief Checks whether a directory can be opened. * @param strUrl The URL of the directory to check. * @return True when it can be opened, false otherwise. */ bool CanOpenDirectory(const char* strUrl) { return XBMC_can_open_directory(m_Handle, m_Callbacks, strUrl); } /*! * @brief Creates a directory. * @param strPath Path to the directory. * @return True when it was created, false otherwise. */ bool CreateDirectory(const char *strPath) { return XBMC_create_directory(m_Handle, m_Callbacks, strPath); } /*! * @brief Checks if a directory exists. * @param strPath Path to the directory. * @return True when it exists, false otherwise. */ bool DirectoryExists(const char *strPath) { return XBMC_directory_exists(m_Handle, m_Callbacks, strPath); } /*! * @brief Removes a directory. * @param strPath Path to the directory. * @return True when it was removed, false otherwise. */ bool RemoveDirectory(const char *strPath) { return XBMC_remove_directory(m_Handle, m_Callbacks, strPath); } protected: void* (*XBMC_register_me)(void *HANDLE); void (*XBMC_unregister_me)(void *HANDLE, void* CB); void (*XBMC_log)(void *HANDLE, void* CB, const addon_log_t loglevel, const char *msg); bool (*XBMC_get_setting)(void *HANDLE, void* CB, const char* settingName, void *settingValue); void (*XBMC_queue_notification)(void *HANDLE, void* CB, const queue_msg_t type, const char *msg); bool (*XBMC_wake_on_lan)(void *HANDLE, void* CB, const char* mac); char* (*XBMC_unknown_to_utf8)(void *HANDLE, void* CB, const char* str); char* (*XBMC_get_localized_string)(void *HANDLE, void* CB, int dwCode); char* (*XBMC_get_dvd_menu_language)(void *HANDLE, void* CB); void (*XBMC_free_string)(void *HANDLE, void* CB, char* str); void* (*XBMC_open_file)(void *HANDLE, void* CB, const char* strFileName, unsigned int flags); void* (*XBMC_open_file_for_write)(void *HANDLE, void* CB, const char* strFileName, bool bOverWrite); unsigned int (*XBMC_read_file)(void *HANDLE, void* CB, void* file, void* lpBuf, int64_t uiBufSize); bool (*XBMC_read_file_string)(void *HANDLE, void* CB, void* file, char *szLine, int iLineLength); int (*XBMC_write_file)(void *HANDLE, void* CB, void* file, const void* lpBuf, int64_t uiBufSize); void (*XBMC_flush_file)(void *HANDLE, void* CB, void* file); int64_t (*XBMC_seek_file)(void *HANDLE, void* CB, void* file, int64_t iFilePosition, int iWhence); int (*XBMC_truncate_file)(void *HANDLE, void* CB, void* file, int64_t iSize); int64_t (*XBMC_get_file_position)(void *HANDLE, void* CB, void* file); int64_t (*XBMC_get_file_length)(void *HANDLE, void* CB, void* file); void (*XBMC_close_file)(void *HANDLE, void* CB, void* file); int (*XBMC_get_file_chunk_size)(void *HANDLE, void* CB, void* file); bool (*XBMC_file_exists)(void *HANDLE, void* CB, const char *strFileName, bool bUseCache); int (*XBMC_stat_file)(void *HANDLE, void* CB, const char *strFileName, struct __stat64* buffer); bool (*XBMC_delete_file)(void *HANDLE, void* CB, const char *strFileName); bool (*XBMC_can_open_directory)(void *HANDLE, void* CB, const char* strURL); bool (*XBMC_create_directory)(void *HANDLE, void* CB, const char* strPath); bool (*XBMC_directory_exists)(void *HANDLE, void* CB, const char* strPath); bool (*XBMC_remove_directory)(void *HANDLE, void* CB, const char* strPath); private: void *m_libXBMC_addon; void *m_Handle; void *m_Callbacks; struct cb_array { const char* libPath; }; }; };