2013/10/01

Eclipse 的 Workspace 該怎麼用

剛開始用 Eclipse 開發 Android Apps。在學習過程中,一直有一個疑問:workspace 該怎麼用?一個 app 一個 workspace?還是一個 workspace 通吃大部分的 app?這兩種策略又有何差異?

以下這邊文章解答了我部份的疑問 (簡單說,用一個 workspace 通吃大部分的 apps):
還有其他考量嗎?繼續研究當中,有心得再來更新。

2013/09/16

將多張 JPEG 圖形檔合成一個多頁文檔

想將多張 JPEG 圖形檔合成一個多頁文檔?沒問題,但你要先知道 JPEG 格式目前沒有多頁模式。所以要轉成支援多頁的格式,譬如 .PDF 或 .TIFF。

Ubuntu 上似乎預設就有此功能:
convert file1.jpg file2.jpg file3.jpg output.pdf
此功能是包含在 imagemagick 套件上,若沒有上述 convert 程式,可以自己安裝此套件:
sudo apt-get install imagemagick
據說 Windows 和 MacOS 平台上也都有此程式。

2013/08/31

在 Ubuntu 使用 USB RS232 轉接線

現在的 PC 或 NB 已經很少看到 RS232 接口了。但有些時候,如開發 embedded system 時,還是很需要 serial console。此時就需要 USB RS232 轉接線。

在 Ubuntu 上使用 USB RS232 轉接線很簡單。首先,插入 USB RS232 轉接線後馬上執行以下命令查出 device name:
$ dmesg | grep tty
[ 7842.193255] usb 2-2: pl2303 converter now attached to ttyUSB0
如上述範例的  device name 的是 ttyUSB0。一般來說,你可能會沒有足夠的權限:
$ ls -l /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 0  8月 31 10:33 /dev/ttyUSB0
像上述範例,你如果不是 root,就要把自己加入 dialout 那個 group (修改 /etc/group)。然後就可用自己喜好的 terminal emulator 開始上工了。

以下是其他一些可能會需要的診斷工具,僅供參考:
  • 查看連接上的 USB 裝置的資訊:lsusblsusb -v
  • 查查裝置剛插入時有什麼狀況發生:tail /var/log/syslog

2013/08/02

在 Ubuntu 上將 YouTube 的 MV 轉成 MP3 檔

先聲明,以下這方法不是最簡單的,只是個人喜好的步驟 (其實,有網站提供此服務)。

首先,先在 Firefox 安裝可下載 YouTube 影片的 Add-on,譬如:1-Click YouTube Video Download。將喜歡的 MV 轉成 MP4 檔。

然後,執行以下指令:
avconv -i input.mp4 -f mp3 -vn output.mp3
若不能成功,可能是缺少 mp3 codec,用以下方法安裝:
sudo apt-get install libavcodec-extra-53
不習慣 avconv (亦即之前的 ffmpeg) 命令列的,可以安裝 winff 來用 GUI。

參考資料:


2013/07/24

Android/Eclipse 上 Java 的 Tab 處理

Android 的 Code Style Guidelines 明確規定縮排是用四個空白,而且強調 We never use tabs。既然最權威的原創者有明確的規定,我們開發 Android Apps 時,若沒有特別的理由,建議也比照辦理。

有趣的是,Eclipse 的預設跟此規定恰好相反:用相當於四個空白寬度的 tab 來縮排。改變此設定的方法如下:
  • Window > Preferences > Java > Code Style > Formatter > New
  • Java Conventions [built-in] 當樣板,新增一個 Android Style profile
  • 修改此 profile,將 Tab policy 改成 Spaces only,Tab size 設成 4
有了上面的設定,用 eclipse 開發 android app 時,縮排用 tab 就會自動變成四個空白。我建議再做以下設定,讓 eclipse 明確顯示 space、tab 和 newline 等字元,以便精準掌握「空白」是不是你所想要的那種「空白」:
  • Window > Preferences > General > Editors > Text Editors > Show whtiespace characters

2013/07/20

Ubuntu 的網路設定

一般來說,Ubuntu 的網路設定不會是個問題,安裝時幾乎就幫你搞定一切了。但若你後來更換網路卡,或者將安裝硬碟換到不同的機器,你可能就需要自己稍微調整一下設定了。以下是我的一些經驗,僅供參考。

