I am LAZY bones ? all linux

分类: '编程相关' 的归档

谷歌音乐下载器

之前有很多下载baidu mp3的程序,有bash的,java的,python的,其中也包括我这个.
但是baidu的歌曲都是用程序收集自网络的,所以排行榜的歌曲质量就没有保障了,下载下来的歌曲ID3信息可谓一塌糊涂,而且还可能下载到网友自己翻唱的歌或者其他杂七杂八的东西,严重影响我们的听觉神经.
而谷歌(不是google)最近推出了谷歌音乐搜索,联合top100,也推出了类似百度榜单的音乐排行榜.但不同于百度的是,谷歌里的歌曲都是收集整理过的,不会有死链,质量也很不错,而且,对于最终非商业用途的个人用户而言,是不存在版权问题的(但我不确定批量下载下来的有没有版权问题.请用户自行考虑.).
所以我顺势就推出了这个谷歌音乐下载器 .
目前程序还很简陋,没有图形界面,也没有很多可以设置的地方.运行程序只会把”华语新歌”这个榜单的100首歌下载到本地当前目录.所以仅供有兴趣尝鲜的同学测试使用.但是以后,我打算把这个程序做成有图形界面的,可以试听/下载/播放的一个整合工具,哈哈.请大家多多关注吧.

PS:有人说这类工具还是不要发布出来,小范围流传下比较好,因为发布出来以后,很可能遭到google的封杀.这说法其实也有些道理,但是我想想,如果谷歌真的因为这个来封杀我,我也够有面子的,嘿嘿.所以我还是按照Google的Project hosting页面所说的做了: Release early, release often

SQLite简介

SQLite大致就是”SQL lite”,也就是一个微型的SQL解释器.它的赞助商和使用者包括mozilla,adobe,symbian等软件巨头,也算是来头不小了.
说它微型,那么它到底有多微型呢?我们可以看看它的可执行文件的大小,linux版本的打包文件是203.93 KiB,解压以后是350.88 KiB,是不是很微型呢?
除了微型之外,SQLite主要还要以下特点:

  • 无须配置: SQLite不需要安装,直接解压可执行文件即可运行.
  • 没有服务进程: SQLite无须通过TCP/IP等通信协议提交SQL到服务端,处理后再返回结果.
  • 单个数据文件: SQLite将用户数据存于单个普通文件里面.也就是说用户只要有数据文件的读权限,就可以读取所有数据;有写权限也能改变数据.
  • 数据文件可跨平台迁移: SQLite本身是跨平台的,它的数据文件同样也是跨平台的.数据文件和平台的字节序无关,也和CPU的位数无关.直接复制数据文件就可以实现数据迁移.
  • 紧凑: 如上所述,SQLite的运行环境非常小,如果在编译的时候去掉不需要的功能,可以减小至170KiB,用于嵌入式环境也是没问题的.
  • 松散数据类型: 不同于其他数据库的严格的数据类型检查,SQLite在尝试类型转换失败以后,允许在任何表的任何列里面插入任何类型的数据(一个例外是:整型的主键列里面只能存整型数据)
  • 变长的数据记录: 任何文本都是VARCHAR
  • 可读性很高的源码: 普通的程序员都能读懂,关键的变量和函数都有详细的注释.
  • SQL语句编译成虚拟机器语言: SQLite把SQL语句预编译成一种类似机器预言的代码,程序员可以方便得打印出代码及代码的执行结果,这样对debug很有好处.
  • 完全的公开: SQLite的源码可以任意下载使用,没有任何约束和版权(一些文档和测试代码是受开源license保护的).
  • SQL语言扩展: SQLite可以模块化地添加扩展,以增强其功能

说了这么多特点,那么,SQLite究竟怎么使用呢?
在一般的linux发行版下,安装 sqlite 这个包以后,就可以使用 sqlite3 这个命令来创建和处理数据库文件了.windows/DOS则下载这个文件解压到系统目录,mac则是下载这个文件.
安装完毕以后,就可以用

sqlite3 test.db

这个命令来创建一个空的数据库文件了.
然后,你可以用以下命令来建立一个含有两个列的表:

sqlite3 test.db "create table memos(text, priority INTEGER);"
sqlite3 test.db "insert into memos values('deliver project description', 10);"
sqlite3 test.db "insert into memos values('lunch with Christine', 100);"

