Arss看能否激起你什么创作灵感?

ARSS-the Analysis & Resynthesis Sound Spectrograph (formerly known as the Analysis & Reconstruction Sound Engine),通俗的说就是声音到图片(灰度图片)的相互转化,这个小工具可是开源的哦。
通过它音乐可以转化为图片,同样图片也可以还原为声音。呵呵。

可以看看ARSS上的demo,另外也可以看看LShift上的一些尝试,下载ARSS
我也尝试了一把,生成了下面这个图片:
开机声音
有兴趣的朋友可以把这个图片用ARSS给还原一下:


D:\arss-0.2.3-windows>arss start.bmp start.mp3
The Analysis & Resynthesis Sound Spectrograph 0.2.3
Input file : start.bmp
Output file : start.mp3
Choose the mode (Press 1, 2 or 3) :
1. Analysis
2. Sine synthesis
3. Noise synthesis
> 2
Bits per sample (8/16/32) [16] :
Sample rate [44100] :
Min. frequency (Hz) [27.500]:
Bands per octave [21.667]:
Max. frequency : 10556.154 Hz
Pixels per second [150.000]:
Sound duration : 4.820 s
187/187   10556.17 Hz
Processing time : 0.516 s
Press Return to quit

听听吧,你肯定熟悉这个声音,呵呵,就是windows XP开机启动的那个声音。
参考:
http://www.lshift.net/blog/2008/07/25/listening-to-your-webcam#comments
http://arss.sourceforge.net/index.shtml

erlang mergesort and quicksort

参看:
http://en.wikipedia.org/wiki/Merge_sort
http://en.wikipedia.org/wiki/Quick_sort
http://jchris.mfdz.com/life/2008/8/erlang_mergesort
合并排序,把要排序的列表切分成两个长度相等的sublist,对sublist进行排序后合并。重复这个过程直至排序完成。
对于长度为0和1的list,认为其为已经排序好的list。

快速排序,取出一个元素称为pivot,随后将list中所有小于pivot的元素放在左侧,所有大于等于pivot的元素放在右侧。此时pivot的位置为其最终位置,对左侧和右侧sublist,递归进行此操作。

看erlang实现的代码:
mergesort:


sort([]) -> [];
sort([L]) -> [L];
sort(List) ->
    {Left, Right} = lists:split(length(List) div 2, List),
    merge(sort(Left),sort(Right)).

merge(L, []) -> L;
merge([], R) -> R;
merge([L|Left], [R|_]=Right) when L < R ->
    [L | merge(Left, Right)];
merge(Left, [R|Right]) ->
    [R | merge(Left, Right)].

快速排序:


qsort([]) -> [];
qsort([H|T]) ->
       qsort([X || X <- T, X < H])
	++ [H]
	++ qsort([X || X <- T, X >= H]).

非常简洁明了

又一本erlang图书出版了。

从erlang maillist 中得到的消息。

Erlang Programming
by Francesco Cesarini and Simon Thompson

 

但是没有人找到这本书的更多相关的信息。

ejabberd moudle 开发 - http modules(二)

继续上一部分,我们已经可以开发一个简单的ejabberd module了,这次让我们开发一个简单的http处理模块。这个http模块可以输出服务器中登录的用户列表(json格式)。

首先,再我们上节的my_module中添加一个process/2导出函数:


-module(mod_http_hello_world).
-author('your@mail.com').
-vsn('1.0').

-define(EJABBERD_DEBUG, true).

-behavior(gen_mod).

-export([
    start/2,
    stop/1,
    process/2
    ]).

-include(”ejabberd.hrl”).
-include(”jlib.hrl”).
-include(”ejabberd_http.hrl”).

start(_Host, _Opts) ->
    ok.

stop(_Host) ->
    ok.

process(_Path, _Request) ->
    “Hello World”.

process/2用来处理ejabberd http服务器中的请求,其中第一个参数Path表示url中的路径,比如
http://example.com/this/cool/article 这个URL如果要我们的模块处理,对应的Path为:["this", "cool", "article"],对了,就是路径拆分后的一个list。这里我们先不对路径做任何处理,匹配,我们首先验证我的http handler module是否可以工作。

