def _is_kodi_supported_version(cls):
     if utils.get_kodi_major_version() < 18:
         utils.dialog(
             'Kodi 18+ Required',
             'The minimum version of Kodi required for DASH/DRM '
             'protected content is v18. Please upgrade in order to '
             'use this feature.')
         return False
     return True
    def _get_ia_direct(self, update=False, drm=True):
        """Get IA direct

        Download inputstream.adaptive zip file from remote repository and save
        in Kodi's 'home' folder, unzip to addons folder.
        """
        utils.dialog(
            'No longer supported',
            'This feature is no longer supported. Please upgrade '
            'your Kodi installation to a newer v18 build, or for '
            'Linux installations you should be able to obtain '
            'from your package manager eg. '
            '"sudo apt update && sudo apt install kodi-inputstream'
            '-adaptive"')
 def _install_addon(self):
     try:  # see if there's an installed repo that has it
         xbmc.executebuiltin('InstallAddon(inputstream.adaptive)', True)
         addon = self._get_addon()
         utils.log('inputstream.adaptive installed from repo')
         return addon
     except RuntimeError:
         utils.dialog(
             'inputstream.adaptive not installed',
             'inputstream.adaptive not installed. This '
             'addon now comes supplied with newer builds '
             'of Kodi 18 for Windows/Mac/LibreELEC/OSMC, '
             'and can be installed from most Linux package '
             'managers eg. "sudo apt install kodi-'
             'inputstream-adaptive"')
    def _progress_download(self, url, download_path, display_filename=None):
        """Progress download

        Download file in Kodi with progress bar
        """
        utils.log('Downloading {0}'.format(url))
        try:
            res = requests.get(url, stream=True, verify=False)
            res.raise_for_status()
        except requests.exceptions.HTTPError:
            utils.dialog('Download failed',
                         'HTTP ' + str(res.status_code) + ' error')
            return False
        except Exception as exc:
            utils.dialog('Download failed', 'Exception was: {0}'.format(exc))
            return False

        total_length = float(res.headers.get('content-length'))
        dp = xbmcgui.DialogProgress()
        if not display_filename:
            display_filename = download_path.split()[-1]
        dp.create("Downloading {0}".format(display_filename),
                  "Downloading File", url)

        with open(download_path, 'wb') as f:
            chunk_size = 1024
            downloaded = 0
            for chunk in res.iter_content(chunk_size=chunk_size):
                f.write(chunk)
                downloaded += len(chunk)
                percent = int(downloaded * 100 / total_length)
                if dp.iscanceled():
                    dp.close()
                    res.close()
                dp.update(percent)
        utils.log('Download {0} bytes complete, saved in {1}'.format(
            int(total_length), download_path))
        dp.close()
        return True
    def _get_wvcdm(self):
        """Get the Widevine CDM library

        Win/Mac: download Chrome extension blob ~2MB and extract
        widevinecdm.dll
        Linux: download Chrome package ~50MB and extract libwidevinecdm.so
        Linux arm: download widevine package ~2MB from 3rd party host
        """
        addon = self.get_addon()
        if not addon:
            utils.dialog('inputstream.adaptive not found'
                         'inputstream.adaptive add-on must be installed '
                         'before installing widevide_cdm module')
            return

        if self._is_android():
            utils.dialog('Not available',
                         'This module cannot be updated on Android')
            return

        cdm_paths = self._get_wvcdm_paths(addon)
        cdm_path = self._get_wvcdm_path(addon, cdm_paths)
        plat = self._get_platform()
        current_cdm_ver = self._get_wvcdm_current_ver()
        url = config.WIDEVINE_CDM_URL[plat].format(current_cdm_ver)
        filename = url.split('/')[-1]
        wv_cdm_fn = self._get_wvcdm_filename()

        if not os.path.isdir(cdm_path):
            utils.log('Creating directory: {0}'.format(cdm_path))
            os.makedirs(cdm_path)
        cdm_fn = os.path.join(cdm_path, wv_cdm_fn)
        if os.path.isfile(cdm_fn):
            utils.log('Removing existing widevine_cdm: {0}'.format(cdm_fn))
            os.remove(cdm_fn)
        home_folder = self._get_home_folder()
        download_path = os.path.join(home_folder, filename)
        if not self._progress_download(url, download_path, wv_cdm_fn):
            return

        dp = xbmcgui.DialogProgress()
        dp.create('Extracting {0}'.format(wv_cdm_fn),
                  'Extracting {0} from {1}'.format(wv_cdm_fn, filename))
        dp.update(0)

        if self._is_windows():
            self._unzip_windows_cdm(download_path, cdm_path)
        else:
            self._execute_cdm_command(plat, filename, cdm_path, home_folder)

        dp.close()
        # TODO(andy): Test it was actually successful. Can be cancelled
        utils.dialog(
            'Success', '{0} successfully installed at {1}'.format(
                wv_cdm_fn, os.path.join(cdm_path, wv_cdm_fn)))
        return True
    def check_inputstream(self, drm=True):
        """Check InputStream Adaptive is installed and ready

        Main function call to check all components required are available for
        DRM playback before setting the resolved URL in Kodi.
        drm -- set to false if you just want to check for inputstream.adaptive
        and not widevine components eg. HLS playback
        """
        # DRM not supported
        if drm and not self._is_wv_drm_supported():
            # TODO(andy): Store something in settings to prevent this message
            # appearing more than once?
            utils.dialog(
                'Platform not supported',
                '{0} not supported for DRM playback. '
                'For more information, see our DRM FAQ at {1}'
                ''.format(self.get_platform_name(), config.DRM_INFO))
            return False

        # Kodi version too old
        if drm and utils.get_kodi_major_version() < 18:
            utils.dialog(
                'Kodi version not supported for DRM',
                'This version of Kodi is not currently supported for viewing '
                'DRM encrypted content. Please upgrade to Kodi v18.')
            return False

        addon = self.get_addon()
        if not addon:
            utils.dialog(
                'Missing inputstream.adaptive add-on',
                'inputstream.adaptive VideoPlayer InputStream add-on not '
                'found or not enabled. This add-on is required to view DRM '
                'protected content.')
            return False

        utils.log('Found inputstream.adaptive version is {0}'.format(
            addon.getAddonInfo('version')))

        # widevine built into android - not supported on 17 atm though
        if self._is_android():
            utils.log('Running on Android')
            return True

        # checking for installation of inputstream.adaptive (eg HLS playback)
        if not drm:
            utils.log('DRM checking not requested')
            return True

        # only 32bit userspace supported for linux aarch64 no 64bit wvcdm
        if self._get_platform() == ('Linux', 'aarch64'):
            if self._get_kodi_arch() == '64bit':
                utils.dialog(
                    '64 bit build for aarch64 not supported',
                    'A build of your OS that supports 32 bit userspace '
                    'binaries is required for DRM playback. We recommend '
                    'CoreELEC to support this.')

        cdm_fn = self._get_wvcdm_filename()
        cdm_paths = self._get_wvcdm_paths(addon)
        if not any(os.path.isfile(os.path.join(p, cdm_fn)) for p in cdm_paths):
            if utils.dialog_yn(
                    'Missing Widevine module',
                    '{0} not found in any expected location.'.format(cdm_fn),
                    'Do you want to attempt downloading the missing '
                    'Widevine CDM module to your system for DRM support?'):
                self._get_wvcdm()
            else:
                # TODO(andy): Ask to never attempt again
                return False

        return True