首先,確認 kernel 認到多少張網路卡:
root@ubuntu:~# dmesg | grep eth
[    1.678186] i2c-core: driver [aat2870] using legacy suspend method
[    1.678186] i2c-core: driver [aat2870] using legacy resume method
[    2.718021] via-rhine 0000:01:06.0: eth0: VIA Rhine II at 0xfebffc00, 00:11:22:ab:cd:ed, IRQ 19
[    2.718735] via-rhine 0000:01:06.0: eth0: MII PHY found at address 8, status 0x782d advertising 01e1 Link cde1
[    2.726899] forcedeth: Reverse Engineered nForce ethernet driver. Version 0.64.
[    2.727153] forcedeth 0000:00:0f.0: PCI INT A -> Link[LMAC] -> GSI 20 (level, low) -> IRQ 20
[    2.727160] forcedeth 0000:00:0f.0: setting latency timer to 64
[    3.253390] forcedeth 0000:00:0f.0: ifname eth1, PHY OUI 0x732 @ 1, addr 00:33:44:ab:cd:ed
[    3.253394] forcedeth 0000:00:0f.0: highdma pwrctl mgmt gbit lnktim msi desc-v3
以上輸出,很清楚看到系統抓的兩張網路卡,eth0 & eth1。有些時候,你會看到 "eth0 is renamed to eth1" 之類的訊息。這時候,你用 ifconfig 去看時,會發現網路界面的名稱跟系統抓到的好像不一致。遇到這種情況,請檢查 /etc/udev/rules.d/70-persistent-net.rules:
# PCI device 0x1106:/sys/devices/pci0000:00/0000:00:0a.0/0000:01:06.0 (via-rhine)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:11:22:ab:cd:ef", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

# PCI device 0x10de:/sys/devices/pci0000:00/0000:00:0f.0 (forcedeth)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:33:44:ab:cd:ef", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"
也就是說,網路界面的名稱可被 udev 重新定義。確認網路界面之後 (確認沒有的網路卡,可以直接刪除),就可以設定各個界面的網路型態:
root@ubuntu:~# cat /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
address 192.168.1.1
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
以上範例,eth0 會自動取得 IP,eth1 則自行指定 IP 位址。

2013/04/17

Epson Stylus Office TX610FW 灰階列印 @ Ubuntu

彩色墨水不便宜,因此我習慣不需要時就用灰階列印。Epson Stylus Office TX610FW 在 Ubuntu 上的驅動程式沒有很 user friendly,用灰階列印需要一點巧門。

一般來說,要啟用灰階列印是:
  • 在列印對話框選定 Epson 印表機
  • 進入「進階」選項
  • 在 Paper & Quality Options 的 Color 選 「Grayscale」
  • 上一動會出現警告圖示,只說設定有衝突,很難猜出原因是什麼。解法是在底下的 Color Management 將 Color Mode 從 「Epson Vivid」 改成 「No Color Adjustment」
若你想將灰階列印設成預設模式,就要去改變印表機的屬性:
  • 系統 > 管理 > 列印
  • 選定印表機 > 右鍵 > 屬性 > 印表機選項
  • 接下來的動作和前面所述一致,但須注意可能有中英文的差異:
    • Color = 彩色
    • Grayscale = 灰階
    • Epson Vivid = EPSON 鮮艷色彩
這個課題還沒有結束。如果你按照本人介紹的方式 在 Ubuntu 上安裝 Acrobat Reader,這版 Acrobat Reader 串接印表的方式似乎不是 Ubuntu 的標準作法,或者有其他 bug。我的心得是:根本無法切換彩色或灰階模式,因為無此選項。

我懷疑是 bug,因為 Acrobat Reader 點選列印之後,你可以點 Properties 去設定列印參數,而這些參數有兩個一樣的 Color 選項,但都不是用來選擇 Color 或 Grayscale 的。我的解法是先去改設定印表機的預設模式,再啟動 Acrobat Reader 出來列印,注意一下 Properties 的 Printer Command 有 「-o Color=Grayscale」 這一參數即可。

2013/03/31

Remote Desktop 和 Desktop Sharing

這兩個應用很接近,不小心就會混淆。