老规矩,编译module,然后放到ejabbered的ebin目录:

mv mod_http_hello_world.beam /var/lib/ejabberd/ebin

配置ejabberd.cfg,添加我们的module


{modules,
 [
  {mod_register, [{access, register}]},
  …
  {mod_http_hello_world, []}  % []mod_http_hello_world:start/2中的第二个参数
  ]}.

到这里步骤和jabberd moudle 开发(一)中,基本相似,可是我们要让我们的module处理http请求,那么我们需要继续下面的配置,打开ejabberd.cfg,找到:

{5280, ejabberd_http, [http_poll, web_admin]}

修改如下:

{5280, ejabberd_http, [http_poll, web_admin,
{request_handlers, [{["hello_world"], mod_http_hello_world}
]}]}

好了,重启ejabberd,在浏览器中输入:
http://example.com:5280/hello_world
页面会显示Hello World,一切正常。

我们开头说过我们的http module要把当前服务器中所有登录的用户打印出来。让我们修改一下process/2函数:


process(_Path, _Request) ->
    [Username ++ "@" ++ Server || {Username, Server} <- ejabberd_auth:dirty_get_registered_users()].

我们通过ejabberd_auth:dirty_get_registered_users/0获取用户列表,随后显示出来。
_Request包含请求的方法,路径,参数,post数据,认证的信息,可以更好的处理HTTP 请求。

最后说明一下我们这个modoule是如何被ejabberd执行的,毫无疑问,通过我们对ejabberd_http部分的配置,ejabber加载了新的http 处理模块,在其ejabberd_http.erl中,当收到http请求时,其遍历所有的http module,找到Path匹配的Moudle,然后执行Module:process/2函数,从而做到http 请求的分发。如果没有找到合适的handler,那么将调用ejabberd_web:error(not_found)。

下节我们开发一个XMPP 机器人模块。

ejabberd moudle 开发(一)

参考:
http://anders.conbere.org/journal/
http://www.process-one.net/en/wiki/ejabberd_module_development/

ejabberd的内部的很多模块都是以插件的形式工作,这样我们也可以开发自己的模块融合到ejabberd中去,完成各种各样我们独特的需求。

ejabberd定义了一个gen_mod behaviour,其要求下面的callback:

start(Host, Opts) -> ok
stop(Host) -> ok
* Host = string()
* Opts = [{Name, Value}]
* Name = Value = string()

其中Host是运行这module的一个虚拟的主机。
Opts是在配置中指定的mod的参数(后面会讲到),可以通过gen_mod:get_module_opt/4获取(参看gen_mod.erl代码得知这些信息存储在ets中)。

我们要实现一个mod非常容易,就非常容易了:


-module(my_module).
-author('your@mail.com').
-behaviour(gen_mod).
-include('ejabberd.hrl').

%% gen_mod callback
-export([start/2, stop/1]).

start(_Host, _Opt) -> ok.
stop(_Host) -> ok.

让我们在添加一代码,让我们这个“无用”的mod更加清晰一些


start(_Host, _Opt) ->
    ?DEBUG("EXAMPLE MODULE LOADING").

编译my_module,将my_module.beam放到你的ejabberd/ebin目录中:
mv my_module.beam /var/lib/ejabberd/ebin

接着,我们需要对ejabberd.cfg做一些配置,告诉ejabberd加载我们的my_module:


{modules,
 [
  {mod_register, [{access, register}]},
  …
  {my_module, []}  % []为my_module:start/2中的第二个参数
  ]}.

好了,一切OK后,重新启动ejabberd,如果你的loglevel设置为5,那么你将看到如下信息:

=INFO REPORT==== 2008-07-17 15:33:27 ===
D(<0.37.0>:ejabberd_auth_my_auth:44) : EXAMPLE MODULE LOADING

我们的ejabberd module顺利加载了。
写到这里,您可能会问,如何实现一个更加强大的module呢?
原来ejabberd为我们提供了很多的API,可以供我们使用,包含如下:
ejabberd core modules (ejabberd核心模块)
ejabberd events and hooks(ejabberd 事件及钩子)
ejabberd IQ handlers
ejabberd route table (ejabberd 路由表)
ejabberd HTTP request handlers(ejabberd HTTP 请求处理)

