Wednesday, October 11, 2023

敵人 Enemy

在戰區的朋友今天傳來消息,她家裡一位行動不便的人來不及逃亡,被炸死了。

九二一地震時,也有許多人自己逃得了,但眼睜睜看著慢一步的親人罹難。這種痛,除了失去親人外,還加上倖存者的罪惡感。

而戰爭帶來的苦難,又比天災更進一步:天地不仁,帶來災難,人類也只能面對;但戰爭卻是人為的,是某些人覺得自己某些利益比他人的生命更寶貴,而覺得可以犧牲他人生命。這種痛,又更上一層。


很多人生日許願時常說要祈求世界和平,好像真的有一位專管生日許願的神,來應允每個人的三個願望。我沒聽過有這樣的神。

生日許願,不應像求阿拉丁神燈,求完了就沒自己事了;而應像新年立願一樣,當做是自己努力的目標。

真想要世界和平,至少先把自己與他人的關係弄好,想辦法減少自己外在的敵人與內在的敵意。


朋友痛失家人生命的離去,我立願以減少自己暴戾之氣作為新生命的開始。


Tuesday, April 30, 2019

Streaming Custom Videos in Google Hangouts

Summary:

With this method, I was able to send Google Hangouts any video contents, such as me with a news broadcast background, while the small TV in that background is showing my desktop playing a live Youtube video.

Update: now there's an easier way: use OBS's v4l2sink plugin + v4l2loopback kernel module. See this article.


OBS is a fine tool that enables us to overlay various visual/audio sources, on the fly, for streaming and/or recording. Unfortunately, it doesn't support a virtual cam under Linux (there is a plugin that only works under Windows), i.e. I can't send a complex composition of a live desktop screen, webcam, video, etc. to Google Hangouts.

Webcamoid is another fine tool that supports output to a virtual cam under Linux, which Google Hangouts can directly use.

Several attempts were made, but I wasn't able to get a result with low enough latency for video conferencing. The video latency caused an unacceptable out-of-sync problem with the audio.

I reached an easy workaround, which is resource heavy, but works quite well.
  1. Use OBS to construct the target scene, say, a chroma keyed webcam, with a video background, and a logo foreground, as well as a live chat overlay.
  2. In OBS, right click on the preview, and project it under a separate screen.
  3. In Webcamoid, choose that screen as the source.
  4. In Google Hangouts, choose Webcamoid's virtual cam instead of the real webcam.
  5. Voila! Now I have full control of what others see in my video conferencing.
This solution needs one whole screen just to link OBS and webcamoid. Any of the following improvement of either project will make this workflow even better:
Hopefully either will come soon.

Friday, October 13, 2017

uwsgi wrong python interpreter

In some projects, I use uwsgi behind nginx to drive Django. I also use virtualenv to manage my environments (by the way, Panda's introducing .ix and then deprecating it wasn't fun). In a recent update, I was pulling my hair out trying to figure out why I'm getting the following error message, and a wrong Python interpreter.


Could not find platform independent libraries
Could not find platform dependent libraries
Consider setting $PYTHONHOME to [:]
Python version: 3.5.4 |Continuum Analytics, Inc.| (default, Aug 14 2017, 13:26:58)  [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
Set PythonHome to /opt/anaconda
Fatal Python error: Py_Initialize: Unable to get the locale encoding
ImportError: No module named 'encodings'



It turned out that the problem was in the binary code of uwsgi in my environment. It was compiled for another environment, with the environment path hard-coded in. Yes, in the binary. I had done that in another environment and the compiled package stayed in the pip cache, and the new environment just picked it up from the cache, causing inconsistency!

The solution:


pip install --no-cache uwsgi

Tuesday, July 11, 2017

Ergodox EZ Configurator Layer Manipulation

Ergodox EZ provides a great configurator; however, it doesn't provide all editing functions I need. Unfortunately, the source code disappeared from github (multiple unofficial documents have links to that repo so I assume the source was once available; this is rather disappointing, since the company made it look like that they are using all open source resources.)

One of the functions that I need the most is swapping the layers.

Here's what I did to achieve it:

Upon examining the minimized javascript, it was written against the React framework. Therefore, I installed the React debugger extension for chrome, in order to find and manipulate the variable that stores the layer information.

Once the extension is installed, reload the page, and open up the Developer Tools in Chrome.
Click on React to open the debugging panel.
Make sure the correct scope "App" is selected.
Now the variable $r will contain the React object, including the state, for editing.
The layers (including all key assignment) information is in the array: $r.state.layout.layers

Here's an example of swapping layer 3 and 4.


$r.state.layout.layers = [
$r.state.layout.layers[0],
$r.state.layout.layers[1],
$r.state.layout.layers[2],
$r.state.layout.layers[4],
$r.state.layout.layers[3],
$r.state.layout.layers[5],
$r.state.layout.layers[6],
$r.state.layout.layers[7],
]



Note that if there are layer switching keys, you'll also need to manually modify those from the GUI.

I also did some batch editing offline, and then re-assign the whole $r.state.layout.layers
by first converting the variable to JSON and write it to a local file, with this snippet.

Also when you copy/create a layer, make sure to use the GUI to first allocate the variable $r.state.layout.layers[x].keyboard_layout_id on their server and then carefully copy those values.

Here's my current setup, if you are interested.



Saturday, February 6, 2016

Fixing Lenovo U31-70 WiFi Problem

Abstract

Lenovo U31-70 is a lightweight laptop. Its WiFi performance has been a headache to many people. Most people report unstable signal dropping.

For those who use Windows and are experiencing unstable WiFi problem, you just need to solve the hardware problem.

I use Linux, so I had to go a different route to solve my driver problem.

The Hardware Problem

I opened up the laptop, and found that the two antenna cables were not properly attached to the card. There was a tape (not shown in the picture) trying to keep the two cables attached, but failed due to the tension from the bending; also, the screw to attach the card onto the main board is too close to one of the antenna contacts so it automatically grounds it, making that antenna useless. This is a design problem.



I first re-attached the two cables back to their contacts and re-tape them, and put some non-conductive material between the screw and the contact to prevent the grounding. It helped.

The Atheros 10K Driver Problem under Linux

I had used several Thinkpads since its IBM days, so I was quite surprised to have found that this Lenovo's Atheros 10K chip was not supported under Linux. People were reporting stable driver performance under Windows, and some efforts were made to bring the firmware from Windows driver to Linux. I waited a few months for Linux kernel to come to version 4.3 and spent a lot of time trying various hacks to get the driver working. I was never able to get stable performance.

I decided to replace the card with Intel Dual Band Wireless AC 3160, which is well supported by native Linux.

(I have no idea which antenna cable is intended for WiFi and which is for bluetooth, but this works for me; besides, tension-wise, this is the only way I could keep the contacts isolated.)

It has been working flawlessly.


Saturday, January 30, 2016

Coordinate Transformation Matrix for Touchscreen in multi-screen setup in X11

Currently I have a twin screen setup in Arch Linux, like this:

On the left, DELL 1901FP is turned 90 degree counter-clockwise in its portrait mode. On the right, DELL P2314T, a touch screen, is in its regular landscape orientation, with its bottom line aligning with the bottom of the rotated screen on the left.

Here's my xorg.conf for that. (Although one can also setup screen arrangement in KDE/Plasma/Gnome/etc., for KDM/SDDM/GDM/etc. to recognize it in the login screen, it's important to put this in xorg.conf)