Remote Desktop 是遠端桌面。也就是在某 PC 上登入並獨自擁有一份遠端主機的桌面,就像你用本地的螢幕鍵盤來登入和操控本地主機的桌面一樣。譬如,你家裡電腦開著,然後在辦公室連回家裡,看到的是和在家裡時一樣的登入畫面。從登入、操作到登出,這個 session 都是你自己在進行。一台主機,通常允許建立很多的遠端桌面,大家各作各的,不會有衝突。

Desktop Sharing 則是桌面分享。也就是你已經登入某一台主機之後,開放權限讓遠端另一個人也可以看到或操作你的桌面。通常這是為了解決某些問題,譬如你不會安裝某個軟體,請遠端的朋友代勞。桌面只有一份,所以要先講好某個時間由誰操作,不然會亂成一團。

Ubuntu 上的 Remote Desktop,server 端可以安裝 xrdp/vnc4server (背景執行),client 則用 tsclient/rdesktop (應用程式 > 網際網路 > 終端伺服器客戶端)。

Ubuntu 上的 Desktop Sharing,server 端可以用 vino-server (系統 > 設定 > 遠端桌面),client 則用 vingare (應用程式 > 網際網路 > 遠端桌面檢視器)。

2013/03/20

修改 xterm 的 title

我是 Gnome Terminal 分頁的重度使用者,往往一開就是十多個分頁。有些在不同工作目錄編輯文件;有些可能在用 gdb 除錯;有些連到其他主機做編譯之類的任務。這樣非常方便,但有一個很大的困擾:經常找不到想去的分頁。

Gnome Terminal 分頁預設以使用者+主機+工作目錄當作 title。乍看之下,似乎可以達到某個程度的分辨功能,但一來相似度太高,二來分頁一多 title 就只剩下前面相同的部份。因此,到後來只能憑腦袋記憶分頁位置。無奈,年紀越大,記憶就越不靈光...

以下介紹解決這個問題的方法:自訂 xterm 的 title (只針對 bash 來介紹,其他 shell 可能能需要些微調整)。

修改 title 的指令為:
echo -ne "\033]0;NEW TITLE\007"
若你當場測試,八成會說我騙你。請再試試以下指令:
echo -ne "\033]0;NEW TITLE\007"; read
第一個指令看起來無效的原因是因為 bash 在完成你的指令之後,馬上又將他改掉了。第二個指令多加一個 read,就是為了讓你看清楚。利用這個特性,內容如下的 ~/bin/vi 在你用 vi 編輯 hello.c 時分頁 titile 會是 "vi hello.c",讓你一目了然:

#!/bin/bash
echo -ne "\033]0;vi $*\007"
/usr/bin/vi $*
同樣的方法,你可以應用到 gdb、adb、minicom 等等。

順道一提,每次在 bash shell 執行完指令就會設定一次 titile,這個動作是設定在 .bashrc 的以下段落:
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac
注意 PS1 定義。其中 \e 和 \a 相當於前面指令的 \033 和 \007、\u 是使用者名稱、\h 是主機名稱、\w 是工作目錄。切換目錄時 title 會跟著改,就是因為 \w 的關係。\w 用在 prompt 很好,但當作 title 就太長了,建議用 \W 當 title,也就是整個路徑的最後一個目錄名稱。

參考資料

2013/03/13

用 vim 調整 tab 和空白混合的程式碼

之前的筆記提過混合 tab 和空白造成 coding style 混亂的問題和建議解法:
在你決定好 coding style 之後,還是要面對一個問題:如何將 tab 和空白已經混亂的程式碼調整好?

方法一是用 Artistic Style 之類的程式碼美化軟體重新編排。這種方法的優點和缺點是重新編排的範圍包含縮排和斷行方式,甚至運算子和括號前後是否需要加上空白等等。若只想針對 tab 和空白做調整,這方式是有風險的大手術。

方法二是利用 vim 半人工轉換。此方法適合縮排大致正確,只需處理 tab 和空白的情況。以下,簡單介紹這個方法。
  1. 首先,請 設定 vim 分別顯示 tab 和空白字元,這樣你才能清楚分辨。
  2. 參考本文一開始介紹的兩篇文章,設定好你理想的 tab 字元處理方式。
  3. 瀏覽你的程式碼,確認縮排位置是否正確,有錯就修正。注意!只看位置,不管 tab 和空白是否混淆。
  4. 然後,執行 vim 的 ":retab" 指令就可按照你的設定重新調整 tab 和空白了 (記得存檔)。若你 coding style 的縮排是用空白字元,也就是這次調整你要將 tab 轉成空白,以上方法可達到完美的程度。但,若你決定以 tab 字元縮排,以上方法會保留不含 tab 的連續空白 (安全起見),不一定每個地方都轉換到。若你確定要全改,用 ":retab!" 指令即可。



