So, almost a month ago I wrote about reading MP3 information using ColdFusion. I promised a follow up the next day and ended up getting a bit busy with a new job, trips, etc. The sad thing is that I wrote the code a few days afterwards and it ended up being exceptionally simple. So - first off - sorry for the delay. Let's look at the CFC I ended up with. As you can see, it is so simple I can share all the code right here:

<cfcomponent displayName="MP3" hint="Reads ID3 information from an MP3" output="false">

	<cfset variables.filename = "">
	<cfset variables.loaded = false>
	<cfset variables.id3tag = "">
	
	<cffunction name="init" access="public" returnType="mp3" output="false">
		<cfargument name="filename" type="string" required="false">
		
		<!--- create an instance of the java code --->
		<cfset variables.mp3 = createObject("java", "org.farng.mp3.MP3File")>

		<cfif structKeyExists(arguments, "filename")>
			<!--- read it in --->
			<cfset variables.filename = arguments.filename>
			<cfset read(variables.filename)>			
		</cfif>
		
		<cfreturn this>
	</cffunction>
	
	<cffunction name="checkLoaded" access="private" returnType="void" output="false"
				hint="Helper function to throw error if no mp3 loaded.">
		<cfif not variables.loaded>
			<cfthrow message="You must first read in an MP3!">
		</cfif>
	</cffunction>

	<cffunction name="getAlbumTitle" access="public" returnType="string" output="false"
				hint="Returns the album title.">
		<cfreturn variables.id3tag.getAlbumTitle()>
	</cffunction>

	<cffunction name="getSongGenre" access="public" returnType="string" output="false"
				hint="Returns the song genre.">
		<cfreturn variables.id3tag.getSongGenre()>
	</cffunction>
	
	<cffunction name="getSongTitle" access="public" returnType="string" output="false"
				hint="Returns the song title.">
		<cfreturn variables.id3tag.getSongTitle()>
	</cffunction>

	<cffunction name="getTrackNumber" access="public" returnType="string" output="false"
				hint="Returns the song title.">
		<cfreturn variables.id3tag.getTrackNumberOnAlbum()>
	</cffunction>

	<cffunction name="getYearReleased" access="public" returnType="string" output="false"
				hint="Returns the song's release date.">
		<cfreturn variables.id3tag.getYearReleased()>
	</cffunction>
	
	<cffunction name="hasID3V1" access="public" returnType="boolean" output="true"
				hint="Returns true if the mp3 has id3v1 information.">
		<cfset checkLoaded()>

		<cfreturn variables.mp3.hasID3v1Tag()>
	</cffunction>

	<cffunction name="hasID3V2" access="public" returnType="boolean" output="false"
				hint="Returns true if the mp3 has id3v2 information.">
		<cfset checkLoaded()>
		
		<cfreturn variables.mp3.hasID3v2Tag()>
	</cffunction>
	
	<cffunction name="read" access="public" returnType="void" output="false">
		<cfargument name="filename" type="string" required="true">

		<!--- does the file exist? --->	
		<cfif not fileExists(arguments.fileName)>
			<cfthrow message="#arguments.fileName# does not exist.">
		</cfif>

		<!--- copy to global scope --->
		<cfset variables.filename = arguments.filename>
		
		<cftry>
			<cfset variables.mp3.init(variables.filename)>
			<cfset variables.loaded = true>
			
			<cfif hasID3V1()>
				<cfset variables.id3tag = variables.mp3.getID3v1Tag()>
			</cfif>
			<cfif hasID3V2()>
				<cfset variables.id3tag = variables.mp3.getID3v2Tag()>
			</cfif>
			
			<cfcatch>
				<cfthrow message="Invalid MP3 file: #arguments.filename# #cfcatch.message#">
			</cfcatch>
		</cftry>
	</cffunction>
	
</cfcomponent>

So - first - a recap. In the last entry I talked about the Java ID3 Tag Library. This is the open source project that I'm wrapping with ColdFusion. ID3 tags are the encoded information in the MP3 file that tslks about the song. It contains different bits of information based on the style of ID3 tag used in the file. There are two main version of ID3, and various sub versions of each. The Java ID3 Tag Library supports working with both main styles of ID3 tags and has specific API calls to work with them.

But - and this is why I love the project so much - the author also wrote a set of simple methods that will work with any version ID3 tag. In the code above, check out getAlbumTitle and getSongTitle. While I could have used specific API calls for the two versions of ID3, I didn't have to since there were generic functions built into the code.

To be honest, I got lucky. This was one of the first Java libraries I found, and it just turned out to be darn easy and useful. So how could you use this? You can imagine a site that let's users upload mp3s. (Legal of course.) Instead of asking the user to enter information about the song, you can use ColdFusion to read out all the ID3 information automatically.

Anyway - let me know if you actually use this on a production site. I'd be curious to see it in use.