/*
* 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.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Properties;
import org.jajuk.services.core.SessionService;
import org.jajuk.services.notification.NotificatorTypes;
import org.jajuk.ui.actions.JajukActions;
import org.jajuk.ui.perspectives.SimplePerspective;
import org.jajuk.util.log.Log;
/**
* Manage all the configuration and user preferences of jajuk.
* <p>
* Singleton
*/
public final class Conf implements Const {
/** Properties in memory. */
private static volatile Properties properties = new Properties();
/** Default properties cache. */
private static volatile Properties defaults = new Properties();
static {
setDefaultProperties();
properties = (Properties) properties.clone();
}
/**
* Instantiates a new conf.
*/
private Conf() {
// empty hidden constructor
}
/**
* Return the value of a property, or null if the property is not found.
*
* @param pName Name of the property.
*
* @return String Value of the property named pName.
*/
public static String getString(String pName) {
return properties.getProperty(pName);
}
/**
* Return the value of a property as a boolean or default value or default
* value if value cannot be parsed.
*
* @param pName Name of the property.
*
* @return boolean value of the property named pName.
*/
public static boolean getBoolean(String pName) {
boolean out = false;
try {
out = Boolean.parseBoolean(properties.getProperty(pName));
} catch (Exception e) {
out = Boolean.parseBoolean(defaults.getProperty(pName));
Log.debug("Cannot parse property: " + pName);
Log.debug(e);
}
return out;
}
/**
* Invert a boolean value.
*
* @param pName
*/
public static void invert(String pName) {
boolean b = Boolean.parseBoolean(properties.getProperty(pName));
setProperty(pName, Boolean.toString(!b));
}
/**
* Return the value of a property as a float or default value or default value
* if value cannot be parsed.
*
* @param pName Name of the property.
*
* @return float value of the property named pName.
*/
public static float getFloat(String pName) {
float out = 0f;
try {
out = Float.parseFloat(properties.getProperty(pName));
} catch (Exception e) {
out = Float.parseFloat(defaults.getProperty(pName));
Log.debug("Cannot parse property: " + pName);
Log.debug(e);
}
return out;
}
/**
* Return the value of a property as an integer or default value if value
* cannot be parsed.
*
* @param pName Name of the property.
*
* @return int value of the property named pName.
*/
public static int getInt(String pName) {
int out = 0;
try {
out = Integer.parseInt(properties.getProperty(pName));
} catch (NumberFormatException e) {
out = Integer.parseInt(defaults.getProperty(pName));
Log.debug("Cannot parse property: " + pName);
Log.debug(e);
}
return out;
}
/**
* Reset a given property to its defaults.
*
* @param property
*/
public static void setDefaultProperty(String property) {
String defaultValue = (String) defaults.get(property);
if (defaultValue != null) {
properties.put(property, defaultValue);
} else {
Log.debug("Cannot reset thsi property: " + property);
}
}
/**
* Set default values.
*/
public static void setDefaultProperties() {
// We fill with current values to keep some parameters
// like passwords and that we don't want to reset
defaults = (Properties) properties.clone();
defaults.put(CONF_OPTIONS_LANGUAGE, LocaleManager.getNativeLocale().getLanguage());
// User preferences
defaults.put(CONF_PERSPECTIVE_DEFAULT, SimplePerspective.class.getName());
defaults.put(CONF_STATE_REPEAT, FALSE);
defaults.put(CONF_STATE_REPEAT_ALL, FALSE);
defaults.put(CONF_STATE_KARAOKE, FALSE);
defaults.put(CONF_STATE_SHUFFLE, FALSE);
defaults.put(CONF_STATE_CONTINUE, TRUE);
defaults.put(CONF_STATE_INTRO, FALSE);
// no startup file by default
defaults.put(CONF_STARTUP_ITEM, "");
defaults.put(CONF_STARTUP_MODE, STARTUP_MODE_LAST_KEEP_POS);
defaults.put(CONF_STARTUP_STOPPED, "false");
defaults.put(CONF_CONFIRMATIONS_DELETE_FILE, TRUE);
defaults.put(CONF_CONFIRMATIONS_EXIT, FALSE);
defaults.put(CONF_CONFIRMATIONS_REMOVE_DEVICE, TRUE);
defaults.put(CONF_CONFIRMATIONS_DELETE_COVER, TRUE);
defaults.put(CONF_CONFIRMATIONS_CLEAR_HISTORY, TRUE);
defaults.put(CONF_CONFIRMATIONS_RESET_RATINGS, TRUE);
defaults.put(CONF_CONFIRMATIONS_REFACTOR_FILES, TRUE);
defaults.put(CONF_CONFIRMATIONS_BEFORE_TAG_WRITE, FALSE);
defaults.put(CONF_OPTIONS_HIDE_UNMOUNTED, FALSE);
defaults.put(CONF_OPTIONS_PUSH_ON_CLICK, FALSE);
defaults.put(CONF_OPTIONS_PUSH_ON_DROP, FALSE);
defaults.put(CONF_OPTIONS_NOVELTIES_AGE, "30");
defaults.put(CONF_OPTIONS_VISIBLE_PLANNED, "10");
defaults.put(CONF_BUFFER_SIZE, "16000");
// -1 : max available buffer set default trace level, debug in debug
// mode and warning in normal mode
defaults.put(CONF_AUDIO_BUFFER_SIZE, "-1");
if (SessionService.isIdeMode()) {
defaults.put(CONF_OPTIONS_LOG_LEVEL, Integer.toString(Log.DEBUG));
} else {
defaults.put(CONF_OPTIONS_LOG_LEVEL, Integer.toString(Log.WARNING));
}
defaults.put(CONF_OPTIONS_TAB, "0");
defaults.put(CONF_OPTIONS_INTRO_BEGIN, "0");
defaults.put(CONF_OPTIONS_INTRO_LENGTH, "20");
defaults.put(CONF_UI_NOTIFICATOR_TYPE, NotificatorTypes.NONE.name());
defaults.put(CONF_P2P_SHARE, FALSE);
defaults.put(CONF_P2P_ADD_REMOTE_PROPERTIES, FALSE);
defaults.put(CONF_P2P_HIDE_LOCAL_PROPERTIES, TRUE);
defaults.put(CONF_HISTORY, "-1");
defaults.put(CONF_TAGS_USE_PARENT_DIR, TRUE);
defaults.put(CONF_BOOKMARKS, "");
defaults.put(CONF_STARTUP_DISPLAY, Integer.toString(DISPLAY_MODE_MAIN_WINDOW));
defaults.put(CONF_BESTOF_TRACKS_SIZE, "20");
defaults.put(CONF_VOLUME, "0.5");
defaults.put(CONF_REGEXP, FALSE);
defaults.put(CONF_BACKUP_SIZE, "40");
defaults.put(CONF_PATTERN_REFACTOR, PATTERN_DEFAULT_REORG);
defaults.put(CONF_COLLECTION_CHARSET, "UTF-8");
defaults.put(CONF_NETWORK_USE_PROXY, FALSE);
defaults.put(CONF_NETWORK_NONE_INTERNET_ACCESS, FALSE);
// default proxy name, just a guess
defaults.put(CONF_NETWORK_PROXY_HOSTNAME, "proxy");
defaults.put(CONF_NETWORK_PROXY_PORT, "3128");
defaults.put(CONF_NETWORK_PROXY_LOGIN, "");
defaults.put(CONF_NETWORK_CONNECTION_TO, "10");
defaults.put(CONF_NETWORK_PROXY_TYPE, PROXY_TYPE_HTTP);
defaults.put(CONF_COVERS_AUTO_COVER, TRUE);
defaults.put(CONF_COVERS_MIRROW_COVER, FALSE);
defaults.put(CONF_COVERS_MIRROW_COVER_FS_MODE, TRUE);
defaults.put(CONF_COVERS_SHUFFLE, FALSE);
defaults.put(CONF_COVERS_SAVE_EXPLORER_FRIENDLY, FALSE);
defaults.put(FILE_DEFAULT_COVER, "front;cover;folder;back");
defaults.put(CONF_COVERS_SIZE, "3"); // medium and large
defaults.put(CONF_TRACKS_TABLE_EDITION, FALSE);
defaults.put(CONF_FILES_TABLE_EDITION, FALSE);
defaults.put(CONF_ALBUMS_TABLE_EDITION, FALSE);
defaults.put(CONF_FILES_TABLE_COLUMNS, XML_PLAY + ',' + Const.XML_TRACK + ',' + Const.XML_ALBUM
+ ',' + Const.XML_ARTIST + ',' + Const.XML_TRACK_GENRE + ',' + Const.XML_TRACK_RATE + ','
+ Const.XML_TRACK_LENGTH);
defaults.put(CONF_TRACKS_TABLE_COLUMNS, XML_PLAY + ',' + Const.XML_NAME + ',' + Const.XML_ALBUM
+ ',' + Const.XML_ARTIST + ',' + Const.XML_TRACK_GENRE + ',' + Const.XML_TRACK_LENGTH + ','
+ ',' + Const.XML_TRACK_RATE);
defaults.put(CONF_PLAYLIST_EDITOR_COLUMNS, XML_PLAY + ',' + Const.XML_TRACK_NAME + ',' + ','
+ Const.XML_TRACK_ARTIST + ',' + Const.XML_TRACK_RATE);
defaults.put(CONF_PLAYLIST_REPOSITORY_COLUMNS, XML_PLAY + ',' + Const.XML_NAME + ','
+ Const.XML_PATH);
defaults.put(CONF_QUEUE_COLUMNS, XML_PLAY + ',' + Const.XML_TRACK_NAME + ',' + ','
+ Const.XML_TRACK_ARTIST + ',' + Const.XML_TRACK_RATE);
defaults.put(CONF_ALBUMS_TABLE_COLUMNS, XML_PLAY + ',' + Const.XML_ALBUM + ','
+ Const.XML_ARTIST + ',' + Const.XML_GENRE + ',' + Const.XML_YEAR + ','
+ Const.XML_TRACK_RATE + ',' + Const.XML_TRACK_LENGTH + ',' + Const.XML_TRACKS + ','
+ Const.XML_TRACK_DISCOVERY_DATE);
defaults.put(CONF_WEBRADIO_COLUMNS, XML_PLAY + ',' + Const.XML_NAME + ',' + Const.XML_DESC
+ ',' + Const.XML_KEYWORDS + ',' + Const.XML_GENRE + ',' + Const.XML_ORIGIN);
defaults.put(CONF_WINDOW_POSITION, "");
defaults.put(CONF_WINDOW_MAXIMIZED, "true");
defaults.put(CONF_THUMBS_SHOW_COVER, Integer.toString(Const.CATALOG_VIEW_COVER_MODE_ALL));
defaults.put(CONF_THUMBS_SIZE, THUMBNAIL_SIZE_100X100);
defaults.put(CONF_THUMBS_SORTER, "2"); // sort by album
// filter on albums
defaults.put(CONF_THUMBS_FILTER, "0");
defaults.put(CONF_WIKIPEDIA_LANGUAGE, defaults.get(CONF_OPTIONS_LANGUAGE));
defaults.put(CONF_FADE_DURATION, "6");
// sort by genre
defaults.put(CONF_LOGICAL_TREE_SORT_ORDER, "0");
defaults.put(CONF_DEFAULT_DJ, "");// default dj
defaults.put(CONF_DEFAULT_AMBIENCE, "");// default ambience
// wrong player show again boolean
defaults.put(CONF_GLOBAL_RANDOM_MODE, MODE_TRACK);
defaults.put(CONF_NOVELTIES_MODE, MODE_TRACK);
defaults.put(CONF_PATTERN_ANIMATION, PATTERN_DEFAULT_ANIMATION);
defaults.put(CONF_FRAME_POS_FORCED, "");
defaults.put(CONF_OPTIONS_HOTKEYS, FALSE);
defaults.put(CONF_MPLAYER_ARGS, "");
defaults.put(CONF_ENV_VARIABLES, "");
defaults.put(CONF_USE_VOLNORM, "false");
defaults.put(CONF_SHOW_TIP_ON_STARTUP, FALSE);
defaults.put(CONF_CATALOG_PAGE_SIZE, "100");
defaults.put(CONF_SHOW_POPUPS, FALSE);
defaults.put(CONF_SHOW_SYSTRAY, TRUE);
defaults.put(CONF_MINIMIZE_TO_TRAY, FALSE);
defaults.put(CONF_TRAY_CLICK_DISPLAY_WINDOW, FALSE);
defaults.put(CONF_FONTS_SIZE, "12");
defaults.put(CONF_MPLAYER_PATH_FORCED, "");
defaults.put(CONF_INC_RATING, "5");
defaults.put(CONF_OPTIONS_LNF, LNF_DEFAULT_THEME);
defaults.put(CONF_DEFAULT_WEB_RADIO, DEFAULT_WEBRADIO);
defaults.put(CONF_CHECK_FOR_UPDATE, TRUE);
defaults.put(CONF_IGNORED_RELEASES, "");
defaults.put(CONF_LASTFM_AUDIOSCROBBLER_ENABLE, FALSE);
defaults.put(CONF_LASTFM_INFO, TRUE);
defaults.put(CONF_WEBRADIO_WAS_PLAYING, FALSE);
defaults.put(CONF_PERSPECTIVE_ICONS_SIZE, "32");
// We use trailing pattern to allow scripting like MSN plugins to
// detect jajuk frames and extract current track
defaults.put(CONF_PATTERN_FRAME_TITLE, '~' + PATTERN_TRACKNAME + " (" + PATTERN_ARTIST + ")~");
defaults.put(CONF_PATTERN_BALLOON_NOTIFIER,
Messages.getString("FIFO.10") + " " + Messages.getString("InformationJPanel.8"));
defaults.put(CONF_PATTERN_INFORMATION,
Messages.getString("FIFO.10") + " " + Messages.getString("InformationJPanel.8"));
defaults.put(CONF_SHOW_DUPLICATE_PLAYLISTS, FALSE);
defaults.put(CONF_FORMAT_TIME_ELAPSED, "0");
defaults.put(CONF_AUTO_SCROLL, TRUE);
// Let the OS show the slimbar to an optimal position.
defaults.put(CONF_SLIMBAR_POSITION, "");
defaults.put(CONF_SLIMBAR_DISPLAY_QUEUE, FALSE);
defaults.put(CONF_SLIMBAR_SMART_MODE, JajukActions.SHUFFLE_GLOBAL.toString());
defaults.put(CONF_ALARM_ACTION, ALARM_START_ACTION);
defaults.put(CONF_ALARM_ENABLED, FALSE);
defaults.put(CONF_ALARM_FILE, "");
defaults.put(CONF_ALARM_MODE, STARTUP_MODE_SHUFFLE);
defaults.put(CONF_ALARM_TIME_HOUR, "08");
defaults.put(CONF_ALARM_TIME_MINUTES, "00");
defaults.put(CONF_ALARM_TIME_SECONDS, "00");
defaults.put(CONF_EXPLORER_PATH, "");
defaults.put(CONF_BIT_PERFECT, FALSE);
defaults.put(CONF_TITLE_ANIMATION, FALSE);
defaults.put(CONF_SPLASH_SCREEN, TRUE);
defaults.put(CONF_SHOW_VIDEOS, FALSE);
defaults.put(CONF_PRESERVE_FILE_DATES, FALSE);
defaults.put(CONF_MANUAL_RATINGS, FALSE);
defaults.put(CONF_STARTUP_QUEUE_INDEX, "-1");
// NOT SHOW AGAIN
defaults.put(CONF_NOT_SHOW_AGAIN_PLAYER, FALSE);
defaults.put(CONF_NOT_SHOW_AGAIN_CROSS_FADE, FALSE);
defaults.put(CONF_NOT_SHOW_AGAIN_LAF_CHANGE, FALSE);
defaults.put(CONF_STATS_MIN_VALUE_GENRE_DISPLAY, "2");
defaults.put(CONF_TARGET_WORKSPACE_PATH, UtilSystem.getUserHome());
// Make a copy of default values
properties = (Properties) defaults.clone();
}
/**
* Allow again to get hidden messages
*/
public static void resetDontShowAgain() {
setProperty(CONF_NOT_SHOW_AGAIN_PLAYER, FALSE);
setProperty(CONF_NOT_SHOW_AGAIN_CROSS_FADE, FALSE);
setProperty(CONF_NOT_SHOW_AGAIN_LAF_CHANGE, FALSE);
}
/**
* Return default property for given key.
*
* @param key
*
* @return default property for given key
*/
public static String getDefaultProperty(String key) {
return defaults.getProperty(key);
}
/**
* Restore a specific property.
*
* @param key property name to restore
*/
public static void restoreValue(String key) {
setProperty(key, defaults.getProperty(key));
}
/**
* Set a property and persist the configuration
*
* @param sName property name
* @param sValue property value as string
*/
public static void setProperty(String sName, String sValue) {
// [Perf] Ignore cases where the same value is set again
Object current = properties.get(sName);
if (current != null && current.equals(sValue)) {
return;
}
properties.setProperty(sName, sValue);
try {
commit();
} catch (IOException e) {
Log.error(e);
}
}
/**
* Set a bunch of properties and persist the configuration
*
* @param properties a map of string key to string values
*/
public static void setProperties(final HashMap<String, String> properties) {
for (String propertyName : properties.keySet()) {
Conf.properties.setProperty(propertyName, properties.get(propertyName));
}
try {
commit();
} catch (IOException e) {
Log.error(e);
}
}
/**
* Commit properties into a file.
*
* @throws IOException Signals that an I/O exception has occurred.
*/
private static void commit() throws IOException {
java.io.File out = SessionService.getConfFileByPath(Const.FILE_CONFIGURATION + "."
+ Const.FILE_SAVING_FILE_EXTENSION);
OutputStream str = new FileOutputStream(out);
// Write the temporary file
try {
properties.store(str, "User configuration");
} finally {
str.flush();
str.close();
}
// Commit with recovery support
java.io.File finalFile = SessionService.getConfFileByPath(Const.FILE_CONFIGURATION);
UtilSystem.saveFileWithRecoverySupport(finalFile);
Log.debug("Conf commited to : " + finalFile.getAbsolutePath());
}
/**
* Contains property.
*
* @param property
*
* @return whether the given property is known
*/
public static boolean containsProperty(String property) {
return properties.containsKey(property);
}
/**
* Load properties from in file.
*/
public static void load() {
try {
File confFile = SessionService.getConfFileByPath(Const.FILE_CONFIGURATION);
UtilSystem.recoverFileIfRequired(confFile);
// Conf file doesn't exist at first launch
if (confFile.exists()) {
// Now read the conf file
InputStream str = new FileInputStream(confFile);
try {
properties.load(str);
} finally {
str.close();
}
}
} catch (Exception e) {
Log.error(e);
Messages.showErrorMessage(114);
}
}
/**
* Gets the properties.
*
* @return Returns the properties.
*/
public static Properties getProperties() {
return properties;
}
/**
* Remove a property.
*
* @param sKey property key to remove
*/
public static void removeProperty(String sKey) {
properties.remove(sKey);
}
}