Monday, March 29, 2010

X application startup script with wnck

It is common that several X applications are involved for one task. For example, web browser is used for searching and help document, Emacs is used to edit, and X termainal is used for testing. Here, script can be used to startup several X programs with one command typing or click.

But simple shell script can only startup applications. You must arrange the screen layout by hand. In fact the screen layout can be program with script too. Python + wnck can be used for that.

The script as follow is an example. It startup pidgin and gnome-terminal, minimize pidgin and maximize gnome-terminal vertically. With wnck, you can arrage the layout of your X applications arbitrarily.

#!/usr/bin/python

import gobject
import gtk
import wnck
import os
import time

def gtk_wait():
gobject.idle_add(gtk.main_quit)
gtk.main()

def get_wnck_apps_from_wins(wins):
apps = set()
for win in wins:
app = win.get_application()
apps.add(app)
return list(apps)

def screen_get_wnck_apps(s):
wins = s.get_windows()
return get_wnck_apps_from_wins(wins)

def screen_find_windows_by_pid(s, pid):
wins = []
all_wins = s.get_windows()
for win in all_wins:
app = win.get_application()
if app.get_pid() == pid:
wins.append(win)
return wins

def gtk_wait_timeout():
gtk_wait()
time.sleep(0.1)

def apply_timeout(func, args, timeout = 10, wait = gtk_wait_timeout):
start = time.time()
res = None
while not res:
res = apply(func, args)
now = time.time()
if now - start > timeout:
break
wait()
return res

def wait_child_proc():
try:
os.waitpid(-1, os.WNOHANG)
except OSError, err:
if err.errno == 10: # No child processes
pass

def pid_is_valid(pid):
return os.path.exists('/proc/%d' % (pid,))

def screen_find_windows_by_pid_timeout(s, pid):
while True:
wins = apply_timeout(screen_find_windows_by_pid, (s, pid), 0.5)
if wins:
break
wait_child_proc()
if not pid_is_valid(pid):
break
return wins

def init():
global screen
screen = wnck.screen_get_default()
gtk_wait()

class app(object):
def __init__(self, pid):
self.pid = pid
self.update()
def update(self):
self.wnck_wins = screen_find_windows_by_pid_timeout(screen, self.pid)
self.wnck_apps = get_wnck_apps_from_wins(self.wnck_wins)
def minimize(self):
for win in self.wnck_wins:
win.minimize()
def maximize(self):
for win in self.wnck_wins:
wt = win.get_window_type()
if wt == wnck.WINDOW_NORMAL:
win.maximize()
def maximize_vertically(self):
for win in self.wnck_wins:
wt = win.get_window_type()
if wt == wnck.WINDOW_NORMAL:
win.maximize_vertically()
def close(self):
for win in self.wnck_wins:
win.close(0)

class app_info(object):
def __init__(self, start_argv, app_name):
object.__init__(self)
self.start_argv = start_argv
self.app_name = app_name
def get_instances(self):
pids = []
wnck_apps = screen_get_wnck_apps(screen)
for wnck_app in wnck_apps:
if wnck_app.get_name() == self.app_name:
pids.append(wnck_app.get_pid())
if pids:
return [app(pid) for pid in pids]
else:
return [self.new_instance()]
def new_instance(self):
argv = self.start_argv[:]
argv.insert(0, 'nohup')
pid = os.spawnvp(os.P_NOWAIT, 'nohup', argv)
return app(pid)

def start_apps():
pidgin_info = app_info(['pidgin'], 'Pidgin')
terminal_info = app_info(['gnome-terminal'], 'Terminal')

os.system('rm -f nohup.out ~/nohup.out')

apps = pidgin_info.get_instances()
apps = pidgin_info.get_instances()
for app in apps:
app.close()

apps = terminal_info.get_instances()
for app in apps:
app.maximize_vertically()

init()
start_apps()

Disk reading performance with hdparm

hdparm can be used to get disk reading performance with following command line:

  • hdparm -T <dev>. Get cached disk reading performance. In fact, the page cache performance is tested.
  • hdparm -t <dev>. Get raw disk reading performance.

