Monday, August 8, 2011

*Listen* to Youtube on linux (legally)

Per the terms of service, you are not supposed to download YouTube videos. However, it does NOT say that you cannot view them in something other than a web browser.  The main problem with youtube is how much garbage/dodginess there is.  Also, most of the time I just want to listen to the music anyway.... what to do?

The answer: use youtube-dl to provide the correct download link, then stream to mplayer and null the video.

Steps:
  1. Download youtube-dl and put somewhere in your path (such as ~/bin/) and make executable.  If your player breaks, just download the latest version (up within 24 hrs of a youtube site modification) and it should work again.   They have a youtube-dl .deb package in the ubuntu repos, but it is obsoleted pretty fast (for instance 10.04 doesn't work).
  2. make sure mplayer and python are installed: (sudo apt-get install mplayer python)
  3. Use this command:
mplayer -vo null -cookies -cookies-file /tmp/cookie.txt $(youtube-dl -g -f 34 --cookies /tmp/cookie.txt "http://www.youtube.com/watch?v=pGruu89cCw8")


Of course, you will change the video link to be the one you like.  Here is some explanation of what is going on:
  • Youtube requires cookies to be enabled.  We get the video link via youtube-dl and put it into the cookie file.  mplayer is using cookies and reads the url to play from the cookie file.
  • The -g means get the url, and -f changes which file format you are getting the link to (look up youtube codes... current options are 5, 34, 35, 18, 22, 37, 38, 43, 44, 45, 17).  34 is the lowest resolution flv format at 128 kbits/s sound (and I think is standard "360").  18 would give you 96 kbits/s sound.   
  • -vo null means no video output.  Use -fs instead if you want full screen, or nothing for that option if you want regular.
There you have it.  Robust, legal, streaming audio player for youtube.

This also seems to work on short playlists, but not always:

mplayer -vo null -cookies -cookies-file /tmp/cookie.txt $(youtube-dl -g -f 34 --cookies /tmp/cookie.txt "http://www.youtube.com/view_play_list?p=460F66B8E8E56FB6")


Navigate through the tracks with ">" and "<".



Monday, April 11, 2011

rvm with Ubuntu 10.04 and 10.10

If you plan on doing a lot of development in ruby, then rvm (ruby version manager) is the way to use lots of different ruby versions and gems. If you just want to run ruby, you should use your system's package manager.

This is a condensed version of Chistopher Irish's excellent write-up

(leading $ is the bash prompt)

$ sudo apt-get install curl git-core ruby
$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)

If you haven't already replaced your .bashrc, you probably have a line in there like this:
[ -z "$PS1" ] && return

Replace that line with:

if [[ -n "$PS1" ]]; then

Then, add this to the last line of the .bashrc file (however, you can leave off that very final, dangling 'fi' if you did NOT have a return statement that you replaced earlier).

if [[ -s $HOME/.rvm/scripts/rvm ]] ; then source $HOME/.rvm/scripts/rvm ; fi

fi

There are going to be prerequisites to installing most ruby's. Use the command rvm notes to discover those dependencies for your system.

Okay, we'll grab some prerequisites for compiling 1.9.2:

$ sudo aptitude install build-essential bison openssl libreadline5 libreadline-dev curl git-core zlib1g zlib1g-dev libssl-dev vim libsqlite3-0 libsqlite3-dev sqlite3 libreadline-dev libxml2-dev git-core subversion autoconf

Now, we can list the ruby versions we can install, install 1.9.2, and set it as default.


rvm list known  # see which ruby versions we could install
rvm install 1.9.2-head
rvm --default 1.9.2-head  # make ruby 1.9.2 our default

Tuesday, March 15, 2011

bacon and autotest

Took a little to figure this out, so thought I would share.  You need an empty file in your spec folder called .bacon in your spec folder.  This appears to load up a lot of the proper bacon environment things into autotest.  However, if you want to override specific behaviors, you do that in a .autotest file in the top directory.


touch spec/.bacon

Inside .autotest:
require 'rubygems'
require 'bacon'
require 'autotest/bacon'

# see inside /lib/autotest/bacon.rb for template

class Autotest::Bacon < Autotest
  undef make_test_cmd
  def make_test_cmd(files_to_test)
    # I modified this to only include _spec.rb files:
    args = files_to_test.keys.flatten.select {|v| v =~ /_spec.rb$/ }.join(' ')
    args = '-a' if args.empty?
    # TODO : make regex to pass to -n using values
    # use bacon -h to see all your possible options!
    "#{ruby} -S bacon -I#{libs} -o TestUnit #{args}"
  end
