/** * MobScroblet.java * * This program is distributed under the terms of the GNU General Public * License * Copyright 2008 NJ Pearman * * This file is part of MobScrob. * * MobScrob is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MobScrob is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MobScrob. If not, see <http://www.gnu.org/licenses/>. */ package mobscrob.midlet; import javax.microedition.lcdui.Alert; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.List; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; import mobscrob.alert.AlertType; import mobscrob.alert.Alertable; import mobscrob.event.FileCommandListener; import mobscrob.id3.TrackMetadata; import mobscrob.logging.Log; import mobscrob.logging.LogFactory; import mobscrob.logging.MicroLog; import mobscrob.navigator.SEFileNavigator; import mobscrob.player.MP3Player; import mobscrob.player.PlayProcessor; import mobscrob.player.ScrobbleProcessor; import mobscrob.player.TagReaderProcessor; import mobscrob.player.TrackMetadataFilePersistor; import mobscrob.player.TrackMetadataPersistor; import mobscrob.player.TrackMetadataRMSPersistor; import mobscrob.playlist.Playlist; import mobscrob.playlist.PlaylistRMSPersister; import mobscrob.properties.MobScrobProperties; import mobscrob.properties.PropertiesScreen; import mobscrob.properties.PropertyRMSPersistor; import mobscrob.scrobbler.MobScrobblerImpl; /** * MobScroblet is the main MIDlet in the MobScrobblerImpl mobile media player * * @author Neill * */ public class MobScroblet extends MIDlet implements CommandListener, Alertable { private static Log log; private static final String MENU_PLAYLIST = "Playlist"; private static final String MENU_CURRENT = "Current"; private static final String MENU_CONFIG = "Configure"; public static final String[] MENU_ITEMS = { MENU_PLAYLIST, MENU_CURRENT, MENU_CONFIG }; private Command exitCommand = new Command("Exit", Command.EXIT, 1); private Command navigatorCommand = new Command("Browse", Command.ITEM, 1); private List mainMenu; private Display display; private MP3Player player; private PlayProcessor tagProcessor; private ScrobbleProcessor scrobbleProcessor; private SEFileNavigator fileNavigator; private Playlist playlist; private MobScrobblerImpl scrobbler; private MobScrobProperties props; private PropertiesScreen propsScreen; /** * Inits the MobScrob MIDlet */ public MobScroblet() { final String methodName = "1"; try { MicroLog.configure(this); LogFactory.setImplementation("mobscrob.logging.MicroLog"); log = LogFactory.getLogger(MobScroblet.class); log.info("", "*************************"); log.info("", " Starting MobScrobblerImpl "); log.info("", "*************************"); display = Display.getDisplay(this); initMainMenu(); display.setCurrent(mainMenu); // load properties props = new MobScrobProperties(new PropertyRMSPersistor()); props.load(); // create the default return callback Callback returnCB = new Callback() { public void callback() { log.info(methodName, "Returning to main screen"); display.setCurrent(mainMenu); } }; player = new MP3Player(returnCB); scrobbler = new MobScrobblerImpl(props); scrobbler.setAlertable(this); // tag processor as a pre-processor tagProcessor = new TagReaderProcessor(); tagProcessor.start(); player.setPrePlayProcessor(tagProcessor); // scrobble processor as a post processor scrobbleProcessor = new ScrobbleProcessor(scrobbler); scrobbleProcessor.start(); TrackMetadataRMSPersistor scrobblePersister = new TrackMetadataRMSPersistor(TrackMetadataRMSPersistor.SCROBBLE_QUEUE_RECORD_STORE_NAME); scrobblePersister.load(this.scrobbleProcessor); player.addPostPlayProcessor(scrobbleProcessor); props.setScrobbleProcessor(scrobbleProcessor); playlist = new Playlist(returnCB); playlist.addFileListener(new FileCommandListener() { public void perform(int command, String file) { if (command == FileCommandListener.SELECT) { log.info(methodName, "Playing selected from playlist"); player.play(file); } } }); PlaylistRMSPersister playlistPersister = new PlaylistRMSPersister(); playlistPersister.load(playlist); player.addPlaylist(playlist); // create file navigator as root fileNavigator = new SEFileNavigator(returnCB, this); fileNavigator.loadFileSystem(); fileNavigator.addPlaylist(playlist); // add the listener to play MP3s selected in the FileNavigator fileNavigator.addFileListener(new FileCommandListener() { public void perform(int command, String file) { if (command == FileCommandListener.SELECT) { log.info(methodName, "Playing file " + file); player.play(file); } } }); propsScreen = new PropertiesScreen(props, returnCB, new Callback() { public void callback() { log.info(methodName, "Returning to main screen"); display.setCurrent(mainMenu); alert(AlertType.INFO, "Config saved"); } }, this); propsScreen.init(); } catch(Throwable t) { log.error(methodName, "Unable to initialise Mobscroblet: "+t.getMessage(), t); } } /** * Initialises the main menu. */ private void initMainMenu() { mainMenu = new List("MobScrob", List.IMPLICIT, MENU_ITEMS, null); mainMenu.addCommand(exitCommand); mainMenu.addCommand(navigatorCommand); mainMenu.setCommandListener(this); } protected void destroyApp(boolean unconditional) { final String methodName = "destroyApp"; log.info(methodName, "Destroying"); // stop on destroy if (player != null) { player.stopCurrentTrack(); } // wait for any current submission to finish, and // save unsubmitted tracks to file scrobbleProcessor.shutdown(); PlaylistRMSPersister playlistPersister = new PlaylistRMSPersister(); playlistPersister.save(this.playlist); TrackMetadataPersistor persistor; if(props.scrobbleOffline()) { persistor = new TrackMetadataFilePersistor( TrackMetadataFilePersistor.SCROBBLE_QUEUE_FILENAME, TrackMetadata.getSerializer()); persistor.save(this.scrobbleProcessor); } else { persistor = new TrackMetadataRMSPersistor(TrackMetadataRMSPersistor.SCROBBLE_QUEUE_RECORD_STORE_NAME); persistor.save(this.scrobbleProcessor); } // need to close the log on exit MicroLog.close(); } protected void pauseApp() { final String methodName = "2"; log.info(methodName, "Pausing"); // stop the player for the time being if (player != null) { player.stopCurrentTrack(); } } protected void startApp() throws MIDletStateChangeException { final String methodName = "3"; log.info(methodName, "Starting MobScroblet"); } /* * (non-Javadoc) * * @see * javax.microedition.lcdui.CommandListener#commandAction(javax.microedition * .lcdui.Command, javax.microedition.lcdui.Displayable) */ public void commandAction(Command command, Displayable s) { final String methodName = "4"; // just want to play a track at the moment if (command == exitCommand) { log.info(methodName, "Exiting"); destroyApp(true); notifyDestroyed(); } else if (command == List.SELECT_COMMAND) { int curr = mainMenu.getSelectedIndex(); if (curr > -1 && curr < MENU_ITEMS.length) { String currItem = MENU_ITEMS[curr]; if (MENU_PLAYLIST.equals(currItem)) { // open playlist log.info(methodName, "Opening playlist"); playlist.open(this.display); } else if (MENU_CURRENT.equals(currItem)) { // show current playing file log.info(methodName, "Displaying currently playing track"); player.displayCurrentTrack(this.display); } else if (MENU_CONFIG.equals(currItem)) { log.info(methodName, "Opening config screen"); propsScreen.open(this.display); } else { log.error(methodName, "Unexpected menu item: " + currItem); } } else { log.error(methodName, "Invalid main menu index: " + curr); } } else if (command == navigatorCommand) { openNavigator(); } else { log.info(methodName, "Unexpected command type: " + command.getCommandType()+", "+command.getLabel()); } } private void openNavigator() { final String methodName = "5"; if (fileNavigator == null) { log.error(methodName, "File navigator is null!"); } else { log.info(methodName, "Opening navigator..."); fileNavigator.open(this.display); } } public void alert(AlertType type, String msg) { // create new Alert final Displayable currDisplay = display.getCurrent(); final Command alertExitCommand = new Command("Done", Command.EXIT, 1); Alert alert = new Alert(type.getType(), msg, null, type.getUIType()); alert.setTimeout(3000); alert.addCommand(alertExitCommand); alert.setCommandListener(new CommandListener() { Displayable prevDisplay = currDisplay; public void commandAction(Command command, Displayable s) { if (command == alertExitCommand) { // exit and display the previous display display.setCurrent(prevDisplay); } } }); // display for 7 secs display.setCurrent(alert, display.getCurrent()); } }