After going through the chaos and matters in Feb., finally I have two days off to do something interesting. I have been thinking about to find a lyrics fetcher on OS X for a long time, but I failed to find one.
For IOS users, you can download musicXmatch. For Windows users, you can download MiniLyrics. These two softwares work like a charm on the mentioned platforms, but for OS X, I still could not find a versatile one. Therefore, I came up with an idea that why not try to make one with Python.
However, and you know there’s a however because my writing doesn’t seem to be exciting, the prerequisite that using Python to control iTunes is really challenging and nearly impossible at this time. Specifically speaking, I need to know the song’s name to fetch lyrics, right? But Python has no direct way to retrieve the information or manipulate with iTunes using direct commands, thereby Objective-C and Applescript come into help. This is what causing confusion and trouble because there’s no way to debug since I am not familiar with the other two languages.
From the Internet, the best solution I can find is to use something called ScriptingBridge from Apple, but it seems to lack official support since first published in 2007. ScriptingBridge is a module that can be used to input commands to Applescript from mainstream programming languages including Python. To use this package, we need to install PyObjC package in Python, and its installation is extremely slow so be prepared for it.
Actually, the code using ScriptingBridge to retrieve information from iTunes is very limited. Following is the code I use as an example. Bear in mind that to avoid encoding issue because sometimes I listen to mandarin and cantonese songs, I use try-except block to get rid of errors.
from Foundation import *
from ScriptingBridge import *
iTunes = SBApplication.applicationWithBundleIdentifier_("com.apple.iTunes")
Easy? NO! The problem is that it is quite a unstable program and only works under specific conditions. First, in the try-except block you’ll find I use currentTrack() method, it will work when you are listening to a downloaded song in your iTunes library or a streaming song in the radio section. Second, the true code to get the information from streaming song, which is currentStreamTitle() method following the try-except block, does not work, only returning object “None”. Third, for streaming songs outside of radio tab, for example, the “For You” tab, neither of the previous mentioned methods will work.
At first, I thought this is due to the not-perfect compatibility between Python and iTunes, and thought using Applescript will solve this problem. However, even if I used Applescript directly, I still keep getting confusing conclusions.
tell application "iTunes"
current stream title
I found a post in stackoverflow and one user pointed out this problem is due to Apple itself:
It appears that, in iTunes 12.2, a whole variety of interesting things are going on.
current stream title returns missing value when requesting the name of a stream coming from “For You” (e.g. something not in your current music library). name of the current track doesn’t exist. For example, I’m listening to “Alternative Gems: 1994” from “For You” right now (Yay- grad school days) and I can’t get any information about what is playing. If I go to the album the track is playing from to play something else, missing value and error -1728 on name of current track too.
When listening to Beats 1 radio as per @ivan above, I also get missing value but for name of the current track I get “Beats 1”. As @dougscripts points out, the stream title stuff varies all over the map.
Listening to a radio station created via a “For You” seems to give me the correct name of the current track.
So, in short, chaos.
Well, at least for now, I have to find an app to get the lyrics instead of using Python to automate this workflow. To be frank, OS X is constraining software development more and more strictly as its version grows, when on earth could it be as compatible-friendly to softwares as Microsoft’s Windows?