2013/03/12

在 Ubuntu 上安裝字型

我對字型的要求不高,只要夠用就好,但有時不得不需要安裝一些新字型。譬如,拿到一份重要的 PDF 文件,因為缺字型的關係,Acrobat Reader 上文字變成小黑點無法閱讀。我直覺是少了 A 字型,用相近的預設 B 字型取代不就好了?但似乎沒有這麼簡單,因為找不到這種設定方法。

有一種解法是上傳到 Google Doc,從 Google Doc 閱讀。若想要在 PC 上閱讀,就只能新增該種字型了。以下是 Ubuntu 安裝字型的方法:
  1. 先取得字型檔。以個人下載兩個字型的經驗,FontZone 字型不少,下載也很方便。
  2. 執行以下命令將字型複製到預設目錄,並讓字型生效 (亦可參考網友 Han-Pei Lin 的留言):
    sudo cp FONT-DOWNLOADED /usr/share/fonts/truetype
    sudo fc-cache -f -v

2013/03/10

讓 vim 顯示 tab 和行末的空白字元

之前的筆記提過混合 tab 和空白造成 coding style 混亂的問題和建議解法:
以上的解法要團隊共同遵守才有效,但我們經常需接手其他作法不同的團隊的程式。因 tab 和空白都以空白顯示,要分辨原來團隊的作法並不容易。

以下是讓 vim 顯示 tab 和行末空白字元的指令:
set listchars=eol:$,tab:>.,trail:~,extends:>,precedes:<
set list
這種設定會以一般的「大於」和「句點」等一般符號來表現 tab 和行末空白。若怕會混淆,可以試試以下的特殊符號 (至少在 Ubuntu 上可用):
set listchars=eol:↵,tab:»·,trail:╳,extends:»,precedes:«
set list
建議將此指令加在 `~/.vimrc`,當成預設組態。這樣,每次用 vim 時 tab 都會有特別的顯示方式,而看起空白的就是真的空白 (行末的空白除外),很容易分辨。用以下指令就可暫時取消這種顯示方式:
set nolist
有些人可能希望空白也能有不同的顯示方法。方法如下:
highlight Whitespace cterm=underline gui=underline ctermbg=NONE guibg=NONE ctermfg=yellow guifg=yellow
autocmd ColorScheme * highlight Whitespace gui=underline ctermbg=NONE guibg=NONE ctermfg=yellow guifg=yellow
match Whitespace /  \+/
參考資料:

2013/02/26

Silent Block -- Firefox 過濾 URL 的擴充套件

介紹一個 Firefox 的擴充套件 -- Silent Block,可以用來過濾你指定的 URL。這個套件很好用 (過濾能力又強又有彈性),但不容易用。因為你要自訂 regular expression 來定義 URL, 而且要自己用 editor 寫。此套件網址如下:
https://addons.mozilla.org/en-US/firefox/addon/silentblock/
簡單舉一個使用情境:你經常需要連到網頁 A,此頁面又會顯示一些大又無用的圖案,造成頁面顯示緩慢。這時,你就可以用 Silent Block 不聲不響的濾掉這些圖檔。

使用此擴充套件你必須在自己的 profile 目錄編輯一個 contentblock-regex.txt 檔案。檔案內容就是一條條想要擋下的 URL。套件的官方網址如下 (間單扼要,跟套件的實作風格一樣):
http://www.schuzak.jp/fx/silentblock.html

頁面最底下有一個設定範例。沒用過 regular expression 的人,看過之後肯定馬上放棄。有興趣挑戰的人,可以參考 Mozilla 的文件:
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Regular_Expressions#Writing_a_Regular_Expression_Pattern

2013/02/13

Epson Stylus Office TX610FW @ Ubuntu