Implementation

hdparm -T
ioctl(devfd, BLKFLSBUF, NULL);
read(devfd, buf, READING_SIZE)
do {
seek(devfd, 0, SEEK_SET);
read(devfd, buf, READING_SIZE);
} while (/* time is not over */);

Because the data to be read is in page cache always (if READING_SIZE << memory size), the result is page cache performance.

hdparm -t
ioctl(devfd, BLKFLSBUF, NULL);
do {
read(devfd, buf, READING_SIZE);
} while (/* time is not over */);

Because the data to be read is not in page cache, and the bottleneck lies in raw disk reading speed, the result is raw disk reading performance.

reading prepare *         *         *
memory copy - -
raw disk read ++++++++ ++++++++

As in above figure, reading reparation and memory copying in testing is neglectable, especially when readahead is considered.

Reading notes: Linux kernel perf event source

For Linux kernel 2.6.33

perf event enumeration

Kernel has no hardware perf event enumeration interface.

  • tools command line: perf list
  • Available abstract hardware perf events are hard-coded in perf user space tool. Raw hardware perf events are not enumerated by the tool, they can be specified via a 64-bit number in the tool command line. Abstract hardware perf events are implemented with the raw hardware perf events. Whether the abstract hardware perf events are available can be queried via syscall perf_event_open.
  • Software trace point are exported in debugfs (/debugfs/tracing/events)

perf event management

  • There is at most one perf event context for each task and each CPU. This is used to manage all perf events inside one context (task or CPU).
  • All perf events in a context are linked as list in context->event_list.
  • Perf events in one context are organized into groups. All group leaders in a context is linked as list in context->group_list. All perf events in a group is linked as list in group_leader->sibling_list.
  • It seems that perf events in the group share some attributes, such as enable/disable, cpu, inherit, etc. In "perf record", for task events, one group is created for perf events for one CPU. In __perf_event_sched_in, it is assumed perf events in one group is for one CPU. But in "perf_record", group support can not be turned on now, that is, group is not used at all now.
  • perf events inherited in child tasks are linked as list in parent_perf_event->child_list.
  • In "perf record", for task profile, for one perf event type, one perf event is created for each task and each CPU. For perf event operation, it appears that one perf event for each task is sufficient, because one task can only run on one CPU at any time. But perf events may be inherited by children perf events in children tasks (forked tasks). The children perf events use the original perf events for sample output. To make sample ring buffer a per-CPU data structure, perf events are created for each CPU too. So that, when parent and child tasks run on different CPU simultaneously, they all use perf events in parent task for output, but they use different perf events for corresponding CPU.

perf event state track

  • task schedule in/out (perf_event_task_sched_in/out). Record/disable counter before schedule out, restore/enable counter after schedule in. The schedule in/out event is recorded too.
  • task fork
    • perf_event_fork: record fork event.
    • perf_event_init_task: perf_event->attr.inherit control whether to inherit. If inheriting, child perf event will be created for child task. Children events information is accumulated in some statistics. The sample collected via children events are sent to corresponding parent events for same CPU.
  • task exit
    • perf_event_exit_task: feed back event values to parent events (child_total_time_running, etc). Free all resources for children events.
  • fd closed, perf_release: free all resources. perf event in original task is managed by corresponding fd. Children perf events in children tasks are freed in perf_event_exit_task.

Dataflow

For perf event samples:

hardware counter ---> perf event mmap data page -> user space tool (perf)
|
soft trace point -/

For ftrace and tracing point:

 software trace point -> tracing ring buffer -> user space 

User space interface

  • File based interface. File descriptor is obtained via a new syscall perf_event_open. Because one file describptor is needed for each perf event. Perf event may for a specific task, cpu, etc.
  • memory map. Sample data is passed from kernel to user space mainly via memory map. Used to implemend shared memory based ring buffer. Details are in ring buffer.
  • ring buffer
    • Work in both per-CPU and not-per-CPU mode
    • write side in kernel, read side in user space. shared memory communication between kernel and user space. It has better performance than memory copy.
    • lock-less write side, similar as Steven Rostedt's unified tracing buffer, perf_mmap_data.head is used to reserve space, while perf_mmap_data.user_page->data_head is used for committed data.

