Пример #1
0
def register_apps(kodi_interface):
    """Register DIAL applications based on the Kodi add-ons that support Cast feature"""
    # We find out which add-ons has "script.appcast" optional dependency,
    # then for each add-on we try import the "DialApp" class included in the path "resources/lib/dial_app_test/"
    addons = kodi_ops.json_rpc(
        'Addons.GetAddons', {
            'type': 'unknown',
            'properties': ['name', 'dependencies', 'enabled', 'path']
        })
    MUTEX.acquire()
    # # Clear previous sys modules added
    # for name in list(sys.modules.keys()):
    #     if name.startswith('dial_app_'):
    #         del sys.modules[name]

    for addon in addons['addons']:
        if not addon['enabled']:
            continue
        if any(dep['addonid'] == 'script.appcast'
               for dep in addon['dependencies']):
            # Try add the DIAL app included in the add-on
            try:
                name = addon['addonid'].split('.')[-1]
                package = 'dial_app_' + name
                module_path_folder1 = file_ops.join_folders_paths(
                    addon['path'], package, package + '.py')
                module_path_folder2 = file_ops.join_folders_paths(
                    addon['path'], 'resources/lib/' + package, package + '.py')
                # Check if the add-on has the package file
                if file_ops.file_exists(module_path_folder1):
                    module_path = module_path_folder1
                elif file_ops.file_exists(module_path_folder2):
                    module_path = module_path_folder2
                else:
                    LOGGER.error(
                        'register_apps: missing module file {}.py on {} add-on',
                        package, addon['addonid'])
                    continue
                # Load the external module (and allow it's own relative imports)
                spec = importlib.util.spec_from_file_location(
                    package, module_path, submodule_search_locations=[])
                module = importlib.util.module_from_spec(spec)
                sys.modules[module.__name__] = module
                spec.loader.exec_module(module)
                # Get the "DialApp" class from the loaded module
                app_class = getattr(module, 'DialApp', None)
                if app_class is None:
                    LOGGER.error(
                        'register_apps: "DialApp" class not found in {}.py file of {} add-on',
                        package, addon['addonid'])
                    continue
                register_app(app_class, kodi_interface)
            except Exception:
                LOGGER.error(
                    'register_apps: could not import the DIAL app from {}',
                    addon['addonid'])
                import traceback
                LOG.error(traceback.format_exc())
    MUTEX.release()
Пример #2
0
def install(pathitems, params):
    LOG.info('Start install Kodi "{}" (params "{}")', pathitems[-1], params)
    use_task_scheduler = G.ADDON.getSettingBool('usetaskscheduler')
    save_downloads = G.ADDON.getSettingBool('save_downloads')
    # Download the file
    if not kodi_ops.dlg_confirm(
            kodi_ops.get_local_string(30070),
            kodi_ops.get_local_string(30071).format(pathitems[-1])):
        return
    # Check if the task is installed
    if use_task_scheduler and not misc.check_task():
        kodi_ops.dlg_ok(kodi_ops.get_local_string(30070),
                        kodi_ops.get_local_string(30072))
        return
    # Check if destination path exist
    if not folder_exists(G.INSTALLER_TEMP_PATH):
        create_folder(G.INSTALLER_TEMP_PATH)
    # Check if the setup installer is already downloaded
    dwn_filepath = join_folders_paths(G.DOWNLOADS_PATH,
                                      '/'.join(pathitems[:-1]), pathitems[-1])
    # Temp file path will be used by the Windows Task scheduled
    temp_filepath = join_folders_paths(G.INSTALLER_TEMP_PATH,
                                       G.INSTALLER_TEMP_NAME)
    if params.get('is_local', 'False') == 'True':
        # Get the file to install from "downloads" folder
        if not file_exists(dwn_filepath):
            raise FileExistsError('The file {] not exists'.format(
                pathitems[:-1]))
        copy_file(dwn_filepath, temp_filepath)
    else:
        # Download the file
        if save_downloads and file_exists(dwn_filepath):
            # Copy the existing file to the temp file path
            copy_file(dwn_filepath, temp_filepath)
        else:
            # Download the setup installer file
            url_file_path = '/'.join(pathitems)
            if not download_file(G.MIRROR_BASE_URL + url_file_path,
                                 temp_filepath, pathitems[-1]):
                # Download cancelled
                kodi_ops.show_notification(kodi_ops.get_local_string(30073))
                return
            # Save the setup installer file
            if save_downloads:
                copy_file(temp_filepath, dwn_filepath)
    with kodi_ops.show_busy_dialog():
        # Run the "AutoUpdateWorker" bash script
        _run_auto_update_worker(use_task=use_task_scheduler)
        # Wait a bit before close Kodi,
        # the bash script have to read the executable path from the Kodi process before continue
        time.sleep(2)
        kodi_ops.json_rpc('Application.Quit')
Пример #3
0
def register_internal_apps(kodi_interface):
    """Register the internal DIAL applications based on the installed Kodi add-ons"""
    # The DIAL apps will be loaded from "resources/lib/apps" sub-folders
    directory_base = file_ops.join_folders_paths(G.ADDON_DATA_PATH,
                                                 'resources/lib/apps')
    dirs, _ = file_ops.list_dir(directory_base)
    MUTEX.acquire()
    for dir_name in dirs:
        try:
            if dir_name.startswith('_') or dir_name == 'dial_app_test':
                continue
            class_file_path = file_ops.join_folders_paths(
                directory_base, dir_name, dir_name + '.py')
            if not file_ops.file_exists(class_file_path):
                LOG.error(
                    'register_internal_apps: missing module file {}.py on {} folder',
                    dir_name, dir_name)
                continue
            # Load the internal module
            loaded_module = importlib.import_module('resources.lib.apps.' +
                                                    dir_name + '.' + dir_name)
            app_class = getattr(loaded_module, 'DialApp', None)
            if app_class is None:
                LOGGER.error(
                    'register_internal_apps: "DialApp" class not found in {}.py file',
                    dir_name)
                continue
            register_app(app_class, kodi_interface)
        except Exception:
            LOGGER.error(
                'register_internal_apps: could not import the DIAL app from {} folder',
                dir_name)
            import traceback
            LOG.error(traceback.format_exc())
    MUTEX.release()
Пример #4
0
def retrieve_dial_data(app_name):
    """Retrieve the DIAL data key/value pairs from a file"""
    # NOTE: the reference code store the file in the application folder, we read the file in our data folder
    #   perhaps other changes will be needed to allow USE_ADDITIONAL_DATA feature to work
    file_path = 'dial_data/' + app_name + '.json'
    if not fileops.file_exists(file_path):
        return {}
    data = fileops.load_file_def(file_path)
    return json.loads(data)
Пример #5
0
 def reset_database(self):
     """Delete the entire database and recreate it from scratch"""
     if file_ops.file_exists(self.db_file_path):
         file_ops.delete_file(self.db_file_path)
     self.initialize_connection()