2012年12月19日 星期三

利用 libudev 實作 USB 熱拔插偵測功能

udev 是 Linux kernel 的裝置管理服務,我們可以用它提供的 libudev 撰寫裝置熱拔插相關的程式。以下是一個實際範例程式。它每隔一小段時間就會檢查是否有收到 USB 熱拔插事件,並且將收到事件內容顯示到螢幕上。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libudev.h>

#define PROBE_INTERVAL (500)

int main(int argc, char** argv)
{
	struct udev* udev = NULL;
	struct udev_monitor* udev_monitor = NULL;
	struct udev_device* dev = NULL;
	int udev_fd = -1;
	fd_set fds;
	struct timeval tv;
	int ret;
	char node_string[64] = {};
	char serial_string[10] = {};
	const char* tmp = NULL;

	udev = udev_new();
	udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
	udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", NULL);
	udev_monitor_enable_receiving(udev_monitor);
	udev_fd = udev_monitor_get_fd(udev_monitor);

	while(1)
	{
		FD_ZERO(&fds);
		FD_SET(udev_fd, &fds);
		tv.tv_sec = 0;
		tv.tv_usec = 0;

		ret = select(udev_fd + 1, &fds, NULL, NULL, &tv);

		if(ret > 0 && FD_ISSET(udev_fd, &fds))
		{
			dev = udev_monitor_receive_device(udev_monitor);

			tmp = udev_device_get_devtype(dev);

			if(dev && tmp && !strcmp(tmp, "usb_device"))
			{
				if(!strcmp(udev_device_get_action(dev), "add"))
				{
					serial_string[0] = 0;
					strcat(serial_string, udev_device_get_sysattr_value(dev,"idVendor"));
					strcat(serial_string, udev_device_get_sysattr_value(dev,"idProduct"));
					fprintf(stderr, "USB Device [%s] added\n", serial_string);
					fprintf(stderr, "Node \"%s\" created\n", udev_device_get_devnode(dev));

				}else if(!strcmp(udev_device_get_action(dev), "remove"))
				{
					fprintf(stderr, "USB Device removed\n", serial_string);
					fprintf(stderr, "Node \"%s\" deleted\n", udev_device_get_devnode(dev));
				}

				udev_device_unref(dev);
			}
		}

		usleep(1000 * PROBE_INTERVAL);
	}

	udev_monitor_unref(udev_monitor);
	udev_unref(udev);
	udev = NULL;
	udev_monitor = NULL;

	return EXIT_SUCCESS;
}

2012年11月19日 星期一

隱藏 gvfs 中的硬碟分割區圖示

目前有許多檔案管理程式包括 Nautilus、Thunar、PCManFM,使用 gvfs 來存取檔案系統。在預設的情況下,它會把硬碟中的各個分割當成可卸除式磁碟一樣在桌面上或檔案管理視窗中顯示圖示,如果不希望它們被當成隨身碟一樣掛載到 /media/,可以在 /etc/udev/rules.d/ 新增一項規則:

KERNEL=="sda1", ENV{UDISKS_PRESENTATION_HIDE}="1"

這樣就可以把 sda1 的圖示隱藏,其他的分割區依此類推把 sda1 替換掉。規則可以寫到 /etc/udev/rules.d/10-local.rules。

2012年11月2日 星期五

Linux 下的 DVD shrink 替代方案

一般商業 DVD 通常因為區碼和加密而需要像 DVD shrink 這樣的軟體才能做備份,Linux 下除了用 wine 跑 DVD shrink 以外,其實還有 dvdbackup 這個套件可以用。

要做整片 DVD 備份,只需要以下的指令:

$ dvdbackup -M

這樣就可以將整張 DVD 備份到目前的工作目錄。另外記得要裝 libdvdcss2 來支援解密,Debian users 可以從 Debian multimedia 下載這個套件。

2012年10月10日 星期三

PSP NetParty 正體中文版

PSP NetParty 是一個類似 XLink、MHP tunnel 的 PSP 連線軟體。PSP連線可以使用 TCP 或UDP 且客戶端不需要開放通訊埠。


原作者網站(日本語)
 

