/* * Jajuk * Copyright (C) The Jajuk Team * http://jajuk.info * * This program 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 2 * of the License, or any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package org.jajuk.ui.wizard.prepare_party; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; import org.apache.commons.lang.StringUtils; import org.jajuk.base.Playlist; import org.jajuk.ui.windows.JajukMainWindow; import org.jajuk.util.Conf; import org.jajuk.util.Const; import org.jajuk.util.IconLoader; import org.jajuk.util.JajukIcons; import org.jajuk.util.LocaleManager; import org.jajuk.util.Messages; import org.jajuk.util.UtilPrepareParty; import org.jajuk.util.error.JajukException; import org.jajuk.util.log.Log; import org.qdwizard.Screen; import org.qdwizard.Wizard; /** * Wizard to select a set of files and write them to a separate directory * outside of the collection in order to use them in a MP3 device or any other * media player. * * TODO: progress bar is not done yet * * TODO: a "cancel" button in the progress bar would be nice to let the user * cancel if he finds out that too many were selected */ public class PreparePartyWizard extends Wizard { /** Wizard data*/ enum Variable { /** Which source to use for the tracks. */ MODE, /** Which item was selected in the first page of the wizard. */ ITEM, /** Where to put the files. */ DEST_PATH, /** Whether there is a track number max */ MAXTRACKS_ENABLED, /** Key for max. number of track */ MAXTRACKS, /** Whether there is a size max. */ MAXSIZE_ENABLED, /** Key for max. size of party */ MAXSIZE, /** Whether there is a length max.*/ MAXLENGTH_ENABLED, /** Key for max length of party. */ MAXLENGTH, /** Whether we limit conversion to one format. */ ONE_MEDIA_ENABLED, /** Key for limit to one audio type. */ ONE_MEDIA, /** Key for audio type conversion. */ CONVERT_MEDIA, /** Key for the command to use for audio conversion. */ CONVERT_COMMAND, /** Used to enable replacing characters outside the normal range. */ NORMALIZE_FILENAME, /** Ratings level. */ RATING_LEVEL, /** store a temporary playlist that is provided by the PlaylistView without storing it in the PlaylistManager we keep it * here to be able to re-display it in the Pages later on * We need to keep it outside the ActionSelectionPanel because the panel is re-created during back-forward operations. */ TEMP_PLAYLIST } /** * The source of the Party. */ enum Mode { /** Use one of the available DJs. */ DJ, /** Use one of hte available Ambiences. */ Ambience, /** Use random tracks from all available track. */ Shuffle, /** Use a playlist. */ Playlist, /** Use songs from the BestOf list. */ BestOf, /** Use songs from the Novelties list. */ Novelties, /** Use songs from the current play queue. */ Queue, /** Use the available bookmarks. */ Bookmarks, /** Special mode for when the dialog is invoked with a newly created playlist. */ ProvidedPlaylist } /** * Default constructor that lets the user choose where the tracks are taken * from. * * @param bProvidedPlaylist Indicates that a playlist was provided to the dialog and thus the * first page is not displayed */ public PreparePartyWizard(boolean bProvidedPlaylist, Playlist playlist) { super(new Wizard.Builder(Messages.getString("PreparePartyWizard.1"), bProvidedPlaylist ? PreparePartyWizardGeneralOptionsScreen.class : PreparePartyWizardActionSelectionScreen.class, JajukMainWindow.getInstance()) .hSize(800).vSize(550).locale(LocaleManager.getLocale()) .icon(IconLoader.getIcon(JajukIcons.PREPARE_PARTY_32X32))); if (playlist != null) { setPlaylist(playlist); } restoreProperties(); } /** * Set the provided playlist so that the first page can be skipped if wanted. * * This needs to be done as static method as the Wizard-constructor already * needs to have this data available! * * @param playlist The playlist to use for the party */ public void setPlaylist(Playlist playlist) { // store playlist and the mode that we are now having data.put(Variable.TEMP_PLAYLIST, playlist); // store the mode and the playlist in the data as well data.put(Variable.MODE, Mode.ProvidedPlaylist); data.put(Variable.ITEM, playlist.getName()); } @Override public void finish() { // write properties to keep the selected directory storeProperties(); // retrieve the full list of files according to the selected mode List<org.jajuk.base.File> files = getFiles(); if (files == null) { return; } // define the target directory final Date curDate = new Date(); // Do not use ':' character in destination directory, it's // forbidden under Windows final SimpleDateFormat stamp = new SimpleDateFormat("yyyyMMdd-HHmm", Locale.getDefault()); final String dirName = "Party-" + stamp.format(curDate); final java.io.File destDir = new java.io.File(((String) data.get(Variable.DEST_PATH)), dirName); if (!destDir.mkdir()) { Log.warn("Could not create destination directory " + destDir); } Log.debug("Going to copy " + files.size() + " files to directory {{" + destDir.getAbsolutePath() + "}}"); // perform the actual copying UtilPrepareParty.copyFiles(files, destDir, isTrue(Variable.NORMALIZE_FILENAME), isTrue(Variable.ONE_MEDIA_ENABLED) && isTrue(Variable.CONVERT_MEDIA), (String) data.get(Variable.ONE_MEDIA), (String) data.get(Variable.CONVERT_COMMAND)); } /** * Return if the specified element is true in the data-map. * * @param key The key to look up in the data-object. * * @return true if the value was stored as boolean true, false otherwise. */ private final boolean isTrue(final Variable key) { return data.containsKey(key) && Boolean.TRUE.equals(data.get(key)); } /** * Gets the list of files to copy depending on the current mode. * * @return the files */ private List<org.jajuk.base.File> getFiles() { List<org.jajuk.base.File> files; if (Mode.DJ.equals(data.get(Variable.MODE))) { files = UtilPrepareParty.getDJFiles((String) data.get(Variable.ITEM)); } else if (Mode.Ambience.equals(data.get(Variable.MODE))) { files = UtilPrepareParty.getAmbienceFiles((String) data.get(Variable.ITEM)); } else if (Mode.Playlist.equals(data.get(Variable.MODE)) || Mode.ProvidedPlaylist.equals(data.get(Variable.MODE))) { try { Playlist tempPlaylist = (Playlist) data.get(Variable.TEMP_PLAYLIST); files = UtilPrepareParty.getPlaylistFiles((String) data.get(Variable.ITEM), tempPlaylist); } catch (JajukException e1) { Log.error(e1); return null; } } else if (Mode.Shuffle.equals(data.get(Variable.MODE))) { files = UtilPrepareParty.getShuffleFiles(); } else if (Mode.BestOf.equals(data.get(Variable.MODE))) { try { files = UtilPrepareParty.getBestOfFiles(); } catch (JajukException e1) { Log.error(e1); return null; } } else if (Mode.Queue.equals(data.get(Variable.MODE))) { try { files = UtilPrepareParty.getQueueFiles(); } catch (JajukException e1) { Log.error(e1); return null; } } else if (Mode.Bookmarks.equals(data.get(Variable.MODE))) { try { files = UtilPrepareParty.getBookmarkFiles(); } catch (JajukException e1) { Log.error(e1); return null; } } else if (Mode.Novelties.equals(data.get(Variable.MODE))) { try { files = UtilPrepareParty.getNoveltiesFiles(); } catch (JajukException e1) { Log.error(e1); return null; } } else { throw new IllegalArgumentException("Unknown mode in PreparePartyWizard: " + data.get(Variable.MODE)); } // filter by media first if (isTrue(Variable.ONE_MEDIA_ENABLED) && !isTrue(Variable.CONVERT_MEDIA)) { files = UtilPrepareParty.filterMedia(files, (String) data.get(Variable.ONE_MEDIA)); } // then filter out by rating if (data.containsKey(Variable.RATING_LEVEL)) { files = UtilPrepareParty.filterRating(files, (Integer) data.get(Variable.RATING_LEVEL)); } // filter max length if (isTrue(Variable.MAXLENGTH_ENABLED)) { files = UtilPrepareParty.filterMaxLength(files, (Integer) data.get(Variable.MAXLENGTH)); } // filter max size if (isTrue(Variable.MAXSIZE_ENABLED)) { files = UtilPrepareParty.filterMaxSize(files, (Integer) data.get(Variable.MAXSIZE)); } // filter max tracks if (isTrue(Variable.MAXTRACKS_ENABLED)) { files = UtilPrepareParty.filterMaxTracks(files, (Integer) data.get(Variable.MAXTRACKS)); } return files; } /** * Stores all the values that are stored in the data-map to the Conf-system. */ private void storeProperties() { storeValue(Variable.MODE); storeValue(Variable.ITEM); storeValue(Variable.DEST_PATH); storeValue(Variable.MAXTRACKS_ENABLED); storeValue(Variable.MAXTRACKS); storeValue(Variable.MAXSIZE_ENABLED); storeValue(Variable.MAXSIZE); storeValue(Variable.MAXLENGTH_ENABLED); storeValue(Variable.MAXLENGTH); storeValue(Variable.ONE_MEDIA_ENABLED); storeValue(Variable.ONE_MEDIA); storeValue(Variable.CONVERT_MEDIA); storeValue(Variable.CONVERT_COMMAND); storeValue(Variable.NORMALIZE_FILENAME); storeValue(Variable.RATING_LEVEL); } /** * Store one value as String. * * @param key The name of the property to store in the overall configuration */ private void storeValue(final Variable key) { // nothing to do? if (data.get(key) == null) { return; } Conf.setProperty(Const.CONF_PREPARE_PARTY + key, data.get(key).toString()); } /** * Restore all the values that are potentially stored in the configuration * system. */ private void restoreProperties() { restoreModeAndItemValue(); restoreStringValue(Variable.DEST_PATH); restoreBooleanValue(Variable.MAXTRACKS_ENABLED); restoreIntValue(Variable.MAXTRACKS); restoreBooleanValue(Variable.MAXSIZE_ENABLED); restoreIntValue(Variable.MAXSIZE); restoreBooleanValue(Variable.MAXLENGTH_ENABLED); restoreIntValue(Variable.MAXLENGTH); restoreBooleanValue(Variable.ONE_MEDIA_ENABLED); restoreStringValue(Variable.ONE_MEDIA); restoreBooleanValue(Variable.CONVERT_MEDIA); restoreStringValue(Variable.CONVERT_COMMAND); if (StringUtils.isBlank((String) data.get(Variable.CONVERT_COMMAND))) { data.put(Variable.CONVERT_COMMAND, "pacpl"); // use default value if none set // yet } restoreBooleanValue(Variable.NORMALIZE_FILENAME); restoreIntValue(Variable.RATING_LEVEL); } /** * Restore one string value from the configuration. * * @param key The key to restore. */ private void restoreStringValue(final Variable key) { String sValue = Conf.getString(Const.CONF_PREPARE_PARTY + key); // nothing to do if not set if (sValue == null) { return; } data.put(key, sValue); } /** * Restore one integer value from the configuration. * * @param key The key to restore. */ private void restoreIntValue(final Variable key) { // do nothing if not available yet if (Conf.getString(Const.CONF_PREPARE_PARTY + key) == null) { return; } data.put(key, Conf.getInt(Const.CONF_PREPARE_PARTY + key)); } /** * Restore one boolean value from the configuration. * * @param key The key to restore. */ private void restoreBooleanValue(final Variable key) { // do nothing if not available yet if (Conf.getString(Const.CONF_PREPARE_PARTY + key) == null) { return; } data.put(key, Conf.getBoolean(Const.CONF_PREPARE_PARTY + key)); } /** * Restore mode and item values, they may require some special handling. */ private void restoreModeAndItemValue() { String sMode = Conf.getString(Const.CONF_PREPARE_PARTY + Variable.MODE); // nothing to do if not set if (sMode == null) { return; } try { data.put(Variable.MODE, Mode.valueOf(sMode)); } catch (IllegalArgumentException e) { Log.warn("Could not convert mode: " + sMode + ", using default mode: " + Mode.DJ); data.put(Variable.MODE, Mode.DJ); } switch ((Mode) data.get(Variable.MODE)) { // restore the value for the ones where we have a selection case Ambience: case DJ: case Playlist: data.put(Variable.ITEM, Conf.getString(Const.CONF_PREPARE_PARTY + Variable.ITEM)); break; // nothing to do case BestOf: case Bookmarks: case Shuffle: case Novelties: case Queue: // we usually are not able to restore this, therefore don't do anything case ProvidedPlaylist: default: break; } } @Override public Class<? extends Screen> getNextScreen(Class<? extends Screen> screen) { if (PreparePartyWizardActionSelectionScreen.class.equals(screen)) { return PreparePartyWizardGeneralOptionsScreen.class; } else if (PreparePartyWizardGeneralOptionsScreen.class.equals(screen)) { return PreparePartyWizardPathSelectionScreen.class; } return null; } @Override public Class<? extends Screen> getPreviousScreen(Class<? extends Screen> screen) { // there is no "back" if we got a playlist passed in if (PreparePartyWizardGeneralOptionsScreen.class.equals(screen) && !Mode.ProvidedPlaylist.equals(data.get(Variable.MODE))) { return PreparePartyWizardActionSelectionScreen.class; } else if (PreparePartyWizardPathSelectionScreen.class.equals(screen)) { return PreparePartyWizardGeneralOptionsScreen.class; } return null; } }