Saturday, December 30, 2017

Dealing with a partially installed Windows 7 update

On one computer the June 2017 monthly rollup (KB4022719) somehow installed improperly or got corrupted. It couldn't be uninstalled, and future rollups couldn't be installed. Apparently, the process of installing a new rollup first needs to uninstall the previous one.

The Windows Update user interface simply gave the useless 80004005 error, but detailed information about the failure was available in c:\windows\logs\cbs\cbs.log:

2017-12-28 20:54:05, Error                 CBS    Failed. Attempted to uninstall a version of a non-driver component that is not installed, version: 0X700061db15cfe, component: amd64_microsoft-windows-w..lient-aux.resources_31bf3856ad364e35_7.6.7601.23806_en-us_e79af1b12d6db6c9, owner: Package_835_for_KB4022719~31bf3856ad364e35~amd64~~6.1.1.6.4022719-2919_neutral_LDR [HRESULT = 0x80004005 - E_FAIL]

Each update is a package which refers to many other packages, like Package_835_for_KB4022719~31bf3856ad364e35~amd64~~6.1.1.6.4022719, and each of those packages refers to components, like 2919_neutral_LDR. If you're curious, you can unpack an update and look inside it. First unpack the .msu to get the CAB and then unpack the CAB. You probably must use Microsoft's expand.exe to unpack the CAB because it may use intra package delta (IPD) compression which is not supported by 7-Zip.

Inside the CAB you will find various .mum files, which correspond to the main package and those sub-packages. The logical thing to do would be to reinstall these problematic components. However, I don't see a way to install from a .mum file.

So, I ended up uninstalling the messed up update by editing its already installed .mum file, found in c:\windows\servicing\packages, as  package_for_kb4022719_sp1~31bf3856ad364e35~amd64~~6.1.1.6.mum. (Note the absence of a number after "package" in the file name.) That directory is set up by default so only TrustedInstaller can write there. Not even SYSTEM can write there! So, I had to temporarily grant access to Administrators. The sections to remove are like this:

<update name="4022719-4117_neutral_PACKAGE">
<package integrate="hidden">
<assemblyIdentity name="Package_835_for_KB4022719" version="6.1.1.6" language="neutral" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" />
</package>
</update>


After removing the sections referring to messed up sub-packages, it was possible to uninstall the rollup. However, reinstalling it didn't fix the problem. I guess the messed up partly installed sub-packages don't get reinstalled? Fortunately, I was able to install the December roll-up without problems. Hopefully future roll-ups will install, and the only consequences will be a few small unnecessary but harmless files and registry entries.

Monday, December 04, 2017

How to log in to SoundCloud in Kodi

The SoundCloud add-on for Kodi accesses SoundCloud via its API and OAuth2 authentication. It is supposed to log in once using your username and password, and get a token. After this, there is no need for your password, and it can access SoundCloud using just the token.

The problem is that SoundCloud's initial procedure for obtaining the token has changed, and you now need to use the /connect method. But, once the add-on has the token, it can log in. So, the solution is to get the token using another method.

Soundnode is a desktop app which also authenticates to SoundCloud via OAuth2. After authenticating, the token can be found in its configuration files.  In Linux, URL strings including the token can be found in ~/.config/Soundnode/Cache/data_*. Look for URL inside like https://api.soundcloud.com/me.json?&oauth_token=something . Then add the token to your add-on configuration file, in Linux at ~/.kodi/userdata/addon_data/plugin.audio.soundcloud/settings.xml. You need to add <setting id="login.access_token" value="something" /> .

While the add-on doesn't need the login.username and login.password, its code is written such that they need to exist and the login.hash needs to match. You can compute the hash in Python using:

import hashlib
username = 'username'
password = 'whatever'
m = hashlib.md5()
m.update(username.encode('utf-8') + password.encode('utf-8'))
m.hexdigest()


Since the add-on is incapable of actually using this information to log in, feel free to not actually put your real password there. The OAuth2 token provides access to your SoundCloud account, so keep that secure.

This may not be a complete solution, because although I can access lists of things, playback fails with a HTTP 401 error. I don't know if that means the SoundNode API quota is depleted or if I need to do other things. Setting CLIENT_ID and User-Agent in ~/.kodi/addons/plugin.audio.soundcloud/resources/lib/content/client.py did not help.

Friday, March 17, 2017

Streaming video from an MJPEG network camera to applications in Linux

I recently got a D-Link DCS-930L network camera. It outputs a motion JPEG (MJPEG) stream at http://address/video.cgi. Although there's no kernel driver for receiving that, it is possible to send it to applications from user space via v4l2loopback.

First you need to install the module. Debian and Ubuntu have it in the v4l2loopback-dkms. If your distribution doesn't have it, then you'll need to build it and install it yourself. Then, load the module. If you want Chrome to see it, load it with the exclusive_caps=1 parameter, like sudo modprobe v4l2loopback exclusive_caps=1 .

Then, run a program to read the video and send it to the loopback device. It's possible with ffmpeg, using something like this:

ffmpeg -f mjpeg -i http://user:pass@192.168.1.30/video.cgi -s 640x480 -vf format=pix_fmts=yuv420p -f v4l2 /dev/video0

Note user:pass, which would be the credentials needed to log in to the camera. If you put yours there, note that it's insecure, as ps shows command lines. Also note the resolution and video device, which you may need to change.

A similar method could be used if you wanted to read from one video device, apply effects, and then present the video with effects to an application.