安裝方式:
  1. 請先下載網路安裝程式,安裝最新的 PspNetParty 日文版。
  2. 下載中文版檔案,用壓縮檔內的檔案替換掉 PspNetParty 裡 jar 資料夾內的檔案。
  3. 執行 PlayClient.exe (Windows) 或 java -jar jar/PlayClient.jar (Linux) 啟動程式。

※ SSID 功能(目前為 Windows only)需要 msvcp100.dll 和 msvcr100.dll 兩個檔案,沒有這兩個檔案的人請到微軟網站安裝 Microsoft VC++ 2010 runtime。


※ 如果無線網路裝置清單沒有出現你的無線網卡,請確認是否已經安裝 winpcap

※ Linux 使用者如果抓不到網卡,請確定你有 root 權限。執行 PlayClient 時記得設定 LD_LIBRARY_PATH=./ 讓PNP抓得到 libjnetpcap.so,否則清單只會顯示尚未選擇。


相關連結:

原作者 github
https://github.com/montehunter/PSP-NetParty

正體中文版 github
https://github.com/ryuanlu/PSP-NetParty

※ 最終版本為 0.8b (commit:c47d4c7)

2012年9月19日 星期三

精簡版 OpenGL 3.x/4.x+ 初始化

以下的程式碼會用 root window 建立一個 legacy render context,然後再呼叫 glXCreateContextAttribsARB 建立指定版本的 render context。
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <GL/gl.h>
#include <GL/glext.h>

GLXContext glXCreateContextAttribsARB(Display*, GLXFBConfig, GLXContext, Bool, const int*);

int main(int argc, char **argv)
{
	int visual_attr[] = {	GLX_RGBA,
				GLX_DOUBLEBUFFER,
				GLX_RED_SIZE, 8,
				GLX_GREEN_SIZE, 8,
				GLX_BLUE_SIZE, 8,
				GLX_DEPTH_SIZE, 16,
				0 };

	int version_attr[] = {	GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
				GLX_CONTEXT_MINOR_VERSION_ARB, 3, 0};
	int nitems;

	Display* display = NULL;
	Window window;
	XVisualInfo* vi = NULL;
	GLXContext rc = 0;
	GLXContext newrc = 0;
	GLXFBConfig* fbconfig = NULL;

	display = XOpenDisplay(NULL);
	window = XRootWindow(display, 0);
	fbconfig = glXChooseFBConfig(display, DefaultScreen(display), 0, &nitems);

	vi = glXChooseVisual(display,DefaultScreen(display),visual_attr);
	rc = glXCreateContext(display, vi, 0, GL_TRUE);
	glXMakeCurrent(display, window, rc);

	newrc = glXCreateContextAttribsARB(display, *fbconfig, 0, 1, version_attr);
	if(newrc)
		glXDestroyContext(display, rc);

	XCloseDisplay(display);

	return EXIT_SUCCESS;
}

2012年7月21日 星期六

Linux 下進行 DVDrip

DVD 影片本身以標題(Title)和章節(Chapter)分割成好幾個部份,所以 rip 的時候先將需要的章節合併成單一個 vob 檔再轉檔會比較方便。

底下是用 mplayer dump 特定章節的範例:

mplayer dvd://1 -chapter 1-5 -dumpstream -dumpfile 01.vob

dvd://1 代表第一個標題,-chapter 1-5 表示從第一到第五個章節,輸出檔案為 01.vob。Dump 出來的 vob 檔會含 CC 字幕,之後再用 mencoder 轉成其他格式。


2012年6月16日 星期六

network manager 安裝

network manager 是 Gnome 桌面的預設網路管理服務,它可以讓使用者很方便地設定系統的網路裝置。在預設的情況下它會忽略 /etc/network/interfaces 裡的裝置,所以如果要讓 network manager 完全掌控系統上的網路裝置的話,請將 /etc/network/interfaces 清空,只留 loopback 那行。

或者修改 /etc/NetworkManager/NetworkManager.conf 設定檔,把 ifupdown 的 managed 改為 true,這樣 network manager 才會接管 /etc/network/interfaces 列出的裝置。