Code generation for software tracing point

  • A set of macro is defined for software tracing point related code generation, such as binary format description, trace point function generation, etc.
  • Some macros are un-defined and re-defined again and again, and some files are included again and again for different set of macro definitions. This is tricky but really powerful. Source code is in include/trace/define_trace.h and include/trace/ftrace.h.

Tracing and perf event

  • Lock-less trace ring buffer is not used in perf event, another simple ring buffer implementation for mmap data pages is used instead.
  • For software tracing point, the tracing point sample collecting code is shared between tracing and perf event.

Random thought

  • ring buffer in perf event has some special features.
    • work in both per-CPU and not-per-CPU mode
    • shared memory communication between kernel and user space, with write side in kernel and read side in user space.
  • In the code generation for software tracing point
    • macro is un-defined and re-defined again and again, and some files are included again and again for different set of macro definitions.

Thursday, March 4, 2010

SWRAP: Session WRAPper

Why we need this?

Even when working on one project, usually multiple software are needed. For example, in programming, emacs is used to edit source code, one bash is used for testing, another is used for compiling. It is tedious to startup them, open latest file, type latest command etc. screen and session management of the software can be used to facilitate this. Multiple software can be started by screen automatically if you specify them in ~/.screenrc, Latest opened files can be saved by emacs desktop mechanism, latest typed command can be remember by bash history.

But it is common to work on multiple projects simultaneously. Even if you work on just one project, you may use your computer both for work and leisure. The configuration and saved state for different projects may conflict. For example, two project may use different coding style, so that different emacs configuration are needed. The bash history from one project may flush that from another project. swrap provides a way to manage mutiple configuration and saved state for each software using a simple directory based scheme. A group of software for one project can be managed with a directory hierarchy. While multiple projects are managed with multiple directory hierarchy.

Introduction

swrap stands for Session WRAPper, it provides a directory based session management for some software. The session here incude configuration files, saved state files etc. All configuration files, saved state files and other related files for each session are put into one directory. So that you can have multiple configuration, saved state at the same time. For example, you can have multiple bash histories, one for each session. This way, if you work on multiple projects simultaneously, bash history uses in one project will not flush the bash history used in another project.

Usage

swrap <command> <session directory> [<arg1> <arg2> ...]

Where

  • <command> is software that is wrapped.
  • <session directory> is the directory to store session related file, which can be an absolute, relative path name or a directory under ~/sessions. The base name of the <session directory> will be used as the session name at least for screen.
  • <arg1> <arg2> ... are arguments for <command>.

Supported software

Bash

Configuration
  • .bashrc in session directory instead of the global one will be used if provided.
Saved state
  • A dedicated .bash_history in session directory will be used instead of the global one.

Emacs

Configuration
  • emacs_init.el in session directory will be used as initialization file in addition to the default one.
Saved state
  • Emacs desktop is used to save state, and saved state (.emacs.desktop) will be put into session directory instead of emacs startup directory or home directory.

Screen

Configuration
  • screenrc in session directory will be used as initialization file instead of default one, but the default one can be loaded in this file if desired.
  • screen is used to manage other software, so screen session can be seen as a compound session, while software run inside screen can be seen as sub-sesssion. So it is natural to make session directories for software run inside screen the sub-directories of screen session directory. These sub-directories can be specified as session directories for software run in screen in screenrc.
Saved state
  • No saved state is supported

Example

Directory "example" shows a project session directory hierarchy managed by swrap. There are 3 software in project: screen, emacs and bash. "example" is session directory for screen, "example/screenrc" is screen configuration file. "example/0" is session directory for emacs, which is in window 0 of screen. "example/1" is session directory for bash, which is in window 1 of screen. "example/screenrc" is as follow:

source ~/.screenrc