有了这些API,我们可以实现任何我们想要的功能。
下节实现一个简单http处理模块

couchdb scribd php ming等等

最近随便在网上找些相关的东西,并了解一些相关的技术.
看很多人custom google search,我也就定义了一个关于erlang的搜索, 收集了20多个erlang的blog和website.可以适用一下哦,–>页面右上角

RabbitMQ还真是一个通用的MQ解决方案,核心思想就是消息的转发,以及各种转发规则,官网中有好几个例子,其中一个是用RabbitMQ来做一个视频聊天室,把视频数据作为MSG进行1对多中转,还有一个朋友问是否可以用在其自身的负载均衡系统中,作为消息系统.RabbitMQ其本质就是一些规则指导下的消息产生及消耗过程.

对couchdb很有兴趣,看了一些slide和一些演示,很期待可以在项目中使用.

一直在用两个document share的网站:scribd/ 梦想称为document领域的youtube(因为他们都使用了flash的技术?), slideshare共享的幻灯片阅读,他们两个实现中都涉及到flash,其中flashpaper是adobe提供的工具可以将doc,ppt等转化为pdf或swf,方便显示.而scribd似乎更有实力,其不满于flashpaper的一些限制,提供了自己的ipaper(比flashpaper更完善),并开放丰富的API.

想抓取youku的视频,发现不是很容易.flv player内部的交互都比较隐蔽,也很容易修改,因此想获取flv的最终url,分析协议好象总不是好办法.

为了体验一把ming(swf output libary),
在windows 2003上装php5,总是iis总是显示”拒绝您访问此计算机”, google了半天,原来是防火墙把svhost给拦截了.
iis + PHP5原来就几个重点:
1, 修改php.ini,指定扩展的路径
2, 配置IIS中的ISAPI筛选器中,添加指向PHP安装目录下php5isapi.dll的筛选器
3, 在主目录,配置中,添加.php到ISAPI的映射
4, 在web服务扩展中,允许PHP
5, 通过phpinfo(),查看你的php.ini加载,以及各项配置是否正确

都是为自己以后抓耳挠腮的时候,留个参考.
原谅我总是使用windows,其实我真的不想,谁让我天天要写windows的客户端呢?

再谈erlang中的日志

再说说erlang中的日志,erlang中的日志记录在mryufeng的一篇日志中已经提及过,今天我在说明一下,自己在写代码过程中的一些认识.

本机环境(Windows 2003 + R12B-3)

erlang中的日志记录,主要是kernel中error_logger.erl模块,其为一个event manager, 我们可以添加我们自己的log event handler(实现gen_event behaviour),从而实现我们需要的日志记录格式,比如我们要将日志存到数据库中,那么我们要实现一个log_db.erl,随后通过调用
error_logger:add_report_handler/1,2 函数将log_db加入到handler list中:


error_logger:add_report_handler(log_db)
% 也可以调用下面方法添加handler
gen_event:add_handler(error_logger, log_db, [])

这样我们在调用error_logger的info_msg, warning_msg之类的方法,log_db就可以捕获,并写入到数据库中了.

erlang默认有三种error_logger相关的handler:
1,tty将log写到屏幕,这是默认模式
2,file将log写入到某个文件
3,rotating log循环log,在某个目录中循环适用log文件

我们可以通过config来修改logger处理方式,
可以指定日志输出为某个文件:


[{sasl, [
	 {sasl_error_logger, {file, "c:/log.txt"}}
	 ]}]

可以指定日志输出到c:/log目录,每个日志文件最大尺寸为10M,最多拥有100个日志文件(注意最大为256):


[{sasl, [
	 {sasl_error_logger, false},
	 {error_logger_mf_dir, "c:/ecrawler"},
	 {error_logger_mf_maxbytes, 10485760}, % 10M
	 {error_logger_mf_maxfiles, 100}
	]}].

写好配置后,命名为somename.config,随后在启动erl:
> erl -boot start_sasl -cofnig somename
就OK了,随后调用error_logger:info_msg(”info”),之类的函数测试一下.

不过这里需要说明,erlang的循环日志是采用stdlib中的log_mf_h.erl模块实现,而此模块有个bug,在handle_event/2函数中:


