tag:blogger.com,1999:blog-4810960690643747252024-03-05T12:10:19.877-05:00Still Reflection 返照Tsan-Kuang Lee's Blog 李璨光個人網誌Unknownnoreply@blogger.comBlogger149125tag:blogger.com,1999:blog-481096069064374725.post-26762105084077455732023-10-11T03:16:00.003-04:002023-10-11T03:47:24.445-04:00敵人 Enemy<p>在戰區的朋友今天傳來消息,她家裡一位行動不便的人來不及逃亡,被炸死了。</p><p>九二一地震時,也有許多人自己逃得了,但眼睜睜看著慢一步的親人罹難。這種痛,除了失去親人外,還加上倖存者的罪惡感。</p><p>而戰爭帶來的苦難,又比天災更進一步:天地不仁,帶來災難,人類也只能面對;但戰爭卻是人為的,是某些人覺得自己某些利益比他人的生命更寶貴,而覺得可以犧牲他人生命。這種痛,又更上一層。</p><p><br /></p><p>很多人生日許願時常說要祈求世界和平,好像真的有一位專管生日許願的神,來應允每個人的三個願望。我沒聽過有這樣的神。</p><p>生日許願,不應像求阿拉丁神燈,求完了就沒自己事了;而應像新年立願一樣,當做是自己努力的目標。</p><p>真想要世界和平,至少先把自己與他人的關係弄好,想辦法減少自己外在的敵人與內在的敵意。</p><p><br /></p><p>朋友痛失家人生命的離去,我立願以減少自己暴戾之氣作為新生命的開始。</p><p><br /></p><span><a name='more'></a></span><p><br /></p><p>A friend lost one of her family members to the recent war bombing. Others had to leave that disabled member behind.</p><p>Taiwan experienced a devastating earthquake in 1999, during which a lot of people also had to leave their loved ones behind in their narrow escape. On top of the loss, they also have to carry the survivor guilt.</p><p>Facing natural disasters is part of life and we do not have other choices but to face them, but wars happen because somebody prioritizes their interest over other people's lives. The pain brought by the war is therefore on another level.</p><p><br /></p><p>Many people's birthday wishes include world peace. Who are we hoping to grant these wishes? I am unaware of any deity who specializes in granting birthday wishes.</p><p>Perhaps birthday wishes should not be wishes asked of a genie, but rather, resolutions, like the New Year ones, which are more like goals that we work hard to achieve.</p><p>In hoping for the world peace, perhaps we should start from improving our own personal relationships, by at least reducing our hostility toward others, and ourselves.</p><p><br /></p><p>Today I make a wish to honor that lost life by starting a new journey to reduce my negativity.</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-36731893287711271382019-04-30T02:35:00.002-04:002020-04-19T22:44:43.726-04:00Streaming Custom Videos in Google HangoutsSummary:<br />
<br />
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.<br />
<br />
Update: now there's an easier way: use OBS's v4l2sink plugin + v4l2loopback kernel module. See this <a href="https://srcco.de/posts/using-obs-studio-with-v4l2-for-google-hangouts-meet.html">article</a>.<br />
<br />
<br />
<a href="https://obsproject.com/">OBS</a> 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 <i>is</i> <a href="https://github.com/CatxFish/obs-virtual-cam">a plugin</a> 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.<br />
<br />
<a href="https://webcamoid.github.io/">Webcamoid</a> is another fine tool that supports output to a virtual cam under Linux, which Google Hangouts can directly use.<br />
<br />
<a href="https://github.com/CatxFish/obs-virtual-cam/issues/17">Several attempts</a> 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.<br />
<br />
I reached an easy workaround, which is resource heavy, but works quite well.<br />
<ol>
<li>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.</li>
<li>In OBS, right click on the preview, and project it under a separate screen.</li>
<li>In Webcamoid, choose that screen as the source.</li>
<li>In Google Hangouts, choose Webcamoid's virtual cam instead of the real webcam.</li>
<li>Voila! Now I have full control of what others see in my video conferencing.</li>
</ol>
<div>
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:</div>
<div>
<ul>
<li>When Webcamoid supports <a href="https://github.com/webcamoid/webcamoid/issues/180">a window as a source</a> (right now only whole screens can be sources), we can hide the window so it doesn't take up our screen real estate.</li>
<li>When OBS can <a href="https://github.com/CatxFish/obs-virtual-cam/issues/17#issuecomment-486121295">correctly piping a video stream into a linux virtual cam</a>, or even better, correctly implements its own virtual cam.</li>
</ul>
Hopefully either will come soon.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-84779730623884765452017-10-13T17:02:00.000-04:002017-10-13T17:03:47.618-04:00uwsgi wrong python interpreterIn 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.<br />
<br />
<code><br /><span style="background-color: white;">Could not find platform independent libraries <prefix>
</prefix></span><br />Could not find platform dependent libraries <exec_prefix>
<br />Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
<br />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)]
<br />Set PythonHome to /opt/anaconda
<br />Fatal Python error: Py_Initialize: Unable to get the locale encoding
<br />ImportError: No module named 'encodings'<br />
</exec_prefix></prefix></exec_prefix></code><br />
<br />
<br />
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!<br />
<br />
The solution:<br />
<br />
<code><br />
pip install --no-cache uwsgi<br />
</code>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-86349903579684455902017-07-11T23:00:00.000-04:002017-07-18T02:53:05.507-04:00Ergodox EZ Configurator Layer ManipulationErgodox EZ provides a great <a href="http://configure.ergodox-ez.com/keyboard_layouts/qgbavy/edit" target="_blank">configurator</a>; however, it doesn't provide all editing functions I need. Unfortunately, the source code <a href="https://github.com/ErgoDox-EZ/fusion" target="_blank">disappeared</a> 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 <a href="https://ergodox-ez.com/pages/our-firmware" target="_blank">look like</a> that they are using all open source resources.)<br />
<br />
One of the functions that I need the most is swapping the layers.<br />
<br />
Here's what I did to achieve it:<br />
<br />
Upon examining the minimized javascript, it was written against the <a href="https://facebook.github.io/react/" target="_blank">React</a> framework. Therefore, I installed the <a href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en" target="_blank">React debugger extension for chrome</a>, in order to find and manipulate the variable that stores the layer information.<br />
<br />
Once the extension is installed, reload the page, and open up the Developer Tools in Chrome.<br />
Click on React to open the debugging panel.<br />
Make sure the correct scope "App" is selected.<br />
Now the variable <span style="font-family: "courier new" , "courier" , monospace;">$r</span> will contain the React object, including the state, for editing.<br />
The layers (including all key assignment) information is in the array: <span style="font-family: "courier new" , "courier" , monospace;">$r.state.layout.layers</span><br />
<br />
Here's an example of swapping layer 3 and 4.<br />
<br />
<code><br />
$r.state.layout.layers = [<br />
$r.state.layout.layers[0],<br />
$r.state.layout.layers[1],<br />
$r.state.layout.layers[2],<br />
$r.state.layout.layers[4],<br />
$r.state.layout.layers[3],<br />
$r.state.layout.layers[5],<br />
$r.state.layout.layers[6],<br />
$r.state.layout.layers[7],<br />
]<br />
</code><br />
<br />
<br />
Note that if there are layer switching keys, you'll also need to manually modify those from the GUI.<br />
<br />
I also did some batch editing offline, and then re-assign the whole <span style="font-family: "courier new" , "courier" , monospace;">$r.state.layout.layers</span><br />
by first converting the variable to JSON and write it to a local file, with <a href="http://bgrins.github.io/devtools-snippets/#console-save" target="_blank">this snippet</a>.<br />
<br />
Also when you copy/create a layer, make sure to use the GUI to first allocate the variable <span style="font-family: "courier new" , "courier" , monospace;">$r.state.layout.layers[x].keyboard_layout_id</span> on their server and then carefully copy those values.<br />
<br />
Here's my <a href="http://configure.ergodox-ez.com/keyboard_layouts/qbbndp/edit" target="_blank">current setup</a>, if you are interested.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgs1XsPgLdmZv0Ueq1ICCQsZSeYlvz9lzPyv1VRbDB99Uf8XvZ9S544wjrN0hFlhHFd3P8Ee-qT3Yx94aJkyK5SJyeFK_o1jhQjIRXVfN7rgmRmVrqW1HslhSP8x6jR900YaqX64Abv244/s1600/ergodox_layers_manipulation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="931" data-original-width="1492" height="247" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgs1XsPgLdmZv0Ueq1ICCQsZSeYlvz9lzPyv1VRbDB99Uf8XvZ9S544wjrN0hFlhHFd3P8Ee-qT3Yx94aJkyK5SJyeFK_o1jhQjIRXVfN7rgmRmVrqW1HslhSP8x6jR900YaqX64Abv244/s400/ergodox_layers_manipulation.png" width="400" /></a></div>
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-79195506579758566462016-02-06T01:24:00.000-05:002016-02-06T01:31:26.808-05:00Fixing Lenovo U31-70 WiFi Problem<h2>
Abstract</h2>
Lenovo U31-70 is a lightweight laptop. Its WiFi performance has been a headache to many people. Most people report unstable signal dropping.<br />
<br />
For those who use Windows and are experiencing unstable WiFi problem, you just need to solve the hardware problem.<br />
<br />
I use Linux, so I had to go a different route to solve my driver problem.<br />
<br />
<h2>
The Hardware Problem</h2>
<div>
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.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK9ezS-jJEctiqRBBTJIeV7sdiEJKDS0XggH1KW4GZ2O4s-WQ7MI3KW6hSir3KfgwQZBiyiBdwcmXbwyKnfvinsHpYFX1qeJRl6lUTKPICZPJ_x8OjhbkL4_Sgzaax6w3a64fmZMBbrgw/s1600/original_wifi_card.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK9ezS-jJEctiqRBBTJIeV7sdiEJKDS0XggH1KW4GZ2O4s-WQ7MI3KW6hSir3KfgwQZBiyiBdwcmXbwyKnfvinsHpYFX1qeJRl6lUTKPICZPJ_x8OjhbkL4_Sgzaax6w3a64fmZMBbrgw/s400/original_wifi_card.jpg" width="400" /></a></div>
<br />
<br />
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.<br />
<br />
<h2>
The Atheros 10K Driver Problem under Linux</h2>
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.<br />
<br />
I decided to replace the card with Intel Dual Band Wireless AC 3160, which is well supported by native Linux.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit_pNeNdLX3eaU92n7Zk08L1ul3Fq1xy65U3PUyTjEeJzq_HbZVIiB-UY32agGQ5S8Ej7tcQmqB-nJ143mQ5eN2-ryTYJ6tPDnDxDjjd5jVt8Dvx0zBgh_pcQ240cedCEFXASUaDB0nUw/s1600/replaced_wifi.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="356" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit_pNeNdLX3eaU92n7Zk08L1ul3Fq1xy65U3PUyTjEeJzq_HbZVIiB-UY32agGQ5S8Ej7tcQmqB-nJ143mQ5eN2-ryTYJ6tPDnDxDjjd5jVt8Dvx0zBgh_pcQ240cedCEFXASUaDB0nUw/s400/replaced_wifi.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
(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.)</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
It has been working flawlessly.<br />
<br />
<br />Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-481096069064374725.post-62404033633816614012016-01-30T03:31:00.002-05:002016-02-22T18:28:22.580-05:00Coordinate Transformation Matrix for Touchscreen in multi-screen setup in X11<div class="separator" style="clear: both; text-align: left;">Currently I have a twin screen setup in Arch Linux, like this:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidWUUJDpYjXrkAHhUbLRXXvlIDYGK7XfYlATbVY4Px9zP0e-QGlnqb_tOO1JXAIKkZerOMOEI6g4xsmP5E1ewHzcGSzO4k07x2fm7nqybeWJRrJnApTDZgl4sShVLkW8jLt81ZldKtKfU/s1600/arrangement_of_screens.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="143" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidWUUJDpYjXrkAHhUbLRXXvlIDYGK7XfYlATbVY4Px9zP0e-QGlnqb_tOO1JXAIKkZerOMOEI6g4xsmP5E1ewHzcGSzO4k07x2fm7nqybeWJRrJnApTDZgl4sShVLkW8jLt81ZldKtKfU/s320/arrangement_of_screens.png" width="320" /></a></div><br />
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.<br />
<br />
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)<br />
<br />
<pre><code>
<textarea style="height: 7em; margin: 0px; width: 100%;"># /etc/X11/xorg.conf
# relevant section of screen rotation
Section "Screen"
Identifier "Screen0"
Device "Device0"
Monitor "Monitor0"
DefaultDepth 24
Option "Stereo" "0"
Option "nvidiaXineramaInfoOrder" "DFP-2"
Option "metamodes" "DVI-I-1: 1280x1024_75 +0+0 {rotation=right}, HDMI-0: nvidia-auto-select +1024+200"
Option "SLI" "Off"
Option "MultiGPU" "Off"
Option "BaseMosaic" "off"
SubSection "Display"
Depth 24
EndSubSection
EndSection
</textarea>
</code>
</pre><br />
X11 sees a (1024+1920) wide * 1280 high DISPLAY, with an upper-right corner being invisible.<br />
<br />
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.<br />
<br />
<a href="https://wiki.ubuntu.com/X/InputCoordinateTransformation" target="_blank">Coordinate Transformation Matrix</a> is precisely the needed configuration.<br />
<br />
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:<br />
<pre><code>
<textarea style="height: 6em; margin: 0px; width: 100%;"># (coordinates are in the format of (x,y))
(0, 0) => (1024, 1280-1080)
(1024+1920-1, 1280-1) => (1024+1920-1, 1280-1)
(1024+1920-1, 0) => (1024+1920-1, 1280-1080)
(0, 1280-1) => (1024, 1280-1)
</textarea>
</code>
</pre>So that means we are solving the following system:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjntUzcCPcsCmM_BjC2DE8jlZGSV7pgJ0mZDKpWm4gdQ4sd2X5X8qzZslWe4bCgHLDDr4__dRYNcQ3VzWW6wAyAXboN_thV-E7hngYZmmyNCoTwHP38qRykmnJP3nEH-8zzkP6XE5numSM/s1600/Matrix_equation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="50" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjntUzcCPcsCmM_BjC2DE8jlZGSV7pgJ0mZDKpWm4gdQ4sd2X5X8qzZslWe4bCgHLDDr4__dRYNcQ3VzWW6wAyAXboN_thV-E7hngYZmmyNCoTwHP38qRykmnJP3nEH-8zzkP6XE5numSM/s400/Matrix_equation.png" width="400" /></a></div><br />
Here's the solution:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU6gv1L91F20wlsUaxvBs-QVe448rGmH25P7od5IdmBhvKveLjgoDJ5u7xOHKJ8HOTlqN0Jo1zMQqdX6g4s7tBa4Kc8II_J4sjxoK1DyuWzF9BvQETzVJRLm_Sf1g8r7l6GlmbcmQcxIo/s1600/matrix_solution.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="103" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU6gv1L91F20wlsUaxvBs-QVe448rGmH25P7od5IdmBhvKveLjgoDJ5u7xOHKJ8HOTlqN0Jo1zMQqdX6g4s7tBa4Kc8II_J4sjxoK1DyuWzF9BvQETzVJRLm_Sf1g8r7l6GlmbcmQcxIo/s200/matrix_solution.png" width="200" /></a></div>Convert it to float numbers:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtsgT-1hZTiVmq920b22Epsvo86pP95mL_zQ3zglvt01hOsbt1nW5EdcNi3OXX1RkaR_FzmHJL8iZynnRDh1sl59aiW3MmGGeGtjwnw5CzNAvS1NB9mohHnwIOm5MigJ1uKiRohUJwtjs/s1600/matrix_solution_float.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="38" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtsgT-1hZTiVmq920b22Epsvo86pP95mL_zQ3zglvt01hOsbt1nW5EdcNi3OXX1RkaR_FzmHJL8iZynnRDh1sl59aiW3MmGGeGtjwnw5CzNAvS1NB9mohHnwIOm5MigJ1uKiRohUJwtjs/s400/matrix_solution_float.png" width="400" /></a></div><br />
Now we can put these numbers into the configuration, as the document instructed.<br />
<br />
<pre><code>
<textarea style="height: 4em; margin: 0px; width: 100%;"># This does NOT work
xinput set-prop "Advanced Silicon S.A CoolTouch(TM) System" --type=float "Coordinate Transformation Matrix" .652056 0 1024 0 .8436278 200 0 0 1
</textarea>
</code>
</pre><br />
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.<br />
<br />
So <code> 1024.0/(1024+1929) = .3476766, 200.0/1280 = .15625</code><br />
<br />
<pre><code>
<textarea style="height: 4em; margin: 0px; width: 100%;"># This works
xinput set-prop "Advanced Silicon S.A CoolTouch(TM) System" --type=float "Coordinate Transformation Matrix" .652056 0 .3479442 0 .8436278 .15625 0 0 1
</textarea>
</code>
</pre><br />
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.<br />
<br />
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.<br />
<br />
<pre><code>
<textarea style="height: 4em; margin: 0px; width: 100%;">
#!/bin/sh
# my xorg.conf has this line:
# Option "metamodes" "DVI-I-1: 1280x1024_75 +0+0 {rotation=right}, HDMI-0: nvidia-auto-select +2944+0 {rotation=right}, DP-1: nvidia-auto-select +1024+200"
gksu "xrandr --output DP-1 --primary --auto --pos 1024x200 --output DVI-I-1 --auto --pos 0x0 --rotation right --output HDMI-0 --auto --pos 2944x0 --rotation right"
</textarea>
</code>
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-47575064122566028482015-10-19T18:43:00.002-04:002015-10-21T14:42:57.725-04:00Install Sibelius 8.0.1 on a non-C drive in WindowsSince 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 href="http://blog.tklee.org/2015/08/sibelius-8-installation-on-non-standard.html" target="_blank">a hack to install it</a>. 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.<br />
<br />
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.<br />
<br />
First, we need to create a Virtual Hard Drive (VHD) as our C:\ drive. I learned how to do this via <a href="https://stackoverflow.com/a/18112515/701284" target="_blank">this answer</a>:<br />
<ul>
<li>Start → run → diskmgmt.msc (accept all defaults... I'm not doing anything special below) </li>
<li>From the menu bar select Action → Create VHD </li>
<li>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. </li>
<li>Right click on the Disk # (underneath will be Unknown and the size and "Not Initialized"). Select "Initialize Disk" and click OK </li>
<li>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!</li>
</ul>
Now that we have a C: drive, we can link the important folders. I learned how to do that from <a href="http://www.sevenforums.com/tutorials/278262-mklink-create-use-links-windows.html" target="_blank">this post</a>:<br />
<ul>
<li>Start → run → cmd, then right click and choose "Run as Administrator". </li>
<li>In the prompt, type the following:</li>
</ul>
<pre><code>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)
</code>
</pre>
<br />
<br />
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.<br />
<br />
Afterwards, you can reboot, and safely delete the vhd file.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-481096069064374725.post-29268354316466712032015-09-24T01:19:00.000-04:002015-09-24T01:21:38.412-04:00大易二十七年,行列二十七小時<h2>
綱要</h2>
<div>
我打大易輸入法很快,甚至比一些人用講的還快,但最近考慮換到行列輸入法。</div>
<h2>
我學大易輸入法的歷史</h2>
我小學正是Apple II電腦剛進入台灣的時候。那時候Apple II能插一張「佳佳漢卡」來顯示中文。打字方面只有倉頡與注音。我試學了幾次倉頡,最後都放棄。主要也因為那時候打中文的機會少,所以茍且用注音好多年。<br />
<br />
注音很好學,但因為中文同音字太多,選字鍵就只那一排數字鍵,導至最後總鍵數高,輸入速度大大受限。<br />
<br />
高一時做科展,要寫一堆文字報告。那時我字寫得難看,於是決定趁機把中打好好學。剛好大易輸入法剛出來,在雜誌上廣告,看到後就決定去他們公司問問看。下課後拎了書包就搭了公車去太易公司在中山北路(?)的辦公室。那時好像只有三位員工。其中一位先生看到高中生想學大易,很興奮。49元賣了我一本原價99的書,給我一疊字根卡,希望我回班上幫忙推廣。<br />
<h2>
大易的優點</h2>
大易說真的很了不起。讓我一個晚上就能把規則學完,看字根表打字。一星期內就完全不需要字根表了。我成功的例子也讓身邊很多人學大易用大易至今。那位先生應該覺得很欣慰。:)<br />
<br />
用了二十七年的大易,打字速度其實蠻快的,有幾個朋友應該看過我打字追上一些人講話的速度。<br />
<br />
我覺得大易的設計很好,字根的分類很直覺。基本上看到字就知道怎麼拆。其實,中文打多了,大部份人應該看到字就直接能跳過拆碼,直接以手指記憶打出來。<br />
<br />
另外一個大優點是字根與字鍵的分布很平均,所以在常用字裡,需要選字的機會其實不多。<br />
<h2>
一些常見輸入法的問題</h2>
倉頡難學。字鍵數也偏多。<br />
<br />
注音的問題上面提過,即使有些朋友熟到連選字鍵選字頁都一起背了起來,總鍵數還是太多,容易疲勞。<br />
<div>
<br /></div>
現在有很多智慧型輸入法,可以自動選字,或自動選詞,速度很快。但我對打字的需求比較傳統:我需要能夠完全預測什麼鍵會出什麼字。也就是說,我需要不用看瑩幕就能正確地打字。這樣能讓我做筆記時,眼睛不需要去顧打字窗。不管在做筆記或是創作,選字會讓我分心。我覺得這和演奏樂器的原理一樣,一個音彈拉吹敲下去,音高、音色、強弱都應該要能精確預期。<br />
<br />
還有這些輸入法大多以詞為單位來做智慧選擇。字詞的頻率在不同軟體版本中會有出入,造成可預測性降低。<br />
<h2>
大易的缺點</h2>
<h3>
版權的問題</h3>
<div>
<a href="http://hyperrate.com/thread.php?tid=27654" target="_blank">大易的版權並非完全自由</a>,許多自由軟體無法直接包含大易。網路上流通的合法版本是太易公司多年前釋出的,字數有限。後來雖然有許多熱心人士擴充,但也造成版本間有出入的問題。</div>
<div>
<h3>
平台的問題</h3>
</div>
<div>
我常用的作業系統有五個:Linux為主,手機Android,筆記型電腦是OSX,音樂的工作用Windows,以及平版的iOS。各個平台共通內建的繁體中文輸入法,只有注音與倉頡。(其他輸入法有的名稱相同,內容卻不統一)</div>
<div>
<br /></div>
<div>
由於上述的版權問題,軟體無法直接包含大易,所以這個過程只能手動。雖然花點力氣,也能把大易都裝上去(gcin, Lime, Open vanilla, 內建, JB/iAccess),但辛苦的是,每次系統或是作業環境升級,這個過程就得重來一次。</div>
<h3>
選字鍵的問題</h3>
<div>
大易的選字鍵和其他輸入法不同。大部份輸入法用上排數字鍵來選字,但大易把上排數字鍵和英文字母鍵都拿來當字根。這個設計,有效地讓總鍵數及選字的頻率都大大減少。但使用非標準選字鍵的缺點是,軟體必須特別設計來支援大易。隨著其他智慧型輸入法普及後,大易的使用族群變為少數,願意為大易特別設計的軟體就變少了。</div>
<h2>
可能的解決方案</h2>
<div>
最近發現令人驚艷的「<a href="http://www.openfoundry.org/of/projects/1371" target="_blank">瑲珩--動態拆碼暨動態組字</a>」計畫,也許能解決版權、版本及字數的問題。</div>
<div>
<br /></div>
<div>
但平台的問題,卻是我目前面臨的挑戰。比方說,gcin是很優秀的程式,但在Chromium或是Qt升級間常常造成不相容(問題不一定是gcin本身)。雖然問題總會解決,但發生的頻率高到太不方便。<br />
<br />
我考慮用iBus之類較普及的平台,看與其他軟體的相容性會不會好一點。選了軟體後,也要找大部份軟體都支援的輸入法,能直接用標準安裝,不用自己來。也許等大易版權過幾年釋出後,我就不用自己想辦法裝大易。但在那之前怎麼辦?<br />
<br />
順道一提,這陣子我開始用手機上 Google 的中文語音輸入,準確度很高,但輸入標點符號很麻煩,而且跨平台很不方便,隱私上也有些顧慮。<br />
<h2>
行列輸入法</h2>
前陣子發現<a href="http://www.array.com.tw/company/company.htm" target="_blank">行列輸入法和自由軟體的精神相符</a>:</div>
<div>
<blockquote class="tr_bq">
開放理念: </blockquote>
<blockquote class="tr_bq">
中文輸入法必須跟發明人的生命及推廣該輸入法的公司分離,當使用者學會之後,不管發明人是否在世,各系統都要能夠繼續支援,使用者才有永遠的保障,就像倉頡和注音輸入法一樣。 </blockquote>
<blockquote class="tr_bq">
要讓使用者可以永遠使用,只有像倉頡一樣開放授權才可能,因此行列採開放授權,任何一種系統,都可以找工程師把行列寫進系統,成為系統的一部份。 </blockquote>
在生活與工作上,我已儘量使用自由開源軟體,所以行列輸入法發明人廖明德這段話和我很對味。官方網站公布大方公布的內容,就足夠讓我學輸入法。這點令人激賞。<br />
<br />
行列的設計和大易一樣好學,一個晚上就能看著字根表打所有字。我相信沒多久就可以把字根表丟掉。目前初步的印象是,行列字根的分類,雖然也很有道理,但感覺上大易保留書寫直覺還是多一點。不過這個問題,應該在熟練之後就會自動消失。<br />
<h2>
結(未)論</h2>
<div>
老實說,我才剛學行列,還不知道(這篇仍是用大易打的)。也許我最後會放棄大易,完全轉用行列,也許我會發現行列的問題,再回到大易。但行列原發明人的胸襟,讓我很願意下功夫試試。</div>
<div>
<br /></div>
<div>
另外,我這篇也提到使用智慧型輸入法的潛在問題。也許從沒學過字根輸入的人可以試試能完全掌握打字結果的方法。</div>
</div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-481096069064374725.post-46094074272572040052015-08-05T19:59:00.001-04:002015-10-19T18:48:09.325-04:00Sibelius 8 Installation on Non-standard Windows System DriveUPDATE: This doesn't work for Sibelius 8.0.1. See <a href="http://blog.tklee.org/2015/10/install-sibelius-801-on-non-c-drive-in.html" target="_blank">this post</a> instead for that.<br />
<br />
Over the years I have many generations of audio software and plugins installed on Windows, which itself has gone through many version upgrades. I can't remember why but one upgrade called for changing the system drive from C: to K: (probably for a backup reason), and ever since then K: has been my system drive.<br />
<br />
Between projects, I decided to give Sibelius 8 a try. However, the installation file (Install_Sibelius.exe, unpacked from Sibelius_8.0.0_Win.zip) downloaded from Avid gave me this error:<br />
<br />
<code><br />
Error 1327 invalid drive C:\.<br />
</code><br />
<br />
By inspecting the log, I concluded that was hard-coded in the installer (FAIL! To tell the truth, it has been a familiar feeling ever since Avid acquired Sibelius).<br />
<br />
I really don't want to change the system drive again, since it would involve the painful process of re-configuring a million things. It's also after their support hours so I did some <a href="http://avid.force.com/pkb/articles/en_US/How_To/Sibelius-Silent-Install-Procedure">research</a>, and after some trial and error, this is what worked for me:<br />
<br />
1. run cmd.exe as Administrator.<br />
2. Change into the directory where Install_Sibelius.exe resides<br />
3. Run the following command<br />
<br />
<code><br />
J:\Users\composer\Desktop>J:\Install_Sibelius.exe /s /v"/qn /l*v %temp%\AvidSibeliusx64.log"<br />
<br />
</code><br />
<br />
4. Follow the standard procedure to activate the software<br />
<br />
That's it.<br />
<br />
PS: I very much look forward to <a href="http://blog.steinberg.net/2015/06/development-diary-part-11/">Daniel Spreadbury's new score writer</a>.Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-481096069064374725.post-159517212492983092015-05-06T22:43:00.000-04:002015-05-07T14:06:32.533-04:00X11 Multi-seat running KDE and GNOMEI was archiving data on my old machine and decided to share my old multi-seat configurations (I don't need multi-seat anymore), in case somebody out there is trying to do the same thing.<br />
<br />
It was a 7-year-old Dell PowerEdge server SC-1430 running dual Xeon (8 virtual cores), excellent for compiling, number crunching (machine learning), and video processing (Cinelerra), and on top of all that, it served as a file/media server running RAID 5 over RAID 0.<br />
<br />
It was a power beast, in another sense, too, though -- it consumed a lot of power.<br />
<br />
Since it was consuming power anyway, I decided to get rid of other computers and maximize its use, by setting up a multi-seat X11, so two users could use it at the same time. There were two sets of everything: two screens (on two NVIDIA cards), two keyboards, two mouses, and two USB sound cards. It worked just like two independent machines. In fact, one seat ran KDE and the other one ran GNOME. The login screen ran KDM, with two login boxes (default to the regular user login name) on respective screens and matching wallpapers. We were even able to play "networked" game against each other.<br />
<br />
(Actually I had three sets of xorg.conf to support multi-seat, left-side dual screen, and right-side dual screen, and I used symlinks to dynamically switch to a different configuration. However, there's more info on dual screen setups out there so I skipped those here.)<br />
<br />
For me, there were a few files to configure. These are the ones relevant to most people:<br />
<ul>
<li>/etc/X11/xorg.conf</li>
<li>/etc/kde/kdm/kdmrc</li>
<li>/etc/kde/kdm/backgroundrc.seat0</li>
<li>/etc/kde/kdm/backgroundrc.seat1</li>
<li>/etc/udev/rules.d/60-dell-keyboards.rules (omit here; see my <a href="http://blog.tklee.org/2011/09/create-distinguishable-device-id-for.html" target="_blank">other post on udev</a> for that)</li>
<li>/etc/udev/rules.d/90-creative-xmod.rules</li>
</ul>
For the sound cards, I just used the GUI setup in KDM and Gnome, respectively, to choose the right pulse audio sound device. I did use the udev to make the names easier to tell them apart.<br />
<div>
<br /></div>
I ran Arch Linux 64 on that one so the paths may be different if you use a different distro. I apologize in advance for not explaining the details here, many of which were specific to my system back then. I also wish I had time to dig out the document sources for these configs.<br />
<br />
<br />
/etc/X11/xorg.conf<br />
<pre><textarea style="height: 20em; margin: 0px; width: 100%;"># File: /etc/X11/xorg.conf
# nvidia-settings: X configuration file generated by nvidia-settings
# nvidia-settings: version 280.11 (mockbuild@hephaestus.wilsonet.com) Sun Jul 31 18:18:43 EDT 2011
#Section "ServerLayout"
# Identifier "Layout0"
# Screen 0 "Screen0" 0 0
# Screen 1 "Screen1" RightOf "Screen0"
# InputDevice "Keyboard0" "CoreKeyboard"
# InputDevice "Mouse0" "CorePointer"
# Option "Xinerama" "0"
#EndSection
Section "ServerLayout"
Identifier "Seat0"
Screen 0 "Screen0" 0 0
InputDevice "Keyboard0" "CoreKeyboard"
InputDevice "Keyboard0.1"
InputDevice "webcam_Button"
#InputDevice "X10_Lola.keyboard"
InputDevice "XmodControl.0"
InputDevice "Mouse0.Naga" "CorePointer"
InputDevice "MouseKeys0a.Naga"
InputDevice "Mouse0.1"
#InputDevice "MouseKeys0b.Naga"
Option "Xinerama" "0"
Option "AutoEnableDevices" "false"
Option "AutoAddDevices" "false"
Option "AllowEmptyInput" "true"
EndSection
Section "ServerLayout"
Identifier "Seat1"
Screen 0 "Screen1" 0 0
InputDevice "Keyboard1" "CoreKeyboard"
InputDevice "XmodControl.1"
InputDevice "Mouse1.Salmosa" "CorePointer"
Option "Xinerama" "0"
Option "AutoEnableDevices" "false"
Option "AutoAddDevices" "false"
Option "AllowEmptyInput" "true"
EndSection
Section "Files"
FontPath "/usr/share/fonts/default/Type1"
EndSection
Section "InputDevice"
Identifier "Mouse0.Naga"
Driver "evdev"
Option "GrabDevice" "true"
Option "Protocol" "auto"
Option "Device" "/dev/input/by-id/usb-Razer_Razer_Naga-event-mouse"
Option "Emulate3Buttons" "no"
Option "ZAxisMapping" "4 5"
EndSection
Section "InputDevice"
Identifier "MouseKeys0a.Naga"
Driver "evdev"
Option "Device" "/dev/input/by-id/usb-Razer_Razer_Naga-event-kbd"
EndSection
Section "InputDevice"
Identifier "MouseKeys0b.Naga"
Driver "evdev"
Option "Device" "/dev/input/by-id/usb-Razer_Razer_Naga-if01-event-kbd"
EndSection
Section "InputDevice"
Identifier "Mouse0.1"
Driver "evdev"
Option "Device" "/dev/input/by-id/usb-Logitech_USB_Receiver-event-mouse"
EndSection
Section "InputDevice"
Identifier "Mouse1.Salmosa"
Driver "evdev"
Option "GrabDevice" "true"
Option "Protocol" "auto"
Option "Device" "/dev/input/by-id/usb-Razer_Razer_Salmosa-event-mouse"
Option "Emulate3Buttons" "no"
Option "ZAxisMapping" "4 5"
EndSection
#Section "InputDevice"
# # generated from data in "/etc/sysconfig/keyboard"
# Identifier "Keyboard0"
# Driver "keyboard"
# Option "XkbLayout" "us"
# Option "XkbModel" "pc105"
#EndSection
Section "InputDevice"
Identifier "Keyboard0"
Driver "evdev"
Option "Device" "/dev/input/dell_keyboard_2003"
Option "XkbLayout" "us"
Option "XkbModel" "pc105"
EndSection
Section "InputDevice"
Identifier "Keyboard0.1"
Driver "evdev"
Option "Device" "/dev/input/by-id/usb-Logitech_USB_Receiver-event-kbd"
Option "XkbLayout" "us"
Option "XkbModel" "pc105"
EndSection
Section "InputDevice"
Identifier "Keyboard1"
Driver "evdev"
Option "Device" "/dev/input/dell_keyboard_2105"
Option "XkbLayout" "us"
Option "XkbModel" "pc105"
EndSection
Section "InputDevice"
Identifier "webcam_Button"
Driver "evdev"
Option "Device" "/dev/input/by-id/usb-046d_0809_BD4BC0AA-event-if00"
EndSection
Section "InputDevice"
Identifier "X10_Lola.keyboard"
Driver "evdev"
Option "Device" "/dev/input/x10_lola"
EndSection
Section "InputDevice"
Identifier "XmodControl.0"
Driver "evdev"
Option "Device" "/dev/input/by-path/pci-0000:00:1d.2-usb-0:1.2:1.3-event"
EndSection
Section "InputDevice"
Identifier "XmodControl.1"
Driver "evdev"
Option "Device" "/dev/input/by-path/pci-0000:00:1d.0-usb-0:1:1.3-event"
EndSection
#Section "Monitor"
# # HorizSync source: edid, VertRefresh source: edid
# Identifier "Monitor0"
# VendorName "Unknown"
# ModelName "DELL 1907FP"
# HorizSync 30.0 - 81.0
# VertRefresh 56.0 - 76.0
# Option "DPMS"
#EndSection
Section "Monitor"
# HorizSync source: edid, VertRefresh source: edid
Identifier "Monitor0"
VendorName "Unknown"
ModelName "ViewSonic VA2431 Series"
HorizSync 24.0 - 82.0
VertRefresh 50.0 - 75.0
Option "DPMS"
#Option "BlankTime" "4"
#Option "StandbyTime" "1"
#Option "SuspendTime" "1"
#Option "OffTime" "5"
EndSection
Section "Monitor"
# HorizSync source: edid, VertRefresh source: edid
Identifier "Monitor1"
VendorName "Unknown"
ModelName "DELL 1901FP"
HorizSync 30.0 - 80.0
VertRefresh 56.0 - 76.0
Option "DPMS"
Option "BlankTime" "4"
Option "StandbyTime" "1"
Option "SuspendTime" "1"
Option "OffTime" "5"
EndSection
Section "Device"
Identifier "Device0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "GeForce 8500 GT"
BusID "PCI:4:0:0"
EndSection
Section "Device"
Identifier "Device1"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "ION"
BusID "PCI:7:0:0"
EndSection
Section "Screen"
Identifier "Screen0"
Device "Device0"
Monitor "Monitor0"
DefaultDepth 24
Option "TwinView" "0"
Option "metamodes" "nvidia-auto-select +0+0"
SubSection "Display"
Depth 24
EndSubSection
EndSection
Section "Screen"
Identifier "Screen1"
Device "Device1"
Monitor "Monitor1"
DefaultDepth 24
Option "TwinView" "0"
Option "metamodes" "nvidia-auto-select +0+0"
SubSection "Display"
Depth 24
EndSubSection
EndSection
#Section "ServerFlags"
# # Even if mouse detection fails, X will start
# Option "AllowMouseOpenFail" "yes"
#
# # VT switching is disabled
# Option "DontVTSwitch" "yes"
#
# # X restart (Ctrl+Alt+Backspace) is disabled
# # For some reason, this would cause Ctrl-C to terminate X
# #Option "DontZap" "yes"
#EndSection
</textarea>
</pre>
<br />
/usr/share/config/kdm/kdmrc<br />
<pre><textarea style="height: 20em; margin: 0px; width: 100%;"># File: /usr/share/config/kdm/kdmrc
#
# KDM master configuration file
#
# Definition: the greeter is the login dialog, i.e., the part of KDM
# which the user sees.
#
# You can configure every X-display individually.
# Every display has a display name, which consists of a host name
# (which is empty for local displays specified in {Static|Reserve}Servers),
# a colon, and a display number. Additionally, a display belongs to a
# display class (which can be ignored in most cases; the control center
# does not support this feature at all).
# Sections with display-specific settings have the formal syntax
# "[X-" host [":" number [ "_" class ]] "-" sub-section "]"
# You can use the "*" wildcard for host, number, and class. You may omit
# trailing components; they are assumed to be "*" then.
# The host part may be a domain specification like ".inf.tu-dresden.de".
# It may also be "+", which means non-empty, i.e. remote displays only.
# From which section a setting is actually taken is determined by these
# rules:
# - an exact match takes precedence over a partial match (for the host part),
# which in turn takes precedence over a wildcard ("+" taking precedence
# over "*")
# - precedence decreases from left to right for equally exact matches
# Example: display name "myhost:0", class "dpy".
# [X-myhost:0_dpy] precedes
# [X-myhost:0_*] (same as [X-myhost:0]) precedes
# [X-myhost:*_dpy] precedes
# [X-myhost:*_*] (same as [X-myhost]) precedes
# [X-+:0_dpy] precedes
# [X-*:0_dpy] precedes
# [X-*:0_*] (same as [X-*:0]) precedes
# [X-*:*_*] (same as [X-*])
# These sections do NOT match this display:
# [X-hishost], [X-myhost:0_dec], [X-*:1], [X-:*]
# If a setting is not found in any matching section, the default is used.
#
# Every comment applies to the following section or key. Note that all
# comments will be lost if you change this file with the systemsettings frontend.
# The defaults refer to KDM's built-in values, not anything set in this file.
#
# Special characters need to be backslash-escaped (leading and trailing
# spaces (\s), tab (\t), linefeed (\n), carriage return (\r) and the
# backslash itself (\\)).
# In lists, fields are separated with commas without whitespace in between.
# Some command strings are subject to simplified sh-style word splitting:
# single quotes (') and double quotes (") have the usual meaning; the backslash
# quotes everything (not only special characters). Note that the backslashes
# need to be doubled because of the two levels of quoting.
[General]
# This option exists solely for the purpose of a clean automatic upgrade.
# Do not even think about changing it!
ConfigVersion=2.4
# List of permanent displays. Displays with a hostname are foreign. A display
# class may be specified separated by an underscore.
# Default is ":0"
StaticServers=:0,:1
# List of on-demand displays. See StaticServers for syntax.
# Default is ""
ReserveServers=:2,:3,:4
# VTs to allocate to X-servers. A negative number means that the VT will be
# used only if it is free. If all VTs in this list are used up, the next free
# one greater than the last one in this list will be allocated.
# Default is ""
ServerVTs=-1
# TTYs (without /dev/) to monitor for activity while in console mode.
# Default is ""
ConsoleTTYs=tty1,tty2,tty3,tty4,tty5,tty6
# Where KDM should store its PID (do not store if empty).
# Default is ""
PidFile=/var/run/kdm.pid
# Whether KDM should lock the PID file to prevent having multiple KDM
# instances running at once. Do not change unless you are brave.
# Default is true
#LockPidFile=false
# Where to store authorization files.
# Default is "/var/run/xauth"
#AuthDir=/tmp
# Whether KDM should automatically re-read configuration files, if it
# finds them having changed.
# Default is true
#AutoRescan=false
# Additional environment variables KDM should pass on to all programs it runs.
# LD_LIBRARY_PATH and XCURSOR_THEME are good candidates;
# otherwise, it should not be necessary very often.
# Default is ""
#ExportList=LD_LIBRARY_PATH,ANOTHER_IMPORTANT_VAR
# A character device KDM should read entropy from.
# Empty means use the system's preferred entropy device.
# Default is ""
#RandomDevice=/dev/altrandom
# Where the command sockets should be created; make it empty to disable
# them.
# Default is "/var/run/xdmctl"
#FifoDir=/tmp
# The group to which the global command socket should belong;
# can be either a name or a numerical ID.
# Default is 0
#FifoGroup=xdmctl
# The user the greeter should run as. Empty results in root.
# Consider the impact on LogSource when setting it.
# Default is ""
GreeterUID=kdm
# The directory in which KDM should store persistent working data.
# Default is "/var/lib/kdm"
#DataDir=
# The directory in which KDM should store users' .dmrc files. This is only
# needed if the home directories are not readable before actually logging in
# (like with AFS).
# Default is ""
#DmrcDir=/nfs-shared/var/dmrcs
[Xdmcp]
# Whether KDM should listen to incoming XDMCP requests.
# Default is true
Enable=false
# The UDP port on which KDM should listen for XDMCP requests. Do not change.
# Default is 177
#Port=177
# File with the private keys of X-terminals. Required for XDM authentication.
# Default is ""
#KeyFile=/usr/share/config/kdm/kdmkeys
# XDMCP access control file in the usual XDM-Xaccess format.
# Default is "/usr/share/config/kdm/Xaccess"
Xaccess=/usr/share/config/kdm/Xaccess
# Number of seconds to wait for display to respond after the user has
# selected a host from the chooser.
# Default is 15
#ChoiceTimeout=10
# Strip domain name from remote display names if it is equal to the local
# domain.
# Default is true
#RemoveDomainname=false
# Use the numeric IP address of the incoming connection on multihomed hosts
# instead of the host name.
# Default is false
#SourceAddress=true
# The program which is invoked to dynamically generate replies to XDMCP
# DirectQuery or BroadcastQuery requests.
# If empty, no program is invoked and "Willing to manage" is sent.
# Default is ""
Willing=/usr/share/config/kdm/Xwilling
[Shutdown]
# The command (subject to word splitting) to run to halt the system.
# Default is "/sbin/shutdown -h -P now"
HaltCmd=/sbin/poweroff
# The command (subject to word splitting) to run to reboot the system.
# Default is "/sbin/shutdown -r now"
RebootCmd=/sbin/shutdown -r now
# Whether it is allowed to shut down the system via the global command socket.
# Default is false
#AllowFifo=true
# Whether it is allowed to abort active sessions when shutting down the
# system via the global command socket.
# Default is true
#AllowFifoNow=false
# The boot manager KDM should use for offering boot options in the
# shutdown dialog.
# "None" - no boot manager
# "Grub" - Grub boot manager
# "Grub2" - Grub2 boot manager
# "Burg" - Burg boot manager
# "Lilo" - Lilo boot manager (Linux on i386 & x86-64 only)
# Default is None
#BootManager=Grub
# Rough estimations about how many seconds KDM will spend at most on
# - opening a connection to the X-server (OpenTime) if the attempt
# - times out: OpenTimeout
# - is refused: OpenRepeat * OpenDelay
# - starting a local X-server (ServerTime):
# ServerAttempts * (ServerTimeout + OpenDelay)
# - starting a display:
# - local display: ServerTime + OpenTime
# - foreign display: StartAttempts * OpenTime
# - XDMCP display: OpenTime (repeated indefinitely by client)
# Core config for all displays
[X-*-Core]
# How long to wait before retrying to connect a display.
# Default is 15
#OpenDelay=15
# How long to wait before timing out a display connection attempt.
# Default is 120
#OpenTimeout=120
# How many connection attempts to make during a start attempt. Note that
# a timeout aborts the entire start attempt.
# Default is 5
#OpenRepeat=5
# Try at most that many times to start a display. If this fails, the display
# is disabled.
# Default is 4
#StartAttempts=4
# Ping remote display every that many minutes.
# Default is 5
#PingInterval=5
# Wait for a Pong that many minutes.
# Default is 5
#PingTimeout=5
# The name of this X-server's Xauth file.
# If empty, a random name in the AuthDir directory will be used.
# Default is ""
#AuthFile=
# Specify a file with X-resources for the greeter, chooser and background.
# The KDE frontend does not use this file, so you do not need it unless you
# use another background generator than krootimage.
# Default is ""
#Resources=
# The xrdb program to use to read the above specified recources.
# Subject to word splitting.
# Default is "/usr/bin/xrdb"
#Xrdb=
# A program to run before the greeter is shown. Can be used to start an
# xconsole or an alternative background generator. Subject to word splitting.
# Default is ""
Setup=/usr/share/config/kdm/Xsetup
# A program to run before a user session starts. Subject to word splitting.
# Default is ""
Startup=/usr/share/config/kdm/Xstartup
# A program to run after a user session exits. Subject to word splitting.
# Default is ""
Reset=/usr/share/config/kdm/Xreset
# The program which is run as the user which logs in. It is supposed to
# interpret the session argument (see SessionsDirs) and start an appropriate
# session according to it. Subject to word splitting.
# Default is "/usr/bin/xterm -ls -T"
Session=/usr/share/config/kdm/Xsession
# The program to run if Session fails.
# Default is "/usr/bin/xterm"
#FailsafeClient=
# The PATH for the Session program.
# Default is "/usr/local/bin:/usr/bin:/bin:/usr/games"
#UserPath=
# The PATH for Setup, Startup and Reset, etc.
# Default is "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
#SystemPath=
# The default system shell.
# Default is "/bin/sh"
#SystemShell=/bin/bash
# Where to put the user's X-server authorization file if ~/.Xauthority
# cannot be created.
# Default is "/tmp"
#UserAuthDir=
# If true, UserAuthDir will be used unconditionally.
# Default is false
#ForceUserAuthDir=true
# Whether to automatically restart sessions after X-server crashes.
# Note that enabling this makes circumventing screen lockers other than
# KDE's built-in one possible!
# Default is false
#AutoReLogin=true
# Allow root logins?
# Default is true
AllowRootLogin=false
# Allow to log in, when user has set an empty password?
# Default is true
AllowNullPasswd=false
# Who is allowed to shut down the system. This applies both to the
# greeter and to the command sockets.
# "None" - no "Shutdown..." menu entry is shown at all
# "Root" - the root password must be entered to shut down
# "All" - everybody can shut down the machine
# Default is All
AllowShutdown=Root
# Who is allowed to abort active sessions when shutting down.
# "None" - no forced shutdown is allowed at all
# "Root" - the root password must be entered to shut down forcibly
# "All" - everybody can shut down the machine forcibly
# Default is All
#AllowSdForceNow=Root
# The default choice for the shutdown condition/timing.
# "Schedule" - shut down after all active sessions exit (possibly at once)
# "TryNow" - shut down, if no active sessions are open; otherwise, do nothing
# "ForceNow" - shut down unconditionally
# Default is Schedule
#DefaultSdMode=ForceNow
# How to offer shutdown scheduling options:
# "Never" - not at all
# "Optional" - as a button in the simple shutdown dialogs
# "Always" - instead of the simple shutdown dialogs
# Default is Never
#ScheduledSd=Optional
# The directories containing session type definitions in .desktop format,
# ordered by falling priority.
# Default is "/usr/share/apps/kdm/sessions"
SessionsDirs=/usr/share/config/kdm/sessions,/usr/share/apps/kdm/sessions
# The file (relative to $HOME) to redirect the session output to. The
# following character pairs are replaced:
# - %d -> current display
# - %u -> current user
# - %r -> empty at first. See below.
# - %% -> a single %
# When the constructed filename cannot be used safely and the specification
# contains %<stuff>r, other names will be tried - this time expanding %<stuff>r
# to <stuff> followed by a random number.
# Default is ".xsession-errors"
ClientLogFile=.xsession-errors-%d
# Fallback when ClientLogFile cannot be used. The same expansions are
# supported. DO NOT use relative paths here.
# Default is "/tmp/xerr-%u-%d%-r"
#ClientLogFallback=/var/log/xsession-errors/%u-%d%-r
# Whether KDM's built-in utmp/wtmp/lastlog registration should be used.
# Default is true
#UseSessReg=false
# Greeter config for all displays
[X-*-Greeter]
# Specify the widget style for the greeter. Empty means to use the
# built-in default which currently is "Oxygen-air".
# Default is ""
#GUIStyle=Plastique
# Specify the widget color scheme for the greeter. Empty means to use the
# built-in default which currently is "Oxygen-air".
# Default is ""
#ColorScheme=MidnightMeadow
# What should be shown in the greeter's logo are:
# "None" - nothing
# "Logo" - the image specified by LogoPixmap
# "Clock" - a neat analog clock
# Default is Clock
LogoArea=Logo
# The image to show when LogoArea=Logo.
# Default is ""
LogoPixmap=/usr/share/apps/kdm/pics/kdelogo.png
# The relative coordinates (X,Y in percent) of the center of the greeter.
# Default is "50,50"
#GreeterPos=30,40
# The screen the greeter should be displayed on in multi-headed and Xinerama
# setups. The numbering starts with 0. For Xinerama, it corresponds to the
# listing order in the active ServerLayout section of XF86Config; -1 means
# to use the upper-left screen, -2 means to use the upper-right screen.
# Default is 0
#GreeterScreen=-1
# The headline in the greeter. The following character pairs are replaced:
# - %d -> current display
# - %h -> host name, possibly with domain name
# - %n -> node name, most probably the host name without domain name
# - %s -> the operating system
# - %r -> the operating system's version
# - %m -> the machine (hardware) type
# - %% -> a single %
# Default is "Welcome to %s at %n"
GreetString=Bending Fern Glade
# Whether the fonts used in the greeter should be antialiased.
# Default is false
AntiAliasing=true
# The font for the greeter headline. The value is encoded.
# Default is "Serif 20pt bold"
GreetFont=Serif,16,-1,5,50,0,0,0,0,0
# The normal font used in the greeter. The value is encoded.
# Default is "Sans Serif 10pt"
StdFont=Sans Serif,10,-1,5,50,0,0,0,0,0
# The font used for the "Login Failed" message. The value is encoded.
# Default is "Sans Serif 10pt bold"
FailFont=Sans Serif,10,-1,5,75,0,0,0,0,0
# What to do with the Num Lock modifier for the time the greeter is running:
# "Off" - turn off
# "On" - turn on
# "Keep" - do not change the state
# Default is Keep
#NumLock=Off
# Language and locale to use in the greeter, encoded like $LANGUAGE.
# If empty, the settings from the environment are used.
# Default is ""
#Language=de_DE
# Enable autocompletion in the username line edit.
# Default is false
UserCompletion=true
# Enable user list (names along with images) in the greeter.
# Default is true
#UserList=false
# User selection for UserCompletion and UserList:
# "NotHidden" - all users except those listed in HiddenUsers
# "Selected" - only the users listed in SelectedUsers
# Default is NotHidden
#ShowUsers=Selected
# For ShowUsers=Selected. @<group> means all users in that group.
# Default is ""
#SelectedUsers=root,johndoe
# For ShowUsers=NotHidden. @<group> means all users in that group.
# Default is ""
HiddenUsers=root
# Special case of HiddenUsers: users with a non-zero UID less than this number
# will not be shown as well.
# Default is 0
MinShowUID=1000
# Complement to MinShowUID: users with a UID greater than this number will
# not be shown as well.
# Default is 65535
MaxShowUID=65000
# If false, the users are listed in the order they appear in /etc/passwd.
# If true, they are sorted alphabetically.
# Default is true
#SortUsers=false
# Specify, where the users' pictures should be taken from.
# "AdminOnly" - from <facedir>/$USER.face[.icon]
# "PreferAdmin" - prefer <facedir>, fallback on $HOME
# "PreferUser" - ... and the other way round
# "UserOnly" - from the user's $HOME/.face[.icon]
# Default is AdminOnly
FaceSource=PreferUser
# The directory containing the user images if FaceSource is not UserOnly.
# Default is "/usr/share/apps/kdm/faces"
#FaceDir=/usr/share/faces
# Specify, if/which user should be preselected for log in.
# "None" - do not preselect any user
# "Previous" - the user which successfully logged in last time
# "Default" - the user specified in the DefaultUser option
# Default is None
#PreselectUser=Previous
# If this is true, the password input line is focused automatically if
# a user is preselected.
# Default is false
FocusPasswd=true
# If this is true, the entered password is echoed as bullets. Otherwise,
# no feedback is given at all.
# Default is true
#EchoPasswd=false
# If true, krootimage will be automatically started by KDM; otherwise, the
# Setup script should be used to setup the background.
# Default is true
#UseBackground=false
# The configuration file to be used by krootimage.
# Default is "/usr/share/config/kdm/backgroundrc"
BackgroundCfg=/usr/share/config/kdm/backgroundrc
# Whether to grab keyboard and mouse while the greeter is visible. Grabs
# may improve security, but make on-screen keyboards, etc. unusable.
# "Never" - never grab
# "IfNoAuth" - grab if the display requires no X authorization
# "Always" - always grab
# Default is IfNoAuth
#GrabInput=Always
# Hold the X-server grabbed the whole time the greeter is visible. This
# may be more secure, but it will disable any background and other
# X-clients started from the Setup script.
# Default is false
#GrabServer=true
# How many seconds to wait for grab to succeed.
# Default is 3
#GrabTimeout=3
# Warn, if display has no X-authorization (local auth cannot be created,
# XDMCP display wants no auth, or display is foreign from StaticServers).
# Default is true
#AuthComplain=false
# Random seed for forging saved session types, etc. of unknown users.
# This value should be random but constant across the login domain.
# Default is 0
ForgingSeed=1386325123
# Specify conversation plugins for the login dialog. Each plugin can be
# specified as a base name (which expands to $kde_modulesdir/kgreet_$base)
# or as a full pathname.
# Default is "classic"
#PluginsLogin=sign
# Same as PluginsLogin, but for the shutdown dialog.
# Default is "classic"
#PluginsShutdown=modern
# A list of options of the form Key=Value. The conversation plugins can query
# these settings; it is up to them what possible keys are.
# Default is ""
#PluginOptions=SomeKey=randomvalue,Foo=bar
# Show the "Console Login" action in the greeter (if ServerTTY/ConsoleTTYs
# is configured).
# Default is true
#AllowConsole=false
# A program to run while the greeter is visible. It is supposed to preload
# as much as possible of the session that is going to be started (most
# probably).
# Default is ""
Preloader=/usr/bin/preloadkde
# Whether the greeter should be themed.
# Default is false
UseTheme=true
# The theme to use for the greeter. Can point to either a directory or an XML
# file.
# Default is ""
Theme=/usr/share/apps/kdm/themes/elarun
# Enable the Alt-Ctrl-D shortcut to toggle greeter theme debugging.
# Default is false
#AllowThemeDebug=true
# Core config for local displays
[X-:*-Core]
# How often to try to run the X-server. Running includes executing it and
# waiting for it to come up.
# Default is 1
#ServerAttempts=1
# How long to wait for a local X-server to come up.
# Default is 30
#ServerTimeout=30
# The command line to start the X-server, without display number and VT spec.
# This string is subject to word splitting.
# Default is "/usr/bin/X"
ServerCmd=/usr/bin/X -br -novtswitch -quiet
# Additional arguments for the X-servers for local sessions.
# This string is subject to word splitting.
# Default is ""
ServerArgsLocal=-background none -nolisten tcp
# Additional arguments for the X-servers for remote sessions.
# This string is subject to word splitting.
# Default is ""
#ServerArgsRemote=
# The user the X-server should run as. Empty results in root.
# Default is ""
#ServerUID=_x11
# Restart instead of resetting the local X-server after session exit.
# Use it if the server leaks memory etc.
# Default is true
#TerminateServer=false
# Create X-authorizations for local displays.
# Default is true
#Authorize=false
# Which X-authorization mechanisms should be used.
# Default is "MIT-MAGIC-COOKIE-1"
#AuthNames=
# Need to reset the X-server to make it read initial Xauth file.
# Default is false
#ResetForAuth=true
# See above
AllowNullPasswd=false
# See above
AllowShutdown=All
# Enable password-less logins on this display. USE WITH EXTREME CARE!
# Default is false
#NoPassEnable=true
# The users that do not need to provide a password to log in. NEVER list root!
# "*" means all non-root users. @<group> means all users in that group.
# Default is ""
#NoPassUsers=fred,ethel
# Greeter config for local displays
[X-:*-Greeter]
# See above
PreselectUser=Previous
# See above
FocusPasswd=true
# Specify whether the greeter of local displays should start up in host chooser
# (remote) or login (local) mode and whether it is allowed to switch to the
# other mode.
# "LocalOnly" - only local login possible
# "DefaultLocal" - start up in local mode, but allow switching to remote mode
# "DefaultRemote" - ... and the other way round
# "RemoteOnly" - only choice of remote host possible
# Default is LocalOnly
LoginMode=DefaultLocal
# A list of hosts to be automatically added to the remote login menu. The
# special name "*" means broadcast.
# Default is "*"
#ChooserHosts=*,host1,host2,host3.local,login.domain.com
# Show the "Restart X Server"/"Close Connection" action in the greeter.
# Default is true
AllowClose=false
# Core config for 1st local display
[X-:0-Core]
# The VT the X-server should run on; auto-assign if zero, don't assign if -1.
# Better leave it zero and use ServerVTs.
# Default is 0
ServerVT=7
# Enable automatic login. USE WITH EXTREME CARE!
# Default is false
#AutoLoginEnable=true
# If true, auto-login after logout. If false, auto-login is performed only
# when a display session starts up.
# Default is false
#AutoLoginAgain=true
# The delay in seconds before automatic login kicks in.
# Default is 0
#AutoLoginDelay=10
# The user to log in automatically. NEVER specify root!
# Default is ""
#AutoLoginUser=fred
# The password for the user to log in automatically. This is NOT required
# unless the user is logged into a NIS or Kerberos domain. If you use this
# option, you should "chmod 600 kdmrc" for obvious reasons.
# Default is ""
#AutoLoginPass=secret!
# Immediately lock the automatically started session. This works only with
# KDE sessions.
# Default is false
#AutoLoginLocked=true
# See above
ClientLogFile=.xsession-errors
# See above
ServerArgsLocal=-nolisten tcp -novtswitch -keeptty -config xorg.conf -layout Seat0
# Greeter config for 1st local display
[X-:0-Greeter]
# See above
PreselectUser=Default
# The user to preselect if PreselectUser=Default.
# Default is ""
DefaultUser=user1
# See above
BackgroundCfg=/usr/share/config/kdm/backgroundrc.seat0
# See above
FocusPasswd=true
# See above
GreeterPos=0,100
# See above
LoginMode=DefaultLocal
# See above
LogoArea=None
# See above
UserCompletion=false
# See above
UserList=false
# See above
Preloader=/usr/bin/preloadkde
[X-:1-Greeter]
# See above
BackgroundCfg=/usr/share/config/kdm/backgroundrc.seat1
# See above
DefaultUser=user2
# See above
FocusPasswd=true
# See above
GreeterPos=100,100
# See above
LoginMode=DefaultLocal
# See above
LogoArea=None
# See above
PreselectUser=Default
# See above
UserCompletion=false
# See above
UserList=false
[X-:1-Core]
# See above
AutoLoginEnable=false
# See above
AutoLoginLocked=false
# See above
AutoLoginUser=
# See above
ServerArgsLocal=-nolisten tcp -sharevts -keeptty -config xorg.conf -layout Seat1
# See above
ServerVT=9
</textarea>
</pre>
<br />
/usr/share/config/kdm/backgroundrc.seat0<br />
<pre><textarea style="height: 20em; margin: 0px; width: 100%;"># File: /usr/share/config/kdm/backgroundrc.seat0
[Desktop0]
BackgroundMode=Flat
BlendBalance=100
BlendMode=NoBlending
ChangeInterval=60
Color1=0,0,200
Color2=192,192,0
CurrentWallpaper=/usr/share/config/kdm/20100519-190000.jpg
LastChange=0
MinOptimizationDepth=1
MultiWallpaperMode=NoMulti
Pattern=fish
Program=
ReverseBlending=false
UseSHM=false
Wallpaper=/usr/share/config/kdm/20100519-190000.jpg
WallpaperMode=ScaleAndCrop
</textarea>
</pre>
<br />
/usr/share/config/kdm/backgroundrc.seat1<br />
<pre><textarea style="height: 20em; margin: 0px; width: 100%;"># File: /usr/share/config/kdm/backgroundrc.seat1
[Desktop0]
BackgroundMode=Flat
BlendBalance=100
BlendMode=NoBlending
ChangeInterval=60
Color1=0,0,200
Color2=192,192,192
CurrentWallpaper=/usr/share/config/kdm/20100519-185835.jpg
LastChange=0
MinOptimizationDepth=1
MultiWallpaperMode=NoMulti
Pattern=fish
Program=
ReverseBlending=false
UseSHM=false
Wallpaper=/usr/share/config/kdm/20100519-185835.jpg
WallpaperMode=ScaleAndCrop
</textarea>
</pre>
<br />
/etc/udev/rules.d/90-creative-xmod.rules<br />
<pre><textarea style="height: 20em; margin: 0px; width: 100%;"># File: /etc/udev/rules.d/90-creative-xmod.rules
# udev rules to disginguish the two Creative usb sound cards that plug into the usb hub
#DEVPATH=="/devices/pci0000:00/0000:00:1d.7/usb1/1-6/1-6.7/1-6.7.1*", GOTO="CreativeXmodLEFT"
#DEVPATH=="/devices/pci0000:00/0000:00:1d.7/usb1/1-6/1-6.4*", GOTO="CreativeXmodRIGHT"
DEVPATH=="/devices/pci0000:00/0000:00:1d.7/usb*/*-6/*-6.7/*-6.7.1*", GOTO="CreativeXmodLEFT"
DEVPATH=="/devices/pci0000:00/0000:00:1d.7/usb*/*-6/*-6.4*", GOTO="CreativeXmodRIGHT"
GOTO="CreativeXmodEnd"
##### LEFT SEAT
LABEL="CreativeXmodLEFT"
ENV{ID_MODEL}="Creative_Xmod_LeftSeat", ENV{ID_MODEL_ENC}="Creative\x20Xmod\x20LeftSeat", ENV{ID_SERIAL}="Creative_Technology_Ltd_Creative_Xmod_LeftSeat", ENV{NAME}="Creative Xmod leftSeat"
SYMLINK=="input/by-path/pci-0000:00:1d.7-usb-0:6.7.1:1.3-event", SYMLINK+="input/by-id/CreativeXmod-Button-LeftSeat"
SYMLINK=="snd/by-path/pci-0000:00:1d.7-usb-0:6.7.1:1.0", SYMLINK+="snd/by-id/usb-Creative_Technology_Ltd_Creative_Xmod-LeftSeat"
#ENV{ID_MODEL}="Creative_Xmod", SYMLINK+="snd/by-id/usb-Creative_Technology_Ltd_Creative_Xmod-LeftSeat"
GOTO="CreativeXmodEnd"
### END LEFT ###
# RIGHT SEAT
LABEL="CreativeXmodRIGHT"
ENV{ID_MODEL}="Creative_Xmod_RightSeat", ENV{ID_MODEL_ENC}="Creative\x20Xmod\x20RightSeat", ENV{ID_SERIAL}="Creative_Technology_Ltd_Creative_Xmod_RightSeat", NAME="Creative Xmod RightSeat"
SYMLINK=="input/by-path/pci-0000:00:1d.7-usb-0:6.4:1.3-event", SYMLINK+="input/by-id/CreativeXmod-Button-RightSeat"
SYMLINK=="snd/by-path/pci-0000:00:1d.7-usb-0:6.4:1.0", SYMLINK+="snd/by-id/usb-Creative_Technology_Ltd_Creative_Xmod-RightSeat"
### END RIGHT ###
### common ened
LABEL="CreativeXmodEnd"
</textarea>
</pre>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-1434486458228483352015-03-06T00:43:00.001-05:002018-01-31T01:42:21.124-05:00憶老方(My high school homeroom teacher passed away, and this is my tribute and eulogy to him. There's no English translation.)<br />
<br />
憶老方<br />
<br />
老方是我師大附中三年的導師。年初他病逝,我們694班同學在臉書上私人社團裡,紛紛表達對他的懷念。我人在遠方,無法親自參加公祭,託同學把我對他的懷念和感謝帶上。<br />
<br />
在那個時代,給老師取綽號算是不敬。老方知道我們在背後這麼叫他,卻一笑置之。回想起來,「老方」的暱稱,和益師益友的他其實很相襯。<br />
<br />
老方教數學,扎實的數學底子,讓我一生受益無窮。但我特別欣賞的,是他在課堂上不做作的態度。有時候他導公式寫了滿黑板,最後發現結果不對,他會請同學幫忙一起看,然後發現之前錯了一步時,他會拍頭一笑,回過重來。這種和學生一起探索的態度,和我與國外博士班指導教授討論想法,竟有異曲同工之妙。後來在工作上,我也用一樣的態度來帶新進的人員。我帶出來的人,特別有實驗精神,敢於表達意見,也讓我的團隊贏得最有創意的名聲。<br />
<br />
老方對同學們一視同仁,但我個人有個印象深刻的小故事。<br />
<br />
社團是附中特色之一。學生們在社團裡學習經營,發揮創意,結交朋友。但不少社團幹部會因此而影響學業,所以如果成績太離譜,學校會發一張「紅單子」,讓學業成績太離譜的學生不得再擔任幹部。有趣的是,在社聯會(所有社團幹部的聯誼會)裡,「拿紅單子」有時候反而被視為努力經營社團的光榮象徵。<br />
<br />
高二時我擔任社團社長,把大部分心力都用在社團經營上,成績一度跌落谷底。有一天,老方把我叫到他辦公室;我當然知道他要說什麼,但我覺得反正他不可能了解社團人的執著,準備好硬著頭皮聽訓,聽完就算了。<br />
<br />
進到他辦公室,他看著我笑了笑,問我知不知道他為什麼叫我來。我點了點頭。沒想到他說,「那就好。沒其他事了。」<br />
<br />
霎時間,所有我事前的心戰策略全無用武之地。他輕輕一點,讓簡單的真理乍現:你成績怎樣是你的事,你知道自己在幹什麼就好。<br />
<br />
雖然這好像是廢話,但我之前在一個逼讀文化(不管是當面逼,還是用制度逼)下成長學習,這是第一次看到師長直接移步側站,讓我自己去面對問題、抉擇及後果。<br />
<br />
老方那句話,是我這輩子最後一次讓別人來擔心我的學業。<br />
<br />
傳道,授業,解惑,老方也。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-51237426464107758072015-02-21T01:24:00.003-05:002015-02-21T02:24:28.844-05:00Sage Math Live CD for VirtualBox<a href="http://www.sagemath.org/" target="_blank">Sage Math</a> consists of many mathematical and scientific tools and therefore the library dependencies can be quite hairy. Live CD makes it easier to do some quick and dirty job. However, booting into a live CD is quite inconvenient as far as data transportation goes, so I was trying to use VirtualBox to run a server and connect to it from the host computer.<br />
<br />
There's a slight problem though. The <a href="http://www.sagemath.org/download-livecd.html" target="_blank">Live CD image listed on the official download page</a> is actually a raw image to write into a USB thumb drive. VirtualBox does not support mounting a image as a USB drive. Therefore, we need to convert the bootable USB thumb drive image to another format. I converted it to a hard drive image for more flexibility.<br />
<br />
Here's how (I found it in <a href="http://www.macfreek.nl/memory/Mounting_a_USB_stick_with_VirtualBox" target="_blank">this guide</a>):<br />
<br />
<pre style="border: 1px dashed rgb(47, 111, 171); font-family: monospace, 'Courier New'; font-size: 12.8000001907349px; line-height: 1.3em; padding: 1em;">$ VBoxManage convertfromraw -format VDI 2014-11-16-sage_6.4-debian_wheezy-live_3.0.5-1.img 2014-11-16-sage_6.4-debian_wheezy-live_3.0.5-1.vdi
</pre>
<br />
By the way, <span style="font-family: Courier New, Courier, monospace;">2014-11-16-sage_6.4-debian_wheezy-live_3.0.5-1.img</span> is a 64-bit Debian image, which needs to be configured properly in VirtualBox.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-7838145302994078052014-11-27T22:00:00.000-05:002017-01-01T22:36:19.084-05:00Use 802.11n on Asus RT-N16 with OpenWrt(If you come from OpenWrt's <a href="http://wiki.openwrt.org/toh/asus/rt-n16?&#other_info" target="_blank">official wiki</a>, skip forward to the section "802.11n" for your answer.)<br />
<h2>Overview</h2><div>It took me a while to figure out how to setup 802.11n in OpenWrt on Asus RT-N16 so I figured I'd share the process, hopefully to save somebody's time.</div><h2>Background</h2>I've used <a href="http://www.dd-wrt.com/">dd-wrt</a> for a long time (on 4 wireless routers over the years). However, my network setup is getting more and more complex. While dd-wrt allows some customization, the inconsistency between GUI and the command-line configuration made it very hard for me to maintain. For example, editing the DHCP static address table from the GUI is a tedious process because it doesn't sort so it's very hard to detect duplication. I could edit the configuration file directly but the GUI does not reflect my changes correctly. Saving from the GUI can easily overwrite my manually edited config files.<br />
<h2>Choosing Alternatives</h2>Therefore, I started to look for an alternative. Besides dd-wrt, <a href="http://tomatousb.org/mods" target="_blank">Tomato and it's family</a>, and <a href="https://openwrt.org/" target="_blank">OpenWrt</a> are the other two high-profile router firmware development efforts. And both lineages provide very customizable environment.<br />
<br />
However, there are two things I'm looking for.<br />
<br />
1. I am looking for a project that's still actively maintained, especially after <a href="http://en.wikipedia.org/wiki/Heartbleed" target="_blank">Heart Bleed</a>, <a href="http://en.wikipedia.org/wiki/Shellshock_(software_bug)" target="_blank">Shell Shock</a>, and <a href="http://en.wikipedia.org/wiki/POODLE" target="_blank">Poodle</a>. (Note that these vulnerabilities don't necessarily compromise home routers, but in my environment, I'd rather not take the chance.) While a repository system allows individual package upgrade, I want the base developers to still be around.<br />
<br />
2. I'm looking for a project that's owned by a team rather than individuals. In the WRT history, there have been many brilliant individuals that made crucial advances for everyone. However, it has happened a few times when these individuals moved on, their projects died, too.<br />
<br />
Therefore, I ended up choosing OpenWrt.<br />
<h2>Installation</h2>It was quite straightforward to switch to OpenWrt from dd-wrt, as instructed in <a href="http://wiki.openwrt.org/toh/asus/rt-n16" target="_blank">the official guide</a>.<br />
<br />
Securing the admin access was obvious. However, it took me a while to realize that I also needed to reboot my Cable Modem for it to reset its DHCP. If you are also doing this, I suggest you open all installation guides in the browser first before you flash your new firmware. I had to use my phone to check the guides before my internet was up.<br />
<h2>802.11n</h2>This took me a while because <a href="http://wiki.openwrt.org/doc/hardware/soc/soc.broadcom.bcm47xx" target="_blank">the guide</a> is not very obvious. Anyway, after some trials and errors, broadcom-wl was the only one that worked for me (thanks to <a href="http://blog.tklee.org/2014/11/use-80211n-on-asus-rt-n16-with-openwrt.html?showComment=1427714521475#c836489691175741641" target="_blank">Stratos</a> about the dependency nas. I already had that so I didn't realize that dependency).<br />
<br />
<br />
<ol><li><span style="font-family: Courier New, Courier, monospace;"># opkg update</span></li>
<li><span style="font-family: Courier New, Courier, monospace;"># opkg install kmod-brcm-wl wl wlc</span></li>
<li><span style="font-family: Courier New, Courier, monospace;"># rm /etc/config/wireless</span></li>
<li><span style="font-family: Courier New, Courier, monospace;"># opkg install nas</span></li>
<li><span style="font-family: Courier New, Courier, monospace;"># reboot</span></li>
</ol><div>Then login to shell again to edit /etc/config/wireless . This is mine.</div><div><br />
</div><div><blockquote class="tr_bq"><span style="font-family: Courier New, Courier, monospace;">config wifi-device wl0<br />
option type broadcom<br />
option channel 1<br />
option txantenna 3<br />
option rxantenna 3<br />
option txpower '20'<br />
option plcphdr 'auto'<br />
option frameburst 1<br />
option disabled 0<br />
config wifi-iface<br />
option device wl0<br />
option network lan<br />
option mode ap<br />
option ssid YOUR_SSID<br />
option key YOUR_KEY<br />
option wmm 1<br />
option encryption 'psk2'<br />
option disabled '0'</span></blockquote><div>I added <span style="font-family: Courier New, Courier, monospace;">plcphdr</span> and <span style="font-family: 'Courier New', Courier, monospace;">frameburst</span> after reading <a href="http://www.linksysinfo.org/index.php?threads/my-asus-rt-n16-wireless-transmission-speed-useless.37412/" target="_blank">this discussion thread</a>.</div></div><div><br />
Another strange thing to work around is that after reboot, while a client can connect to the router with 802.11n, the DHCP failed to issue IPs. I had to turn the wifi off and on for it to work properly.</div><div><div><blockquote class="tr_bq"><span style="font-family: Courier New, Courier, monospace;"><br class="Apple-interchange-newline" /># wifi down<br />
# wifi up</span></blockquote>I did not spend time debugging. Instead, as a temporary workaround, I added that to /etc/rc.local, which now looks like this:</div><br />
<blockquote class="tr_bq"><pre><span style="font-family: Courier New, Courier, monospace;"># Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.
# workaround for Broadcom proprietary driver problem
/sbin/wifi down
/bin/sleep 1
/sbin/wifi up
exit 0</span>
</pre></blockquote><br />
</div>Update: <a href="http://blog.tklee.org/2014/11/use-80211n-on-asus-rt-n16-with-openwrt.html?showComment=1435297044681#c261516243541448667" rel="nofollow" target="_blank">badineu in the comment</a> mentioned that he also needed to manually select the wifi frequency. You may also have to do so if, for some reason, it's not already properly set.<br />
<br />
Unknownnoreply@blogger.com22tag:blogger.com,1999:blog-481096069064374725.post-91324555504395497782014-10-12T00:38:00.000-04:002014-10-12T03:47:39.620-04:00Arduino IDE 1.5.8 on Banana PiI use Arch Linux on Banana Pi. In my <a href="http://blog.tklee.org/2014/10/control-arduino-ide-158-with-command.html">previous post</a>, I used a workaround to compile Arduino code on an x86_64 platform and then copy the *.hex file to upload to Arduino from Banana Pi. While i7-4770 is very fast, it's also very power hungry. I dug a little bit and managed to get Arduino IDE 1.5.8 running on my Banana Pi.<br />
<br />
If you want to install Arduino 1.0.5-1, Arch Assualt Repo has an <a href="https://archassault.org/packages/archassault/armv7h/arduino/">almost working version</a>. To make it work, you'll need to install java-rxtx, and replace /usr/share/arduino/lib/librxtxSerial.so with a symlink to /usr/lib/librxtxSerial.so , and also RXTXcomm.jar -> /usr/share/java/rxtx/RXTXcomm.jar<br />
<br />
Now, this is how I got version 1.5.8 working (thanks to <a href="http://forum.arduino.cc/index.php?topic=190163.0">this post</a> for a pointer):<br />
<br />
Use the following PKGBULID (modified from <a href="https://aur.archlinux.org/packages/arduino-beta/">its AUR</a> for x86 and x86_64) to build and install a package:<br />
<br />
<pre><blockquote># Maintainer: Lauri Hakko <lauri dot hakko at gmail dot com>
# Contributor: PyroPeter <googlemail.com@abi1789>
# Contributor: darkapex <me@jailuthra.in>
pkgname=arduino-beta
epoch=1
pkgver=1.5.8
pkgrel=1
pkgdesc="Arduino SDK Beta release"
arch=('armv7h')
url="http://arduino.cc/en/Main/Software"
options=(!strip)
license=('GPL')
depends=('avr-libc' 'libusb-compat' 'java-runtime')
install="arduino.install"
conflicts=('arduino' 'arduino-toolchain')
provides=('arduino')
source=("http://downloads.arduino.cc/arduino-${pkgver//_/-}-linux32.tgz"
'arduino'
'arduino.png'
'arduino.desktop')
md5sums=('289b1e3ad64f29db3ed13b06880dce40'
'5e385c8cba80ca1b4227b162e4cad5cd'
'9e36d33891d5e68d38ec55d1494499a5'
'eebc4d6495864bea99ad057af801afb9')
package() {
cd "$srcdir/arduino-${pkgver//_/-}"
# arduino excutable should accept arguments
sed -i 's/^java .* processing.app.Base$/\0 "$*"/' arduino
mkdir -p "$pkgdir"/usr/{bin,share/{doc,applications,pixmaps}}
# copy the whole SDK to /usr/share/arduino/
cp -r . "$pkgdir/usr/share/arduino"
# at least support the FHS a little bit:
install -m755 "$srcdir/arduino" "$pkgdir/usr/bin/arduino"
ln -s /usr/share/arduino/reference "$pkgdir/usr/share/doc/arduino"
# desktop icon
install -m644 "$srcdir/arduino.desktop" "$pkgdir/usr/share/applications/"
install -m644 "$srcdir/arduino.png" "$pkgdir/usr/share/pixmaps/"
}
</blockquote></pre><br />
This version won't run because /usr/share/arduino/hardware/tools/* are compiled for x86. We need those files compiled for Arm7. Let's remove /usr/share/arduino/hardware/tools now.<br />
<br />
Download a pre-compiled version 1.5.4 by UDOO folks (big thanks for their efforts!). Go to their <a href="http://www.udoo.org/downloads">download page</a>, click on Driver & Tools, and click on <a href="http://udoo.org/download/files/arduino-1.5.4-for_UDOO.tar.gz">Arduino IDE for UDOO</a>. Unpack the archive. We only need arduino/hardware/tools . Move it to /usr/share/arduino/hardware/tools<br />
<br />
Since 1.5.8 above expects avr tools in /usr/share/arduino/hardware/tools/avr, and Arch installs it separately, so we need to make another two symlinks.<br />
<br />
$ ln -s /usr/bin /usr/share/arduino/hardware/tools/avr/<br />
$ ln -s /etc /usr/share/arduino/hardware/tools/avr/<br />
<br />
There's one more file we need to replace: arduino/lib/libastylej.so . I just installed astyle from archlinuxarm.org and do a symlink libastylej.so -> /usr/lib/libastyle.so<br />
<br />
That's it.<br />
<br />
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-481096069064374725.post-56556493668410062072014-10-10T20:13:00.000-04:002014-10-12T03:39:41.956-04:00Control Arduino IDE 1.5.8 with command lineMy workbench for Arduino development does not have enough space for a high power PC so I use lower power Arm devices (<a href="http://www.raspberrypi.org/">Raspberry Pi</a>, <a href="http://www.bananapi.org/">Banana Pi</a>, and <a href="http://www.dragino.com/products/yunshield/item/86-yun-shield.html">Yun Shield</a>) instead. However, Arduino IDE 1.5.x is not well supported yet (Raspbery Pi has a working version but not the other two, which I prefer. UPDATE: I <a href="http://blog.tklee.org/2014/10/arduino-ide-158-on-banana-pi.html">figured it out</a>.), and several Makefile solutions are still buggy against 1.5.x's libraries.<br />
<br />
My temporary solution is to outsource the compiling to the more powerful machine (my i7-4770 running Arch 64 finishes compilation almost instantly, as opposed to 40 seconds on Raspberry Pi), and grab the compiled *.hex file back to these Arm devices to upload to Arduino via the USB serial connection.<br />
<br />
As of October 4, 2014, Arduino IDE 1.5.8 has a buggy command line parameter passing, so I cannot compile the code remotely without doing a remote X session, and I want to avoid having to run an X server on these Arm devices (although Banana Pi actually runs X quite well). Therefore, I use the following hack to trigger the compiling via the command line.<br />
<br />
<blockquote>$ DISPLAY=:0 xdotool search --name "Arduino 1.5.8" windowactivate --sync windowfocus mousemove --window %1 10 30 click 1</blockquote><br />
<i>xdotool</i> searches for a window whose title contains "Arduino 1.5.8", activates the virtual desktop it's on, focuses on the window, moves the mouse cursor to coordinates (10,30) relative to the application window (where the "Verify/Compile" button is) and then clickes on it to trigger the compilation.<br />
<br />
For some reason sending ctrl+r doesn't work for me. If anyone knows why, I'd love to know.<br />
<br />
<blockquote>$ # this doesn't work<br />
$ DISPLAY=:0 xdotool search --name "Arduino 1.5.8" windowactivate --sync windowfocus key ctrl+r<br />
</blockquote>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-1048516614790797222013-09-11T23:51:00.003-04:002013-09-11T23:51:59.728-04:00Some trivia for search enginesFor those who have the need to search for these answers. :)<br />
<br />
The first ruler of England was "Egbert", King of Wessex. (See World History, Historical Figures).<br />
<br />
The "Mayflower" Compact was America's first written constitution. (See U.S. History).<br />
<br />
Francis Lightfoot Lee, one of the original signers of the Declaration of Independence, was a "farmer" by trade. (See U.S. History, Signers of the Declaration).<br />
<br />
James Monroe, 5th President of The United States, was the son of "Spence" Monroe and Eliza Jones. (See Presidents' Biographies).<br />
<br />
"glansnost" is another word for openness or candor. (See Language, Foreign Words).<br />
<br />
A "bug" is a mistake that occurs in a program within a computer. (See Language, Computerese).<br />
<br />
Sandy Koufax won the Cy Young Award "3" times. (See Sports, Baseball).<br />
<br />
"Mach" is a word used to describe supersonic speed. (See Weights, Measures and Numbers, Breaking the Sound Barrier).<br />
<br />
According to the National Film Registry, the film Casablanca was released in the year "1942". (See Arts and Media - Movies, National Film Registry).<br />
<br />
Cary Grant's original first name was "Archibald". (See Noted Personalities, Original Names).<br />
<br />
What famous boxer hails from the Bluegrass State? "Muhammad Ali". (See States of the Union, Kentucky).<br />
<br />
Peggy Fleming won the Olympic gold medal in women's singles figure skating in "1968". (See Sports, Winter Olympics).<br />
<br />
More wheat and rice is grown in "China" than any other country in the world. (See Agriculture).<br />
<br />
William "Tyler" Page, Clerk of the U.S. House of Representatives, wrote "The American's Creed." (See Great Seal, American's Creed).<br />
<br />
Clint Eastwood was born in "San Francisco", California. (See Noted Personalities, Entertainers).<br />
<br />
In the year 1540, Spanish explorer Hernando Alarcon discovered the "Colorado" River. (See World Exploration and Geography, Early Explorers of the Western Hemisphere).<br />
<br />
"Batman" was the top grossing movie of 1989. (See Arts and Media - Plays; Movies, All Time Top 50 American Movies, 1989).<br />
<br />
Elzie C. Segar was the creator of the cartoon "Popeye". (See Noted Personalities, Cartoonists)<br />
<div>
<br /></div>
Unknownnoreply@blogger.com7tag:blogger.com,1999:blog-481096069064374725.post-1924321269071076762012-11-30T18:11:00.003-05:002012-11-30T18:18:01.751-05:00Thinn Ooh Ooh (Darkening Sky) for Viola Ensemble 天黑黑 (中提琴合奏) I was commissioned by Tim Deighton early this year to write this piece for his viola ensemble.<br />
<br />
這是我今年初受中提琴家 Tim Deighton 委托的作品。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/lC9R-I7Adts?feature=player_embedded' frameborder='0'></iframe></div>
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-47683269505751589222012-11-19T03:22:00.001-05:002012-11-19T04:59:38.834-05:00Segmentation of Bopomofo SymbolsA friend of mine is working on a project in which he needs to display <a href="http://en.wikipedia.org/wiki/Bopomofo" target="_blank">Bopomofo</a> (Chinese phonetic symbols used in Taiwan). He decided to display, in his program, each syllable as one unit that consists of vertically stacked phonetic symbol. To generate those well positioned symbols, he used MS Word to type all syllables he needs, captured the screenshot as images, and asked me to segment them. He gave me 26 files in total. Each files has several lines of something like this:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9j6Bh62AFoGriUCvFG3PcUMFlDcKgfX8tWU8AL318w_-0zW0eK2mGxHn0NZAFA3YK4FdMj7A6PFPo40PPUfS4FLqAL7LTCfKA3ZT4OC-vAf2sYBUYWnw9hEoljx0lc_BPZghcfv1380k/s1600/source.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="44" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9j6Bh62AFoGriUCvFG3PcUMFlDcKgfX8tWU8AL318w_-0zW0eK2mGxHn0NZAFA3YK4FdMj7A6PFPo40PPUfS4FLqAL7LTCfKA3ZT4OC-vAf2sYBUYWnw9hEoljx0lc_BPZghcfv1380k/s320/source.png" width="320" /></a></div><br />
<a name='more'></a>Segmentation is a standard OCR procedure. I found a <a href="http://www.mathworks.com/matlabcentral/fileexchange/31322-optical-character-recognitionlower-case-and-space-included" target="_blank">MATLAB script written by Ankit Saroch</a>. His script detects a horizontal empty line to determine the line break, and then a vertical empty row to determine letter boundaries. While this works for English letters, segmenting Bopomofo turned out to be a bit more complicated, because of the spacing between each symbol:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzypCoeBjY3H6GHzeU-Sy77zCKiwXzxoiNTGfti2tCn7aSSHvAlVd_tzqB9A2Ifv8qkKHJMKhLONhHp6SdeAPDPNo40FW2ShpoE_ZbXZQ_9h5bdpt-U5CznSoJI89Sq9JpAkRfaXJJek0/s1600/problem.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="42" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzypCoeBjY3H6GHzeU-Sy77zCKiwXzxoiNTGfti2tCn7aSSHvAlVd_tzqB9A2Ifv8qkKHJMKhLONhHp6SdeAPDPNo40FW2ShpoE_ZbXZQ_9h5bdpt-U5CznSoJI89Sq9JpAkRfaXJJek0/s320/problem.png" width="320" /></a></div>The red line shows the horizontal empty line, incorrectly marking a line break. Actually, the <a href="http://en.wikipedia.org/wiki/Bopomofo#Tonal_marks" target="_blank">tone marks</a> on the right also causes some boundary problem (not shown).<br />
<br />
The solution is simple. We need to use bigger empty regions to detect boundaries.<br />
<br />
The following is the modified source code (from Ankit Saroch's original script) that I ran in <a href="http://en.wikipedia.org/wiki/GNU_Octave">Octave</a>, which is compatible with MATLAB (note that I didn't need some functions Ankit origially used in MATLAB which are not available in standard Octave packages). The main program is segmentation.m, which reads in the source image, calls line_crop and letter_crop to crop each syllable (i.e. the vertically stacked symbols). max_space is the defined number of consecutive empty lines to form the line/syllable boundary. I also included a modified function clip.m that was useful to leave arbitrary width/height of the boundaries. Some debug/experimentation comments can also be found.<br />
<style>.matlabCode {font-size: 10px; line-height: 90%; overflow: auto;}</style><br />
<pre class="brush: matlab; toolbar: true; collapse: true; tab-size: 2; class-name: 'matlabCode'; stripBrs: true;">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% line_crop.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [fl re]=lines_crop(im_texto)
% Divide text in lines
% im_texto->input image; fl->first line; re->remain line
im_texto=clip(im_texto);
max_space = 5;
num_filas=size(im_texto,1);
for s=1:num_filas
if sum(im_texto(s,:))==0
if (s+max_space < num_filas) && (sum(im_texto(s+max_space,:)) == 0)
nm=im_texto(1:s-1+max_space, :); % First line matrix
%pause(1);
rm=im_texto(s+max_space:end, :);% Remain line matrix
%pause(1);
fl = clip(nm);
%pause(1);
re=clip(rm);
%*-*-*Uncomment lines below to see the result*-*-*-*-
%subplot(2,1,1);imshow(fl);
%subplot(2,1,2);imshow(re);
break
endif
else
fl=im_texto;%Only one line.
re=[ ];
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% letter_crop.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [fl re space]=letter_crop(im_texto)
% Divide letters in lines
im_texto=clip(im_texto);
num_filas=size(im_texto,2);
max_space = 5;
for s=1:num_filas
s;
if sum(im_texto(:,s)) == 0
if (s+max_space < num_filas) && (sum(im_texto(:,s+max_space)) == 0)
k = 'true';
nm=im_texto(:,1:s-1+max_space); % First letter matrix
%figure,imshow(nm);
%title('first letter in the function letter_in_a_line');
%pause(1);
rm=im_texto(:,s+max_space:end);% Remaining line matrix
%figure,imshow(rm);
%title('remaining letters in the function letter_in_a_line');
%pause(1);
fl = clip(nm);
%pause(1);
re=clip(rm);
space = size(rm,2)-size(re,2);
%*-*-*Uncomment lines below to see the result*-*-*-*-
%subplot(2,1,1);imshow(fl);
%subplot(2,1,2);imshow(re);
break
endif
else
fl=im_texto;%Only one line.
re=[ ];
space = 0;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% clip.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function img_out=clip(img_in)
[x y]=size(img_in);
[f c]=find(img_in);
max_r = max(f) + 0;
if max_r > x
max_r = x;
endif
temp_img = img_in(min(f):max_r,min(c):max(c));
[f1 c1]=find(temp_img);
img_out=temp_img(min(f1):max(f1),min(c1):max(c1));
endfunction
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% segmentation.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function result=segmentation(filename)
warning off;
serial=0;
imagen=imread(strcat(filename,'.jpg'));
% Show image
imagen1 = imagen;
% Convert to gray scale
if size(imagen,3)==3 %RGB image
imagen=rgb2gray(imagen);
end
% Convert to BW
threshold = graythresh(imagen);
imagen =~im2bw(imagen,threshold);
imagen2 = imagen;
re=imagen;
while 1
%Fcn 'lines_crop' separate lines in text
[fl re]=lines_crop(re); %fl= first line, re= remaining image
imgn=fl;
n=0;
%Uncomment line below to see lines one by one
if (size(fl)>0)
%figure,imshow(fl);pause(.5)
else
break;
endif
%-----------------------------------------------------------------
spacevector = []; % to compute the total spaces betweeen
% adjacent letter
rc = fl;
while 1
%Fcn 'letter_crop' separate letters in a line
[fc rc space]=letter_crop(rc); %fc = first letter in the line
%rc = remaining cropped line
%space = space between the letter
% cropped and the next letter
%uncomment below line to see letters one by one
if (size(fc)>0)
imwrite(~fc,strcat(filename,"-",num2str(serial),".png"));
%figure,imshow(fc);pause(0.5);
serial=serial+1;
else
break;
endif
end
end
endfunction
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% licence.txt
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (c) 2012, Tsan-Kuang Lee
% Copyright (c) 2011, Ankit Saroch
% Copyright (c) 2006, Diego Orlando Barragan Guerrero
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%
% * Redistributions of source code must retain the above copyright
% notice, this list of conditions and the following disclaimer.
% * Redistributions in binary form must reproduce the above copyright
% notice, this list of conditions and the following disclaimer in
% the documentation and/or other materials provided with the distribution
% * Neither the name of the EQBYTE Instruments Cía. Ltda. nor the names
% of its contributors may be used to endorse or promote products derived
% from this software without specific prior written permission.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.
</pre><br />
<link href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css" rel="stylesheet" type="text/css"></link><br />
<link href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css" rel="stylesheet" type="text/css"></link><br />
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js" type="text/javascript"></script><script type="text/javascript">
/**
* Author: James Rohal
* http://www.jamesrohal.com
*/
SyntaxHighlighter.brushes.Matlab = function()
{
var functions = 'abs accumarray acos acosd acosh acot acotd acoth acsc acscd acsch actxcontrol actxcontrollist actxcontrolselect actxGetRunningServer actxserver addCause addevent addframe addlistener addOptional addParamValue addpath addpref addprop addproperty addRequired addsample addsampletocollection addtodate addts airy align alim all allchild alpha alphamap amd ancestor and angle annotation Annotation Arrow Properties Annotation Doublearrow Properties Annotation Ellipse Properties Annotation Line Properties Annotation Rectangle Properties Annotation Textarrow Properties Annotation Textbox Properties ans any area Areaseries Properties arrayfun ascii asec asecd asech asin asind asinh assert assignin atan atan2 atand atanh audioplayer audiorecorder aufinfo auread auwrite avifile aviinfo aviread axes Axes Properties axis balance bar barh bar3 bar3h Barseries Properties base2dec beep bench besselh besseli besselj besselk bessely beta betainc betaln bicg bicgstab bin2dec binary bitand bitcmp bitget bitmax bitor bitset bitshift bitxor blanks blkdiag box break brighten brush bsxfun builddocsearchdb builtin bvp4c bvp5c bvpget bvpinit bvpset bvpxtend calendar calllib callSoapService camdolly cameratoolbar camlight camlookat camorbit campan campos camproj camroll camtarget camup camva camzoom cart2pol cart2sph case cast cat catch caxis cd cd cdf2rdf cdfepoch cdfinfo cdfread cdfwrite ceil cell cell2mat cell2struct celldisp cellfun cellplot cellstr cgs char checkin checkout chol cholinc cholupdate circshift cla clabel class classdef clc clear clearvars clear clf clipboard clock close close close closereq cmopts colamd colorbar colordef colormap colormapeditor ColorSpec colperm comet comet3 commandhistory commandwindow compan compass complex computer cond condeig condest coneplot conj continue contour contour3 contourc contourf Contourgroup Properties contourslice contrast conv conv2 convhull convhulln convn copyfile copyobj corrcoef cos cosd cosh cot cotd coth cov cplxpair cputime create createClassFromWsdl createCopy createSoapMessage cross csc cscd csch csvread csvwrite ctranspose cumprod cumsum cumtrapz curl customverctrl cylinder daqread daspect datacursormode datatipinfo date datenum datestr datetick datevec dbclear dbcont dbdown dblquad dbmex dbquit dbstack dbstatus dbstep dbstop dbtype dbup dde23 ddeget ddesd ddeset deal deblank debug dec2base dec2bin dec2hex decic deconv del2 delaunay delaunay3 delaunayn delete delete delete delete delete delete deleteproperty delevent delsample delsamplefromcollection demo depdir depfun det detrend detrend deval diag dialog diary diff diffuse dir dir disp disp disp disp disp display divergence dlmread dlmwrite dmperm doc docopt docsearch dos dot double dragrect drawnow dsearch dsearchn dynamicprops echo echodemo edit eig eigs ellipj ellipke ellipsoid else elseif enableservice end eomday eps eq eq erf erfc erfcx erfinv erfcinv error errorbar Errorbarseries Properties errordlg etime etree etreeplot eval evalc evalin eventlisteners events events Execute exifread exist exit exp expint expm expm1 export2wsdlg eye ezcontour ezcontourf ezmesh ezmeshc ezplot ezplot3 ezpolar ezsurf ezsurfc factor factorial FALSE fclose fclose feather feof ferror feval Feval fft fft2 fftn fftshift fftw fgetl fgetl fgets fgets fieldnames figure Figure Properties figurepalette fileattrib filebrowser File Formats filemarker fileparts fileread filesep fill fill3 filter filter filter2 find findall findfigs findobj findobj findprop findstr finish fitsinfo fitsread fix flipdim fliplr flipud floor flow fminbnd fminsearch fopen fopen for format fplot fprintf fprintf frame2im fread fread freqspace frewind fscanf fscanf fseek ftell ftp full fullfile func2str function function_handle functions funm fwrite fwrite fzero gallery gamma gammainc gammaln gca gcbf gcbo gcd gcf gco ge genpath genvarname get get get get get get get get get getabstime getabstime getappdata GetCharArray getdatasamplesize getDefaultStream getdisp getenv getfield getframe GetFullMatrix getinterpmethod getpixelposition getpref getqualitydesc getReport getsampleusingtime getsampleusingtime gettimeseriesnames gettsafteratevent gettsafterevent gettsatevent gettsbeforeatevent gettsbeforeevent gettsbetweenevents GetVariable GetWorkspaceData ginput global gmres gplot grabcode gradient graymon grid griddata griddata3 griddatan gsvd gtext guidata guide guihandles gunzip gzip hadamard handle hankel hdf hdf5 hdf5info hdf5read hdf5write hdfinfo hdfread hdftool help helpbrowser helpdesk helpdlg helpwin hess hex2dec hex2num hgexport hggroup Hggroup Properties hgload hgsave hgsetget hgtransform Hgtransform Properties hidden hilb hist histc hold home horzcat horzcat hostid hsv2rgb hypot i idealfilter idivide if ifft ifft2 ifftn ifftshift ilu im2frame im2java imag image Image Properties imagesc imfinfo imformats import importdata imread imwrite ind2rgb ind2sub Inf inferiorto info inline inmem inpolygon input inputdlg inputname inputParser inspect instrcallback instrfind instrfindall int2str int8 int16 int32 int64 interfaces interp1 interp1q interp2 interp3 interpft interpn interpstreamspeed intersect intmax intmin intwarning inv invhilb invoke ipermute iqr is* isa isappdata iscell iscellstr ischar iscom isdir isempty isempty isempty isequal isequal isequalwithequalnans isevent isfield isfinite isfloat isglobal ishandle ishold isinf isinteger isinterface isjava isKey iskeyword isletter islogical ismac ismember ismethod isnan isnumeric isobject isocaps isocolors isonormals isosurface ispc ispref isprime isprop isreal isscalar issorted isspace issparse isstr isstrprop isstruct isstudent isunix isvalid isvalid isvalid isvarname isvector j javaaddpath javaArray javachk javaclasspath javaMethod javaObject javarmpath keyboard keys kron last lasterr lasterror lastwarn lcm ldl ldivide rdivide le legend legendre length length length length length libfunctions libfunctionsview libisloaded libpointer libstruct license light Light Properties lightangle lighting lin2mu line Line Properties Lineseries Properties LineSpec linkaxes linkdata linkprop linsolve linspace list listdlg listfonts load load load loadlibrary loadobj log log10 log1p log2 logical loglog logm logspace lookfor lower ls lscov lsqnonneg lsqr lu luinc magic makehgtform mat2cell mat2str material matlabcolon matlabrc matlabroot matlab matlab max max MaximizeCommandWindow maxNumCompThreads mean mean median median memmapfile memory menu mesh meshc meshz meshgrid metaclass methods methodsview mex MException mexext mfilename mget min min MinimizeCommandWindow minres mislocked mkdir mkdir mkpp mldivide mrdivide mlint mlintrpt mlock mmfileinfo mmreader mod mode more move movefile movegui movie movie2avi mput msgbox mtimes mu2lin multibandread multibandwrite munlock namelengthmax NaN nargchk nargin nargout nargoutchk native2unicode nchoosek ndgrid ndims ne ne netcdf newplot nextpow2 nnz noanimate nonzeros norm normest not notebook notify now nthroot null num2cell num2hex num2str numel nzmax ode15i ode23 ode45 ode113 ode15s ode23s ode23t ode23tb odefile odeget odeset odextend onCleanup ones open openfig opengl openvar optimget optimset or ordeig orderfields ordqz ordschur orient orth otherwise pack padecoef pagesetupdlg pan pareto parfor parse parseSoapResponse partialpath pascal patch Patch Properties path path2rc pathsep pathtool pause pbaspect pcg pchip pcode pcolor pdepe pdeval peaks perl perms permute persistent pi pie pie3 pinv planerot playshow plot plot plot3 plotbrowser plotedit plotmatrix plottools plotyy pol2cart polar poly polyarea polyder polyeig polyfit polyint polyval polyvalm pow2 power ppval prefdir preferences primes print printopt printdlg printpreview prod profile profsave propedit propedit properties propertyeditor psi publish PutCharArray PutFullMatrix PutWorkspaceData pwd qmr qr qrdelete qrinsert qrupdate quad quadgk quadl quadv questdlg quit Quit quiver quiver3 Quivergroup Properties qz rand rand randi randi randn randn randperm randperm RandStream RandStream rank rat rats rbbox rcond read readasync real reallog realmax realmin realpow realsqrt record rectangle Rectangle Properties rectint recycle reducepatch reducevolume refresh refreshdata regexp regexpi regexprep regexptranslate registerevent rehash release relationaloperators rem remove removets rename repmat resample resample reset reset reshape residue restoredefaultpath rethrow rethrow return rgb2hsv rgbplot ribbon rmappdata rmdir rmdir rmfield rmpath rmpref root object Root Properties roots rose rosser rot90 rotate rotate3d round rref rsf2csf run save save save saveas saveobj savepath scatter scatter3 Scattergroup Properties schur script sec secd sech selectmoveresize semilogx semilogy sendmail serial serialbreak set set set set set set set set setabstime setabstime setappdata setDefaultStream setdiff setdisp setenv setfield setinterpmethod setpixelposition setpref setstr settimeseriesnames setxor shading shg shiftdim showplottool shrinkfaces sign sin sind single sinh size size size size size slice smooth3 snapnow sort sortrows sound soundsc spalloc sparse spaugment spconvert spdiags specular speye spfun sph2cart sphere spinmap spline spones spparms sprand sprandn sprandsym sprank sprintf spy sqrt sqrtm squeeze ss2tf sscanf stairs Stairseries Properties start startat startup std std stem stem3 Stemseries Properties stop stopasync str2double str2func str2mat str2num strcat strcmp strcmpi stream2 stream3 streamline streamparticles streamribbon streamslice streamtube strfind strings strjust strmatch strncmp strncmpi strread strrep strtok strtrim struct struct2cell structfun strvcat sub2ind subplot subsasgn subsindex subspace subsref substruct subvolume sum sum superiorto support surf surfc surf2patch surface Surface Properties Surfaceplot Properties surfl surfnorm svd svds swapbytes switch symamd symbfact symmlq symrcm symvar synchronize syntax system tan tand tanh tar tempdir tempname tetramesh texlabel text Text Properties textread textscan textwrap throw throwAsCaller tic toc timer timerfind timerfindall timeseries title todatenum toeplitz toolboxdir trace transpose trapz treelayout treeplot tril trimesh triplequad triplot trisurf triu TRUE try tscollection tsearch tsearchn tsprops tstool type typecast uibuttongroup Uibuttongroup Properties uicontextmenu Uicontextmenu Properties uicontrol Uicontrol Properties uigetdir uigetfile uigetpref uiimport uimenu Uimenu Properties uint8 uint16 uint32 uint64 uiopen uipanel Uipanel Properties uipushtool Uipushtool Properties uiputfile uiresume uisave uisetcolor uisetfont uisetpref uistack uitable Uitable Properties uitoggletool Uitoggletool Properties uitoolbar Uitoolbar Properties uiwait undocheckout unicode2native union unique unix unloadlibrary unmkpp unregisterallevents unregisterevent untar unwrap unzip upper urlread urlwrite usejava userpath validateattributes validatestring values vander var var varargin varargout vectorize ver verctrl verLessThan version vertcat vertcat vertcat view viewmtx visdiff volumebounds voronoi voronoin wait waitbar waitfor waitforbuttonpress warndlg warning waterfall wavfinfo wavplay wavread wavrecord wavwrite web weekday what whatsnew which while whitebg who whos wilkinson winopen winqueryreg wk1finfo wk1read wk1write workspace xlabel ylabel zlabel xlim ylim zlim xlsfinfo xlsread xlswrite xmlread xmlwrite xor xslt zeros zip zoom';
this.regexList = [
{ regex: /%.*$/gm, css: 'comments' }, // one line comments
{ regex: /\{\%[\s\S]*?\%\}/gm, css: 'comments' }, // multiline comments
{ regex: SyntaxHighlighter.regexLib.singleQuotedString, css: 'string' }, // strings
{ regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'string' }, // strings
{ regex: new RegExp(this.getKeywords(functions), 'gm'), css: 'functions bold' }
];
};
SyntaxHighlighter.brushes.Matlab.prototype = new SyntaxHighlighter.Highlighter();
SyntaxHighlighter.brushes.Matlab.aliases = ['matlab'];
</script><br />
<script type="text/javascript">SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.all();</script>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-481096069064374725.post-36161699017085156662011-12-26T04:46:00.000-05:002014-10-12T03:57:39.691-04:00HomelessThis post is a translation of <a href="http://blog.tklee.org/2011/12/blog-post.html">my other post in Chinese</a>. I wrote that to share my personal reaction toward a <a href="http://www.youtube.com/watch?v=ikfW-MNP4sk">recent incident in Taiwan</a>: the municipal administration used water jets to drive away homeless people in the park in a cold evening.<br />
<br />
Please note that since this is a direct translation from the original Chinese post, the composition flow may not be as natural to English readers. Please bear with me and hear out what I have to say, if you are interested in reading this anyway.<br />
<br />
<hr style="width: 80%;" />
<br />
When I moved from Southern California to Philadelphia for my graduate study in 1998, I was shocked to see so many homeless people. I witnessed a country in which the rich can personally own a hill, while the poor would seek food in the garbage can. While some spend their afternoons watching seagulls with their beer on the beach, some others try to survive a cold night by staying close to the external vent of a building's heater.<br />
<a name='more'></a>I was lucky enough then to be granted enough scholarship to support myself, while also being able to buy a lunch box or two for a couple of homeless people in the community. After a while, I learned that some of them were veterans but things didn't work out too well for them after they came back from the battlefields. They had spent their best years on the battleground, so going back to school was not easy for them. They did try to apply for jobs, but since they were poor and couldn't afford the rent, they were homeless, and very few business would provide opportunities to people without a fixed address. According to them, the shelters were filled with sick people and the people who worked there didn't treat them with any respect. They'd rather be homeless than losing the basic dignity.<br />
<br />
From them, I actually learned about my own blind spots. Blaming them for being lazy or rejecting help is basically like saying "<a href="http://en.wikipedia.org/wiki/Let_them_eat_cake">Let them eat cake</a>". I am not a princess living in a palace so I managed to somewhat overcome my own blind spots. Taiwan's recent economic depression and the unemployment rate, coupled with high rents, makes it possible for me to imagine how a person without a job for a while can eventually end up homeless.<br />
<br />
A decade or so ago, during the <a href="http://en.wikipedia.org/wiki/1997_Asian_financial_crisis">Asian financial crisis</a>, many families in South Korea chose to commit suicide. Most people in Taiwan were able to understand and sympathize. Now when Taiwan's own people are suffering and homeless, why do we choose to further insult them by <a href="http://www.youtube.com/watch?v=ikfW-MNP4sk">using the water jets against them in a cold night</a>?<br />
<br />
I wasn't the only one in Philadelphia to notice the homelessness problem. Students there organized events to help people understand the problems at a deeper level. They were called "Students Against Homelessness". Today, we need to be careful -- we are against with the problem (the homelessness), not the victims (the homeless).<br />
<br />
Homelessness is a structural problem that my buying an extra lunchbox cannot solve. And this water jet against homeless incident prompted me to re-inspect my personal value system and concept of societal responsibilities.<br />
<br />
If I cannot completely solve the problem, may I just as well do nothing?<br />
<br />
I admit that I am not willing to take care of strangers in need in a long run. However, does that mean I may as well do nothing? I ask myself: since I will die eventually, does my life have to be meaningless? My own answer to that question is: the meaning of my life lies in its process. Now, even if I can only help them with just one meal, that one meal can help sustain the person's life by a little bit, and that little bit of life time is still meaningful.<br />
<br />
Now, who is responsible for homelessness?<br />
<br />
A society's system in a particular time and place, always benefits some people more than others. For example, in Taiwan's current society, those with more advanced academic degrees enjoy more professional and financial opportunities; those who studied arts and humanity, earn, in average, much less than those who do law, medicine, business, or engineering. If I really look at it objectively, I simply happen to benefit from those particular conditions, i.e. I happened to be in an environment where things work for me. As for those who don't have things work for them just right, I have to ask myself, is it totally their fault?<br />
<br />
When I enjoy societal resources, do I affect others, directly or indirectly? For example, if I am extra capable and can cover two people's responsibilities in a position, so the boss is happy giving me higher salary instead of hiring two people, am I taking away one other person's job opportunity while I enjoy my higher salary?<br />
<br />
Well, I am still quite selfish. If there <i>is</i> such a higher paying job for me, I will gladly take it. However, I will have to remind myself that a position taken by me is a position not taken by somebody else.<br />
<br />
Such realization of limited resources makes me be extra aware of the pride that I may have when helping out those in need. I am giving not because I am superior or more able, but because I am also connected to the causes to the problems.<br />
<br />
Homelessness is a collective <a href="http://en.wikipedia.org/wiki/Karma_in_Buddhism">karma</a> and everyone is connected to its causes. Most of us are not saints, but at least we can learn not to take away people's dignity simply because they can't afford a home.<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-49833104420646153922011-12-26T03:46:00.000-05:002014-10-12T03:57:39.694-04:00街友(English readers, you may be interested in my <a href="http://blog.tklee.org/2011/12/homeless.html">English translation of this post</a>.)<br />
<br />
記得1998年從美國西岸加州到美國東岸費城讀書時,第一次見到眾多的遊民,大為震憾。美國這個國家,有人富有到坐擁山頭,有人窮到得從垃圾筒翻出別人吃剩的便當出來填肚子;有人每天下午到海灘看沙鷗喝啤酒,有人每天晚上得縮在高樓旁的暖氣通風口取暖度冬夜。<br />
<br />
那時候我很幸運,獎學金夠我過日子,也夠幫一兩位社區內的街友多買個便當。日子久了,和他們聊起來,才知道他們幫國家打仗受傷,戰後政府沒有好好照顧他們,他們寶貴的年輕時間都在戰場上耗掉了,退伍後年紀大要再回學校已是很困難。付擔不起房租,所以居無定所;想要好好老實找份工作,大部份的業主看到他們沒有個固定的住址,都不願意給他們機會。收容所的環境很不好,通風不良,傳染病問題嚴重,生了病很難好,再加上收容所的工作人員對待這些遊民的人態度極度不佳,讓他們寧可餐風露宿,也不願自尊被人踐踏。<br />
<a name='more'></a><br />
從他們身上,我看到自己當時的盲點。說他們懶惰不願意工作,或是不求上進,或是不願接受政府幫助,和「何不食肉糜」沒什麼兩樣。我們不是皇帝,既不高也不遠,所以其實要了解實相並不困難。尤其最近景氣不好,失業人口增加,房價又居高,會有人因長期沒收入,付擔不起房租,最後落到沒地方住的情形, 一點都不難想像。<br />
<br />
十多年前南韓金融風暴讓很多家庭選擇自殺,我們有能力理解,並且為他們難過。現在我們自己的人民流難失所,為什麼反而<a href="http://www.youtube.com/watch?v=LhQ-n5VXi7w">落井下石,污辱他們的人格</a>呢?<br />
<br />
當年在費城,受到無業遊民問題衝擊的不只我一個人。那裡的學生組了社團,辦活動來幫助更多人了解問題真正所在。社團名字叫 Students Against Homelessness (青年學子一起來掃除無家問題)。但如果我們不小心,會變成對人不對事,變成 Against Homeless (掃除無家遊民)。<br />
<br />
遊民是社會的結構問題。我個人幫他們多買個便當,治標不治本。這次向遊民噴水事件,逼我重新審視我的價值觀與社會責任。<br />
<br />
本治不了,標是不是就算了?<br />
<br />
如果我知道自己不願意長期照顧非親非故的鰥寡孤獨,是不是就乾脆連一餐也不用幫了?我試著自問,既然我最後反正要死,我的生命是不是就沒什麼意義?我給自己的答案是,我生命的意義在過程,而不在終點。如果我給自己的答案是這樣,那麼,幫街友弄得一餐,那麼讓這一餐供給他生命所需的營養與能量,來提高他那一小段生命中獲得意義的可能性,不值得做嗎?<br />
<br />
遊民的問題是誰的責任?<br />
<br />
社會的制度規章,讓特定時空的某些人日子容易過些,某些人日子難過些。比方說,我們的社會,讓學歷高的人,在經濟上的機會比較多;學藝術人文的人,平均收入就較學醫法商工的少。說穿了,我不過剛好是種種客觀條件下的既得利益或是因利折腰者。那些「不剛好」的人,難道真的活該?<br />
<br />
當我享用大量社會資源時,有沒有直接或間接減少其他人的機會?比方說,如果我因為個人才智,在職場上發揮所長,一人抵兩人用,讓業主高薪雇用,是不是在享受高薪時也佔據了他人就業的機會?<br />
<br />
我並不偉大無私,如果真有高薪工作讓我來做,我當然積極爭取。但我得提醒自己,所謂的「爭取」,就表示有他人共爭而取不到。 我所獲得的福利,是建築在某些人的痛苦上的。有了這樣的認知,我就得很小心,不要讓自己在幫助遊民時以為自己在施捨,起了驕心。<br />
<br />
遊民的問題,是時代和社會共業,每個人都脫不了關係。非聖非賢的我們,如果僅能幫一小丁點,那麼至少應試著不要污辱他們。<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-29417286212931317932011-11-11T22:09:00.001-05:002015-08-05T20:00:58.075-04:00Google Earth Game: Amazing Race<a href="http://www.personal.psu.edu/txl20/GoogleEarth/AmazingRace/">Penn State's Amazing Race</a>is a game I implemented for a university course taught by <a href="http://www.brandywine.psu.edu/Academics/faculty_uxg3.htm">Dr. Laura Guertin</a>.<br />
<br />
<a href="http://www.personal.psu.edu/txl20/GoogleEarth/AmazingRace/AmazingRace_download.zip">The source code</a> is packed into a zip file for your convenience.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-10106341632192970012011-11-06T17:09:00.001-05:002015-08-05T20:01:15.672-04:00About this blog 關於本網誌The primary topics covered in this blog are listed as "labels" (Arts, Composition, Technology, etc.) so please use them if some topics are less interesting to you.<br />
<br />
I see myself as a citizen of the globe and I believe sharing thoughts in an honest way helps make the world a little bit better. A lot of people are already doing this in a much better way, and I do my small share with this blog. I write things that I think may help somebody out there.<br />
<br />
"Still reflection" sounds non-English and it gives away the fact that English is not my native language. I hope one day the machine translation technology will allow everyone in the world to express themselves with their most comfortable language. However, before that day comes, I still choose the most international language (at the time of writing) to write most posts because I believe linguistic origins should not impair the exchange of thoughts and ideas. Sometimes I'll write in other languages if the specific contents benefit the readers of those languages the most.<br />
<br />
This blog contains decades of posts and earlier posts do show the immaturity and the big ego of an ignorant young man. This blog, therefore, records my growth and self-reflection.<br />
<br />
You can read more about <a href="/search?q=%22about+this+blog%22">blog organization details here</a>.<br />
<br />
本網誌涵蓋的主題列在Labels之下(藝術,音樂創作,科技等等)。 您可用來篩選您有興趣的主題。<br />
<br />
作為一個世界公民,我認為誠懇地交換思想能讓這個世界變好。很多人已做得比我更好,我希望用這個網誌來盡我一小份心力。希望我分享的東西對某些人有幫助。<br />
<br />
「靜思語」的英文翻譯聽來很東方。所以英文讀者一看就猜得出英文不是我母語。希望自動翻譯的科技有一天能讓每個人都用自己最熟練的語言來表達思想,讓不同語族的人都能交換溝通。但在那天到來之前,我只好用目前最國際化的語言來寫。有些內容我用非英文寫,那應該是該內容對某特定語族較為相關。<br />
<br />
這個網誌存了幾十年來的文章。從早期的文章可以看出我年輕時的自大與不成熟。所以,這個網誌其實也記錄了我的成長與自省。<br />
<br />
我之前也寫了<a href="/search?q=%22about+this+blog%22">幾篇關於這個網誌的介紹</a>,有興趣可以參考。Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-57032301015572359212011-11-05T20:58:00.000-04:002011-11-05T20:59:58.939-04:00Contact 與我聯繫If you are responding to one of my posts, please leave your comments there. If you have a reason to send me a private message, please <a href="https://docs.google.com/spreadsheet/viewform?formkey=dF96d0xTdXlleVhBb0g4VXdYUF92aHc6MQ">use this form</a>. However, please understand that I may or may not be able to reply to your message, although I will try.<br />
<br />
Note that <a href="http://blog.tklee.org/2009/06/contact.html">the old contact method</a> no longer works.<br />
<br />
<br />
<br />
如果您要對我某篇文章做回應,請直接在該篇文章回應。如果您仍覺得有必要寄私信給我,請<a href="https://docs.google.com/spreadsheet/viewform?formkey=dF96d0xTdXlleVhBb0g4VXdYUF92aHc6MQ">填此表格</a>。<br />
<br />
<a href="http://blog.tklee.org/2009/06/contact.html">舊的聯絡方式</a>已失效。<br />
<br />Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-481096069064374725.post-48106761756936710442011-09-25T00:00:00.001-04:002015-05-07T13:02:11.890-04:00Create distinguishable device IDs for two Dell KeyboardsI like the Dell keyboard SK-8115 (or L-100) because of the left Ctrl key allows my palm to hold it naturally (as opposed to moving my pinky, or worse, my thumb, toward it by twisting my wrist). When I am setting up <a href="http://en.wikipedia.org/wiki/Multiseat_configuration">MultiSeat</a> under X11, I need to distinguish the two keyboards. Unfortunately, both of them come up as /dev/input/by-id/usb-Dell_Dell_USB_Keyboard-event-kbd (the latter recognized one overwriting the first one) so in my xorg.conf I can't specify either.<br />
<br />
Fortunate for me, they have different product ID (by "cat /proc/bus/input/devices") so I can create a udev rule to produce two different device nodes. (Update: even if both devices have the same product ID, one can still distinguish them according to their USB port addresses)<br />
<br />
/etc/udev/rules.d/60-dell-keyboards.rules<br />
<br />
<div class="progCode"><pre><code>
# /etc/udev/rules.d/60-dell-keyboards.rules
# udev rules for dell keyboards.
# This solves the problem of the same /dev/input/by-id/usb-Dell_Dell_USB_Keyboard-event-kbd problem while I need to distinguish the two Dell Keyboards
# ref: http://reactivated.net/writing_udev_rules.html
# ref: http://sourceforge.net/apps/mediawiki/linuxwacom/index.php?title=Fixed_device_files_with_udev
KERNEL!="event[0-9]*", GOTO="dell_key_end"
# Port specific link for users of multiple keyboards of the same type.
# The ID_PATH variable is set by the "path_id" script in an earlier rule file.
ATTRS{idVendor}=="413c", ENV{ID_PATH}=="?*", SYMLINK="input/by-path/$env{ID_PATH}-dell"
# Type-named links for multiple keyboards
ATTRS{idVendor}=="413c", ATTRS{idProduct}=="2003", SYMLINK+="input/dell_keyboard_2003"
ATTRS{idVendor}=="413c", ATTRS{idProduct}=="2105", SYMLINK+="input/dell_keyboard_2105"
LABEL="dell_key_end"
</code></pre></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-481096069064374725.post-45942880409221003322011-06-05T22:23:00.000-04:002011-06-05T22:23:14.421-04:00Scan old black and white booksI had to digitize an old book with yellowed pages and the following bash command helped me to do the job.<br />
<br />
convert is part of ImageMagick package. pdftk is a utility to manipulate pdf files.<br />
<br />
-threshold split all colors into black and white. +delete removes the extra page created from cropping.<br />
<br />
<div class="progCode"><pre><code>
mkdir work
for i in *[13579].png; do convert $i -crop 2544x3250 +repage -threshold 40% +delete work/$i.pdf; done
for i in *[02468].png; do convert $i -crop 2544x3250 +repage -threshold 40% +delete -flip -flop work/$i.pdf; done
cd work
pdftk *pdf output ../all.pdf
</code></pre></div>Unknownnoreply@blogger.com0