X11 sees a (1024+1920) wide * 1280 high DISPLAY, with an upper-right corner being invisible.

Since the touchscreen is just a regular pointer device (through its driver), when I put my finger on the left border of the touchscreen on the right, the cursor goes all the way to the very left of the DISPLAY. Touchscreen is only useful if the cursor follows my finger. Therefore, we need to do some Input Coordinate Transformation.

Coordinate Transformation Matrix is precisely the needed configuration.

From the documentation above, our goal is to map the following coordinates on the left (X11's default behavior) to the ones on the right:



So that means we are solving the following system:


Here's the solution:

Convert it to float numbers:

Now we can put these numbers into the configuration, as the document instructed.





However, it doesn't work. The cursor stays on the lower right. After some debugging, I found the offsets 1024 and 200 were the culprit. They need to be a percentage, i.e. relative to the full width and height.

So 1024.0/(1024+1929) = .3476766, 200.0/1280 = .15625





I put it in /usr/share/sddm/scripts/Xsetup (or /usr/share/config/kdm/Xsetup if you haven't upgraded to plasma) as well as ~/.xprofile so it automatically runs every time.

Edit 2016-02-22: I ended up having 3 screens with two in the portrait orientation. SDDM correctly uses metamodes setting in xorg.conf, regardless of the screen power. However, KDE is more sensitive to that so sometimes the layout is messed up. Here's a script to quickly correct that.




Monday, October 19, 2015

Install Sibelius 8.0.1 on a non-C drive in Windows

Since Sibelius 8.0.0, Avid changed the installer, and it has a serious bug -- it assumes you have a C: drive before letting you choose the installation destination. I figured out a hack to install it. However, it doesn't work for Sibelius 8.0.1, so here's another way to approach it, before Avid's Sibelius team fixes the bug.

I don't have a C: drive, but Sibelius insists that I must do, so what we are trying to do here is to temporarily create a C: drive, and then create a link pointing crucial directories back to my system drive, K:. After Sibelius is successfully installed, we can then safely remove the temporary C: drive.

First, we need to create a Virtual Hard Drive (VHD) as our C:\ drive. I learned how to do this via this answer:
  • Start → run → diskmgmt.msc (accept all defaults... I'm not doing anything special below) 
  • From the menu bar select Action → Create VHD 
  • Choose the location and name the file (which will be the vhd) and specify the size and click OK. My file is K:\virtual_drive_c.vhd and the size is 1G, but I made it dynamic so it's actual size is around 16MB. 
  • Right click on the Disk # (underneath will be Unknown and the size and "Not Initialized"). Select "Initialize Disk" and click OK 
  • Right click on the black bar of the unallocated disk space and select "new simple volume". A wizard opens up an on the second page it lets you assign the drive letter. We want C: here. Complete the wizard and you're done!
Now that we have a C: drive, we can link the important folders. I learned how to do that from this post:
  • Start → run → cmd, then right click and choose "Run as Administrator". 
  • In the prompt, type the following:
K:\>mklink /j "C:\Program Files" "K:\Program Files"
Junction created for C:\Program Files <<===>> K:\Program Files

K:\>mklink /j "C:\Program Files (x86)" "K:\Program Files (x86)"
Junction created for C:\Program Files (x86) <<===>> K:\Program Files (x86)



After that, Sibelius installation should run normally. In the installer, I still choose to install the program to K:, to avoid future problems running Sibelius, since the bug is on the installer, not Sibelius itself.

Afterwards, you can reboot, and safely delete the vhd file.