在 Ubuntu 要列印到 Epson Stylus Office TX610FW?沒問題,方法如下:
  1. http://www.openprinting.org/driver/epson-stylus-office-tx610fw-series 下載 Epson 提供的 package,我試過 1.0.0 (DEB for LSB 3.2) 這一個。注意!請正確選擇 32bit 或 64bit 版本,而且必須先安裝 lsb 套件。
  2. 安裝指令 sudo dpkg -i epson-inkjet-printer-stylus-office-tx610fw-series_1.0.0-1lsb3.2_amd64.deb
  3. 安裝好之後,打開 Epson 印表機電源。然後執行印表機設定程式 (非 Unity:系統>管理>列印;Unity:點左上的 Ubuntu logo,輸入 printer 搜尋就會出現)
  4. 在印表機程式畫面點「加入」,再點「網路印表機」。一開始只會出現各種 protocol 的選項,稍等一兩分鐘之後,就會出現 Epson Stylus Office TX610FW 選項。點這個選項,再按「下一步」便會出現印表機的名稱設定,直接「套用」就完成了。
在 Ubuntu 上有一個好處:任何支援列印的程式,你都可以用「列印到檔案」的方式來產生 PDF 文件。我經常使用這項功能,但自從安裝 TX610FW 相關套件之後就有一個小麻煩:每次開啟列印的時候都要等很久。因為系統要讀 TX610FW 印表機的狀態,而我只有想列印的時候才會開這台印表機,所以只能等系統 timeout 放棄之後,我才能去選列印到檔案。

這問題有一個簡單的解法,就是新增一台假的本地印表機來當作預設印表機:
  1. 執行印表機設定程式,點選「加入」
  2. 序列埠 #1 > Generic > text-only printer > 輸入你想要的名稱
  3. 選這台剛新增的印表機,印表機 > 設為預設值
這樣下次開啟列印的時候就不會有等待的時間,你可以馬上選擇列印到檔案或 TX610FW。

2013/02/02

不用條件指令,找出兩數中的較大者

這是一個動腦用的程式設計題目,網路上有不少問答。我發現有不少人誤解「不用條件指令 (without conditional operator)」,這部份要用 assembly 的觀點來看比較清楚。簡單說,指令執行時不能有 branch 的動作,但 compare 是允許的。

錯的答案:
larger = max(a, b);
回答的人可能在搞笑。若 max() 符合要求,這個問題就是要問怎麼作到的。
larger = (a + b + abs(a - b)) / 2;
這個答案看起來有點學問,但本質跟前一個答案一樣,要依賴 abs() 的實作方法。另外,(a-b) 也有 overflow 的問題。
larger = (a > b) ? a : b;
這個不用解釋吧?這只是 if else 的變形,一樣是條件指令。
larger = a;
(void)((a < b) && (larger = b));
這個答案利用 short-circuit and 來決定是否令 larger = b,骨子裡一樣需要條件指令。
#include
unsigned d = b - a;
m = -(d >> (sizeof(int) * CHAR_BIT - 1));
larger = (a & m) | (b & ~m);
這個答案很用心,考慮到可攜性。但用到 b - a,就會有 overflow 的問題。

對的答案:
m = -(a > b);
larger = (a & m) | (b & ~m);
這個方法跟前一個接近,但不會有 overflow 的問題,看起來也清爽多了。小瑕疵是有前提:此計算機系統必須採用二的補數 (2's complement) 來表示有號數。但這個假設,目前「幾乎」都會成立。
larger = ((a ^ b) & -(a > b)) ^ b;
這個方法是前一個的再簡化版本,不是一眼可以懂,但乾淨俐落。同樣也有相同的前提。
larger = (a > b) * a + (a <= b) * b;
這個方法不需任何前提,但我不喜歡那兩個乘法。不知有誰可以改掉?
int p[] = { a, b };
larger = p[a < b];
這個方法除了需複製變數之外,其他都很完美。

組合兩個 bitmap 的方法

寫程式的時候,我們經常需要將兩個 bitmap 組合起來。譬如,取 A 的前三 bit 和 B 的後五 bit 組成一個新的 bitmap。通常我們會這麼寫:
M= 0xE0;
C = (A & M) | (B & ~M);
整理舊書時,看到以前唸大學時的筆記有另一個有趣的方法:
M = 0xE0;
C = ((A ^ B) & M) ^ B;
第二個方法沒那麼直覺,但可以省下一個 ~ 運算。

2013/01/11

變數內容對調的方法

一般我們都是用以下的方法來對調變數的內容:
int temp;
temp = var1;
var1 = var2;
var2 = temp;
今天學到一個有趣的新方法:
var1 ^= var2;
var2 ^= var1;
var1 ^= var2;
蠻酷的。