end

Monday, March 7, 2011

image landscapes for ebooks (and other digital-based reading)

The problem with electronic text is that it lacks the spatial character of a book.  You don't really know where you are at in a giant, monolithic column of perfect text, especially when resizing it changes where text is located.  However, in a book, you have several spatial cues that are constant: which page, which part of the page, how deep into the book (depth) and any imperfections on the page itself or with the text.  So, with ebooks, how can you duplicate this effect?

One could write a program that lays books out so that the book is more like a book (there are cues that indicate depth, etc.).  With svg you could easily add certain permanent imperfections to the text to give it more character.

There are two other ways to add a spatial dimension to reading text:

1. Layer text, or pages, into a 3D landscape.  If the pages of your book traversed an interesting cityscape, room, landscape, or mountain path, etc., you would have spatial anchors upon which to peg the text.

2. The page itself could link out into either auto-generated or user defined images (or text).  In this way, each page is given visual character that links it to other ideas and images.

IMO, both the ideas and the implementation of these ideas (i.e., embedding pages of text, with textual imperfections into a 3D landscape, or adding pictures and text to the pages of the book itself, etc.) are obvious and trivial.  Any college student taking a web or 3D design class could do it.  It merely remains for someone to do it.

Monday, February 21, 2011

ruby list comprehension

I have seen list comprehension cited as a feature of python that ruby lacks. I want to play around with the idea to see where it goes...

[disclaimer: this is just scratch space for ideas at the moment]

(I wonder how lazy enumerators will change the ruby approach?)

A nice write up on list comprehensions in python has an example where you can use list comprehension to find prime numbers. They divide it into two steps because it gets a little hairy on one line. Here's finding primes on one line using list comprehension:


>>> [x for x in range(2, 50) if x not in [j for i in range(2, 8) for j in range(i*2, 50, i)]]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

It's not bad, but it's easy to get lost in there (my ruby eyes are not highly trained in python, of course).

Now, one of the things list comprehensions do is it does selection and modification in the same phrase. This part of list comprehensions is easy to implement.

[ add the equivalent python here ]


(2..10).select(&:even?).map {|v| v**2 }
(2..10).map {|v| v**2 if v.even? }.compact

Implementing this aspect of list comprehensions in ruby is less than trivial:


module Enumerable
  def lc(&block)
    block.nil? ? self : self.map(&block).compact
  end
end

The other part of list comprehensions is the fact that the evaluation happens from right to left (in the python code) so that the execution of the code is efficient.

This gets the job done, but the right-most block is executed multiple times to make it work:

(2..50).reject {|j| (2..8).map {|i| (i*2).step(50,i).to_a}.flatten.include?(j) 

# also other ways to think about this (need to finish this post)
Set.new(2..50) - (2..8).reduce(Set.new) {|np,i| np.merge((i*2).step(50,i)) }

Wednesday, February 9, 2011

Using Dropbox and git

Dropbox is really fantastic, but its version control abilities are limited. Git is a fantastic tool for versioning things.  Here's how I use both to keep detailed version history of the projects that matter to me:

Solo Repo (use a Normal git repo)


For most projects, I do not need to merge changes with multiple people, but I want a version history. For these, I set up a normal git repository. This repo has no "origin", so I never push to anything, just stage and checkin.


cd ~/Dropbox/myproject
git init
git add .
git commit -m 'first commit'
# after a while
git status
git commit -a -m 'another commit' 

Easy to do, and all my changes (even when I don't happen to check them in) follow me on all the computers I use dropbox on.

Shared Repo (use a Bare git repo)


In this case, I'll make a bare git repo and then share the folder with others. I'll assume I'm starting with an existing project directory, but it is not a git repo yet. (there are other ways to do this).


# my project is sitting on my local machine somewhere.
# I will make it a normal git repository
cd someproject
git init
git add .
git commit -m 'first commit'
# now make a bare git repository on my dopbox folder
# by convention, bare repos end in '.git'
mkdir -p ~/Dropbox/git/someproject.git  
pushd ~/Dropbox/git/someproject.git 
git init --bare
popd  # back where I was
git remote add origin ~/Dropbox/git/someproject.git
# now we can push and pull to our origin (see below if you get errors)
git pull
git push

If you get trouble when pushing or pulling to your remote, add these lines to your ~/.gitconfig file:


[push]
 default = matching
[branch "master"]
 remote = origin
 merge = refs/heads/master