chdir ~/projects/mce/apei/firmwarekit/linuxfirmwarekit
screen -t build 1
stuff "exec swrap bash $SESSION_DIR/1""^M"
stuff "clear""^M"

screen -t emacs 0
stuff "swrap emacs $SESSION_DIR/0 --no-window-system""^M"

Where swrap is used to execute software in screen windows, and corresponding session directories are specified too.

When you execute:

  swrap screen <path to>/example 

or

  cp -r <path to>/example ~/sessions
sscreen example

You will return to your latest project state or a new project state will be created for you.

Download

swrap can be downloaded at here.

Reading notes: gnome desktop user guide

  • Overall
    • Shift and Alt is often used with mouse to change the default behavior.
  • Keyboard shortcut
    • Ctrl+Alt+D: show desktop
    • Ctrl+Alt+Tab: switch focus between desktop and panels
    • Alt+F9: Minimize window
  • In Open/Save File Dialog
    • Show Hidden Files can be toggle with right click
    • Bookmarks can be added/removed
  • When moving a panel object, alt and shift key can be used to change movement mode (switched, free, push).
  • In Nautilus spatial mode, the folder can be opened with parent folder closed with "shift" pressed. I don't like leaving too much folder windows open or closing them by hand when navigating in file hierarchy.
  • In Nautilus sptial mode, the browser mode can be entered with right click menu: "Browser Folder" on folder.
  • Search can be saved with "File -> Save Search" in Nautilus.
  • In Nautilus icon view, items can be sorted with "View -> Arrange Items -> ...".
  • In Nautilus, "glob" can be used to select items with "Edit -> Select Items Matching ...".
  • $HOME/Templates can be used to place arbitrary document templates, which can be used in "Create Document" menu in Nautilus.
  • Nautilus sripts are placed in "$HOME/.gnome2/nautilus-scripts". Some special environment variables are used to passes some infomation.
  • Custom keyboard shortcut can be added in "Keyboard Shortcuts" preference dialog directly, need not gconf-editor.

Saturday, January 30, 2010

Revise muse-index

Muse is a document writing/publishing tool for Emacs.

Muse-index can be used to show all document in a muse project. But now the file name is shown and sorted by it. I think it will be more useful if document title and create or modify time is shown and sorted by create or modify time. So I revise the muse to do that. The code can be found here.

File Synchronization between N78 and PC

My Nokia N78 have no WIFI support and local GPRS/3G data connection fee is quite high, so I can not synchronize large amount of data between N78 and PC with cloud service. I use N78 disk mode USB link to synchronize, details are as follow. Tested in Debian (gnome version 2.28).

In fact, this is not N78 specific, and can be used to sync files with any devices mountable in Linux.

Setup gnome auto-mount VFAT options

Traditionally VFAT file system is case insensitive, but can preserve case optionally, on the other hand, Linux native file system is case sensitive. So VFAT should be mounted in case sensitive mode for synchronizing software to work properly.

Gnome auto-mount VFAT options can be setup as follow:

Start gconf-editor (System tools -> Configuration editor), check key: /system/storage/default_options/vfat/mount_options, make sure there is "shortname=mixed" instead of something like "shortname=lower" (default value for some distributions) in the value. And "iocharset=utf8" should be set in mount_options too.

Setup autorun upon USB connecting

In gnome, open nautilus-file-management-properties (System -> Preferences -> File management), select tab named "Media", for media handling, set "Open Autorun Prompt" for "Software" media. I have thought gnome-volume-manager will be responsible for autorun script execution, but that is turned off in Debian, and autorun mechanism in nautilus is used instead.

Create a file named ".autorun" in the root directory of the N78 micro-SD card. This is the synchronization script.

Unidirectional synchronization via rsync

Rsync can be used for unidirectional synchronization, such as backup some directories (photos, notes etc) from N78 to PC or push some directories (music, podcast etc) vice versa.

One issue here is that VFAT time resolution is not enough for rsync. This can be fixed via specifying "—modify-window=2" in command line.

Bidirectional synchronization

