Monday, June 22, 2009

Ruby script for setting lyrics in iTunes Library tracks

One of the cool features of the iPod Touch and iPhone is that is possible to see the lyrics of a track while it’s playing. The picture bellow shows that.

 

But the problem is that you have to insert the lyrics manually using the iTunes, for each track you have to use the “Get Info” option and then set the track, just like the pictures bellow.

 

That’s a problem, because if you have hundreds of tracks, it will take lots of clicks and time. In order to solve that problem, I created a Ruby script that tries to set lyrics for all the tracks in my iTunes Library.

The script interacts with the iTunes COM components to get all the tracks in my Library, after that, it uses the LyricWiki web service to get the lyrics for each track and set to it.

The script works only on Windows and it’s available in my github repository:

git://github.com/dougfernando/itunes-helper.git

http://github.com/dougfernando/itunes-helper

Now, every time I get a new album, all I have to do is to run the script again,  like the following images :

The script code is also bellow:

require 'win32ole'
require 'soap/wsdlDriver'
require 'iconv'

class ITunesHelper
def initialize(lyrics_service)
@itunes = WIN32OLE.new('iTunes.Application')
@tracks = @itunes.LibraryPlaylist.Tracks
@lyrics_service = lyrics_service
end

def show_all_tracks
@tracks.each do |track|
print track.Name() + "\n"
end
end

def set_all_lyrics
puts "Number of tracks to be analyzed: #{@tracks.count}"
index = 1
@tracks.each do |track|
if self.is_lyrics_empty(track.lyrics)
lyrics = @lyrics_service.get_lyrics(track.Artist(), track.Name())

if self.is_lyrics_empty(lyrics)
self.print_track(index, @tracks.count, track, "lyrics WAS NOT found")
else
track.lyrics = @lyrics_service.get_lyrics(track.Artist(), track.Name())
self.print_track(index, @tracks.count, track, "lyrics WAS found and set")
end
else
self.print_track(index, @tracks.count, track, "already had lyrics")
end
index = index + 1
end
end

def is_lyrics_empty(lyrics)
lyrics.empty? or lyrics == "Not found"
end

def print_track(index, total, track, result)
puts "Track #{index}/#{total}: #{track.Artist()} - #{track.Name()}: #{result}"
end
end

class LyricsServiceProxy
def initialize
@driver = SOAP::WSDLDriverFactory.new("http://lyricwiki.org/server.php?wsdl").create_rpc_driver
puts "Lyrics web service initialized"
end

def get_lyrics(artist, track_name)
Iconv.iconv("LATIN1", "UTF-8", @driver.getSong(artist, track_name).lyrics).to_s
end
end

itunesH = ITunesHelper.new(LyricsServiceProxy.new)
itunesH.set_all_lyrics


Douglas

Friday, June 12, 2009

Powershell script for converting Word documents to PDF format

In my job, we only send documents to clients in pdf formats. Sometimes we have to send several documents at once and it takes a good time to open each one and save it as a pdf, it’s not a very pleasant task.

In order to minimize this problem, I’ve created a simple powershell script that opens a Word document and saves it as pdf without any user interaction. With such script, I can convert a lot of files at once, just like this:

ls . *.doc* –Recurse | %{ ~\scripts\doc2ps1.ps1 $_.fullname }

With this command, I list recursively each doc/docx file in a directory and save each one as PDF.

By default, Office 2007 apps are not able to save files as PDF, so you have to install the add-in from Microsoft first to use the script. The add-in is available here.

Bellow is the script, it’s also available in my PowerShell scripts repository at GitHub (http://github.com/dougfernando/utility-scripts/tree/master) as doc2pdf.ps1.

param (
[string]$source = $(Throw "You have to specify a source path."))

$extensionSize = 3
if ($source.EndsWith("docx")) {
$extensionSize = 4
}

$destiny = $source.Substring(0, $source.Length - $extensionSize) + "pdf"
$saveaspath = [ref] $destiny
$formatPDF = [ref] 17

$word = new-object -ComObject "word.application"
$doc = $word.documents.open($source)
$doc.SaveAs($saveaspath, $formatPDF)
$doc.Close()

echo "Converted file: $source"

ps winword | kill

An important note, the script closes every Word instance in the end, so save any work previous using it.