beaTunes News

Friday, October 2, 2015

You will want this update

beaTunes4 logo

Thanks to user feedback, I was able to discover and fix a nasty memory leak (Thanks, Willi!). So, if you had any kind of memory problem when using beaTunes, you will definitely want to update.

As always, you can download the update from the download section of the website.

Most important changes in 4.5.4

  • Fixed a memory leak.
  • Fixed lookup of songs with no album.
  • Fixed table order after BPM edit in sorted column.


Friday, September 25, 2015

This Open Key thing is great, but can I have parentheses, please?

beaTunes 4 introduced the capability to easily copy key values to the comment field during analysis. Pretty handy, as it allows easy access to key values from applications that don't really support keys (e.g. iTunes). Recently, I was told, that this works really well, but it would be even better to have parentheses around the Open Key code to better distinguish 2d from 12d when searching.

Thanks to the plugin API, there was a super simple solution to this: Just write a custom Key Text Renderer. The two needed classes, Key and KeyTextRenderer, are documented here and here.

And this is what the Groovy code looks like:

import com.tagtraum.audiokern.key.Key
import com.tagtraum.beatunes.KeyTextRenderer

class BracedOpenKey implements KeyTextRenderer {

     * Create a textual representation for a Key object.
     * @param key key
     * @return textual representation
    def String toKeyString(Key key) {
        String openKeyCode = key.getOpenKeyCode()
        // create the final string
        return "($openKeyCode)"    //  <- this is where we add the parentheses!

     * Create a tooltip representation for a key object.
     * This may also include html-tags.
     * @param key key
     * @return tooltip representation
    def String toToolTip(Key key) {

     * Short name of this renderer. To be used in the user interface.
     * @return name
    def String getName() {
        "Braced OpenKey"


To install, just save it in a file called BracedOpenKey.groovy and place it in the plugins folder. Upon restart, it will show up in the display format preferences and the export-as-comment option (see screenshot above).

Labels: , ,

Wednesday, September 23, 2015

Resetting iTunes Album Ratings

With the introduction of iTunes 12.2 a few months back, quite a few things changed for users and software vendors alike. One of the things that didn't come to my attention until recently is an oddity having to do with album ratings. It seems that hardly anyone really uses them, but if you have rated a couple of songs, iTunes displays an average of those ratings as the album rating. To signal that the values are computed rather than entered, they appear as gray stars as opposed to solid black stars. What happened when iTunes 12.2 was introduced is, that apparently some albums got ratings—nobody really knows where from. This resulted in all the unrated songs also showing ratings—gray ones, as they are computed, not entered. Obviously, everybody using smart playlists based on song ratings suffered.

Quite a bit.

A simple solution to the problem is to reset all album ratings to zero manually. Not very fun. When asked how to best solve the issue, I immediately figured that a library batch action can do the job. Library batch actions are little beaTunes plugins (often beaTlets), that do the same thing for all items in your beaTunes/iTunes library and can easily be scripted in Groovy/Jython/JRuby. So a library batch action for this particular problem really only needs to reset the album rating to 0 for all songs with an album rating other than 0.

Here's the Groovy code (download):

import javax.swing.Action
import java.awt.*
import org.slf4j.LoggerFactory
import com.tagtraum.beatunes.action.standard.LibraryBatchAction
import com.tagtraum.beatunes.action.standard.LibraryBatchAction.EachSongProcessor
import com.tagtraum.beatunes.MessageDialog
import javax.swing.JOptionPane
import com.tagtraum.audiokern.AudioSong

// An action that allows to reset all album ratings.
// The corresponding menu item can be found in the 'Tools' menu.
class ResetAlbumRatings extends LibraryBatchAction {

    // Inner class that implements the
    // com.tagtraum.beatunes.action.standard.LibraryBatchAction.EachSongProcessor
    // interface. Its process method is called for each song.
    class Resetter implements EachSongProcessor {

        static log = LoggerFactory.getLogger("ResetAlbumRatings.groovy")
        String file

        // Called once, before processing starts.
        def void startProcessing(int count) {
   "We are expecting to embed ratings for ${count} songs."

        // Called for each song.
        def void process(AudioSong song, int index) {
            int rating = song.getAlbumRating()
            if (rating > 0) {
      "Reset album rating for " + song)
            } else {
      "No rating set in " + song)

        // Called once all songs were processed.
        def void finishProcessing() {
            new MessageDialog(getApplication().getMainWindow(),

        // Message to be shown in progress dialog.
        def String getProgressDialogMessage(AudioSong song) {
            "Resetting album rating of ${song.getName()}"

        // Title for progress dialog.
        def String getProgressDialogTitle() {
            "Resetting album ratings ..."

    // Unique id
    def String getId() {

    // Is called by beaTunes as part of the lifecycle after instantiation.
    // At this point all other plugins are instantiated and registered.
    // We use this to set the menu item's (i.e. action's) name.
    def void init() {
        putValue(Action.NAME, "Reset Album Ratings")

    // We need to ask the user, whether he really wants to do this.
    // How we ask is defined here.
    def String getConfirmationMessage() {
        "Do you really want to the album ratings of all your files?"

    // Factory method that creates the processor for each song.
    def EachSongProcessor createEachSongProcessor() {
        new Resetter()

You can install this like any other plugin—just make sure the code is in a file called ResetAlbumRatings.groovy (the file name must be the same as the main class name). To reset all album ratings in your library, restart beaTunes after the plugin installation, and open the Tools menu. There should now be a new item called Reset Album Ratings (see init() in the code). When running this action, please be careful: You won't get to say "yes" or "no" for each individual album. That's why it's called a batch action. Also, changes cannot be undone.

Library batch actions are a great way to fix something in your entire library. And it's not rocket science. Basic understanding of Groovy (or some other popular scripting language) is typically all you need.

Labels: , ,

Tuesday, September 22, 2015

Introducing Quick-Search

beaTunes4 logo

With increasing collection sizes, navigating the library becomes more and more difficult. Of course you can filter and search, but quickly going to an album or artist with just a couple of keystrokes is probably the easiest way to navigate. Starting with beaTunes 4.5.3, this is now possible.

Here's how:

For quick-search to work, you need to sort your library by one of the textual columns, e.g. Artist or Album. Make sure the table has the keyboard focus and then start typing the first couple of letters of what you are searching for. In an overlay, beaTunes will show those letters and—once you stop typing—scroll to the next matching row.

As mentioned above, this works for pretty much all textual fields and one additional column: BPM. So when the table is sorted by BPM, you can simply type 100 and beaTunes will scroll to the first song with 100 beats per minute.

There are a couple of other improvements and fixes. Details can be found below. As always, you can download the update from the download section of the website.

Most important changes in 4.5.3

  • Fixed exception after clearing ignored issues.
  • Fixed HiDPI drag and drop images.
  • Fixed error in bpm range coercion arithmetic.
  • Fixed exclusion of audiobooks/iTunesU/home videos from analysis.
  • Added current heap memory use info to About dialog.
  • Added quick-search popup for sorted playlists.
  • Added visual indicator for computed ratings.
  • Improved sync of folder-based-library.
  • Improved built-in Help.
  • Improved AppleScript/COM error reporting.
  • Improved handling of digital booklets.
  • Improved different album artist inspection.

Labels: ,

Thursday, September 17, 2015

Destemming Stems

DJ Techtools just ran a great story that explains how to extract individual stems from stem files using FFmpeg and Audacity. Their well working approach is a mixture of installation, configuration and drag and drop.

If you are using OS X and are comfortable on the command line, you might appreciate a different approach, allowing you to batch destem your stem files to a format of your choice. To do so, simply install FFmpeg, so that it is in the PATH. Then download the BASH script and make sure it's executable (chmod u+x and in the PATH as well (if you don't know how to do that, please do not ask me, but Mr. Google.).

Once installed, the script is pretty self-explanatory. Open a terminal window, go to the folder that contains your stems and type:

MyMac$ aif .

This will destem all files in the current directory and encode the results in AIFF. Other formats are possible. To get a list, simply type:


Yep. Just don't give it any arguments. Explicitly supported are: m4a | flac | wav | ogg | aif.


PS: The script may fail, if there are less/more than 4 stems plus the original in a file. It really isn't the sharpest tool from the shed.

Image by Joshua Rappeneker

Labels: ,

Tuesday, September 15, 2015

DevAssist: Syria Relief

The civil war in Syria has caused tremendous pain and suffering. To help, a bunch of indie developers like myself are going to donate sales on Wednesday 16th September to charity. In the case of beaTunes, this will be Pro Asyl, an organization that gives refugees a voice in German and European politics.

If you want to support this effort, please talk about it and let other people know. Perhaps it makes sense to move an already planned purchase to Wednesday 16th. Participating developers will be listed on


Image from UNHCR Flickr stream under creative commons license.

Labels: , ,

Wednesday, September 9, 2015

How to enable the BPM column in iTunes 12

beaTunes4 logo

iTunes 12.2 with its fancy album views made it a lot harder for the average user to enable the Beats Per Minute column. Here's a quick, visual howto guide.

Labels: ,