Bin = term_to_binary(tag_event(Event))

显然,这里直接将Event转化为binary然后写入文件,因此得出的文件包含很多不可读字符.参看stdlib中的error_logger_file_h.erl(file log)和error_logger_tty_h.erl(tty log) 模块可以进行修改.

参考:
sasl reference manual
configuring a application
Programming erlang P342

一个快速访问erlang doc的小方法

声明:我是跟老外学的哦.
注意:只是在firefox下适用.
1,首先创建一个新的bookmark其URL(地址)为:http://www.erlang.org/doc/man/%s.html
2,设置其关键字(keyword)为:erl
3,回到你的firefox,在地址栏中输入 erl gen_server , 怎么样看到gen_server module的说明了吧.
呵呵,奇淫技巧啊.

使用EUnit进行单元测试

为了写一个好的产品,必定离不开完善的测试。

最近开始筹划项目,因此单元测试必不可少,一定要在开始的时候把测试做好,从下到上才能让产品更加坚固。

我们选择使用EUnit进行单元测试。使用Eunit的好处:减少代码的修改;提高开发速度;有利于接口与实现分离;有利于系统集成;还有测试本身可以作为一种文档。

1,首次从http://support.process-one.net/doc/display/CONTRIBS/EUnit 获取对应的SVN checkout路径,http://svn.process-one.net/contribs/trunk/eunit,通过svn进行下载。

2,将整个eunit目录放到你的erlang安装目录下的lib目录中。也可以使用通过code:add_path/1或者其他编译选项指明eunit的路径,但是不是很方便。

3,在你的module中添加: -include_lib(”eunit/include/eunit.hrl”). 这样就引入了eunit的头文件,此时你的module具有了下面的特性:自动的将以”_test”结尾的函数作为测试函数;为你的module添加并导出了test/0函数;为你提供了丰富的test macro。(自动导出test函数,是通过compile指示符的parse_transform选项进行处理)

此时,我们的module已经具有了eunit赋予的一切权利。注意你从svn下载的代码,没有进行编译,你需要进行编译生成beam文件。由于本人是在windows下工作,编译不是很方便,所以我就直接从这里下载了eunit的beam文件,放到eunit/ebin/目录下。

在我们要测试的module中我们加入一个函数:


basic_test() ->
     ?assert(1 == 1).

好了,编译module,随后运行M:test(),进行单元测试,我们会看到
 Test successful.
的提示。测试ok。

这里bsic_test/0会在执行test/0的时候调用,我们也可以把basic_test/0写成另一种形式:

basic_test_() ->
    fun() -> ?assert(1 == 1) end.

以”_test_”结尾的函数,在EUnit中称为“test generation function”,测试生成函数,
它返回一个或一个函数list,EUnit会依次执行每个函数。为了让代码更紧凑简洁,
我们又有了另一个macro:_test,这样上面的test可以变成这样:


basic_test_() ->
    ?_test(?assert(1 == 1)).

是不是代码少一些了?好的让我们再进一步,我们使用另一个macro:_assert:


basic_test_() ->
    ?_assert(1 == 1).

怎么样,很简单了吧,好的,比如我有一系列的内容要测试,我就可以简单的写成这样:


basic_test_() ->
    [?_assert(1 == 1),
     ?_assert(2 == 2),
     ?_assertEqual(3, 3),
     ?_assertMatch(4,  4),
     ?_assertException(throw, a, throw(a))].

我们非常容易的就测试了某个表达式是否为true,某两个值是否相等assertEqual
(注:这里使用=:=进行判断,因此assertEqual(3, 3.0)不会测试通过),
某个表达式是否匹配,是否产生指定的异常等。
好了,暂时就这些基本的东西,更多的内容查看EUnit的帮助:
http://svn.process-one.net/contribs/trunk/eunit/doc/overview-summary.html

最近工作忙,发表erlang相关文章频率大大降低。

如题,最近工作比较忙,发布erlang相关文档的时间也大大减少。

最近也没有太多时间看erlang,就是前阵子看了看maillist中某个开源项目的merkle tree。还有就是在看mochiweb和rabbitmq。筹划最近用erlang写一个项目,现在正在看国外的paper,相信不久可以实现。