Saturday, August 15, 2009

Using jQuery to build Google Chrome extensions

Today I wanted to learn how to write an extension for Google Chrome. The Chrome extension system is not yet released, but there is alpha support for developing extensions. A HOWTO describes what you need to do. This is actually quite easy: Chrome extensions are very much like regular web pages. They consist of HTML, CSS, JavaScript and images. Some JSON metadata describes the extension that is then packaged into a *.crx file.

As I don't like raw JavaScript very much, I wondered whether it is possible to use my favorite JavaScript library jQuery in Chrome extensions. It turned out that this is actually very straight-forward. It basically works out-of-the box as you would expect it.

I tried to use jQuery in a background page as well as in a content script. Here is the manifest.json file that describes my demo extension:

{
  "name": "A jQuery Chrome extension",
  "version": "0.1",
  "description": "Use jQuery to build Chrome extensions",
  "content_scripts": [
    {
      "matches": ["http://jquery.com/*"],
      "js": ["jquery-1.3.2.js", "content.js"]
    }
  ],
  "background_page": "background.html"
}

To use jQuery in my content script 'content.js', it was enough to list the stock jQuery JavaScript file as the first content script. 'content.js' then has jQuery available:

$('a').css({'background-color': 'yellow'});

Using jQuery in the background page is even more straight-forward. Simply embed it into 'background.html' the same way as you would for every other HTML page:

<html>
  <head>
    <script src='jquery-1.3.2.js'></script>
    <script src='background.js'></script>
  </head>
</html>

This was extremely easy. I think the Chrome team made the right decision to build their extension model on the web page model. Now any web developer can start writing Chrome extensions without having to leave their comfort zone.

Let me end this post with two disclaimers: While I do work for Google as a software engineer, my work is not related to Chrome at all. My interest for writing Chrome extensions is purely private. Also, I have not written any large Chrome extensions. So, it's easily possible that you will encounter problems when using jQuery in a complex use case. YMMV.

Thursday, January 8, 2009

Embedding cover images in MP3 files for Android, iTunes, iPhone, Windows Media Player, and Windows Explorer

This is the continuation of a short series of blog postings about how I tag my MP3 files. Today I'll share my experience in displaying cover art in various media players.

I am using two portable players: An Android phone and an iPhone. On my laptop I usually use iTunes, but sometimes I fall back to Windows Media Player because of its fast startup time. I keep MP3 files in individual folders per album, so I also want the thumbnail view of Windows explorer to show the cover art.

Let's start with a short summary of what works for me: Embed cover images into the first track of every album, and additionally save them as Folder.jpg files in the album directories. See below for the long story.

Analysis of different players

There are various ways of attaching cover art to MP3 files, and every player that I use seems to do it slightly differently. Here is what I found out:

  • iTunes stores cover images in its own proprietary storage in some ITC2 format that I do't know anything about (My Documents\My Music\iTunes\Album Artwork\Download\6118F104927B998E\10\10\05\6118F104927B998E-6DBB7171FCCCC5AA.itc2). Fortunately, it also shows images that are included in the MP3 files.
  • The iPhone seems to display whatever iTunes displays.
  • Android also works fine with cover images embedded into the MP3 files.
  • Windows Explorer expects cover art in Folder.jpg files. It does not show embedded images.
  • Windows Media Player seems to keep cover art in a whole bunch of different hidden files like Folder.jpg, AlbumArtSmall.jpg, AlbumArt_{SOME_GUID}_Large.jpg, etc. It does read covers from the MP3 files however. If you import a MP3 file into the Windows Media Player library it automatically generates all files. This includes Folder.jpg, which is needed for Windows Explorer

In summary, all of my players show images that are embedded in MP3 files. It seems to be enough to embed a cover image into the first track of an album. Windows Explorer needs Folder.jpg, which is easiest to create by importing files into Windows Media Player.

Caveat: Windows Media Player resizes Folder.jpg files to 200x200 pixels without asking, so don't use this file as your primary storage. I want my covers to be 600x600 pixels, which seems to be a good compromise between file size and high quality (e. g. for iTunes cover flow). Because of that I have an additional Cover.jpg file in all of my album directories. This is not needed for any player, but I like to have it there for scripts that I use, e. g. to generate listings of my files.

Getting and embedding cover images with iTunes

Before you can embed cover art into an MP3 file you need to have it. Of course you can scan them yourself, but I find it much easier to use iTunes, which has many album covers in a very high quality.

Here is what you need to do: Import the album MP3s into the iTunes library and choose "Get Album Artwork" in the album context menu:

Sometimes iTunes does not have a matching cover - then you are back to scanning yourself. But more often than not you get a cover image. As mentioned above, iTunes stores it in its own proprietary format, but fortunately it is quite easy to extract. Open the album and right-click the first track, and then "Get Info":

In the dialog that opens go to the "Artwork" tab, select the image and copy it with Ctrl-C or using the context menu. Then immediately paste it back using the context menu or Ctrl-V. Click OK and iTunes saves the image directly into the MP3 file.

It is worth mentioning, that you can of course also paste the copied image into your favorite graphics editor, or straight into an Explorer window. The latter creates a file "image 1.bmp", which you can then convert into a JPEG, e. g. to use it as Folder.jpg

If you don't want to create Folder.jpg yourself, simply import the folder with your MP3 files (and with the embedded cover) into the Windows Media Player library. It will then generate Folder.jpg for you.

Wednesday, December 31, 2008

How to tag MP3 files for Android, iTunes, iPhone, and Windows Explorer

