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.

Sunday, December 18, 2016

How to find good yogurt in Canada

While living in Croatia in the 80s, I enjoyed plain yogurt every day. After moving to Canada, I was very disappointed with the yogurt here.

Now I can find good yogurt in Canada. It's really quite simple: look at the ingredients. Yogurt is supposed to contain milk ingredients and bacterial culture. It is not supposed to contain various gums, gelatin or corn starch. I suppose factories add that to create consistent texture even when they're unable to make proper yogurt which would have a good texture on its own.

Astro Original is consistently good. Middle Eastern brands like Halal and Phoenicia are also good. Danone usually disappoints.

In Canada you can buy lots of different yogurt with added flavour and/or fruit. I generally avoid those, because they have lots of added sugar or artificial sweeteners. It's better to enhance yogurt with fruit on your own. Sour cherries which were washed and pitted in the summer are great for this. Preparing it is a lot of work one day, but it's kind of fun and after that they're easy to use. I freeze them in small containers which after defrosting last for a week or so.

Don't shy away from fat. Research shows that fat isn't that bad, sugar is far worse, and even artificial sweeteners are unhealthy. Without fat, it's hard to get the right consistency and flavour, and many low fat products add other unhealthy things instead. So, 3% yogurt is fine, and don't assume 0% is better.

The same general advice applies to other milk products like kefir, huslanka and even sour cream.

Facebook friend request accepted even though I never sent one

A while ago someone I stayed in touch with over 10 years ago appeared in my suggested friends list. That was probably due to a mutual friend. I looked at the suggested friend's page and public posts for a bit, and decided to not send a friend request. Later that day I was told that he accepted my friend request.

I don't think I made a mistake and accidentally sent a friend request. Furthermore, in the friends activity log at https://www.facebook.com/dreamlayers/allactivity?privacy_source=activity_log&log_filter=cluster_8 I see a "became friends" entry, but no "sent a friend request" entry. I just scrolled through the entire log, to the beginning of my time on Facebook, and still see no friend request. For various other people I see a "sent a friend request" entry followed by "became friends".

This isn't a problem and what happened was probably a good thing. So, I'm not complaining. It's just weird and I'm wondering why this happened.

Monday, December 12, 2016

Notes about unlocking a Vonage VDV23 VoIP box

I got a used Vonage VDV23 VoIP box to play with. Vonage seems expensive and limited compared to other VoIP providers like voip.ms, so I decided to unlock the box for use with other providers. A guide is available, but I ran into various problems trying to follow it, and this was quite an adventure. You can access the guide for free, but need to register at voipfan.net and log in there. The comments here are meant as a supplement to the guide, not a replacement.

Note that buying this device for use with Vonage may be pointless. Vonage will give you a new adapter if you sign up, and may not allow you to use an old one.

Firmware loading via TFTP

Always use the internal phy. It will tell you if autonegotiation worked and you got an Ethernet connection. I never had any success whatsoever when I selected external phy.

Network connectivity from the bootloader sometimes seems terribly unreliable. Pinging the VDV23 only worked once. Other times it at best answered a few pings, often with delays of more than a second. Received pings also spit out error messages to the console. Trying to ping first may even break subsequent TFTP attempts. Don't bother testing the network connection with ping; just try TFTP.

After trying my main PC and router, I ended up using the Ethernet port on this Inspiron 6400 laptop. Also, I was always setting up the network immediately after startup, not later on via the menu. When I did this, TFTP always worked.

The "Board IP Gateway" must exist, because the VDV23 will perform ARP queries for it when starting TFTP. Yes, it will even do this if the address is within the LAN. I just set it to the TFTP server address.

Getting the Admin password

Ignore the password at BF7F0118. Yes, there seems to be a password there, but I could never log in using it. If the password at BF3D00FA is all zeros, you didn't wait long enough for the VDV23 to download the password from Vonage and configure itself. If you wait too long, it will start upgrading firmware.

The first time I couldn't log in with the password from BF3D00FA either. I'm not sure if the "safe" vdv21-3.2.6-na_boot.bin firmware needs to get the password over the Internet from Vonage again. It may also start upgrading firmware if you wait too long. So, you need to disconnect from the Internet and continue with the rest of the guide.

Configuring SIP

I chose to configure via the XML file. First I tried to use an address accessible from the blue WAN port, but I didn't see any HTTP requests. Then I chose the default http://192.168.15.10 address and it worked via the yellow Ethernet port.

