Thursday, September 27, 2007

Miro: offline Youtube application for Mac

I've been looking for a YouTube front-end application forever, for three reasons:
  • the browser isn't integrated with my keyboard's Play / Stop buttons and my apple remote
  • YouTube history sucks, as it gets wiped every session
  • I want to watch all those illegal music videos wonderful user-generated movies offline
Here's what I found so far:
video player

It does concurrent downloads, and tags the unseen videos. This is convenient because I can get multiple variants of the same video, and see / delete the bad dupes. Unfortunately, it doesn't meet my main request -- no integration with the keyboard or apple remote.

Hope this helps people looking for something similar! Please comment if you find something better.

Happy watching,
Victor

Wednesday, September 26, 2007

BSD Sockets in Ruby

I love Ruby. Completely. I don't want to write in anything else. However, meeting with the BSD sockets interface left me with a sour taste. Here's what I learned. Hopefully, you'll find this post and won't waste time if you have to work with Ruby's sockets.

You can send packets with send
The method name is good for consistency, but a horrible choice in general, if you ask me, because it overrides send in Object (used to send a message to an object, same thing as calling a method).

send's parameters are a string representing the data (same encoding as in recv), and a number for flags. The number is NOT optional (messed up choice, in my opinion), so my sockets code always has send data, 0 in it.

send fails oddly
If you're seeeing in `send': symbol string may not contain `\0' (ArgumentError) then your socket is object is null. This happens because nil uses Object's send, so it thinks you're passing it a method name.

pack_sockaddr_in doesn't like localhost
Silly me, I looked the example using www.google.com and I thought I can give pack_sockaddr_in any address. If I give it localhost, I get in `connect': Invalid argument - connect(2) (Errno::EINVAL).
Solution: use 127.0.0.1

Using strings for send / recv is annoying
If I'm using sockets, I'm working at the byte level. Using Fixnum arrays to represent bytes in a packet is a lot more convenient than using strings. Here are snippers for converting between the two formats. (I did Scheme at MIT, so I love map-reduce... I meant, collect-inject).

bytes > string:
block_string = block.flatten.map { |value| value.chr }.join('')


string > bytes:
block = (0...block_string.length).map { |i| block_string[i] }


That's about it. Hope this helps someone!
Victor