Being a proud owner of a brand-new Android phone and having a couple of weeks of vacation over the holidays, I decided that this is the perfect time to reorganize my digital music collection and to rip the last few CDs for which I had not had the time before.

I had to go through some trial-and-error experiments to find a tagging scheme that works for me, so I figured that my results might be interesting for others as well. I'm going to try to make a mini-series of blog postings that explain how I tag my MP3 files. I do not claim that this is the one and only tagging scheme, but it works well for me. If you use a different tagging scheme that works better for you, please let me know.

Tagging across devices, players, and media types

Being me, I want my music to be tagged perfectly for the handful of devices and programs that I use. This includes my iPhone that I recently used mostly as a media player and now also my Android phone. On Windows my main audio player is iTunes, but sporadically I also use Windows Media Player, mainly because it starts up much faster. Finally, I want to use the capability of the Windows Explorer to show the track titles when viewing tracks in the file system.

Tagging MP3s perfectly across these players was more challenging than I anticipated. It is very important to use the right ID3 tags, and until recently, I wasn't even aware of some of them. Here is my list of features of a "perfect" tagging scheme:

  1. Files from the same disc (set) should be be recognized as such. If not tagged correctly, iTunes (and other players) show tracks from the same CD as belonging to multiple CDs. This happens mostly for compilations. See below for the solution.
  2. Files and folders should show cover art in high quality. I want to see my cover art when playing a song, when using iPhone/iTunes cover flow, and as thumbnails in Windows Explorer.
  3. The files should play in the correct order. This seems trivial, but unfortunately it isn't.

Getting the tagging right is not made easier by the quite diverse collection of media types in my collection. I have albums of one artist, compilations from multiple artists, audio books, ballroom dance music, comedy discs, movie sound tracks, musicals, and so on. I also have a number of single MP3 files of an old collection of chart samplers that I didn't want to keep in their entirety.

Getting compilations recognized as single discs

For today, I thought, I'd get started with how to get single discs recognized as single discs. Here is a ballroom dancing album that contains tracks from various artists:

Clearly, every track is labeled with the same album name, so one might expect that iTunes recognizes the tracks as belonging to the same album. Unfortunately, this is not the case. Here is the result:

iTunes only recognized files as belonging to the same album if they also are from the same artist. Fortunately, there is a simple way to make iTunes understand that this is indeed only one album. Just select all tracks, right click, and select "Get Info" in the context menu. Then edit the "Album Artist" tag to have the same value for all tracks. I usually choose "Various", sometimes "Soundtrack" or similar. The album artist field is also useful for albums of a single artist "Somebody" where individual tracks are from "Somebody feat. Somebody Else".

I usually do not edit ID3 tags in iTunes. There are quite some decent ID3 editors out there. My favorite one is ID3-TagIT. Unfortunately it is not developed any more, but it is still available for download from several download archives. Here is how I enter the same information in the "Detailed Information" editor:

Technically, the "Album Artist" information is stored in the 'TPE2' ID3 frame that is defined as follows: “The 'Band/Orchestra/Accompaniment' frame is used for additional information about the performers in the recording.” Arguably, this definition does not quite match what we use it for, but all players seem to use it as the "album artist" as intended.

Let me know if this explanation was helpful for you. Check back later for other topics I'd like to write about in future postings: Which ID3 version(s) to use, how to include cover art, how to handle sets of two or more discs, audio books, and what else comes to my mind until then. Let's hope that I find the time.

Saturday, December 20, 2008

View Android Source Code in Eclipse

Recently, I have been hacking around with Android a lot, and I think it's awesome.

Unfortunately, the Android SDK does not come with source code, and sometimes the docs are not so great, yet. Being an open source project, the Android sources are available online, but they are not very easy to access from Eclipse. For one, the source files are sometimes difficult to find as they are distributed over many individual Git repositories, and then I am not always online.

Integrating source files into Eclipse is usually quite easy, but the Android Eclipse plugin (ADT) does not allow to modify the Java Source Attachment of android.jar in the Android Library. Fortunately, you only have to find out what the default location for source code is. Eric Burke nicely describes how to find that out.

Long story short: Android source code needs to be placed in a "sources" subdirectory of the Android SDK. Here is what you need to do:

  1. Get the Android source code (install repo, repo init, repo sync)
  2. Move all Java sources into a "sources" subdirectory of the Android SDK

Step 2 sounds easier than it is. There are a lot of Java files in the Android sources, and they are sprinkled all over the place. Eclipse, however, needs the source files in a standard Java source directory structure: The path of a source file needs to match its package name. To simplify this task, I have written a short Python script that recursively searches for Java files and packs them into a ZIP file. Unpack that source file into a "sources" subdirectory of the Android SDK. Enjoy:

from __future__ import with_statement  # for Python < 2.6

import os
import re
import zipfile

# open a zip file
DST_FILE = 'sources.zip'
if os.path.exists(DST_FILE):
  print DST_FILE, "already exists"
  exit(1)
zip = zipfile.ZipFile(DST_FILE, 'w', zipfile.ZIP_DEFLATED)

# some files are duplicated, copy them only once
written = {}

# iterate over all Java files
for dir, subdirs, files in os.walk('.'):
  for file in files:
    if file.endswith('.java'):
      # search package name
      path = os.path.join(dir, file)
      with open(path) as f:
        for line in f:
          match = re.match(r'\s*package\s+([a-zA-Z0-9\._]+);', line)
          if match:
            # copy source into the zip file using the package as path
            zippath = match.group(1).replace('.', '/') + '/' + file
            if zippath not in written:
              written[zippath] = 1
              zip.write(path, zippath)
            break;
         
zip.close()