然后可以这样查询出需要的数据:

sqlite3 test.db "select * from memos where priority>20;"
lunch with Christine|100

很简单吧~
下面展示一下,SQLite在C语言下的用法,同样用的是上面那个test.db,我们建立一个test.c,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <sqlite3.h>
 
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
  }
  printf("\n");
  return 0;
}
 
int main(int argc, char **argv){
  sqlite3 *db;
  char *zErrMsg = 0;
  char SQLbuffer[1024];
  int rc;
 
  if( argc!=2 ){
    fprintf(stderr, "Usage: %s num\n", argv[0]);
    return 1;
  }
  rc = sqlite3_open("test.db", &db);
  if( rc ){
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return 1;
  }
  sprintf(SQLbuffer, "select * from memos where priority > %s;", argv[1]);
  rc = sqlite3_exec(db, SQLbuffer, callback, 0, &zErrMsg);
  if( rc!=SQLITE_OK ){
    fprintf(stderr, "SQL error: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
  }
  sqlite3_close(db);
  return 0;
}

gcc -lsqlite3 test.c

进行编译,完成之后,执行

./a.out 30
text = lunch with Christine
priority = 100

怎么样,相当简单吧~

注: 文中部分内容翻译和参考自官方文档和man页.

调srt字幕时间的小脚本

首先,我知道mplayer和很多其他播放都有个类似 -subdelay的开关,可以实现字幕和电影的时间调整。
此脚本和subdelay又部分功能交叉,但是某些特殊的时候,还是用个这个脚本方便。
我当时的是电影一个avi文件,但srt字幕却只找到分CD1和CD2的那种,前半段电影的时间和CD1对上了,但是后半段就没字幕了。
为了解决这个文件,就写了这个脚本,名为 adjsrt.sh
我当时执行了 ./adjsrt.sh 3061 cd2.srt >> cd1.srt 就把第二个字幕的时间整体加上3061秒,然后加在了第一个字幕的后面了,哈哈。
脚本如下:

#!/bin/sh
offset=$1
shift
awk -v offset=$offset '
BEGIN{
	FS="[ :,]+"
}
/^[0-9][0-9]:[0-9]*/ {
	ST=toT($1,$2,$3)+offset;
	ST1=int(ST/3600);
	ST2=int((ST-ST1*3600)/60);
	ST3=ST%60;
	ET=toT($6,$7,$8)+offset;
	ET1=int(ET/3600);
	ET2=int((ET-ET1*3600)/60);
	ET3=ET%60;
	printf("%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d\n",
		ST1,ST2,ST3,$4,ET1,ET2,ET3,$9);
}
$0 !~ /^[0-9][0-9]:[0-9]*/ {
	print $0
}
 
function toT( hour, min , sec ){
	return hour*3600 + min*60 + sec
}
' $*

python多处理器编程

由于上次做的那个一维随机游走程序,虽然简单,但是大数据的时候很费CPU,而且我注意到我的双核处理器始终只有一核是处于满负荷工作,另一个核的性能没有得到发挥.而且我也试过把同样的程序放到一个8核的服务器上运行,结果解题的速度也只是比我本本快那么一点点,估计也只是那服务器的CPU主频(2GHz)比我的1.86GHz略高而已,完全没有发挥出他8核的优势.
所以马上想到了python有没有多处理机的机制,上网google一下,发现由于python是解释型的语言,而Python解释器使用GIL(全局解释器锁)来在内部禁止并行执行,正是这个GIL限制你在多核处理器上同一时间也只能执行一条字节码指令.猜想这个GIL也是当初为了设计解释器方便而搞的吧.而且据说python 3.0 里面已经改进了,默认有了多处理器编程的库了.但是毕竟现在python3.0还没有流行起来,那么现在有没有变通的方法呢?
当然有~不然我就不会写这文章了嘛~
Parallel Python 这个库,正是为了解决我们的问题而设计的,而且它不仅可以多核处理器协同工作,还可以通过网络集群运行呢,嘿嘿.
下面的中文介绍来自这里:

1 简介

PP 是一个Python模块,提供了在SMP(多CPU或多核)和集群(通过网络连接的多台计算机)上并行执行Python代码的机制。轻量级,易于安装,并集成了其他软件。PP也是一个用纯Python代码实现的跨平台,开放源码模块。

2 功能

* 在SMP和集群上并行执行Python代码
* 易于理解和实现的基于工作的并行机制,便于把穿行应用转换成并行的
* 自动构造最佳配置(默认时工作进程数量等同于系统处理器数量)
* 动态处理器分配(允许运行时改变工作处理器数量)
* 函数的工作缓存(透明的缓存机制确保后续调用降低负载)
* 动态负载均衡(任务被动态的分配到各个处理器上)
* 基于SHA的连接加密认证
* 跨平台移植(Windows/Linux/Unix)
* 开放源代码

3 开发动机

现代Python程序已经广泛的应用在商业逻辑,数据分析和科学计算等方面。其中广泛应用着SMP(多处理器或多核)和集群(通过网络连接的多台计算机),市场需要并行的执行的Python代码。
在SMP计算机上编写并行程序最简单的方法是使用多线程。尽管如此,使用 ‘thread’ 和 ‘threading’ 模块仍然无法在字节码一级实现并行。因为Python解释器使用GIL(全局解释器锁)来在内部禁止并行执行。这个GIL限制你在SMP机器上同一时间也只能执行一条字节码指令。
PP 模块正是为了解决这个问题而来,提供简单的方式实现并行Python应用。 ppsmp 在内部使用 进程 和 IPC (进程间通信)来组织并行计算。并处理了所有内部的细节和复杂性,你的应用程序只需要提交工作任务并取回结果就可以了。这也是编写并行程序的最简单的方法。
为了更好的实现,所有使用 PP 的软件通过网络来连接和协作。跨平台和动态负载均衡使得 PP 可以轻松组织多平台、异构的集群计算环境。

4 安装

任何平台:下载模块压缩包,解压,运行setup脚本:
python setup.py install
Windows:下载和执行安装包。

另外,debian和ubuntu用户,也可以通过apt直接下载安装,包名是 python-pp ,但是由于版本比较老,是 1.5.4 版本的,而最新的是 1.5.6 ,所以官方页面上的示例代码可能运行不了,会出现以下错误提示:

Traceback (most recent call last):
File “testpp.py”, line 46, in
job_server = pp.Server(ppservers=ppservers)
File “/var/lib/python-support/python2.5/pp.py”, line 312, in __init__
raise ValueError(“secret must be set using command-line option or configuration file”)
ValueError: secret must be set using command-line option or configuration file

原因是代码的不兼容性,解决办法就是找到 pp.Server 那行,多加一个参数,如下:

job_server = pp.Server(ppservers=ppservers,secret="")

由于这个库,包装得不错,所以用起来也比较简单,基本上看了示例代码,就会了,使用方面也就不多介绍了,如果有可能的话,我倒是想写个gentoo的ebuild文件,嘿嘿.

给 iPod 转视频的脚本

由于新买了个 iPod touch,这几天认真钻研了下它的视频格式,搞了个nautilus脚本,使用mencoder做后端.
以后想把某个视频文件转成iPod的格式的话,直接在 nautilus 里面右键点文件-脚本-toIpod 就可以搞定了.
脚本的特点:
* 借助mplayer的强大,支持N多的源格式(已测试: avi rmvb mov flv).
* 支持srt/ass格式的外挂字幕.
* 自动缩放画面比例到适合ipod touch的480*320,如果是 ipod shuffle 之类的话,可以自己修改下脚本.
* 可视化的进度提示
* 转换速度较快
* 默认保存到当前目录,可修改脚本,输出到统一目录,方便管理.会自动加上 _ipod.mp4 的后缀名.
使用方法,保存以下脚本到 ~/.gnome2/nautilus-scripts/toIpod ,并加可执行权限…或者这里下载

PS: 如果压缩出来的字幕有乱码,请参照我以前的文章,建个 ~/.mplayer/mencoder.conf 文件,写上一行 subcp=cp936 就好了.

#!/bin/bash
#filename: ~/.gnome2/nautilus-scripts/toIpod
#Copyright (c) 2008 bones7456 (bones7456<A>gmail<D>com)
#License: GPL
#version 20081101
#用于将视频转成 ipod touch / iphone 格式.右击文件使用
 
SAVEDIR=`pwd`
#SAVEDIR="/data/movie"
 
INFILE="$1"
PWD=`pwd`
CMD="mencoder -of lavf -lavfopts format=mp4 -oac lavc -ovc lavc "
CMD+="-lavcopts aglobal=1:vglobal=1:vcodec=mpeg4:vbitrate=600:acodec=libfaac:abitrate=128 "
CMD+="-af lavcresample=22050 -vf dsize=480:320:0,scale=0:0,expand=480:320,harddup -ofps 25 -srate 22050 "
P="没有找到对应的字幕."
if [[ -f "${INFILE%.*}.srt" ]];then
	CMD+=" -sub ""\"$PWD/${INFILE%.*}.srt\""
	P="找到字幕文件: ""${INFILE%.*}.srt"
elif [[ -f "${INFILE%.*}.ssa" ]];then
	CMD+=" -sub ""\"$PWD/${INFILE%.*}.ssa\""
	P="找到字幕文件: ""${INFILE%.*}.ssa"
elif [[ -f "${INFILE%.*}.aas" ]];then
	CMD+=" -sub ""\"$PWD/${INFILE%.*}.aas\""
	P="找到字幕文件: ""${INFILE%.*}.aas"
fi
 
CMD+=" -o ""\"$SAVEDIR/${INFILE%.*}_ipod.mp4\""" ""\"$PWD/$INFILE\""
P+="\n\n保存目录: $SAVEDIR"
P+="\n\n是否继续?"
#echo "$CMD" >> ~/toIpod.log
if ! zenity --question --text "$P" ; then
	exit 0;
fi
 
eval "$CMD 2>&1" |\
while read line; do echo $line |\
awk -F '[ :\(\)%]+' '/^Pos/{print "# 速度:",$5,"(点\"取消\"转入后台运行.)";print $4}' ; done |\
zenity --progress --title "正在转换..." --percentage=0 --auto-close --width=500

截图:
工作截图

google code jam

玩了下google编程大赛,我那轮3道题目,题目球猫帖这里了,其中的第3,超烦,算什么打苍蝇的概率,算的累死了,为了不让自己的程序白写,贴在这里晒晒,嘿嘿.
PS: 初学python,发现真好用…

  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3. import math
  4.  
  5. def sg(x,R):
  6.     '''求弓形面积'''
  7.     return math.acos(x/R)*(R**2)-x*math.sqrt(R**2-x**2)
  8.  
  9. inf=file('C-large.in','r')
  10. outf=file('C-large.out','w')
  11. casenum=int(inf.readline())
  12. for c in range(0,casenum):
  13.     tmp=inf.readline()
  14.     f=float(tmp.split(' ')[0])
  15.     R=float(tmp.split(' ')[1])
  16.     t=float(tmp.split(' ')[2])
  17.     r=float(tmp.split(' ')[3])
  18.     g=float(tmp.split(' ')[4])
  19.  
  20.     TotalArea=math.pi*R**2/4.0
  21.     A=0
  22.     fn=0
  23.     r=r+f
  24.     t=t+f
  25.     g=g-2*f
  26.     if g &gt; 0:
  27.         i=0
  28.         while i*(g+r*2.0)+r &lt; (R-t):
  29.             x=i*(g+r*2.0)+r
  30.             xp=x+g
  31.             j=0
  32.             Yi=math.sqrt((R-t)**2-x**2)
  33.             try:
  34.                 Yip=math.sqrt((R-t)**2-xp**2)
  35.             except:
  36.                 Yip=0
  37.             while j*(g+r*2.0)+r  0:
  38.                     fn+=nfn
  39.                     j+=nfn
  40.                     #print "c=",c,"i=",i,"j=",j,nfn
  41.                     continue
  42.  
  43.                 if xp &lt; R-t:
  44.                     if yp  Yip and yp &lt;= Yi:
  45.                         if y  Yi
  46.                         if y &lt; Yip:
  47.                             A+=(sg(x,R-t)-sg(xp,R-t))/2.0-g*y
  48.                             #w="3a.不规则"
  49.                         elif y &lt; Yi:
  50.                             A+=(sg(y,R-t)-sg(Yi,R-t))/2.0-(Yi-y)*x
  51.                             #w="3b.不规则"
  52.                         else: #这个是不可能的
  53.                             print "c=",c,"i=",i,"j=",j,"y=",y,"yp=",yp,"Yi=",Yi,"Yip=",Yip,"x=",x,"xp=",xp,"R-t=",R-t #,w
  54.                 else:
  55.                     if yp &lt;= Yi:
  56.                         A+=(sg(y,R-t)-sg(yp,R-t))/2.0-g*x
  57.                         #w="4.下不规则"
  58.                     else:
  59.                         A+=(sg(y,R-t)-sg(Yi,R-t))/2.0-(Yi-y)*x
  60.                         #w="5.三角不规则"
  61.  
  62.                 j+=1
  63.             i+=1
  64.     A+=fn*g*g
  65.     #print TotalArea,A
  66.     outf.write('Case #%d: %0.6f\n'%(c+1,(1-A/TotalArea)))
  67. inf.close()
  68. outf.close()

C 语言 IQ 题..

http://linuxfire.com.cn/~alecs/fun/xiaoming.txt

小明初学 C 语言,写了个程序,想打印 99 个 ‘#’. 程序如下:

int i, n=99; main() { for(i=0; i<n ; i--) { printf("#"); } }

但是这个程序是错的.

Question 1: 请大家帮他改正, 但只允许 1) 删除一个字符 or 2) 增加一个字符 or 3) 改变一个字符
Question 2: 同样的限制条件, 使得只打印一个 ‘#’
Qeustion 3: 同样的限制条件, 打印 100 个 ‘#’