It seems that unison can be used for bidirectional synchronization. But I have not tried it. Unidirectional synchronization is enough for me.

My autorun script

.autorun in N78

#!/bin/sh

/usr/local/bin/autorun_sync N78

/usr/local/bin/autorun_sync

#!/bin/sh

usage()
{
echo "Usage: $prog <media>"
}

prog=$(basename $0)

if [ $# -lt 1 ]; then
usage
echo -n "Press any key to continue:"
read
exit -1
fi

media=$1
mdir=/media/$media

ldir=$HOME/sync/$media
odir=$ldir/data_out
idir=$ldir/data_in

echo "----------------------------------------------"
echo -n "Rsyncing ..."
rsync -rutv --delete --modify-window=2 $odir/* $mdir/

if [ -f $ldir/dirs.in ]; then
while read d p; do
if [ -z "$d" ]; then
continue;
fi
rsync -rutv --modify-window=2 $p $mdir/$d $idir/
done < $ldir/dirs.in
fi
echo "Done!"
echo "----------------------------------------------"
echo -n "Syncing ..."
sync
echo "Done!"
echo "----------------------------------------------"
echo -n "Unmounting ..."
umount /media/$media
echo "Done!"
echo "----------------------------------------------"
echo -n "Done! press any key to close:"
read

$HOME/sync/N78/dirs.in

Sounds

Work with multiple devices

One big issue of working with multiple devices is synchronizing necessary information among them. For example, synchronizing the document you are writing between multiple PC (notebook, desktop, netbook, handheld), so that you can write it in any time. Synchronizing the web site you are interested between multiple PC and your phone (has web accessing). So the information need to be synchronized should include:

  • PIM information such as calendar, task and contacts etc.
  • Mails
  • Files, including the document you are writing and reading. The bookmark information about your reading progress is necessary too, this can be a reading application specific meta-data file.
  • Web bookmarks, this can be used for URL you want to read but have no time now.

One of the most convenient method to synchronize information amongst multiple devices so far is "cloud" based synchronization. One of the biggest advantages of this method is that it needs not turn on and connect two or more machines simultaneously for synchronization. The disadvantage of this method is the possibility to leak your privacy information, so should use encryption for sensitive information.

I use following cloud services:

  • Google PIM (contacts, calendar, tasks?) for PIM information. On my N78, Google PIM Moblie Sync can be setup as in Nokia Setup Instructions for Google Mobile Sync. Contacts, calendar is supported, but tasks is not supported. On Linux PC, Google PIM Sync can be setup as in How to sync Evolution with Google's PIM apps. Contacts, calendar is supported, but tasks is not supported too.
  • Google GMail for mails. Google Mobile Sync support pushing mail, but my N78 does not support it. But I don't need that too. On Linux PC, GMail can be accessed with IMAP protocol.
  • Dropbox for file synchronization. Dropbox is not opensource software, but UbuntuOne does not work under Debian so far. I may switch to UbuntuOne after it support Debian. Dropbox does not support N78. I use rsync based script to synchronize some data between N78 and my primary PC.
  • Google bookmarks for web bookmarks. N78 can access google bookmarks via web browser, but it is not convenient. Firefox GMarks addon works good with Google bookmarks on PC.

Sony VAIO P

Working on a Sony VAIO P for two days. Some thoughts are as follow.

  • The screen is very good. The backlight is better than my Lenovo Thinkpad X61T, even readable under sun light. But the viewing angle is much worse than X61T. The resolution is good too. The screen size is OK for most tasks, but sometimes I want a bigger screen.
  • It's very thin and light (about 700g?). I can hold it comfortable for hours. So it is very good to be used in holding style. X61T is a little heavy for me to hold (about 1.9kg).
  • Keyboard and trackpoint is good, although the keyboard is a little small for my big hand. I think I can get more comfortable with the keyboard size after more usage. But I hate the position of right shift key. Don't know how long will it take for me to fit in with it. I think I will not programming with it.
  • Terrible Linux support, mainly the graphics drivers. Why does Intel use such graphic card? Hope 2D open source driver ready soon.
  • The CPU of the model I used is only 800MHZ. So the performance is not very good. Not too bad, but not satisfactory too.
  • The battery life is too limited, only 2 to 3 hours.

All in all, I think Sony VAIO P is not the right choice for me. A netbook or CULV notebook with bigger keyboard and screen, longer battery life, better performance and acceptable weight (about 1kg) is better for me.

Linux Softwares for Desktop

Multimedia

EBook management
  • I need an ebook management software, like rhythmbox for musics or f-spot for photos.
Photo management
  • F-spot is an exellent software for photo management. I love it! But it is not very stable, hope it can improve with the time.
  • Comix is good for comics, although I seldom use it.
Music management
  • I think rhythmbox is good. It seems that MP3 ID3 tags editing changes some internal database instead of file itself.
  • For convert the encoding of ID3 tag of MP3 file from GBK to UTF-8, you can use python-mutagen. Command line is: "mid3iconv -e gbk .mp3".
  • To edit ID3 tags of MP3 file, exfalso is good. It seems that easytag is better?

Backup

  • I think backup2l is good for me, because it is very easy to configure.
  • I run backup2l in my working machine for periodic backuping, use rsync to synchronize the backup files to my portable backup hard disk.
  • rsync is used to backup my N78 phone information. It will be run automatically upon plug via ".autorun" mechanism.

Import/sync N78 contacts into/with Evolution

Backup N78 contacts via vcard

In address book of N78, contacts can be backupped from phone to memory card via menu. By default the backupped contacts is saved in Others/Contacts directory of micro-SD card. There is one vcard file (.vcf) for one contact.

Import vcard into Evolution

Vcard can be imported into Evolution, but only one vcard file once. To import vcard files generated by N78, the vcard files from N78 can be catenated into one vcard file, then imported into Evolution.

The vcard file generated by N78 is compatible with Evolution, that is, all information can be imported properly so far. But some information is not displayed in Evolution, and not available when accessed via python-evolution (should be not available in other libedata client too). After changing any field then change back to original value and save the "changes", evething goes OK. Appears a BUG of Evolution, hopes that can be fixed in the future.

Multple contacts in Evolution can exported into one vcard file too. Just select multiple contacts, then click "Save Contact as VCard" in menu, Or save all contacts in one address book with "Save Address Book as VCard".

Import vcard into Evolution via python

Because of the BUG of Evolution vcard importing, I try python-evolution and python-vobject to import N78 vcards into Evolution.

python-vobject is not completely compatible with the vcard 2.1 version, which is used by N78. This can be fixed with simple python scripting or via importing vcards into Evolution then exporting them because Evolution will export vcard 3.0 version file.

This method works good for me. But I encountered one issue too, the address can not be imported because EContactAddress is not wrapped properly in python-evolution yet. Hope that will be resolved in the future. Fortunately, there is only one not so important contact in my N78 address book has address field set.

Import vcard into Evolution via opensync

msynctool --addgroup evo2-file
msynctool --addmember evo2-file evo2-sync
msynctool --addmember evo2-file file-sync
msynctool --configure evo2-file 1
#
# You can keep it as default or use the address book URL in <address_path>
#
msynctool --configure evo2-file 2
#
# Set directory hold the vcard files from N78 in <path>
#

There is issue for this method too. Some information such as phone number is not displayed in imported Evolution contacts, similar with importing vcard with Evolution itself, and can be fixed in same way too. But situation is much better here, that is, more information can be displayed, at least one phone number for each contact.

Bidirectional synchronization with Evolution via opensync

After testing, I found N78 can be bidirectionally synchronized with Evolution via N78 syncml over USB. But again, there is some issues for method too. Like file-Evolution sync via opensync, some information can not be displayed correctly. But among supported object type, contact has the best support, then calendar and task, but notes must be turned off, or opensync will hang.

Firstly, setup USB device file permission for opensync user space driver. Add following lines into udev rules file or put into a rule file under rules.d directory of udev.

BUS=="usb", SYSFS{idProduct}=="007b", SYSFS{idVendor}=="0421", MODE="660", GROUP="plugdev"

Command line as follow can be used to test the USB link.

syncml-obex-client -u
# Found 2 USB OBEX interfaces
# Interface 0:
# Manufacturer: Nokia
# Product: N78
# Interface description: SYNCML-SYNC
# Interface 1:
# Manufacturer: Nokia
# Product: N78
# Interface description: PC Suite Services
syncml-obex-client -u 0 --identifier "PC Suite" --slow-sync text/x-vcard Contacts --wbxml
syncml-obex-client -u 0 --identifier "PC Suite" --slow-sync text/x-vcalendar Calendar --wbxml
syncml-obex-client -u 0 --identifier "PC Suite" --slow-sync text/plain Notes --wbxml

Command line for setup is as follow.

msynctool --addgroup n78-evo2
msynctool --addmember n78-evo2 syncml-obex-client
msynctool --addmember n78-evo2 evo2-sync
msynctool --configure n78-evo2 1
msynctool --configure n78-evo2 2
#
# You can keep it as default or use the address book URL in <address_path>
#

syncml-obex-client configuration is as follow. The notes database name should be left as empty, because notes synchronization for Evolution is not supported, opensync will hang if you set notes database name.

<?xml version="1.0"?>
<config>
<!-- (Only for bluetooth) The bluetooth address if the bluetooth mode is selected -->
<bluetooth_address></bluetooth_address>

<!-- (Only for bluetooth) The bluetooth channel to use. `sdptool browse $MAC` to search for the correct channel -->
<bluetooth_channel></bluetooth_channel>

<!-- (Only for USB) The usb interface number of the SYNCML-SYNC target. use syncml-obex-client -u (you will need access to the USB raw device) to find it. -->
<interface>0</interface>

<!-- The string that the plugin will use to identify itself. Some devices need a special string here. -->
<identifier>PC Suite</identifier>

<!-- The syncml version to use: 0 for 1.0, 1 for 1.1 and 2 for 1.2 -->
<version>1</version>

<!-- if the plugin should use wbxml -->
<wbxml>1</wbxml>

<!-- The username to use. Leave empty to not require a username -->
<username></username>

<!-- the password for the username -->
<password></password>

<!-- sets the connection type to use. 5 means obex over usb, 2 means obex over bluetooth -->
<type>5</type>

<!-- If wbxml is enabled, defines wether the wbxml should use string tables -->
<usestringtable>0</usestringtable>

<!-- Never send ADD command, but send REPLACE (not needed normally) -->
<onlyreplace>0</onlyreplace>

<!-- Workaround around for mobile phones which only use local timestamps and _no_ UTC timestamps! -->
<onlyLocaltime>0</onlyLocaltime>

<!-- Sets the maximum allowed size in bytes of incoming messages (some device need this option set). Example: 10000 -->
<recvLimit>0</recvLimit>

<maxObjSize>0</maxObjSize>

<!-- The name of the contacts db. Must be the same as the phones sends -->
<contact_db>Contacts</contact_db>

<!-- The name of the calendar db. Must be the same as the phones sends -->
<calendar_db>Calendar</calendar_db>

<!-- The name of the note db. Must be the same as the phones sends -->
<note_db></note_db>
</config>

Google Mobile Sync

The last and the best so far. I use it now. The best features of this method are as follow:

  • Works good so far, although some information is not displayed inEvolution, similar with other Evolution importing method.
  • Synchronizing automatically, periodically.
  • Wireless, Evolution side uses WIFI, and N78 side uses GPRS (because my N78 has no WIFI). Some methods above can be done in wireless way too, such as with bluetooth, with some additional work.
  • You need not keep both PC and N78 on for synchronization, because you have the third side now, the Google, in other word, the cloud.

To setup N78 side, you can refer to: Nokia Setup Instructions for Google Mobile Sync.

To setup Evolution side, you can refer to: How to sync Evolution with Google's PIM apps.

Embolden font for PDF rendering

On E-ink devices, PDF seems to be rendered a little light, the readability will improve if it can be rendered a little darker. I found a way to do that, with the "FT_Outline_Embolden", the patch for poppler can be downloaded from here.

Screenshots are as follow:

Hope useful for E-ink PDF viewer or PDF to image converter.

Cellwriter translucence and docking

Cellwriter is my primary on screen virtual keyboard now. But the docking or translucence does not work for me until recently. Now I finally find a way to make it work.

Translucence

Translucence is not the cellwriter's business in fact. It is done by a composite window manager such as compiz. To configure it in compiz, using compizconfig setting manager:

  • Enable "Regex Matching" under "Utility" section.
  • Enable "Opacity, Brightness and Saturation" under "Accessibility" section. Configure this item:
    • In "Opacity" tab page, add "Window specific settings", "class=Cellwriter" for "Windows", "50" for "Window values".
Docking

Cellwriter has full docking support in fact. But it does not work properly in metacity on x86_64. Seems there is a bug of cellwriter and an issue of metacity of gtk+.

  • Enable "window docking" in cellwriter setup.
  • Invoking cellwriter with command line option "—window-struts".
  • Apply the patches to cellwriter (1.3.4).

At first, I found _NET_WM_STRUT_PARTIAL has no effect. After comparing the window strut setting of cellwriter and gnome-panel, I found the main difference lies in data type of struts structure passed into XChangeProperty. Cellwriter uses int, while gnome-panel uses gulong. So I try gulong in cellwriter, and it works like a charm!

Although the format of struts structure passed into XChangeProperty is 32, in "man XChangeProperty", I found following words:

"If the specified format is 32, the property data must be a long array."

So format 32 should be 64-bit on 64 bit machine in fact, and struts should be long instead of int.

Friday, January 29, 2010

Switch network configuration in Debian

Home and office have different network configuration, most lies in proxy setup. A simple script as follow is used to switch configuration. Hope it is useful for someone else too.

#!/bin/bash

prog=$(basename $0)

usage()
{
echo "Usage: $prog <home|work>"
}

if [ $# -ne 1 ]; then
usage
exit -1
fi

tnet=$1
if [ $tnet != "home" -a $tnet != "work" ]; then
usage
exit -1
fi

if [ "$tnet" == "work" ]; then
sudo cp /etc/apt/apt.conf.avail/99proxy /etc/apt/apt.conf.d
gconftool-2 -s -t string /system/proxy/mode auto
else
sudo rm -f /etc/apt/apt.conf.d/99proxy
gconftool-2 -s -t string /system/proxy/mode none
fi

Gnome notify in command line

Method is copied from somebody's blog, can't remember who.

#!/usr/bin/python

import pynotify
import sys

def notify(title="Notify", message=""):
n = pynotify.Notification(title, message)
n.show()


if __name__ == '__main__':
pynotify.init("cli notify")
if len(sys.argv) > 1:
title = sys.argv[1]
msg = " ".join(sys.argv[2:])
notify(title, msg)
else:
notify()

Switch distribution version in Debian

Use testing version of Debian as my primary working environment. But some softwares are available only in sid version, and bugs are fixed in sid firstly. So switching between testing and sid is routine. A simple script as follow is used to simplify/accelerate the operation.

#!/bin/sh

prog=$(basename $0)

usage()
{
echo "Usage: $prog <testing|sid>"
}

current_dist()
{
if grep sid /etc/apt/sources.list > /dev/null; then
echo sid
else
echo testing
fi
}

if [ $# -ne 1 ]; then
usage
exit -1
fi

tdist=$1
if [ $tdist != "sid" -a $tdist != "testing" ]; then
usage
exit -1
fi

cdist=$(current_dist)
if [ "$tdist" != "$cdist" ]; then
cp /etc/apt/sources.list.$tdist /etc/apt/sources.list
mv /var/lib/apt/lists /var/lib/apt/lists.$cdist
if [ -d /var/lib/apt/lists.$tdist ]; then
mv /var/lib/apt/lists.$tdist /var/lib/apt/lists
fi
fi

apt-get update