在家看电影这么久，老早就在琢磨要不要换一个更强大一点的 5.1 环绕立体声系统，因为空间有限，专业的音响系统用不上也听不出差别，最近 XBMC 出了一个模拟立体声的 bug，让我又开始想要不要换到用数字输出才不浪费大部分 BluRay rip 里的 DTS 5.1 音频了。
Mac 的数字音频输出有两种方式，通过集成的数字/模拟音频输出 3.5mm 口用 TOSLINK 线，或者通过 HDMI。因为我用来放电影的 Mac mini 还是 2009 年的型号，所以用 TOSLINK 是唯一的解法。注意 TOSLINK 相比 HDMI 的限制是由于带宽所限无法直接输出 DTS HDMA 或者 Dolby TrueHD 的音频，但考虑到 OS X 的限制即使是用 HDMI 也无法直接输出这两种格式的，所以也就没啥好说的了。
硬件选择上，一开始考虑选择低端的数字音频解码器，比如 Yamaha RX-V473 或者 Pioneer VSX-527-S，价位相近，2000 ~ 3000 kr。优点是这两款低端的解码器对于我的需求来说都绰绰有余了，而且都支持 7.1 的 HD 音频，日后升级也有余地。缺点也很明显，单有解码器只解决一半问题，至少还得买一套 5.1 的音箱系统来替换我原来用的 Logitech Z523 2.1 系统。
所以再仔细一看 Logitech 现在的产品，替换原来的 Z5500 的这套 Z906 倒是个很好的选择：自带 DTS 和 Dolby 5.1 解码，有数字和模拟音频输入，省掉了解码器的费用，而且本身也正好是一套不错的 5.1 音箱。看看到处评价都不错，就买来试试了，一同买的还有一根 TOSLINK – 3.5mm 线，其中 3.5mm 头接 Mac mini，当然也可以买 TOSLINK – TOSLINK 线然后加一个 TOSLINK – 3.5mm 转接头。
今天收到货，接上之后 OS X 直接就识别出了数字输出 (副作用是这样就锁定了音量，必须通过解码终端来控制音量)，在 XBMC 中也切换为数字输出 5.1 DTS/AC3 音频很顺利的就在 Z906 中正确解码了，唯一需要注意的是 Z906 的“Input”选择必须切换为数字输入对应的端口 (有 3 或者 4 两个 TOSLINK 输入，我用的是 3)。相比原来的音箱，感觉音效果然提升不少。
除了 XBMC 以外，MPlayer X 和 VLC 都应该支持 5.1 DTS/AC3 输出，但其他的应用比如 Mac 下的游戏我还没尝试。另外可以考虑再找条 TOSLINK 线试试用 PS3 玩游戏的效果。
不过 Logitech Z906 的缺点也很明显，不支持 DTS HDMA/Dolby TrueHD 解码，也没有 HDMI 输入输出，相信下一代产品会有改进吧。
写一个自动转换 epub 或者 mobi 格式文件的中文简繁体的工具是我一直想做的事情，因为有不少格式内容精美的书籍资源都只有繁体中文版本，而我又不习惯长篇阅读繁体，所以常常要手工转换再用 calibre 封装，不胜其烦，相信其他人也有类似需求。
上周末有空，就用 Python 写了 opf-cc 这个项目，是 Open Packaging Format Chinese Conversion 的缩写，因为 epub 和 Amazon 采用的 mobi 都只是封装方式，具体的文件布局都是按照 OPF 规范的。这里说说实现的思路。
简繁转换这个问题相对好解决，有现成的 OpenCC 在处理多繁一简或者多简一繁的问题上已经很完善了，所以就稍微修改了一下 OpenCC 的代码直接拿来用了，修改都作为 pull request 已经提交到上游了。
解包 epub 比较简单，因为 epub 实际上就是 zip 压缩包，所以用 Python 的 zipfile 模块直接就可以解压。mobi 的解包稍微麻烦一些，如果不用 calibre 那一套庞大的库，mobiunpack 就是最好的选择。
解包后需要找到应该转换的文件，比较麻烦的地方是有的目录中 href 到的文件名本身就是繁体，如果直接整个目录文件一起转换，就得把文件也对应改名，比较麻烦，这里我尝试用 lxml 来解析目录文件，挑出文本来调用 OpenCC 的 Python 模块进行转换，对于 href 属性的内容则不转换。
重新打包 epub 也简单，
用 OS X 的 zip 工具一压就可以了 (更新: fishy 提供了不依赖单独 zip 工具而是直接用 Python 的 zipfile 的实现)，但 mobi 的打包比较麻烦，要么用 calibre 要么用 Amazon 提供的 KindleGen，好处是下载安装一个二进制程序就可以了， 坏处是生成的文件大小要比原来的文件大一倍有余，calibre 就没这个问题 (更新: 经 byelims 推荐使用 kindlestrip 来处理 KindleGen 生成的文件，可以去掉冗余的数据)。
总的说来这个项目还有不少可以改进的地方，除了上述两点以外，还有可以加入简体转繁体的功能，也就是给 OpenCC 传一个不同的参数的事而已。不过我设想该有的功能都已经有了，具体应用的时候遇到什么问题再拿来改进。
另外有兴趣的朋友可以提供更方便的封装，比如用 Automator 或者 ThisService 做成 OS X 的 Service，就可以直接在 Finder 里选中文件右键点击转换了。
In my previous post I talked about leaving Nokia and the Qt community. So what am I joining? Turned out I’m staying in Oslo for Opera Software. Why? There are a few reasons.
- When I applied for a job at Nokia, Qt Development Frameworks, I also sent my resume to Opera. But their response came too late (I got a “Your background looks very interesting…” letter after 4 months), by the time I received it, I have finished my interviews at Nokia and almost decided to join them. So I joined the trolls for 2 years. But I have always been thinking what would be like to work on Opera instead. Now I got the chance.
- I joined the trolls expecting to be a Mac developer, but as it turned out I actually focused on the other interest: typography. It’s wonderful to be one of the few typography engineers in the world, but I still want to sharpen my Cocoa skills from time to time. So now I’m actually working full time as a Mac developer for Opera.
- Working on typography is my dream job since I was a child. But I had the fear that I was too familiar with internals of Qt thus afraid of change and learning new things. Now I got the exposure of a whole new area and have to quickly learn a lot of new things — exactly I wanted.
- Doing framework job is a great learning experience, the code has to be so solid and stable and I get to work with many great engineers. But from time to time I wanted to work on some products that are closer to the end user, like a browser. Something that you can go to the party and tell rest of the people what you are working on. (Explaining Qt to non-tech people is not exactly my strength.)
I have worked in the new Opera office for more than a month and so far it has been a really great experience. The work is fast pace, challenging and my colleagues are friendly. The best thing so far is we have free beers on every Friday I will probably write again about my job after a few months and tell you more.
Two years ago, I started my first job at Nokia, Qt Development Frameworks. Originally planned to become a Mac developer, I ended up working on the text layout and font rendering part of Qt. Not exactly carried out what I wanted to do, it is still a fantastic job with many good memories. Some of my favorite parts of this job are:
- Passionate co-workers with the amount of dedication I have never seen before. I really enjoyed working with the fellows in graphics team. Many of them have spent more than ten or even twenty years on graphics programming. It is truly a team I’m honored to work with and I learnt a lot from them.
- Really high quality code base with decent workflow (git and gerrit are the best tools and JIRA for bug tracking worked well for me).
- Nice office layout with separated rooms.
- Social activities such as climbing, skiing and movie nights, we also helped each other on moving and hang out together in house warming parties – time spent with friendly and helpful trolls is one of my best memories.
- Free drinks and snacks (I enjoyed the apple juice, chocolate milk and cookies).
- Ice creams for the whole summer, and donuts on the first Friday of every month.
- Lønningspils – a Norwegian tradition: monthly beer drinking on paycheck weekends.
- Table tennis – I guess I let a lot of people down as a Chinese yet played just so so in this sport.
- The 8-core Mac Pro I used as the main development machine.
Things that didn’t work that well includes:
- Pressure from Nokia to do some of the stuff I didn’t enjoy that much and ended up not shipping anything, I surely learnt a lot from it, but still felt that is a waste of time.
- Canteen – It was quite good when I joined, but got much worse from the end of last year when the previous chef left. Terrible soup choices and warm food usually tasted awful.
Anyway, after these wonderful two years, I think it’s time to move on. I want to work on something else now. So I didn’t join most of my colleagues transferring to Digia, but I sincerely think that they have a very good chance of succeed and making “Qt Everywhere” more true than it is. It has been a great ride and if anyone is looking for a job and Digia is hiring, I can recommend it without any hesitation.
I will try to cover what’s next for me in the next post, stay tuned
After reading Bret Victor’s new essay Learnable Programming and some of the responses, the idea keep lingering in my head.
While his famous lecture Inventing on Principle tackled the idea of making new principles, people are mostly interested in applying that visualization method on IDEs and such. Although most of these efforts are largely experimental, I still find it harsh to dismiss them and consider them as a failure. Live coding is not the point of Victor’s lecture or essay, but it is still immensely better than a dumb editor and cold console that I used to use to learn programming.
a.out output every time a change was made.)
In the area of learning a new way of thinking, things as simple as live coding can be useful.
What’s more important is how do we progress after grasping basic concepts like iteration and function? While most people think learning programming as a one time effort, I have programmed for more than 10 years and I’m still constantly learning.
Malcolm Gladwell’s Outliers brought us the concept of 10,000 hours of practice. He told us that Bill Joy became a master after practicing programming for 10,000 hours. But what exactly has Bill Joy done in his practice is unknown to us. We all knew that Bill has coded the vi editor and some of the BSD network stack. Did he start practicing from writing a smaller subset of vi or BSD?
The essential question here is how do we learn higher levels of abstraction and design systems more complicated.
First, I personally believe that we need to understand the details to do higher level designs. You won’t be able to design an efficient system without knowing the implementation costs and performance impact of critical code paths. That’s why I usually choose to dive to the bottom and solve/evaluate a few critical issues before looking at the big picture.
However, human mind is not a precise machine that can assemble low level details into high level constructs. After mastering the details sometimes we need to take it away, clear our minds to see a bigger picture, otherwise our heads will be occupied by low level details and have no time to abstract. Contradicted as it is, visualization becomes a really useful tool to hide the details for us.
With visualization as simple as a pie chart, we will suddenly able to free our minds, stand on our previous results and reach higher fruits. That, I think, is the real value of Bret Victor’s idea. What I disagree with him is that his idea doesn’t have to be a groundbreaking rule to revolutionize our ways of programming, the existing tools and IDEs can still equip that as a weapon, to help us tackle even more complex problems.
Imagine code visualization as an amplifier. Without that it is possible to work on certain issues, but with that you are suddenly able to work on harder issues in a more efficient manner.
How to make that really work? Let’s start from small. Take your favorite IDE for example, Xcode can have built-in visualizer for native Cocoa classes such as
NSFont. The code to show them is already there, just need to find a way to present. Qt Creator can have visualizer for
For visualizing the states of a program, it works just like our existing debugger with variable watching feature. Except that is presented in a structural way, specific presentation can be given by the programmer himself, just like writing a test case. We can have a drag-and-drop layout interface to do that.
Some of Bret Victor’s ideas (like parameter tagging) can already be achieved with a static analyzer such as clang. Others can only be done in execution. How to speed up execution to avoid setting up a lot of states is the most interesting problem. I think we can try to reduce the amount of input and take an independent block of code (functions without side effects) for examination in an isolated sandbox environment, supplying the required parameters in a simpler way just like preparing for test data sets.
In summary, I still expect that this visualization tool as a programming assistant. An assistant that can take a piece of code, walk through its execution and explain it to me how it works. Even if can only tell how does one variable transits in a loop, it will still be much better than me evaluating it by hand with paper and pencil. In short, hand the repeating tasks over to your machine and focus on something more creative, that’s what we humans are good at.