这个题目,粗看无聊,仔细想想还挺有意思的,我归纳了下,有这些答案.
下面要帖答案了,要自己思考下的先别往下看了.

点击查看全文 »

跟我一起写 Makefile (PDF)

以前有人在论坛里发过: http://forum.ubuntu.org.cn/viewtopic.php?t=61841
原文在这里: http://blog.csdn.net/haoel/archive/2004/02/24/2886.aspx
作者: 陈皓

我整理成了PDF,并修改少量错字.
给有需要的人,估计受众不会很大,嘿嘿.

这里不能上传文件附件,可以到 这里 或者这里 下载.

链接期的”undefined reference to”问题又一解

今天拿到公司的一个程序,在本机(ubuntu8.04)编译了一下,编译起见是一堆的警告:” 警告: 不建议使用从字符串常量到‘char*’的转换”,可以跳过去,但是到了链接期间,就又是可恶的 “undefined reference to”问题了,网上查了一些资料说是因为找不到 *.a/*.o 之类的库文件,或者是库文件里面没有相关的符号导致,但是我这程序原样复制到服务器里面,借给是可以编译的,而且提示错误的那个 .a 文件也是从服务器复制的,可以保证是一模一样的,但为什么本机编译就是不行呢?后来想到服务器是RHEL4,
gcc –version 的输出是: gcc (GCC) 3.4.6 20060404 (Red Hat 3.4.6-8)
g++ –version 的输出是: g++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-47.3)
而我本机的 gcc和g++确都是 4.2.3 的新版本,会不会是编译器的版本不兼容呢?看makefile里面用的是 g++ ,所以我先安装了 g++-3.4 ,然后把makefile里面的 PUBCC = g++ 改为 PUBCC = g++-3.4 ,再编译的时候发现编译期间的警告没了,但是链接还是照样报错;于是又卸载了 g++-3.4,换成了 g++-3.3,再编译的时候,居然是一切正常,和服务器上的表现一样了….
最后: 虽然是找到了 链接期的”undefined reference to”问题 的又一个答案,但个人对编译器的不兼容问题表示忧虑.

修改了下lunar-applet的源代码

lunar-applet是一个可以显示农历的软件,我一直是用这个代替原来的时钟的。最近把panel改成透明的了,而且壁纸的颜色比较深,这样一来,黑色的时钟文字在深色背景下看起来就有点累了.刚好,TX兄发现了修改applet时钟颜色的方法,可以自己写HTML定义颜色等.但是那个是针对原版的applet的,在lunar-applet上实验了下,居然无效,有点郁闷了.
好在linux下,一切都是自由的,居然原来无效,那就自己加上这功能吧,于是找来源码,自己修改了一些,嘿嘿,实现了想要的功能:

gconftool-2 --set --type string /apps/panel/applets/applet_2/prefs/format "custom"
gconftool-2 --set --type string /apps/panel/applets/applet_2/prefs/custom_format '<span color="#ee1111">%Y-%m-%d %A <b>%H:%M:%S</b></span>'

效果:
lunar-applet
如果有需要,可以放出修改后的源码或者deb包. (其实是因为本人至今都不知道怎么用patch和打deb包…)