The device always sends an HTTP request soon after booting, so I was just unplugging it and plugging it back in to change the configuration. Seems like it first configures itself using stored parameters. Then if the XML file has different parameters the phone light will go out for a while as it reconfigures itself. Don't take the phone off hook during that process, because it will be testing the line. You may end up with a blinking phone light and a console complaint about the ringer equivalence number (REN) being too high.

Pay attention to the dialPlan lines. The one in the provided XML isn't enough for some voip.ms numbers, leading to a fast busy. I couldn't figure out how to support 2 and 3 character * codes except using *xx.T, which waits for a timeout before proceeding with the call. For experimenting, I could reconfigure dialPlan once from the console and see immediate results.

I forwarded port 8660 because it is localPort in the XML, but am not sure if that was necessary. The device is meant to be directly connected to the Internet and act as your gateway, providing NAT while prioritizing VoIP traffic. Since I'm still playing with it, I'm not going to do such a drastic change to my network.

Tuesday, December 06, 2016

How to set the MAC address when connecting to wireless using /etc/network/interfaces

If you try to set the mac address using hwaddress ether xx:xx:xx:xx:xx:xx in /etc/network/interfaces, that fails. It seems ifup tries to set the address after connecting to WiFi. The address needs to be set before, while the interface is down. If you need the MAC address to connect, you won't connect, and if you don't need it and connect, you'll get RTNETLINK answers: Device or resource busy at the end. The solution is to use a pre-up ifconfig wlan0 hw ether xx:xx:xx:xx:xx:xx line instead of the hwaddress ether line.

Monday, December 05, 2016

Exiftran for Windows

The Windoze 10 Photos app doesn’t actually rotate JPEG files, and instead just sets the EXIF orientation. I want my photos to always be displayed in the correct orientation, so this is not acceptable, because the flag is ignored in many situations. Photos can be rotated with jpegtran, but my camera photos also contain a JPEG thumbnail in the Exif data, which also needs to be rotated. I used exiftran for this in Linux and I cross-compiled it for Win32 from Linux using i686-w64-mingw32-gcc. Download the build directory here. I'm distributing the whole thing because of the GPL. To use exiftran, rename exiftran to exiftran.exe and run it. For example, to rotate a file by 90 degrees in place, replacing it with a losslessly rotated version, use "exiftran -9i file".

Monday, November 28, 2016

Switching from IDE to AHCI on an ICH7-M based laptop

Many older laptops have SATA controllers and SATA drives, but set up the chipset in IDE mode instead of AHCI mode. Compared to IDE mode, AHCI can provide faster transfer rates, NCQ and power savings. It may not be possible to select AHCI mode in the BIOS, but it can be done by writing to PCI configuration registers directly. The actual IDE (PATA) ports are not supported in AHCI mode, so a PATA DVD drive would not be usable when AHCI is enabled.

You can read and write PCI registers using setpci in Linux, but if you want to make this change, it must be done before the device is detected. One way to do it is via a kernel patch, but recompiling the kernel every time for updates is kind of annoying. Another way is via GRUB's setpci command. This is very easy, and works well, but breaks resume from sleep, because GRUB doesn't run then and the kernel will encounter the device in IDE mode.

How to do this via GRUB

First, you need to find your controller. Use lspci and look at the output. On my Inspiron 6400 I find "00:1f.2 IDE interface: Intel Corporation 82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] (rev 01)". The 00:1f.2 is the device's identifier in Linux, and lspci -n | grep 00:1f.2 shows "00:1f.2 0101: 8086:27c4 (rev 01)" This gives you the PCI ID of the device: 8086:27c4.

According to the ICH-7 datasheet PDF, you need to set the 8-bit MAP—Address Map Register at offset 0x90 to 0x40. (A patch I had before also set the SCRAE bit in the register at offset 0x94, but that just provides access to some AHCI registers when AHCI is not enabled, and is irrelevant when AHCI is enabled.) This means the following GRUB command is needed.

setpci -d 8086:27c4 90.b=40

You can press e when the GRUB menu is displayed, and add it to the end of the command that boots Linux. Adding it earlier caused a hang, probably because the BIOS cannot handle AHCI mode, and so it needs to be set after the kernel and initrd are loaded. After finding this works, I added an /etc/grub.d/42_ahci file with a stripped down Linux menu entry taken from /boot/grub/grub.cfg. It would be better if I could call the Ubuntu menu entry as a subroutine, but that doesn't seem possible with GRUB.

