<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Hello World &#187; 技术</title>
	<atom:link href="http://blog.sunner.cn/category/tech/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.sunner.cn</link>
	<description>孙志岗的博客</description>
	<lastBuildDate>Fri, 03 Feb 2012 03:13:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>自动同步wordpress的文章到哈工大独立博客</title>
		<link>http://blog.sunner.cn/cross-post-from-wordpress-to-metaweblog/</link>
		<comments>http://blog.sunner.cn/cross-post-from-wordpress-to-metaweblog/#comments</comments>
		<pubDate>Wed, 23 Feb 2011 09:08:55 +0000</pubDate>
		<dc:creator>Sunner</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://blog.sunner.cn/?p=868</guid>
		<description><![CDATA[哈工大独立博客静悄悄地开张很久了。它的域名很惹眼，便注册了一个。稍加了解发现，这个博客在工大范围内的传播能力还是比较强的，只要你发的博文又好又和谐，被管理员推荐，就会登上今日哈工大的首页，访问量会增加不少。不过，我当然舍不得更惹眼的sunner.cn，也舍不得wordpress，所以就寻找在wordpress发文，自动同步到工大独立博客的方案。 工大独立博客支持MetaWeblog API，但可惜这个API太老了，wordpress里所有对它的插件现在都失效了。本着“编程，让生活更美好”的精神，就自己做了一个插件，把新发的文章立即也在独立博客发一份，日后修改文章也能自动同步。此外，发往独立博客的文章末尾还自动添加一条链接指向原始博文，方便读者过来留言。 插件已经用了个把月了，挺稳定，就发布出来了。地址是：https://github.com/sunner/cross-post-to-metaweblog。按照README安装就行了。]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.hit.edu.cn">哈工大独立博客</a>静悄悄地开张很久了。它的域名很惹眼，便注册了<a href="http://blog.hit.edu.cn/sunner">一个</a>。稍加了解发现，这个博客在工大范围内的传播能力还是比较强的，只要你发的博文又好又和谐，被管理员推荐，就会登上<a href="http://today.hit.edu.cn">今日哈工大</a>的首页，访问量会增加不少。不过，我当然舍不得更惹眼的sunner.cn，也舍不得wordpress，所以就寻找在wordpress发文，自动同步到工大独立博客的方案。</p>
<p>工大独立博客支持MetaWeblog API，但可惜这个API太老了，wordpress里所有对它的插件现在都失效了。本着“编程，让生活更美好”的精神，就自己做了一个插件，把新发的文章立即也在独立博客发一份，日后修改文章也能自动同步。此外，发往独立博客的文章末尾还自动添加一条链接指向原始博文，方便读者过来留言。</p>
<p>插件已经用了个把月了，挺稳定，就发布出来了。地址是：<a href="https://github.com/sunner/cross-post-to-metaweblog">https://github.com/sunner/cross-post-to-metaweblog</a>。按照README安装就行了。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sunner.cn/cross-post-from-wordpress-to-metaweblog/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Moodle 2.0值得关注的新特性</title>
		<link>http://blog.sunner.cn/moodle-2-0-new-features/</link>
		<comments>http://blog.sunner.cn/moodle-2-0-new-features/#comments</comments>
		<pubDate>Wed, 06 Oct 2010 02:50:01 +0000</pubDate>
		<dc:creator>Sunner</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[moodle_dev]]></category>
		<category><![CDATA[moodle_using]]></category>

		<guid isPermaLink="false">http://blog.sunner.cn/?p=585</guid>
		<description><![CDATA[2.0是Moodle历史上最大的一次升级，已经发布了RC1版，期望一个月后能正式发布。现在moodle.org就在运行Moodle 2.0，说明它已经能在开发人员的监管下稳定工作。 目前已经有三个可以公开访问的运行2.0的网站，除了moodle.org，还有lang.moodle.org（Moodle的协同翻译平台，注册后就能参与），和qa.moodle.net（公测网站，每个人都可以用管理员、教师或学生身份登录）。通过使用这三个网站，以及Release Notes，对Moodle 2.0已经有了一些感受。 视觉上的主要变化是更漂亮和方便了。2.0官方提供的主题风格的数量和质量都有很大的提升，而且主题本身还可以提供个性化的功能。比如版块不再是只能傻傻地贴在页面上，用户可以把它放到一个停靠栏里，需要的时候才弹出来，很节约空间。 “导航版块”能让用户非常方便地直接进入不同课程的不同活动。“设置版块”有上下文感知能力，会根据你所处的位置不同自动变为最相关的选项。 旧的HTML编辑器被抛弃，换用TinyMCE。它不仅对各种浏览器的支持更好，排版功能更强（比如支持layer、CSS自定义），而且支持可视化的公式编辑，这个太有必要了！ 旧的基于目录的文件管理被“容器”替代。从用户角度看，当需要使用文件的时候，只需从它所在的容器选择它。容器的种类很多，可以是自己上传的文件和目录，也可以提供一个url让moodle自己下载，还可以是从Google Docs、DropBox、Youtube等导入。当然，最主要的导入功能在中国是别指望用了。所有导入的文件都会自动和文件源保持同步。从开发者的角度看，文件不再是以目录、子目录的形式组织，而是被后台用hash一类的方法管理。好处是重复的文件会只有一份，缺点是不能再通过直接访问文件系统来处理文件了。 “活动完成状态跟踪”和“条件”对授课会很有帮助。它可以强制要求学生必须先做完某件事，才能再做另一件。比如，必须先参加一个投票，才能提交某个作业；完成作业1，才能做作业2；如果作业1得分高，可以做作业2，否则做作业3……。这个功能亦扩展到课程级别，从而开始支持先修课。 “反抄袭”功能有了内置API，既可以通过插件的方式扩充多种反抄袭手段，也让任何功能模块都可以调用反抄袭的API。看来与抄袭的斗争已经是世界性的了。 “信息反馈”模块第一次成为标准模块。用它可以自定义各种形式的调查问卷，而不像旧的“问卷调查”模块只能设置固定的几个问题。 表面的主要变化并不是很大，最重的都在后台。比如开始支持Web Service，这使得Moodle可以更好地和其它系统交互，也更便于移动客户端的开发；“备份和恢复”功能完全重写；Wiki完全重写；Workshop完全重写…… 后台的变化意味着它需要更多的测试。估计一年以后俺的乐学网就可以升级到2.0了。在此期间，得把在线评测和反抄袭做个移植。因为底层的变化太多，这个移植动作实在不小，有兴趣的欢迎加入开发！]]></description>
			<content:encoded><![CDATA[<p>2.0是Moodle历史上最大的一次升级，已经发布了<a href="http://docs.moodle.org/en/Moodle_2.0_Release_Candidate_1_release_notes">RC1版</a>，期望一个月后能正式发布。现在<a href="http://moodle.org">moodle.org</a>就在运行Moodle 2.0，说明它已经能在开发人员的监管下稳定工作。</p>
<p>目前已经有三个可以公开访问的运行2.0的网站，除了<a href="http://moodle.org">moodle.org</a>，还有<a href="http://lang.moodle.org">lang.moodle.org</a>（Moodle的协同翻译平台，注册后就能参与），和<a href="http://qa.moodle.net/">qa.moodle.net</a>（公测网站，每个人都可以用管理员、教师或学生身份登录）。通过使用这三个网站，以及<a href="http://docs.moodle.org/en/Moodle_2.0_release_notes">Release Notes</a>，对Moodle 2.0已经有了一些感受。</p>
<p>视觉上的主要变化是更漂亮和方便了。2.0官方提供的主题风格的数量和质量都有很大的提升，而且主题本身还可以提供个性化的功能。比如版块不再是只能傻傻地贴在页面上，用户可以把它放到一个停靠栏里，需要的时候才弹出来，很节约空间。</p>
<p>“导航版块”能让用户非常方便地直接进入不同课程的不同活动。“设置版块”有上下文感知能力，会根据你所处的位置不同自动变为最相关的选项。</p>
<p>旧的HTML编辑器被抛弃，换用TinyMCE。它不仅对各种浏览器的支持更好，排版功能更强（比如支持layer、CSS自定义），而且支持可视化的公式编辑，这个太有必要了！</p>
<p>旧的基于目录的文件管理被“容器”替代。从用户角度看，当需要使用文件的时候，只需从它所在的容器选择它。容器的种类很多，可以是自己上传的文件和目录，也可以提供一个url让moodle自己下载，还可以是从Google Docs、DropBox、Youtube等导入。当然，最主要的导入功能在中国是别指望用了。所有导入的文件都会自动和文件源保持同步。从开发者的角度看，文件不再是以目录、子目录的形式组织，而是被后台用hash一类的方法管理。好处是重复的文件会只有一份，缺点是不能再通过直接访问文件系统来处理文件了。</p>
<p>“活动完成状态跟踪”和“条件”对授课会很有帮助。它可以强制要求学生必须先做完某件事，才能再做另一件。比如，必须先参加一个投票，才能提交某个作业；完成作业1，才能做作业2；如果作业1得分高，可以做作业2，否则做作业3……。这个功能亦扩展到课程级别，从而开始支持先修课。</p>
<p>“反抄袭”功能有了内置API，既可以通过插件的方式扩充多种反抄袭手段，也让任何功能模块都可以调用反抄袭的API。看来与抄袭的斗争已经是世界性的了。</p>
<p>“信息反馈”模块第一次成为标准模块。用它可以自定义各种形式的调查问卷，而不像旧的“问卷调查”模块只能设置固定的几个问题。</p>
<p>表面的主要变化并不是很大，最重的都在后台。比如开始支持Web Service，这使得Moodle可以更好地和其它系统交互，也更便于移动客户端的开发；“备份和恢复”功能完全重写；Wiki完全重写；Workshop完全重写……</p>
<p>后台的变化意味着它需要更多的测试。估计一年以后俺的乐学网就可以升级到2.0了。在此期间，得把<a href="http://code.google.com/p/sunner-projects/">在线评测和反抄袭</a>做个移植。因为底层的变化太多，这个移植动作实在不小，有兴趣的欢迎加入开发！</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sunner.cn/moodle-2-0-new-features/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Moodle插件“热点提问 1.0”发布</title>
		<link>http://blog.sunner.cn/moodle-activity-module-hot-question-1-0-released/</link>
		<comments>http://blog.sunner.cn/moodle-activity-module-hot-question-1-0-released/#comments</comments>
		<pubDate>Sun, 19 Sep 2010 06:26:27 +0000</pubDate>
		<dc:creator>Sunner</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[moodle_dev]]></category>

		<guid isPermaLink="false">http://blog.sunner.cn/?p=571</guid>
		<description><![CDATA[这可能是Moodle第一个为教室服务的插件。其设计灵感来自于普渡大学的Hotseat。 课堂互动是目前教学工作中比较强调的一件事。但中国学生的性格内敛、羞涩，在提问前经常会瞻前顾后，顾虑较多，导致提问不够踊跃，难以形成良好的互动。本插件就是为解决此问题而设计。 在“热点提问”中，学生可以像发微博一样地提问，而且可以匿名提问。还可以对别人的提问投票。教师可以根据投票结果获知学生对什么问题最感兴趣，就能更有选择性地回答学生的问题。 我已经用了两次课，效果还不错。能在上课时访问网络的学生还是不多，所以参与度目前还不算高。可以到这里围观它。 此插件可以在这里下载。这里有安装说明。]]></description>
			<content:encoded><![CDATA[<p>这可能是Moodle第一个为教室服务的插件。其设计灵感来自于普渡大学的<a href="http://www.itap.purdue.edu/tlt/hotseat/">Hotseat</a>。</p>
<p>课堂互动是目前教学工作中比较强调的一件事。但中国学生的性格内敛、羞涩，在提问前经常会瞻前顾后，顾虑较多，导致提问不够踊跃，难以形成良好的互动。本插件就是为解决此问题而设计。</p>
<p>在“热点提问”中，学生可以像发微博一样地提问，而且可以匿名提问。还可以对别人的提问投票。教师可以根据投票结果获知学生对什么问题最感兴趣，就能更有选择性地回答学生的问题。</p>
<p>我已经用了两次课，效果还不错。能在上课时访问网络的学生还是不多，所以参与度目前还不算高。可以到<a href="http://cms.hit.edu.cn/mod/hotquestion/view.php?id=2957">这里</a>围观它。</p>
<p>此插件可以在<a href="http://code.google.com/p/sunner-projects/downloads/list?q=label:hotquestion">这里下载</a>。<a href="http://code.google.com/p/sunner-projects/wiki/HotQuestionActivity">这里</a>有安装说明。</p>
<p style="text-align: center;"><a href="http://blog.sunner.cn/wp-content/uploads/2010/09/hot-question.jpg"><img class="aligncenter size-full wp-image-572" title="hot-question" src="http://blog.sunner.cn/wp-content/uploads/2010/09/hot-question.jpg" alt="" width="607" height="469" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sunner.cn/moodle-activity-module-hot-question-1-0-released/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>在Linux下用ffmpeg自拍课程录像</title>
		<link>http://blog.sunner.cn/screencast-lecture-in-linux/</link>
		<comments>http://blog.sunner.cn/screencast-lecture-in-linux/#comments</comments>
		<pubDate>Thu, 16 Sep 2010 03:09:39 +0000</pubDate>
		<dc:creator>Sunner</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blog.sunner.cn/?p=564</guid>
		<description><![CDATA[某一天突然觉得，上课时直接用电脑自己把屏幕信息录下来，并同步录音，就能做出很不错的课程录像了，而且成本超级低。于是乎，折腾了一番。 因为我的操作系统课全程在Linux下放幻灯片、做演示，所以当然就寻找Linux下的解决方案。 首先试验了xvidcap，它支持命令行和图形界面两种方式，能同步录音和录像，支持多种编码，2006年开始停止更新。最先遇到的问题是不能录音，几经周折发现只有在音频编码设为pcm16的时候才能录音。然后遇到的问题是不稳定，连续工作一会儿就segment fault。于是放弃。 然后试验了recordmydesktop，它是命令行的，有图形前端，能同步录像和录音，只支持ogv编码和格式，2008年停止更新。它的问题是编码器的CPU消耗太高，我把帧率设成1，才能正常地实时编码。它支持先无损压缩捕获，然后再编码的方式，但因为下课就得走人，没那么多时间给它。从它的源码里发现一个未公开的参数&#8211;no-encode，捕获完毕直接退出，以后可以用&#8211;rescue参数慢慢编码。看上去很美，但&#8211;rescue的结果就是segment fault。调了调代码，没搞定，于是放弃。 开始慨叹咋就没一个像windows下Camtasia那样好用的呢？又几经周折，居然发现ffmpeg就能录！而且几乎100%满足我的需求！下面的脚本就是干这个的： #!/bin/sh &#160; wait_til&#40;&#41; &#123; CURRENT=$&#40;date +%s&#41; TARGET=$&#40;date -d &#34;$1&#34; +%s&#41; &#160; SECONDS=$&#40;&#40;$TARGET - $CURRENT&#41;&#41; &#160; if &#91; $SECONDS -lt 0 &#93;; then SECONDS=0 fi &#160; sleep &#34;$SECONDS&#34; &#125; &#160; WORKDIR=~/podcast FILENAME=lecture_`date +%Y%m%d_%H%M`.mkv &#160; if &#91; &#34;$1&#34; != &#34;&#34; &#93;; then wait_til $1 fi &#160; cd $WORKDIR ffmpeg -f [...]]]></description>
			<content:encoded><![CDATA[<p>某一天突然觉得，上课时直接用电脑自己把屏幕信息录下来，并同步录音，就能做出很不错的课程录像了，而且成本超级低。于是乎，折腾了一番。</p>
<p>因为我的<a href="http://cms.hit.edu.cn/course/view.php?id=44">操作系统课</a>全程在Linux下放幻灯片、做演示，所以当然就寻找Linux下的解决方案。</p>
<p>首先试验了<a href="http://xvidcap.sourceforge.net/">xvidcap</a>，它支持命令行和图形界面两种方式，能同步录音和录像，支持多种编码，2006年开始停止更新。最先遇到的问题是不能录音，几经周折发现只有在音频编码设为pcm16的时候才能录音。然后遇到的问题是不稳定，连续工作一会儿就segment fault。于是放弃。</p>
<p>然后试验了<a href="http://recordmydesktop.sourceforge.net/about.php">recordmydesktop</a>，它是命令行的，有图形前端，能同步录像和录音，只支持ogv编码和格式，2008年停止更新。它的问题是编码器的CPU消耗太高，我把帧率设成1，才能正常地实时编码。它支持先无损压缩捕获，然后再编码的方式，但因为下课就得走人，没那么多时间给它。从它的源码里发现一个未公开的参数&#8211;no-encode，捕获完毕直接退出，以后可以用&#8211;rescue参数慢慢编码。看上去很美，但&#8211;rescue的结果就是segment fault。调了调代码，没搞定，于是放弃。</p>
<p>开始慨叹咋就没一个像windows下<a href="http://www.techsmith.com/camtasia.asp">Camtasia</a>那样好用的呢？又几经周折，居然发现ffmpeg就能录！而且几乎100%满足我的需求！下面的脚本就是干这个的：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
&nbsp;
wait_til<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#123;</span>
    <span style="color: #007800;">CURRENT</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">date</span> +<span style="color: #000000; font-weight: bold;">%</span>s<span style="color: #7a0874; font-weight: bold;">&#41;</span>
    <span style="color: #007800;">TARGET</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">date</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;$1&quot;</span> +<span style="color: #000000; font-weight: bold;">%</span>s<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
    <span style="color: #007800;">SECONDS</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">$TARGET</span> - <span style="color: #007800;">$CURRENT</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$SECONDS</span> <span style="color: #660033;">-lt</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #007800;">SECONDS</span>=<span style="color: #000000;">0</span>
    <span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
    <span style="color: #c20cb9; font-weight: bold;">sleep</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$SECONDS</span>&quot;</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #007800;">WORKDIR</span>=~<span style="color: #000000; font-weight: bold;">/</span>podcast
<span style="color: #007800;">FILENAME</span>=lecture_<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">date</span> +<span style="color: #000000; font-weight: bold;">%</span>Y<span style="color: #000000; font-weight: bold;">%</span>m<span style="color: #000000; font-weight: bold;">%</span>d_<span style="color: #000000; font-weight: bold;">%</span>H<span style="color: #000000; font-weight: bold;">%</span>M<span style="color: #000000; font-weight: bold;">`</span>.mkv
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
    wait_til <span style="color: #007800;">$1</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$WORKDIR</span>
<span style="color: #c20cb9; font-weight: bold;">ffmpeg</span> <span style="color: #660033;">-f</span> alsa <span style="color: #660033;">-ac</span> <span style="color: #000000;">1</span> <span style="color: #660033;">-i</span> pulse <span style="color: #660033;">-f</span> x11grab <span style="color: #660033;">-r</span> <span style="color: #000000;">10</span> <span style="color: #660033;">-s</span> 1024x768 <span style="color: #660033;">-i</span> :<span style="color: #000000;">0.0</span> <span style="color: #660033;">-acodec</span> pcm_s16le <span style="color: #660033;">-vcodec</span> libx264 <span style="color: #660033;">-vpre</span> lossless_ultrafast <span style="color: #660033;">-s</span> 512x384 <span style="color: #660033;">-threads</span> <span style="color: #000000;">0</span> <span style="color: #007800;">$FILENAME</span></pre></div></div>

<p>将代码存为capscreen文件，赋予执行权限，然后在命令行输入capscreen命令就立刻开始录像了。录好的文件存放在~/podcast中，文件名是“class_日期_时间.mkv”。capscreen后如果加上一个时间参数，就是等到该时刻才开始录像。比如“capscreen 8:00”就是早8点整开始。</p>
<p>这个脚本为了节约CPU资源（我上课用的是上网本，atom cpu，实在能力不足），设定的是图像无损压缩，音频不压缩，帧率10，屏幕分辨率1024&#215;768，视频文件分辨率512&#215;384。过后，可以再用ffmpeg重新编码，制作出适合各种情况的视频，详情请参考<a href="http://ubuntuforums.org/showthread.php?t=1392026">这里</a>。如果CPU够劲，可以忽略后期过程，直接输出最终格式，再配合上传脚本，或者nfs、smb一类的网络文件系统，以最快的速度发布。每个教室里的教师机都应该考虑搞个类似的东西。</p>
<p>缺点：</p>
<ol>
<li>鼠标指针始终都是一个箭头，而且不能隐藏。这个据说新版ffmpeg已经能处理了。懒得自己编译了，等ubuntu 10.10吧</li>
<li>不能融合摄像头，做出camtasia那样的画中画功能</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.sunner.cn/screencast-lecture-in-linux/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>增加可被LKM调用的内核函数</title>
		<link>http://blog.sunner.cn/more-kernel-functions-called-by-lkm/</link>
		<comments>http://blog.sunner.cn/more-kernel-functions-called-by-lkm/#comments</comments>
		<pubDate>Mon, 13 Sep 2010 05:32:48 +0000</pubDate>
		<dc:creator>Sunner</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blog.sunner.cn/?p=558</guid>
		<description><![CDATA[LKM(Loadable Kernel Module)可以调用的内核函数及变量都列在/usr/src/linux-headers-xxxxxxxxx/Module.symvers里。有些资料说是在/proc/kallsyms里，这是不对的。kallsyms里列出的是内核中的各种符号，但并不是所有的符号都可以被LKM调用。如果使用了不可用的符号，insmod的时候会报错：Unknown symbol in module 如果想调用Module.symvers以外的内核函数，必须修改内核。找到该函数，在函数结束的“}”后加上一行： EXPORT_SYMBOL&#40;funcname&#41;; 在LKM的源文件中，用extern声明一下该函数。如果这个函数是系统调用，在extern后面还要加上asmlinkage，否则参数不会正确传递。]]></description>
			<content:encoded><![CDATA[<p>LKM(Loadable Kernel Module)可以调用的内核函数及变量都列在/usr/src/linux-headers-xxxxxxxxx/Module.symvers里。有些资料说是在/proc/kallsyms里，这是不对的。kallsyms里列出的是内核中的各种符号，但并不是所有的符号都可以被LKM调用。如果使用了不可用的符号，insmod的时候会报错：Unknown symbol in module</p>
<p>如果想调用Module.symvers以外的内核函数，必须修改内核。找到该函数，在函数结束的“}”后加上一行：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">EXPORT_SYMBOL<span style="color: #009900;">&#40;</span>funcname<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>在LKM的源文件中，用extern声明一下该函数。如果这个函数是系统调用，在extern后面还要加上asmlinkage，否则参数不会正确传递。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sunner.cn/more-kernel-functions-called-by-lkm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>强制Makefile中的一条必须执行</title>
		<link>http://blog.sunner.cn/force-makefile/</link>
		<comments>http://blog.sunner.cn/force-makefile/#comments</comments>
		<pubDate>Sun, 05 Sep 2010 04:49:39 +0000</pubDate>
		<dc:creator>Sunner</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blog.sunner.cn/?p=546</guid>
		<description><![CDATA[一个工程有多个子目录。每个子目录下都有一个Makefile，将该子目录下的源代码编译为一个.o文件。根目录下的Makefile控制将这些.o链接到一起形成最终的执行文件。执行文件只依赖.o文件，对每个.o的处理规则都是进入其子目录然后make。这种布局会遇到一个问题，就是子目录里有源码的修改，根目录Makefile定义的依赖关系里检测不到，就不会重新编译。被这个问题困扰很久，今天看qt的Makefile，发现了一个很巧的解决方法。 subdir1/sub1.o: FORCE cd subdir1 &#38;&#38; make &#160; subdir2/sub2.o: FORCE cd subdir2 &#38;&#38; make &#160; FORCE:]]></description>
			<content:encoded><![CDATA[<p>一个工程有多个子目录。每个子目录下都有一个Makefile，将该子目录下的源代码编译为一个.o文件。根目录下的Makefile控制将这些.o链接到一起形成最终的执行文件。执行文件只依赖.o文件，对每个.o的处理规则都是进入其子目录然后make。这种布局会遇到一个问题，就是子目录里有源码的修改，根目录Makefile定义的依赖关系里检测不到，就不会重新编译。被这个问题困扰很久，今天看qt的Makefile，发现了一个很巧的解决方法。</p>

<div class="wp_syntax"><div class="code"><pre class="makefile" style="font-family:monospace;">subdir1/sub1.o: FORCE
    cd subdir1 &amp;&amp; make
&nbsp;
subdir2/sub2.o: FORCE
    cd subdir2 &amp;&amp; make
&nbsp;
FORCE:</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.sunner.cn/force-makefile/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android内核开发的几个便捷命令</title>
		<link>http://blog.sunner.cn/android-kernel-development-env/</link>
		<comments>http://blog.sunner.cn/android-kernel-development-env/#comments</comments>
		<pubDate>Thu, 02 Sep 2010 10:48:32 +0000</pubDate>
		<dc:creator>Sunner</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[android]]></category>

		<guid isPermaLink="false">http://blog.sunner.cn/?p=541</guid>
		<description><![CDATA[在android源码的根目录下执行: . build/envsetup.sh 可以获得下列非常方便的命令： croot:   Changes directory to the top of the tree. m:       Makes from the top of the tree. mm:      Builds all of the modules in the current directory. mmm:     Builds all of the modules in the supplied directories. cgrep:   Greps on all local [...]]]></description>
			<content:encoded><![CDATA[<p>在android源码的根目录下执行:</p>
<p>. build/envsetup.sh</p>
<p>可以获得下列非常方便的命令：</p>
<div id="_mcePaste">croot:   Changes directory to the top of the tree.</div>
<div id="_mcePaste">m:       Makes from the top of the tree.</div>
<div id="_mcePaste">mm:      Builds all of the modules in the current directory.</div>
<div id="_mcePaste">mmm:     Builds all of the modules in the supplied directories.</div>
<div id="_mcePaste">cgrep:   Greps on all local C/C++ files.</div>
<div id="_mcePaste">jgrep:   Greps on all local Java files.</div>
<div id="_mcePaste">resgrep: Greps on all local res/*.xml files.</div>
<div id="_mcePaste">godir:   Go to the directory containing a file.</div>
<p>当我第一次获知它们的时候，内流满面啊……</p>
<p>用“help”命令可以获知更多……</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sunner.cn/android-kernel-development-env/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Android 2.2 (Froyo) 中文联系人拼音检索增强补丁</title>
		<link>http://blog.sunner.cn/patch-for-android-2-2-froyo-enchance-lookuping-chinese-contacts/</link>
		<comments>http://blog.sunner.cn/patch-for-android-2-2-froyo-enchance-lookuping-chinese-contacts/#comments</comments>
		<pubDate>Fri, 20 Aug 2010 10:36:37 +0000</pubDate>
		<dc:creator>Sunner</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[android]]></category>

		<guid isPermaLink="false">http://blog.sunner.cn/?p=523</guid>
		<description><![CDATA[Froyo终于开始官方支持在任何系统语言下都能把中文联系人按照拼音顺序排序，并且支持全拼和简拼（可以从名字中间任意一字的拼音开始）检索。这要感谢一位叫Bai Tao的工程师。 不过，google的改进有一点不如我以前的补丁，只是很小的一点，就是用“gdg”可以搜索到“郭德纲”，而“gdgang”不行。gdgang这种简全混合的模式在同一简拼的联系人较多的时候，只要比纯简拼多敲1-2个字符，就能让检索的结果好很多。比如“gdga”可以过滤掉郭得乖、国大贵、关定格等等。 下面这个补丁，就补全了这个功能： --- a/src/com/android/providers/contacts/ContactLocaleUtils.java +++ b/src/com/android/providers/contacts/ContactLocaleUtils.java @@ -102,7 +102,13 @@ public class ContactLocaleUtils &#123; final Token token = tokens.get&#40;i&#41;; if &#40;Token.PINYIN == token.type&#41; &#123; keyPinyin.insert&#40;0, token.target&#41;; - keyInitial.insert&#40;0, token.target.charAt&#40;0&#41;&#41;; + if &#40;i == tokenCount - 1&#41; &#123; + // Use all characters of the last token + keyInitial.insert&#40;0, token.target&#41;; + &#125; else &#123; [...]]]></description>
			<content:encoded><![CDATA[<p>Froyo终于开始官方支持在任何系统语言下都能把中文联系人按照拼音顺序排序，并且支持全拼和简拼（可以从名字中间任意一字的拼音开始）检索。这要感谢一位叫<a href="http://android.git.kernel.org/?p=platform/packages/providers/ContactsProvider.git;a=history;f=src/com/android/providers/contacts/ContactLocaleUtils.java;h=1c2ad979efdef07f7bcc2354e8f5656c51b8dd51;hb=HEAD">Bai Tao</a>的工程师。</p>
<p>不过，google的改进有一点不如我以前的补丁，只是很小的一点，就是用“gdg”可以搜索到“郭德纲”，而“gdgang”不行。gdgang这种简全混合的模式在同一简拼的联系人较多的时候，只要比纯简拼多敲1-2个字符，就能让检索的结果好很多。比如“gdga”可以过滤掉郭得乖、国大贵、关定格等等。</p>
<p>下面这个补丁，就补全了这个功能：</p>

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;"><span style="color: #888822;">--- a/src/com/android/providers/contacts/ContactLocaleUtils.java</span>
<span style="color: #888822;">+++ b/src/com/android/providers/contacts/ContactLocaleUtils.java</span>
<span style="color: #440088;">@@ -102,7 +102,13 @@ public class ContactLocaleUtils <span style="">&#123;</span></span>
                 final Token token = tokens.get<span style="">&#40;</span>i<span style="">&#41;</span>;
                 if <span style="">&#40;</span>Token.PINYIN == token.type<span style="">&#41;</span> <span style="">&#123;</span>
                     keyPinyin.insert<span style="">&#40;</span><span style="">0</span>, token.target<span style="">&#41;</span>;
<span style="color: #991111;">-                    keyInitial.insert<span style="">&#40;</span><span style="">0</span>, token.target.charAt<span style="">&#40;</span><span style="">0</span><span style="">&#41;</span><span style="">&#41;</span>;</span>
<span style="color: #00b000;">+                    if <span style="">&#40;</span>i == tokenCount - 1<span style="">&#41;</span> <span style="">&#123;</span></span>
<span style="color: #00b000;">+                        // Use all characters of the last token</span>
<span style="color: #00b000;">+                        keyInitial.insert<span style="">&#40;</span><span style="">0</span>, token.target<span style="">&#41;</span>;</span>
<span style="color: #00b000;">+                    <span style="">&#125;</span> else <span style="">&#123;</span></span>
<span style="color: #00b000;">+                        // Use the first character of other tokens</span>
<span style="color: #00b000;">+                        keyInitial.insert<span style="">&#40;</span><span style="">0</span>, token.target.charAt<span style="">&#40;</span><span style="">0</span><span style="">&#41;</span><span style="">&#41;</span>;</span>
<span style="color: #00b000;">+                    <span style="">&#125;</span></span>
                 <span style="">&#125;</span> else if <span style="">&#40;</span>Token.LATIN == token.type<span style="">&#41;</span> <span style="">&#123;</span>
                     // Avoid adding space at the end of String.
                     if <span style="">&#40;</span>keyPinyin.length<span style="">&#40;</span><span style="">&#41;</span> &gt; <span style="">0</span><span style="">&#41;</span> <span style="">&#123;</span>
<span style="color: #440088;">@@ -112,7 +118,13 @@ public class ContactLocaleUtils <span style="">&#123;</span></span>
                         keyOrignal.insert<span style="">&#40;</span><span style="">0</span>, ' '<span style="">&#41;</span>;
                     <span style="">&#125;</span>
                     keyPinyin.insert<span style="">&#40;</span><span style="">0</span>, token.source<span style="">&#41;</span>;
<span style="color: #991111;">-                    keyInitial.insert<span style="">&#40;</span><span style="">0</span>, token.source.charAt<span style="">&#40;</span><span style="">0</span><span style="">&#41;</span><span style="">&#41;</span>;</span>
<span style="color: #00b000;">+                    if <span style="">&#40;</span>i == tokenCount - 1<span style="">&#41;</span> <span style="">&#123;</span></span>
<span style="color: #00b000;">+                        // Use all characters of the last token</span>
<span style="color: #00b000;">+                        keyInitial.insert<span style="">&#40;</span><span style="">0</span>, token.source<span style="">&#41;</span>;</span>
<span style="color: #00b000;">+                    <span style="">&#125;</span> else <span style="">&#123;</span></span>
<span style="color: #00b000;">+                        // Use the first character of other tokens</span>
<span style="color: #00b000;">+                        keyInitial.insert<span style="">&#40;</span><span style="">0</span>, token.source.charAt<span style="">&#40;</span><span style="">0</span><span style="">&#41;</span><span style="">&#41;</span>;</span>
<span style="color: #00b000;">+                    <span style="">&#125;</span></span>
                 <span style="">&#125;</span>
                 keyOrignal.insert<span style="">&#40;</span><span style="">0</span>, token.source<span style="">&#41;</span>;
                 keys.add<span style="">&#40;</span>keyOrignal.toString<span style="">&#40;</span><span style="">&#41;</span><span style="">&#41;</span>;</pre></div></div>

<p>我已经编译好一个，安装方法如下：</p>
<ol>
<li>下载<a href="http://blog.sunner.cn/wp-content/uploads/2010/08/ContactsProvider.apk">ContactsProvider.apk</a>，通过adb、Root Explorer等覆盖Android系统的/system/app/下的同名文件；或者下载<a href="http://blog.sunner.cn/wp-content/uploads/2010/08/pyin-patch-froyo-0.1.zip">pyin-patch-froyo-0.1.zip</a>，用刷rom的方法刷一下。</li>
<li>更改两次系统的语言（比如：中文-&gt;英文-&gt;中文），并且更改后等一小会儿，让系统在后台刷新联系人检索关键词数据库。</li>
<li>搞定！</li>
</ol>
<p>以上内容在CM 6.0 RC3 for G1测试通过。理论上说，只要是2.2的Rom应该都能用，除非厂商自己在ContactsProvider里动了手脚。</p>
<p>欢迎反馈使用情况。如果比较多人喜欢这个，可以考虑提交给google&#8230;&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sunner.cn/patch-for-android-2-2-froyo-enchance-lookuping-chinese-contacts/feed/</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
		<item>
		<title>Linux内核源码中寻找系统调用入口</title>
		<link>http://blog.sunner.cn/search-syscall-entries-in-linux-kernel-source/</link>
		<comments>http://blog.sunner.cn/search-syscall-entries-in-linux-kernel-source/#comments</comments>
		<pubDate>Sun, 15 Aug 2010 04:24:52 +0000</pubDate>
		<dc:creator>Sunner</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blog.sunner.cn/?p=515</guid>
		<description><![CDATA[在内核源码目录下使用下面命令： grep SYSCALL_DEFINE&#91;0-6&#93;\&#40;XXXX * -R --include=*.c XXXX可以替换为任何系统调用名。未必能找到所有的，八九不离十吧。至少2.6.32下是这样。]]></description>
			<content:encoded><![CDATA[<p>在内核源码目录下使用下面命令：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">grep</span> SYSCALL_DEFINE<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">0</span>-<span style="color: #000000;">6</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>\<span style="color: #7a0874; font-weight: bold;">&#40;</span>XXXX <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #660033;">-R</span> <span style="color: #660033;">--include</span>=<span style="color: #000000; font-weight: bold;">*</span>.c</pre></div></div>

<p>XXXX可以替换为任何系统调用名。未必能找到所有的，八九不离十吧。至少2.6.32下是这样。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sunner.cn/search-syscall-entries-in-linux-kernel-source/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moodle Online Judge 1.3.1发布</title>
		<link>http://blog.sunner.cn/moodle-online-judge-1-3-1-released/</link>
		<comments>http://blog.sunner.cn/moodle-online-judge-1-3-1-released/#comments</comments>
		<pubDate>Sat, 22 May 2010 06:13:54 +0000</pubDate>
		<dc:creator>Sunner</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[moodle_dev]]></category>

		<guid isPermaLink="false">http://blog.sunner.cn/?p=435</guid>
		<description><![CDATA[新特性： 支持40余种编程语言的在线评测。新语言的支持来自于ideone.com，这是一个免费的Web服务。所有程序都是在ideone.com运行，所以对您的moodle服务器而言，是相当安全。该功能由刘琦卿开发。 因为可以使用ideone.com运行程序，所以从这个版本开始支持Windows了 下载请到：http://code.google.com/p/sunner-projects/downloads/list]]></description>
			<content:encoded><![CDATA[<p>新特性：</p>
<ol>
<li>支持40余种编程语言的在线评测。新语言的支持来自于ideone.com，这是一个免费的Web服务。所有程序都是在ideone.com运行，所以对您的moodle服务器而言，是相当安全。该功能由刘琦卿开发。</li>
<li>因为可以使用ideone.com运行程序，所以从这个版本开始支持Windows了</li>
</ol>
<p>下载请到：<a href="http://code.google.com/p/sunner-projects/downloads/list">http://code.google.com/p/sunner-projects/downloads/list</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sunner.cn/moodle-online-judge-1-3-1-released/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>

