package com.robonobo.plugin.mp3; import java.io.*; import java.nio.channels.FileChannel; import java.util.Map; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.UnsupportedAudioFileException; import javazoom.spi.mpeg.sampled.file.MpegAudioFileFormat; import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.robonobo.common.pageio.paginator.EqualSizeFilePaginator; import com.robonobo.common.pageio.paginator.Paginator; import com.robonobo.core.RobonoboInstance; import com.robonobo.core.api.AudioPlayer; import com.robonobo.core.api.Robonobo; import com.robonobo.core.api.model.Stream; import com.robonobo.mina.external.buffer.PageBuffer; import com.robonobo.plugin.mplayer.MplayerAudioPlayer; import com.robonobo.spi.FormatSupportProvider; public class Mp3FormatSupportProvider implements FormatSupportProvider { private static final int PAGE_SIZE = 32*1024; Robonobo rbnb; Log log = LogFactory.getLog(getClass()); public void init(Robonobo r) { this.rbnb = r; } public RobonoboInstance getRbnb() { return (RobonoboInstance)rbnb; } public String getFormatName() { return "MP3 Audio"; } public String getMimeType() { return "audio/mpeg"; } public String getDefaultFileExtension() { return "mp3"; } public String[] getSupportedFileExtensions() { return new String[] {"mp3"}; } public boolean supportsBroadcast() { return true; } public boolean supportsReception() { return true; } public Paginator getPaginator() { return new Mp3Paginator(); } public Stream getStreamForFile(File f) throws IOException { AudioFileFormat fileFormat; try { MpegAudioFileReader reader = new MpegAudioFileReader(); fileFormat = reader.getAudioFileFormat(f); // fileFormat = AudioSystem.getAudioFileFormat(f); } catch (UnsupportedAudioFileException e) { throw new IOException("File "+f.getAbsolutePath()+" does not appear to be an mp3 file"); } if(!(fileFormat instanceof MpegAudioFileFormat)) throw new IOException("File "+f.getAbsolutePath()+" does not appear to be an mp3 file"); Stream s = new Stream(); s.setMimeType(getMimeType()); s.setSize(f.length()); Map<String, Object> props = fileFormat.properties(); s.setDuration((getLongProp(props, "duration")) / 1000); // mp3 duration is in microsecs String title = (getStringProp(props, "title")).trim(); if(title.length() == 0) title = getTitleFromFileName(f); s.setTitle(title); String artist = (getStringProp(props, "author")).trim(); if(artist.length() == 0) artist = "Unknown Artist"; s.setAttrValue("artist", artist); String album = (getStringProp(props, "album")).trim(); if(album.length() == 0) album = "Unknown Album"; s.setAttrValue("album", album); s.setDescription((getStringProp(props, "comment")).trim()); s.setAttrValue("year", (getStringProp(props, "date")).trim()); s.setAttrValue("track", (getStringProp(props, "mp3.id3tag.track")).trim()); return s; } private String getTitleFromFileName(File f) { Pattern titlePat = Pattern.compile("^(.*)\\..*?$"); Matcher m = titlePat.matcher(f.getName()); if(m.matches()) return m.group(1); else return "Untitled Track"; } public void paginate(File f, PageBuffer pageBuf) throws IOException { FileChannel fc = new FileInputStream(f).getChannel(); new EqualSizeFilePaginator(PAGE_SIZE, f.length(), 0).paginate(fc, pageBuf); } public AudioPlayer getAudioPlayer(Stream s, PageBuffer pb, ThreadPoolExecutor ex) { // If we have an mplayer, use that, otherwise use the built-in player // String path = rbnb.getConfig().getMplayerExePath(); // if(path != null) { // File mplayerExe = new File(path); // if(mplayerExe.canExecute()) { // try { // log.info("Using mplayer audio player for stream "+s.getStreamId()); // return new MplayerAudioPlayer((ScheduledThreadPoolExecutor) ex, s, pb, mplayerExe); // } catch (IOException e) { // log.error("Caught ioe opening mplayer audio player", e); // } // } else // log.warn("Not using mplayer as supplied path "+mplayerExe.getAbsolutePath()+" does not exist or is not executable"); // } log.info("Using built-in player for stream "+s.getStreamId()); return new Mp3AudioPlayer(s, pb, ex); } private String getStringProp(Map<String, Object> props, String propName) { String result = (String) props.get(propName); if(result == null) return ""; return result; } private Long getLongProp(Map<String, Object> props, String propName) { Long result = (Long) props.get(propName); if(result == null) return 0l; return result; } }