summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/kodi-dev-kit/tools
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/addons/kodi-dev-kit/tools')
-rwxr-xr-xxbmc/addons/kodi-dev-kit/tools/code-generator/code_generator.py76
-rw-r--r--xbmc/addons/kodi-dev-kit/tools/code-generator/src/commitChanges.py91
-rw-r--r--xbmc/addons/kodi-dev-kit/tools/code-generator/src/generateCMake__CMAKE_TREEDATA_COMMON_addon_dev_kit_txt.py56
-rw-r--r--xbmc/addons/kodi-dev-kit/tools/code-generator/src/generateCMake__XBMC_ADDONS_KODIDEVKIT_INCLUDE_KODI_allfiles.py134
-rw-r--r--xbmc/addons/kodi-dev-kit/tools/code-generator/src/helper_Log.py201
-rwxr-xr-xxbmc/addons/kodi-dev-kit/tools/debian-addon-package-test.sh141
-rwxr-xr-xxbmc/addons/kodi-dev-kit/tools/doxygen-header-class-list-creator.py190
7 files changed, 889 insertions, 0 deletions
diff --git a/xbmc/addons/kodi-dev-kit/tools/code-generator/code_generator.py b/xbmc/addons/kodi-dev-kit/tools/code-generator/code_generator.py
new file mode 100755
index 0000000..06cf810
--- /dev/null
+++ b/xbmc/addons/kodi-dev-kit/tools/code-generator/code_generator.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2021 Team Kodi
+# This file is part of Kodi - https://kodi.tv
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# See LICENSES/README.md for more information.
+
+KODI_DIR = "../../../../../"
+DEVKIT_DIR = "xbmc/addons/kodi-dev-kit"
+
+# Global includes
+from optparse import OptionParser
+
+# Own includes
+from src.commitChanges import *
+from src.generateCMake__CMAKE_TREEDATA_COMMON_addon_dev_kit_txt import *
+from src.generateCMake__XBMC_ADDONS_KODIDEVKIT_INCLUDE_KODI_allfiles import *
+from src.helper_Log import *
+
+# ===============================================================================
+def GenerateCMakeParts(options):
+ Log.PrintGroupStart("Generate cmake parts")
+
+ # Generate Kodi's cmake system related include files to find related parts
+ GenerateCMake__XBMC_ADDONS_KODIDEVKIT_INCLUDE_KODI_all_files(options)
+ GenerateCMake__CMAKE_TREEDATA_COMMON_addon_dev_kit_txt(options)
+
+
+# ===============================================================================
+if __name__ == "__main__":
+ # parse command-line options
+ disc = """\
+This utility autogenerate the interface between Kodi and addon.
+It is currently still in the initial phase and will be expanded in the future.
+"""
+ parser = OptionParser(description=disc)
+ parser.add_option(
+ "-f",
+ "--force",
+ action="store_true",
+ dest="force",
+ default=False,
+ help="Force the generation of auto code",
+ )
+ parser.add_option(
+ "-d",
+ "--debug",
+ action="store_true",
+ dest="debug",
+ default=False,
+ help="Add debug identifiers to generated files",
+ )
+ parser.add_option(
+ "-c",
+ "--commit",
+ action="store_true",
+ dest="commit",
+ default=False,
+ help="Create automatic a git commit about API changes (WARNING: No hand edits should be present before!)",
+ )
+ (options, args) = parser.parse_args()
+
+ Log.Init(options)
+ Log.PrintMainStart(options)
+
+ ##----------------------------------------------------------------------------
+ # CMake generation
+ GenerateCMakeParts(options)
+
+ ##----------------------------------------------------------------------------
+ # Commit GIT changes generation (only makes work if '-c' option is used)
+ if options.commit:
+ Log.PrintGroupStart("Git update")
+ CommitChanges(options)
diff --git a/xbmc/addons/kodi-dev-kit/tools/code-generator/src/commitChanges.py b/xbmc/addons/kodi-dev-kit/tools/code-generator/src/commitChanges.py
new file mode 100644
index 0000000..896cca5
--- /dev/null
+++ b/xbmc/addons/kodi-dev-kit/tools/code-generator/src/commitChanges.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2021 Team Kodi
+# This file is part of Kodi - https://kodi.tv
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# See LICENSES/README.md for more information.
+
+# Own includes
+from code_generator import DEVKIT_DIR, KODI_DIR
+from .generateCMake__CMAKE_TREEDATA_COMMON_addon_dev_kit_txt import *
+from .generateCMake__XBMC_ADDONS_KODIDEVKIT_INCLUDE_KODI_allfiles import *
+from .helper_Log import *
+
+# Global includes
+import importlib, os, subprocess
+
+git_found = importlib.find_loader("git") is not None
+if git_found:
+ from git import Repo
+
+
+def CommitChanges(options):
+ """
+ Do a git commit of the automatically changed locations of the dev-kit.
+ """
+ if not options.commit:
+ return
+ if not git_found:
+ Log.PrintFatal(
+ 'Needed "GitPython" module not present! To make commits need them be installed.'
+ )
+ quit(1)
+
+ Log.PrintBegin("Perform GIT update check")
+ Log.PrintResult(Result.SEE_BELOW)
+
+ contains_devkit_change = False
+ contains_external_change = False
+ changes_list = []
+
+ # Hack place one to get also new added files
+ subprocess.run(["git", "add", "-A"], check=True, stdout=subprocess.PIPE).stdout
+
+ r = Repo(KODI_DIR)
+ for x in r.index.diff("HEAD"):
+ if GenerateCMake__XBMC_ADDONS_KODIDEVKIT_INCLUDE_KODI_all_files_RelatedCheck(
+ x.b_path
+ ):
+ Log.PrintBegin(" - Changed file {}".format(x.b_path))
+ contains_devkit_change = True
+ changes_list.append(x.b_path)
+ Log.PrintResult(Result.NEW if x.new_file else Result.UPDATE)
+ elif GenerateCMake__CMAKE_TREEDATA_COMMON_addon_dev_kit_txt_RelatedCheck(
+ x.b_path
+ ):
+ Log.PrintBegin(" - Changed file {}".format(x.b_path))
+ contains_devkit_change = True
+ changes_list.append(x.b_path)
+ Log.PrintResult(Result.NEW if x.new_file else Result.UPDATE)
+ else:
+ Log.PrintBegin(" - Changed file {}".format(x.b_path))
+ Log.PrintFollow(" (Not auto update related)")
+ Log.PrintResult(Result.IGNORED)
+ contains_external_change = True
+
+ # Hack place two to reset about before
+ subprocess.run(["git", "reset", "HEAD"], check=True, stdout=subprocess.PIPE).stdout
+
+ Log.PrintBegin("Perform GIT commit")
+ if contains_devkit_change:
+ # Add changed or added files to git
+ for x in changes_list:
+ r.index.add(x)
+
+ commit_msg = (
+ "[auto][addons] devkit script update ({})\n"
+ "\n"
+ "This commit automatic generated by script '{}/tools/code-generator.py'.\n"
+ "\n"
+ "{}".format(
+ datetime.utcnow().strftime("%d/%m/%Y %H:%M:%S"),
+ DEVKIT_DIR,
+ open(Log.log_file).read(),
+ )
+ )
+ r.index.commit(commit_msg)
+ Log.PrintFollow(" ( Commit SHA256: {})".format(str(r.head.reference.commit)))
+ Log.PrintResult(Result.OK)
+ else:
+ Log.PrintResult(Result.ALREADY_DONE)
diff --git a/xbmc/addons/kodi-dev-kit/tools/code-generator/src/generateCMake__CMAKE_TREEDATA_COMMON_addon_dev_kit_txt.py b/xbmc/addons/kodi-dev-kit/tools/code-generator/src/generateCMake__CMAKE_TREEDATA_COMMON_addon_dev_kit_txt.py
new file mode 100644
index 0000000..20ed447
--- /dev/null
+++ b/xbmc/addons/kodi-dev-kit/tools/code-generator/src/generateCMake__CMAKE_TREEDATA_COMMON_addon_dev_kit_txt.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2021 Team Kodi
+# This file is part of Kodi - https://kodi.tv
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# See LICENSES/README.md for more information.
+
+# Own includes
+from code_generator import DEVKIT_DIR, KODI_DIR
+from .helper_Log import *
+
+# Global includes
+import glob, os, re
+
+
+def GenerateCMake__CMAKE_TREEDATA_COMMON_addon_dev_kit_txt_RelatedCheck(filename):
+ """
+ This function is called by git update to be able to assign changed files to the dev kit.
+ """
+ return True if filename == "cmake/treedata/common/addon_dev_kit.txt" else False
+
+
+def GenerateCMake__CMAKE_TREEDATA_COMMON_addon_dev_kit_txt(options):
+ """
+ This function generate the "cmake/treedata/common/addon_dev_kit.txt"
+ by scan of related directories to use for addon interface build.
+ """
+ gen_file = "cmake/treedata/common/addon_dev_kit.txt"
+
+ Log.PrintBegin("Check for {}".format(gen_file))
+
+ scan_dir = "{}{}/include/kodi/**/CMakeLists.txt".format(KODI_DIR, DEVKIT_DIR)
+ parts = "# Auto generated {}.\n" "# See {}/tools/code-generator.py.\n\n".format(
+ gen_file, DEVKIT_DIR
+ )
+
+ for entry in glob.glob(scan_dir, recursive=True):
+ cmake_dir = entry.replace(KODI_DIR, "").replace("/CMakeLists.txt", "")
+ with open(entry) as search:
+ for line in search:
+ line = line.rstrip() # remove '\n' at end of line
+ m = re.search("^ *core_add_devkit_header\((.*)\)", line)
+ if m:
+ parts += "{} addons_kodi-dev-kit_include_{}\n".format(
+ cmake_dir, m.group(1)
+ )
+ break
+ file = "{}{}".format(KODI_DIR, gen_file)
+ present = os.path.isfile(file)
+ if not present or parts != open(file).read() or options.force:
+ with open(file, "w") as f:
+ f.write(parts)
+ Log.PrintResult(Result.NEW if not present else Result.UPDATE)
+ else:
+ Log.PrintResult(Result.ALREADY_DONE)
diff --git a/xbmc/addons/kodi-dev-kit/tools/code-generator/src/generateCMake__XBMC_ADDONS_KODIDEVKIT_INCLUDE_KODI_allfiles.py b/xbmc/addons/kodi-dev-kit/tools/code-generator/src/generateCMake__XBMC_ADDONS_KODIDEVKIT_INCLUDE_KODI_allfiles.py
new file mode 100644
index 0000000..c1000be
--- /dev/null
+++ b/xbmc/addons/kodi-dev-kit/tools/code-generator/src/generateCMake__XBMC_ADDONS_KODIDEVKIT_INCLUDE_KODI_allfiles.py
@@ -0,0 +1,134 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2021 Team Kodi
+# This file is part of Kodi - https://kodi.tv
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# See LICENSES/README.md for more information.
+
+# Own includes
+from code_generator import DEVKIT_DIR, KODI_DIR
+from .helper_Log import *
+
+# Global includes
+import glob, os, re
+
+
+def GenerateCMake__XBMC_ADDONS_KODIDEVKIT_INCLUDE_KODI_all_files_RelatedCheck(filename):
+ """
+ This function is called by git update to be able to assign changed files to the dev kit.
+ """
+ scan_dir = "{}{}/include/kodi/**/".format(KODI_DIR, DEVKIT_DIR)
+ dirs = sorted(glob.glob(scan_dir, recursive=True))
+ for dir in dirs:
+ source_dir = "{}CMakeLists.txt".format(dir.replace(KODI_DIR, ""))
+ if source_dir == filename:
+ return True
+
+ return False
+
+
+def GenerateCMake__XBMC_ADDONS_KODIDEVKIT_INCLUDE_KODI_all_files(options):
+ """
+ This function generate the "CMakeLists.txt" in xbmc/addons/kodi-dev-kit/include/kodi
+ and sub dirs by scan of available files
+ """
+ Log.PrintBegin(
+ "Generate CMakeLists.txt files in {}/include/kodi dirs".format(DEVKIT_DIR)
+ )
+ Log.PrintResult(Result.SEE_BELOW)
+
+ scan_dir = "{}{}/include/kodi/**/".format(KODI_DIR, DEVKIT_DIR)
+
+ found = False
+ dirs = sorted(glob.glob(scan_dir, recursive=True))
+ for dir in dirs:
+ source_dir = dir.replace(KODI_DIR, "")
+ Log.PrintBegin(" - Check {}CMakeLists.txt".format(source_dir))
+
+ # Scan for *.h
+ os_limits = []
+ header_configure = []
+ header_entry = []
+ src_parts = sorted(glob.glob("{}*.h*".format(dir), recursive=False))
+ for src_part in src_parts:
+ with open(src_part) as search:
+ for line in search:
+ line = line.rstrip() # remove '\n' at end of line
+ m = re.search("^\/\*---AUTO_GEN_PARSE<\$\$(.*):(.*)>---\*\/", line)
+ if m:
+ if m.group(1) == "CORE_SYSTEM_NAME":
+ if src_part.endswith(".in"):
+ Log.PrintResult(Result.FAILURE)
+ Log.PrintFatal(
+ 'File extensions with ".h.in" are currently not supported and require revision of Kodi\'s cmake system!'
+ )
+ exit(1)
+ """
+ NOTE: This code currently unused. About ".in" support need Kodi's cmake build system revised.
+ code = ''
+ for entry in m.group(2).split(","):
+ label = 'CORE_SYSTEM_NAME STREQUAL {}'.format(entry)
+ code += 'if({}'.format(label) if code == '' else ' OR\n {}'.format(label)
+ code += ')\n'
+ code += ' configure_file(${{CMAKE_SOURCE_DIR}}/{}\n'.format(src_part.replace(KODI_DIR, ''))
+ code += ' ${{CORE_BUILD_DIR}}/{} @ONLY)\n'.format(src_part.replace(KODI_DIR, '').replace('.in', ''))
+ code += 'endif()'
+ header_configure.append(code)
+ """
+ for entry in m.group(2).split(","):
+ entry = entry.strip()
+ if not entry in os_limits:
+ os_limits.append(entry)
+ header_entry.append(
+ "$<$<STREQUAL:${{CORE_SYSTEM_NAME}},{}>:{}>".format(
+ entry,
+ src_part.replace(dir, "").replace(".in", ""),
+ )
+ )
+ found = True
+ break
+ if not found:
+ header_entry.append(src_part.replace(dir, ""))
+ found = False
+
+ if len(os_limits) > 0:
+ Log.PrintFollow(
+ " (Contains limited OS header: {})".format(
+ ", ".join(map(str, os_limits))
+ )
+ )
+
+ cmake_cfg_text = (
+ "\n{}".format("".join("{}\n".format(entry) for entry in header_configure))
+ if len(header_configure) > 0
+ else ""
+ )
+ cmake_hdr_text = "set(HEADERS\n{})\n".format(
+ "".join(" {}\n".format(entry) for entry in header_entry)
+ )
+ cmake_part = (
+ source_dir[len(DEVKIT_DIR + "/include_") :].replace("/", "_").rstrip("_")
+ ) # Generate cmake sub part name
+
+ # Make final CMakeLists.txt
+ cmake_file = (
+ "# Auto generated CMakeLists.txt.\n"
+ "# See {}/tools/code-generator.py.\n"
+ "{}"
+ "\n"
+ "{}"
+ "\n"
+ "if(HEADERS)\n"
+ " core_add_devkit_header({})\n"
+ "endif()\n".format(DEVKIT_DIR, cmake_cfg_text, cmake_hdr_text, cmake_part)
+ )
+
+ file = "{}CMakeLists.txt".format(dir)
+ present = os.path.isfile(file)
+ if not present or cmake_file != open(file).read() or options.force:
+ with open(file, "w") as f:
+ f.write(cmake_file)
+ Log.PrintResult(Result.NEW if not present else Result.UPDATE)
+ else:
+ Log.PrintResult(Result.ALREADY_DONE)
diff --git a/xbmc/addons/kodi-dev-kit/tools/code-generator/src/helper_Log.py b/xbmc/addons/kodi-dev-kit/tools/code-generator/src/helper_Log.py
new file mode 100644
index 0000000..6279afa
--- /dev/null
+++ b/xbmc/addons/kodi-dev-kit/tools/code-generator/src/helper_Log.py
@@ -0,0 +1,201 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2021 Team Kodi
+# This file is part of Kodi - https://kodi.tv
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# See LICENSES/README.md for more information.
+
+from datetime import datetime
+import os
+
+
+class Result:
+ OK = 1
+ FAILURE = 2
+ UPDATE = 3
+ ALREADY_DONE = 4
+ NEW = 5
+ SEE_BELOW = 6
+ IGNORED = 7
+
+
+class Log:
+ log_file = "creation_log.txt"
+ current_cursor_pos = 0
+ terminal_columns = 120
+
+ # Class of different styles
+ class style:
+ BOLD = "\033[01m"
+ BLACK = "\033[30m"
+ RED = "\033[31m"
+ GREEN = "\033[32m"
+ YELLOW = "\033[33m"
+ BLUE = "\033[34m"
+ MAGENTA = "\033[35m"
+ CYAN = "\033[36m"
+ WHITE = "\033[37m"
+ UNDERLINE = "\033[4m"
+ RESET = "\033[0m"
+
+ def Init(options):
+ # Try to get terminal with, is optional and no matter if something fails
+ try:
+ columns, rows = os.get_terminal_size(0)
+ Log.terminal_columns = columns
+ except:
+ pass
+
+ if os.path.isfile(Log.log_file):
+ os.rename(Log.log_file, Log.log_file + ".old")
+
+ if options.debug:
+ print("DEBUG: Used command line options: {}".format(str(options)))
+
+ with open(Log.log_file, "w") as f:
+ f.write("Used call options: {}\n".format(str(options)))
+
+ def PrintMainStart(options):
+ print("┌{}┐".format("─" * (Log.terminal_columns - 2)))
+ text = "Auto generation of addon interface code"
+ print(
+ "│ {}{}{}{}{}│".format(
+ Log.style.BOLD,
+ Log.style.CYAN,
+ text,
+ Log.style.RESET,
+ " " * (Log.terminal_columns - len(text) - 3),
+ )
+ )
+ text = "Used options:"
+ print(
+ "│ {}{}{}{}{}{}│".format(
+ Log.style.BOLD,
+ Log.style.WHITE,
+ Log.style.UNDERLINE,
+ text,
+ Log.style.RESET,
+ " " * (Log.terminal_columns - len(text) - 3),
+ )
+ )
+ Log.__printUsedBooleanValueLine("force", options.force)
+ Log.__printUsedBooleanValueLine("debug", options.debug)
+ Log.__printUsedBooleanValueLine("commit", options.commit)
+ print("└{}┘".format("─" * (Log.terminal_columns - 2)))
+
+ def PrintGroupStart(text):
+ print("─" * Log.terminal_columns)
+ print(
+ "{}{} ...{}{}".format(
+ Log.style.CYAN,
+ text,
+ " " * (Log.terminal_columns - len(text) - 4),
+ Log.style.RESET,
+ )
+ )
+ with open(Log.log_file, "a") as f:
+ f.write("{}...\n".format(text))
+
+ def PrintBegin(text):
+ # datetime object containing current date and time
+ dt_string = datetime.utcnow().strftime("%d/%m/%Y %H:%M:%S")
+ Log.current_cursor_pos = len(text) + len(dt_string) + 3
+
+ print(
+ "[{}{}{}] {}{}{}{}".format(
+ Log.style.MAGENTA,
+ dt_string,
+ Log.style.RESET,
+ Log.style.WHITE,
+ Log.style.BOLD,
+ text,
+ Log.style.RESET,
+ ),
+ end="",
+ )
+ with open(Log.log_file, "a") as f:
+ f.write("[{}] {}: ".format(dt_string, text))
+
+ def PrintFollow(text):
+ Log.current_cursor_pos += len(text)
+
+ print(Log.style.CYAN + text + Log.style.RESET, end="")
+ with open(Log.log_file, "a") as f:
+ f.write("{} ".format(text))
+
+ def PrintResult(result_type, result_text=None):
+ text = ""
+ color = Log.style.WHITE
+
+ if result_type == Result.OK:
+ text = "OK"
+ color = Log.style.GREEN
+ elif result_type == Result.NEW:
+ text = "Created new"
+ color = Log.style.CYAN
+ elif result_type == Result.FAILURE:
+ text = "Failed"
+ color = Log.style.RED
+ elif result_type == Result.UPDATE:
+ text = "Updated"
+ color = Log.style.YELLOW
+ elif result_type == Result.ALREADY_DONE:
+ text = "Present and up to date"
+ color = Log.style.GREEN
+ elif result_type == Result.SEE_BELOW:
+ text = "See below"
+ color = Log.style.BLUE
+ elif result_type == Result.IGNORED:
+ text = "Ignored"
+ color = Log.style.YELLOW
+
+ print(
+ "{}{}{}{}".format(
+ color,
+ Log.style.BOLD,
+ text.rjust(Log.terminal_columns - Log.current_cursor_pos),
+ Log.style.RESET,
+ )
+ )
+ f = open(Log.log_file, "a")
+ f.write("{}\n".format(text))
+ if result_text:
+ print("Results of call before:{}\n".format(result_text))
+ f.write("Results of call before:{}\n".format(result_text))
+ f.close()
+
+ def PrintFatal(error_text):
+ # datetime object containing current date and time
+ dt_string = datetime.utcnow().strftime("%d/%m/%Y %H:%M:%S")
+ Log.current_cursor_pos = len(error_text) + len(dt_string) + 3
+
+ print(
+ "[{}{}{}] {}{}FATAL: {}{}".format(
+ Log.style.YELLOW,
+ dt_string,
+ Log.style.RESET,
+ Log.style.RED,
+ Log.style.BOLD,
+ Log.style.RESET,
+ error_text,
+ )
+ )
+ with open(Log.log_file, "a") as f:
+ f.write("[{}] {}\n".format(dt_string, error_text))
+
+ def __printUsedBooleanValueLine(name, value):
+ text = "--{} = {}{}".format(
+ name,
+ Log.style.RED + "yes" if value else Log.style.GREEN + "no",
+ Log.style.RESET,
+ )
+ print(
+ "│ {}{}{}{}{}│".format(
+ Log.style.BOLD,
+ Log.style.WHITE,
+ text,
+ Log.style.RESET,
+ " " * (Log.terminal_columns - len(text) + 6),
+ )
+ )
diff --git a/xbmc/addons/kodi-dev-kit/tools/debian-addon-package-test.sh b/xbmc/addons/kodi-dev-kit/tools/debian-addon-package-test.sh
new file mode 100755
index 0000000..d778954
--- /dev/null
+++ b/xbmc/addons/kodi-dev-kit/tools/debian-addon-package-test.sh
@@ -0,0 +1,141 @@
+#!/bin/bash
+
+# This script is for purely testing purposes!
+#
+# It is meant to be able to test at binary addons the creation of a debian
+# package.
+#
+# The created files are below the source code folder.
+#
+# Example:
+# ./build-debian-addon-package.sh $HOME/your_path/screensaver.stars
+#
+# To remove generated code:
+# ./build-debian-addon-package.sh $HOME/your_path/screensaver.stars --clean
+#
+
+BASE_DIR=""
+REPO_DIR=""
+PACKAGEVERSION=""
+VERSION_MAIN=""
+VERSION_MINOR=""
+VERSION_REVISON=""
+GIT_REV=""
+DIST=""
+TAGREV=${TAGREV:-"0"}
+
+function usage {
+ echo "\
+--------------------------------------------------------------------------------
+
+This script builds a Kodi addon debian package from the given addon source.
+
+As value, the path to the addon must be given.
+In addition --clean can be used to remove the created debian files.
+
+WARNING: This script is for testing purposes only!
+
+--------------------------------------------------------------------------------"
+}
+
+function checkEnv {
+ echo "#------ build environment ------#"
+ echo "BASE_DIR: $BASE_DIR"
+ echo "REPO_DIR: $REPO_DIR"
+ getVersion
+ echo "VERSION_MAIN: $VERSION_MAIN"
+ echo "VERSION_MINOR: $VERSION_MINOR"
+ echo "VERSION_REVISON: $VERSION_REVISON"
+ if [ $GIT_REV ]; then
+ echo "GIT_REV: $GIT_REV"
+ fi
+ echo "TAGREV: $TAGREV"
+ echo "DIST: $DIST"
+ echo "ARCHS: $ARCHS"
+
+ echo "#-------------------------------#"
+}
+
+function getVersion {
+ if [ -d ${BASE_DIR}/.git ]; then
+ getGitRev
+ fi
+ PACKAGEVERSION=$(cat ${BASE_DIR}/$REPO_DIR/addon.xml.in | sed -n '/version/ s/.*version=\"\([0-9]\+\.[0-9]\+\.[0-9]\+\)\".*/\1/p' | awk 'NR == 1')
+ VERSION_MAIN=$(echo $PACKAGEVERSION | awk -F. '{print $1}')
+ VERSION_MINOR=$(echo $PACKAGEVERSION | awk -F. '{print $2}')
+ VERSION_REVISON=$(echo $PACKAGEVERSION | awk -F. '{print $3}')
+}
+
+function getGitRev {
+ cd $BASE_DIR || exit 1
+ GIT_REV=$(git log -1 --pretty=format:"%h")
+}
+
+function cleanup() {
+ echo "Starting to remove debian generated files"
+ cd ${BASE_DIR}
+ rm -rf obj-$ARCHS-linux-gnu
+ rm -rf debian/.debhelper
+ rm -rf debian/"kodi-"$(echo $REPO_DIR | tr . -)
+ rm -rf debian/"kodi-"$(echo $REPO_DIR | tr . -)-dbg
+ rm -rf debian/tmp
+ rm -f debian/changelog
+ rm -f debian/debhelper-build-stamp
+ rm -f debian/files
+ rm -f debian/*.log
+ rm -f debian/*.substvars
+}
+
+if [[ $1 = "-h" ]] || [[ $1 = "--help" ]]; then
+ echo "$0:"
+ usage
+ exit
+fi
+
+if [ ! $1 ] || [ ${1} = "--clean" ]; then
+ printf "$0:\nERROR: Addon source code must be given as the first parameter!\n"
+ usage
+ exit 1
+elif [ ! -d $1 ]; then
+ printf "$0:\nERROR: Given folder is not present or not a valid addon source!\n"
+ usage
+ exit 1
+fi
+
+ARCHS=$(uname -m)
+BASE_DIR=$(realpath ${1})
+REPO_DIR=$(basename ${1})
+DIST=$(lsb_release -cs)
+
+if [ ! -f ${BASE_DIR}/$REPO_DIR/addon.xml.in ]; then
+ echo "$0:
+ERROR: \"required $REPO_DIR/addon.xml.in\" not found!
+
+The base source dir and addon.xml.in containing directory names must be equal"
+ usage
+ exit 1
+fi
+
+checkEnv
+
+ORIGTARBALL="kodi-"$(echo $REPO_DIR | tr . -)"_${PACKAGEVERSION}.orig.tar.gz"
+
+if [[ ${2} = "--clean" ]]; then
+ cleanup
+ exit
+fi
+
+echo "Detected addon package version: ${PACKAGEVERSION}"
+
+sed -e "s/#PACKAGEVERSION#/${PACKAGEVERSION}/g" \
+ -e "s/#TAGREV#/${TAGREV}/g" \
+ -e "s/#DIST#/${DIST}/g" ${BASE_DIR}/debian/changelog.in > ${BASE_DIR}/debian/changelog
+
+echo "Create needed compressed source code file: ${BASE_DIR}/../${ORIGTARBALL}.tar.gz"
+
+# git archive --format=tar.gz -o ${BASE_DIR}/../${ORIGTARBALL} HEAD # Unused git, leaved as optional way
+EXCLUDE=$(cat .gitignore | sed -e '/#/d' -e '/^\s*$/d' -e 's/^/--exclude=/' -e 's/\/$//' | tr '\n' ' ')
+tar -zcvf ${BASE_DIR}/../${ORIGTARBALL} --exclude=.git $EXCLUDE * # Used to prevent on code changed for test a git commit
+
+echo "Building debian-source package for ${DIST}"
+dpkg-buildpackage -us -uc --diff-ignore="()$"
diff --git a/xbmc/addons/kodi-dev-kit/tools/doxygen-header-class-list-creator.py b/xbmc/addons/kodi-dev-kit/tools/doxygen-header-class-list-creator.py
new file mode 100755
index 0000000..0b0590e
--- /dev/null
+++ b/xbmc/addons/kodi-dev-kit/tools/doxygen-header-class-list-creator.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python3
+
+from optparse import OptionParser
+import glob
+import io
+import os
+import re
+import sys
+
+def read_file(name, normalize=True):
+ """ Read a file. """
+ try:
+ with open(name, 'r', encoding='utf-8') as f:
+ # read the data
+ data = f.read()
+ if normalize:
+ # normalize line endings
+ data = data.replace("\r\n", "\n")
+ return data
+ except IOError as e:
+ (errno, strerror) = e.args
+ sys.stderr.write('Failed to read file ' + name + ': ' + strerror)
+ raise
+
+def write_file(name, data):
+ """ Write a file. """
+ try:
+ with open(name, 'w', encoding='utf-8') as f:
+ # write the data
+ if sys.version_info.major == 2:
+ f.write(data.decode('utf-8'))
+ else:
+ f.write(data)
+ except IOError as e:
+ (errno, strerror) = e.args
+ sys.stderr.write('Failed to write file ' + name + ': ' + strerror)
+ raise
+
+def auto_check_header(file):
+ groups_to_check = []
+
+ data = read_file(file)
+ if not 'addon_auto_check' in data:
+ return ''
+
+ for line in io.StringIO(data):
+ line = re.search(r"^.*\/\/\/.*@copydetails *(.*)(_header|_source)_addon_auto_check.*", line, flags=re.UNICODE)
+ if line and line.group(1):
+ group = line.group(1)
+ if group in groups_to_check:
+ continue
+
+ print(' - Found use with %s' % group)
+ groups_to_check.append(line.group(1))
+
+ return groups_to_check
+
+def parse_header(file, group, new_path=''):
+ header_sources = ''
+ header_addon = ''
+ source_addon = ''
+
+ data = read_file(file)
+ group_found = False
+ group_start = False
+ virtual_function_start = False
+ for line in io.StringIO(data):
+ if not group_found and 'defgroup ' + group in line:
+ group_found = True
+ continue
+ elif group_found and not group_start and '///@{' in line:
+ group_start = True
+ continue
+ elif group_start and '///@}' in line:
+ break
+ elif re.match(r'^.*//.*', line) or re.match(r'^.*//.*', line) or line == '\n' or not group_start:
+ continue
+
+ if re.match(r'^.*virtual.*', line):
+ virtual_function_start = True
+
+ if virtual_function_start:
+ header_sources += re.sub(r"^\s+", "", line, flags=re.UNICODE)
+
+ if virtual_function_start and re.match(r'^.*}.*', line):
+ virtual_function_start = False
+
+ if not group_found:
+ return ""
+
+ header_sources = header_sources.replace("\n", "")
+ header_sources = " ".join(re.split("\s+", header_sources, flags=re.UNICODE))
+ header_sources = header_sources.replace("}", "}\n")
+ header_sources = header_sources.replace("= 0;", "= 0;\n")
+ header_sources = header_sources.replace(",", ", ")
+
+ # Generate class header part of list
+ header_addon += '/// @defgroup ' + group + '_header_addon_auto_check Group header include\n'
+ header_addon += '/// @ingroup ' + group + '\n'
+ header_addon += '///@{\n'
+ header_addon += '/// *Header parts:*\n'
+ header_addon += '/// ~~~~~~~~~~~~~{.cpp}\n'
+ header_addon += '///\n'
+ for line in io.StringIO(header_sources):
+ line = re.search(r"^.*virtual.([A-Za-z1-9].*\(.*\))", line, flags=re.UNICODE)
+ if line:
+ header_addon += '/// ' + re.sub(' +', ' ', line.group(1)) + ' override;\n'
+ header_addon += '///\n'
+ header_addon += '/// ~~~~~~~~~~~~~\n'
+ header_addon += '///@}\n\n'
+
+ # Generate class source part of list
+ source_addon += '/// @defgroup ' + group + '_source_addon_auto_check Group source include\n'
+ source_addon += '/// @ingroup ' + group + '\n'
+ source_addon += '///@{\n'
+ source_addon += '/// *Source parts:*\n'
+ source_addon += '/// ~~~~~~~~~~~~~{.cpp}\n'
+ source_addon += '///\n'
+ for line in io.StringIO(header_sources):
+ line = line.replace("{", "\n{\n ")
+ line = line.replace("}", "\n}")
+ for line in io.StringIO(line + '\n'):
+ func = re.search(r"^.*(virtual *) *(.*) ([a-z|A-Z|0-9].*)(\(.*\))", line, flags=re.UNICODE)
+ if func:
+ source_addon += '/// ' + re.sub(' +', ' ', func.group(2) + ' CMyInstance::' + func.group(3) + func.group(4) + '\n')
+ else:
+ source_addon += '/// ' + line
+ if '= 0' in line:
+ source_addon += '/// {\n'
+ source_addon += '/// // Required in interface to have!\n'
+ source_addon += '/// // ...\n'
+ source_addon += '/// }\n'
+
+ source_addon += '/// ~~~~~~~~~~~~~\n'
+ source_addon += '///@}\n\n'
+
+ return header_addon + source_addon
+
+def print_error(msg):
+ print('Error: %s\nSee --help for usage.' % msg)
+
+# cannot be loaded as a module
+if __name__ != "__main__":
+ sys.stderr.write('This file cannot be loaded as a module!')
+ sys.exit()
+
+# parse command-line options
+disc = """
+This utility generate group list about addon header sources to add inside doxygen.
+"""
+
+parser = OptionParser(description=disc)
+parser.add_option(
+ '--header-file',
+ dest='headerfile',
+ metavar='DIR',
+ help='the to checked header [required]')
+parser.add_option(
+ '--doxygen-group',
+ dest='doxygengroup',
+ help='the to checked doxygen group inside header [required]')
+(options, args) = parser.parse_args()
+
+docs = ''
+groups_to_check = []
+
+# Check about use of helper docs
+if options.doxygengroup is None:
+ print('Scaning about used places...')
+ headers = glob.glob("../include/kodi/**/*.h", recursive=True)
+ for header in headers:
+ group = auto_check_header(header)
+ if group:
+ groups_to_check += group
+else:
+ groups_to_check.append(options.doxygengroup)
+
+# Generate the helper docs
+if options.headerfile is None:
+ headers = glob.glob("../include/kodi/**/*.h", recursive=True)
+ print('Parsing about docs:')
+ for header in headers:
+ print(' - %s' % header)
+ for group in groups_to_check:
+ docs += parse_header(header, group)
+else:
+ for group in groups_to_check:
+ docs += parse_header(options.headerfile, group)
+
+write_file("../include/groups.dox", docs)