#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
menuentry 'Ubuntu AHCI' --class ubuntu --class gnu-linux --class gnu --class os {
recordfail
insmod ext2
set root='hd0,msdosPARTITION_NUMBER_HERE'
linux /vmlinuz root=UUID=PUT_UUID_HERE ro resume=SWAP_PARTITION
initrd /initrd.img
setpci -d 8086:27c4 90.b=40
}

The Results

This change increases sudo nice -n -19 dd if=/dev/sda bs=1M of=/dev/null count=1000 speed from 128 MB/s to 141 MB/s with a PNY SSD2SC120G1CS1754D117-551 SSD. It also enables NCQ, and causes the DVD drive to not be detected at all. Here are the IDE lines which disappear from dmesg. Note that this is based on diff output and is just a list of lines in order, not a continuous section.

pci 0000:00:1f.2: [8086:27c4] type 00 class 0x010180
pci 0000:00:1f.2: legacy IDE quirk: reg 0x10: [io 0x01f0-0x01f7]
pci 0000:00:1f.2: legacy IDE quirk: reg 0x14: [io 0x03f6]
pci 0000:00:1f.2: legacy IDE quirk: reg 0x18: [io 0x0170-0x0177]
pci 0000:00:1f.2: legacy IDE quirk: reg 0x1c: [io 0x0376]
ata_piix 0000:00:1f.2: version 2.13
ata_piix 0000:00:1f.2: MAP [ P0 P2 IDE IDE ]
scsi host0: ata_piix
scsi host1: ata_piix
ata1: SATA max UDMA/133 cmd 0x1f0 ctl 0x3f6 bmdma 0xbfa0 irq 14
ata2: PATA max UDMA/100 cmd 0x170 ctl 0x376 bmdma 0xbfa8 irq 15
ata2.00: ATAPI: SONY DVD+/-RW DW-Q58A, UDS2, max UDMA/33
ata1.00: 234441648 sectors, multi 2: LBA48 NCQ (depth 0/32)
ata2.00: configured for UDMA/33
scsi 1:0:0:0: CD-ROM SONY DVD+-RW DW-Q58A UDS2 PQ: 0 ANSI: 5
sr 1:0:0:0: [sr0] scsi3-mmc drive: 24x/24x writer cd/rw xa/form2 cdda tray
cdrom: Uniform CD-ROM driver Revision: 3.20
sr 1:0:0:0: Attached scsi CD-ROM sr0
sr 1:0:0:0: Attached scsi generic sg1 type 5


Here are the new lines which appear instead:

pci 0000:00:1f.2: [8086:27c5] type 00 class 0x010601
pci 0000:00:1f.2: reg 0x24: [mem 0x00000000-0x000003ff]
pci 0000:00:1f.2: BAR 5: assigned [mem 0x80000000-0x800003ff]
ahci 0000:00:1f.2: version 3.0
ahci 0000:00:1f.2: enabling device (0005 -> 0007)
ahci 0000:00:1f.2: forcing PORTS_IMPL to 0xf
ahci 0000:00:1f.2: SSS flag set, parallel bus scan disabled
ahci 0000:00:1f.2: AHCI 0001.0100 32 slots 4 ports 1.5 Gbps 0xf impl SATA mode
ahci 0000:00:1f.2: flags: 64bit ncq ilck stag pm led clo pmp pio slum part
scsi host0: ahci
scsi host1: ahci
scsi host2: ahci
scsi host3: ahci
ata1: SATA max UDMA/133 abar m1024@0x80000000 port 0x80000100 irq 27
ata2: SATA max UDMA/133 abar m1024@0x80000000 port 0x80000180 irq 27
ata3: SATA max UDMA/133 abar m1024@0x80000000 port 0x80000200 irq 27
ata4: SATA max UDMA/133 abar m1024@0x80000000 port 0x80000280 irq 27
ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
ata1.00: 234441648 sectors, multi 2: LBA48 NCQ (depth 31/32), AA
ata2: failed to resume link (SControl 0)
ata2: SATA link down (SStatus 0 SControl 0)
ata3: SATA link down (SStatus 0 SControl 300)
ata4: failed to resume link (SControl 0)
ata4: SATA link down (SStatus 0 SControl 0)

A better solution

Another alternative, which can support suspend to RAM, is to set registers from an altered DSDT. Read about the DSDT changes here and read about how to use a custom DSDT in Linux here. You first need to dump your DSDT, decompile it and fix it so it can compile properly. People do this sort of thing for running Mac OS on a PC, and you can find plenty of info on sites relating to that. Then you can add your modifications. In Ubuntu, simply copy the compiled dsdt.aml to /boot and run update-grub.