Skip to content

Commit 75a8c84

Browse files
committed
Support vendor widevine library
This adds support for a vendor-supported Widevine library.
1 parent e63cbfe commit 75a8c84

File tree

21 files changed

+297
-48
lines changed

21 files changed

+297
-48
lines changed

lib/inputstreamhelper/__init__.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
import os
77

88
from . import config
9-
from .kodiutils import (addon_version, delete, exists, get_proxies, get_setting, get_setting_bool, get_setting_float, get_setting_int, jsonrpc,
10-
kodi_to_ascii, kodi_version, localize, log, notification, ok_dialog, progress_dialog, select_dialog,
9+
from .kodiutils import (addon_version, delete, exists, get_proxies, get_setting, get_setting_bool, get_setting_float, get_setting_int,
10+
jsonrpc, kodi_to_ascii, kodi_version, localize, log, notification, ok_dialog, progress_dialog, select_dialog,
1111
set_setting, set_setting_bool, textviewer, translate_path, yesno_dialog)
1212
from .utils import arch, http_download, run_cmd, store, system_os, temp_path, unzip
1313
from .widevine.arm import install_widevine_arm, select_best_chromeos_image, unmount
14-
from .widevine.widevine import (backup_path, has_widevinecdm, ia_cdm_path, install_cdm_from_backup, latest_widevine_version,
15-
load_widevine_config, missing_widevine_libs, widevine_config_path, widevine_eula, widevinecdm_path)
14+
from .widevine.widevine import (backup_path, has_vendor_widevinecdm, has_widevinecdm, ia_cdm_path, install_cdm_from_backup,
15+
latest_widevine_version, load_widevine_config, missing_widevine_libs, widevine_config_path,
16+
widevine_eula, widevinecdm_path)
1617

1718
# NOTE: Work around issue caused by platform still using os.popen()
1819
# This helps to survive 'IOError: [Errno 10] No child processes'
@@ -293,6 +294,9 @@ def _check_widevine(self):
293294
if system_os() == 'Android': # no checks needed for Android
294295
return True
295296

297+
if has_vendor_widevinecdm(): # no checks needed for vendor-supplied Widevine
298+
return True
299+
296300
if not exists(widevine_config_path()):
297301
log(4, 'Widevine or Chrome OS recovery.conf is missing. Reinstall is required.')
298302
ok_dialog(localize(30001), localize(30031)) # An update of Widevine is required
@@ -417,14 +421,19 @@ def info_dialog(self):
417421
text += localize(30820) + '\n' # Widevine information
418422
if system_os() == 'Android':
419423
text += ' - ' + localize(30821) + '\n'
424+
elif has_vendor_widevinecdm():
425+
text += ' - ' + localize(30822, version=self._get_lib_version(widevinecdm_path())) + '\n'
420426
else:
421427
from datetime import datetime
422-
wv_updated = datetime.fromtimestamp(get_setting_float('last_update', 0.0)).strftime("%Y-%m-%d %H:%M") if get_setting_float('last_update', 0.0) else 'Never'
423-
text += ' - ' + localize(30822, version=self._get_lib_version(widevinecdm_path()), date=wv_updated) + '\n'
424-
text += ' - ' + localize(30823, path=ia_cdm_path()) + '\n'
428+
if get_setting_float('last_update', 0.0):
429+
wv_updated = datetime.fromtimestamp(get_setting_float('last_update', 0.0)).strftime("%Y-%m-%d %H:%M")
430+
else:
431+
wv_updated = 'Never'
432+
text += ' - ' + localize(30823, version=self._get_lib_version(widevinecdm_path()), date=wv_updated) + '\n'
433+
text += ' - ' + localize(30824, path=ia_cdm_path()) + '\n'
425434

426435
if arch() in ('arm', 'arm64'): # Chrome OS version
427-
text += ' - ' + localize(30824, version=select_best_chromeos_image(load_widevine_config())['version']) + '\n'
436+
text += ' - ' + localize(30825, version=select_best_chromeos_image(load_widevine_config())['version']) + '\n'
428437

429438
text += '\n'
430439

lib/inputstreamhelper/kodiutils.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,17 @@ def get_addon_info(key):
5656

5757

5858
def addon_id():
59-
"""Cache and return add-on ID"""
59+
"""Return add-on ID"""
6060
return get_addon_info('id')
6161

6262

6363
def addon_profile():
64-
"""Cache and return add-on profile"""
64+
"""Return add-on profile"""
6565
return translate_path(ADDON.getAddonInfo('profile'))
6666

6767

6868
def addon_version():
69-
"""Cache and return add-on version"""
69+
"""Return add-on version"""
7070
return get_addon_info('version')
7171

7272

@@ -311,6 +311,31 @@ def kodi_to_ascii(string):
311311
return string
312312

313313

314+
def samefile(src, dest):
315+
"""Check if file is identical"""
316+
stat_src = stat_file(src)
317+
stat_dest = stat_file(dest)
318+
# Check if this is a hardlink
319+
if (stat_src.st_dev(), stat_src.st_ino()) == (stat_dest.st_dev(), stat_dest.st_ino()):
320+
return True
321+
322+
# Check file sizes
323+
if stat_src.st_size() != stat_dest.st_size():
324+
return False
325+
326+
# Check if this is a symlink
327+
from os.path import samefile as opsamefile
328+
if opsamefile(src, dest):
329+
return True
330+
331+
# Otherwise compare content (may be slow)
332+
with open(src, 'r') as srcfd, open(dest, 'r') as destfd:
333+
if srcfd.read() == destfd.read():
334+
return True
335+
336+
return False
337+
338+
314339
def copy(src, dest):
315340
"""Copy a file (using xbmcvfs)"""
316341
from xbmcvfs import copy as vfscopy

lib/inputstreamhelper/utils.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def temp_path():
1919

2020

2121
def update_temp_path(new_temp_path):
22-
""""Updates temp_path and merges files."""
22+
""""Updates temp_path and merges files"""
2323
old_temp_path = temp_path()
2424

2525
set_setting('temp_path', new_temp_path)
@@ -64,7 +64,7 @@ def http_get(url):
6464

6565

6666
def http_download(url, message=None, checksum=None, hash_alg='sha1', dl_size=None):
67-
"""Makes HTTP request and displays a progress dialog on download."""
67+
"""Makes HTTP request and displays a progress dialog on download"""
6868
if checksum:
6969
from hashlib import sha1, md5
7070
if hash_alg == 'sha1':
@@ -174,7 +174,7 @@ def store(name, val=None):
174174

175175

176176
def diskspace():
177-
"""Return the free disk space available (in bytes) in temp_path."""
177+
"""Return the free disk space available (in bytes) in temp_path"""
178178
statvfs = os.statvfs(temp_path())
179179
return statvfs.f_frsize * statvfs.f_bavail
180180

@@ -220,7 +220,7 @@ def run_cmd(cmd, sudo=False, shell=False):
220220

221221

222222
def sizeof_fmt(num, suffix='B'):
223-
"""Return size of file in a human readable string."""
223+
"""Return size of file in a human readable string"""
224224
# https://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size
225225
for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
226226
if abs(num) < 1024.0:
@@ -230,26 +230,36 @@ def sizeof_fmt(num, suffix='B'):
230230

231231

232232
def arch():
233-
"""Map together and return the system architecture."""
233+
"""Map together, cache and return the system architecture"""
234+
235+
if hasattr(arch, 'cached'):
236+
return getattr(arch, 'cached')
237+
234238
from platform import architecture, machine
235239
sys_arch = machine()
236240
if sys_arch == 'aarch64':
237241
import struct
238242
if struct.calcsize('P') * 8 == 32:
239243
# Detected 64-bit kernel in 32-bit userspace, use 32-bit arm widevine
240244
sys_arch = 'arm'
241-
if sys_arch == 'AMD64':
245+
246+
elif sys_arch == 'AMD64':
242247
sys_arch_bit = architecture()[0]
243248
if sys_arch_bit == '32bit':
244249
sys_arch = 'x86' # else, sys_arch = AMD64
250+
245251
elif 'armv' in sys_arch:
246252
import re
247253
arm_version = re.search(r'\d+', sys_arch.split('v')[1])
248254
if arm_version:
249255
sys_arch = 'armv' + arm_version.group()
256+
250257
if sys_arch in config.ARCH_MAP:
251-
return config.ARCH_MAP[sys_arch]
258+
sys_arch = config.ARCH_MAP[sys_arch]
259+
260+
log(0, 'Found system architecture {arch}', arch=sys_arch)
252261

262+
arch.cached = sys_arch
253263
return sys_arch
254264

255265

lib/inputstreamhelper/widevine/arm.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ def install_widevine_arm(backup_path): # pylint: disable=too-many-statements
196196
return False
197197

198198
url = arm_device['url']
199-
downloaded = http_download(url, message=localize(30022), checksum=arm_device['sha1'], hash_alg='sha1', dl_size=int(arm_device['zipfilesize'])) # Downloading the recovery image
199+
# Downloading the recovery image
200+
downloaded = http_download(url, message=localize(30022), checksum=arm_device['sha1'], hash_alg='sha1', dl_size=int(arm_device['zipfilesize']))
200201
if downloaded:
201202
from threading import Thread
202203
from xbmc import sleep

lib/inputstreamhelper/widevine/widevine.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
import os
77

88
from .. import config
9-
from ..kodiutils import addon_profile, exists, get_setting_int, localize, log, mkdir, ok_dialog, translate_path, yesno_dialog
9+
from ..kodiutils import (addon_profile, exists, get_setting_int, localize, log, mkdir, ok_dialog, samefile, translate_path,
10+
yesno_dialog)
1011
from ..utils import arch, cmd_exists, hardlink, http_download, http_get, run_cmd, store, system_os
1112

1213

@@ -80,11 +81,18 @@ def widevinecdm_path():
8081
return os.path.join(ia_cdm_path(), widevinecdm_filename)
8182

8283

84+
def vendor_widevinecdm_path():
85+
"""Get full vendor Widevine CDM path"""
86+
return '{0}_vendor{1}'.format(*os.path.splitext(widevinecdm_path()))
87+
88+
8389
def has_widevinecdm():
8490
"""Whether a Widevine CDM is installed on the system"""
8591
if system_os() == 'Android': # Widevine CDM is built into Android
8692
return True
8793

94+
hardlink_vendor_widevinecdm() # If vendor Widevine is present, hardlink into place
95+
8896
widevinecdm = widevinecdm_path()
8997
if widevinecdm is None:
9098
return False
@@ -95,6 +103,24 @@ def has_widevinecdm():
95103
return True
96104

97105

106+
def has_vendor_widevinecdm():
107+
"""Whether the system has a vendor-supplied widevine CDM"""
108+
if not exists(vendor_widevinecdm_path()):
109+
return False
110+
return True
111+
112+
113+
def hardlink_vendor_widevinecdm():
114+
"""Hardlink vendor Widevine into place"""
115+
vendor_widevinecdm = vendor_widevinecdm_path()
116+
if not exists(vendor_widevinecdm):
117+
return
118+
widevinecdm = widevinecdm_path()
119+
if exists(widevinecdm) and samefile(vendor_widevinecdm, widevinecdm):
120+
return
121+
hardlink(vendor_widevinecdm, widevinecdm)
122+
123+
98124
def ia_cdm_path():
99125
"""Return the specified CDM path for inputstream.adaptive, usually ~/.kodi/cdm"""
100126
from xbmcaddon import Addon

resources/language/resource.language.de_de/strings.po

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,18 @@ msgid "Widevine version: [B]Built into Android[/B]"
272272
msgstr "Widevine Version: [B]In Android eingebaut[/B]"
273273

274274
msgctxt "#30822"
275+
msgid "Widevine version: [B]{version} [COLOR gray](supplied by vendor)[/COLOR][/B]"
276+
msgstr ""
277+
278+
msgctxt "#30823"
275279
msgid "Widevine version: [B]{version}[/B] [COLOR gray](last updated on [B]{date}[/B])[/COLOR]"
276280
msgstr "Widevine Version: [B]{version}[/B] [COLOR gray](zuletzt aktualisiert am [B]{date}[/B])[/COLOR]"
277281

278-
msgctxt "#30823"
282+
msgctxt "#30824"
279283
msgid "Widevine CDM path: [B]{path}[/B]"
280284
msgstr "Widevine CDM Pfad: [B]{path}[/B]"
281285

282-
msgctxt "#30824"
286+
msgctxt "#30825"
283287
msgid "Chrome OS version: [B]{version}[/B]"
284288
msgstr "Chrome OS Version: [B]{version}[/B]"
285289

resources/language/resource.language.el_gr/strings.po

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,18 @@ msgid "Widevine version: [B]Built into Android[/B]"
272272
msgstr "Έκδοση Widevine: [B]Ενδωματωμένη στο Android[/B]"
273273

274274
msgctxt "#30822"
275+
msgid "Widevine version: [B]{version} [COLOR gray](supplied by vendor)[/COLOR][/B]"
276+
msgstr ""
277+
278+
msgctxt "#30823"
275279
msgid "Widevine version: [B]{version}[/B] [COLOR gray](last updated on [B]{date}[/B])[/COLOR]"
276280
msgstr "Έκδοση Widevina: [B]{version}[/B] [COLOR gray](τελευταία ενημερωση [B]{date}[/B])[/COLOR]"
277281

278-
msgctxt "#30823"
282+
msgctxt "#30824"
279283
msgid "Widevine CDM path: [B]{path}[/B]"
280284
msgstr "Διαδρομη CDM του Widevine: [B]{path}[/B]"
281285

282-
msgctxt "#30824"
286+
msgctxt "#30825"
283287
msgid "Chrome OS version: [B]{version}[/B]"
284288
msgstr "Έκδοση του Chrome OS: [B]{version}[/B]"
285289

resources/language/resource.language.en_gb/strings.po

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,18 @@ msgid "Widevine version: [B]Built into Android[/B]"
272272
msgstr ""
273273

274274
msgctxt "#30822"
275-
msgid "Widevine version: [B]{version}[/B] [COLOR gray](last updated on [B]{date}[/B])[/COLOR]"
275+
msgid "Widevine version: [B]{version} [COLOR gray](supplied by vendor)[/COLOR][/B]"
276276
msgstr ""
277277

278278
msgctxt "#30823"
279-
msgid "Widevine CDM path: [B]{path}[/B]"
279+
msgid "Widevine version: [B]{version}[/B] [COLOR gray](last updated on [B]{date}[/B])[/COLOR]"
280280
msgstr ""
281281

282282
msgctxt "#30824"
283+
msgid "Widevine CDM path: [B]{path}[/B]"
284+
msgstr ""
285+
286+
msgctxt "#30825"
283287
msgid "Chrome OS version: [B]{version}[/B]"
284288
msgstr ""
285289

resources/language/resource.language.es_es/strings.po

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,18 @@ msgid "Widevine version: [B]Built into Android[/B]"
272272
msgstr "Versión Widevine: [B]Incorporado en Android[/B]"
273273

274274
msgctxt "#30822"
275+
msgid "Widevine version: [B]{version} [COLOR gray](supplied by vendor)[/COLOR][/B]"
276+
msgstr ""
277+
278+
msgctxt "#30823"
275279
msgid "Widevine version: [B]{version}[/B] [COLOR gray](last updated on [B]{date}[/B])[/COLOR]"
276280
msgstr "Versión Widevine: [B]{versión}[/B] [COLOR gray](última actualización [B]{date}[/B])[/COLOR]"
277281

278-
msgctxt "#30823"
282+
msgctxt "#30824"
279283
msgid "Widevine CDM path: [B]{path}[/B]"
280284
msgstr "Ruta Widevine CDM: [B]{path}[/B]"
281285

282-
msgctxt "#30824"
286+
msgctxt "#30825"
283287
msgid "Chrome OS version: [B]{version}[/B]"
284288
msgstr "Versión Chrome OS: [B]{version}[/B]"
285289

resources/language/resource.language.fr_fr/strings.po

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,18 @@ msgid "Widevine version: [B]Built into Android[/B]"
272272
msgstr "Version Widevine : [B]Intégré dans Android[/B]"
273273

274274
msgctxt "#30822"
275+
msgid "Widevine version: [B]{version} [COLOR gray](supplied by vendor)[/COLOR][/B]"
276+
msgstr ""
277+
278+
msgctxt "#30823"
275279
msgid "Widevine version: [B]{version}[/B] [COLOR gray](last updated on [B]{date}[/B])[/COLOR]"
276280
msgstr "Version Widevine : [B]{version}[/B] [COLOR gray](mise à jour le [B]{date}[/B])[/COLOR]"
277281

278-
msgctxt "#30823"
282+
msgctxt "#30824"
279283
msgid "Widevine CDM path: [B]{path}[/B]"
280284
msgstr "Emplacement de Widevine CDM : [B]{path}[/B]"
281285

282-
msgctxt "#30824"
286+
msgctxt "#30825"
283287
msgid "Chrome OS version: [B]{version}[/B]"
284288
msgstr "Version de ChromeOS : [B]{version}[/B]"
285289

resources/language/resource.language.hr_hr/strings.po

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,18 @@ msgid "Widevine version: [B]Built into Android[/B]"
272272
msgstr "Widevine verzija: [B]Ugrađen u Android[/B]"
273273

274274
msgctxt "#30822"
275+
msgid "Widevine version: [B]{version} [COLOR gray](supplied by vendor)[/COLOR][/B]"
276+
msgstr ""
277+
278+
msgctxt "#30823"
275279
msgid "Widevine version: [B]{version}[/B] [COLOR gray](last updated on [B]{date}[/B])[/COLOR]"
276280
msgstr "Widevine verzija: [B]{version}[/B] [COLOR gray](zadnja nadogradnja [B]{date}[/B])[/COLOR]"
277281

278-
msgctxt "#30823"
282+
msgctxt "#30824"
279283
msgid "Widevine CDM path: [B]{path}[/B]"
280284
msgstr "Widevine CDM mapa: [B]{path}[/B]"
281285

282-
msgctxt "#30824"
286+
msgctxt "#30825"
283287
msgid "Chrome OS version: [B]{version}[/B]"
284288
msgstr "Chrome OS verzija: [B]{version}[/B]"
285289

resources/language/resource.language.hu_hu/strings.po

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,18 @@ msgid "Widevine version: [B]Built into Android[/B]"
272272
msgstr "Widevine verzió: [B]Androiddal telepített[/B]"
273273

274274
msgctxt "#30822"
275+
msgid "Widevine version: [B]{version} [COLOR gray](supplied by vendor)[/COLOR][/B]"
276+
msgstr ""
277+
278+
msgctxt "#30823"
275279
msgid "Widevine version: [B]{version}[/B] [COLOR gray](last updated on [B]{date}[/B])[/COLOR]"
276280
msgstr "Widevine verzió: [B]{version}[/B] [COLOR gray](utolsó frissítés [B]{date}[/B])[/COLOR]"
277281

278-
msgctxt "#30823"
282+
msgctxt "#30824"
279283
msgid "Widevine CDM path: [B]{path}[/B]"
280284
msgstr "Widevine CDM elérési út: [B]{path}[/B]"
281285

282-
msgctxt "#30824"
286+
msgctxt "#30825"
283287
msgid "Chrome OS version: [B]{version}[/B]"
284288
msgstr "Chrome OS verzió: [B]{version}[/B]"
285289

0 commit comments

Comments
 (0)