/*
* PS3 Media Server, for streaming any medias to your PS3.
* Copyright (C) 2008 A.Brochard
*
* 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; version 2
* of the License only.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package net.pms.configuration;
import ch.qos.logback.classic.Level;
import com.sun.jna.Platform;
import java.awt.Color;
import java.awt.Component;
import java.awt.Frame;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import net.pms.Messages;
import net.pms.PMS;
import net.pms.dlna.CodeEnter;
import net.pms.formats.Format;
import net.pms.io.SystemUtils;
import net.pms.util.CoverSupplier;
import net.pms.util.FilePermissions;
import net.pms.util.FileUtil;
import net.pms.util.FileUtil.FileLocation;
import net.pms.util.FullyPlayedAction;
import net.pms.util.InvalidArgumentException;
import net.pms.util.Languages;
import net.pms.util.PropertiesUtil;
import net.pms.util.SubtitleColor;
import net.pms.util.UMSUtils;
import net.pms.util.WindowsRegistry;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.event.ConfigurationListener;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Container for all configurable UMS settings. Settings are typically defined by three things:
* a unique key for use in the configuration file "UMS.conf", a getter (and setter) method and
* a default value. When a key cannot be found in the current configuration, the getter will
* return a default value. Setters only store a value, they do not permanently save it to
* file.
*/
public class PmsConfiguration extends RendererConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(PmsConfiguration.class);
protected static final int DEFAULT_PROXY_SERVER_PORT = -1;
protected static final int DEFAULT_SERVER_PORT = 5001;
// 90000 lines is approximately 10 MiB depending on locale and message length
public static final int LOGGING_LOGS_TAB_LINEBUFFER_MAX = 90000;
public static final int LOGGING_LOGS_TAB_LINEBUFFER_MIN = 100;
public static final int LOGGING_LOGS_TAB_LINEBUFFER_STEP = 500;
/*
* MEncoder has a hardwired maximum of 8 threads for -lavcopts and 16
* for -lavdopts.
* The Windows SubJunk Builds can take 16 for both, but we keep it at 8
* for compatibility with other operating systems.
*/
protected static final int MENCODER_MAX_THREADS = 8;
// TODO: Get this out of here
protected static boolean avsHackLogged = false;
protected static final String KEY_3D_SUBTITLES_DEPTH = "3d_subtitles_depth";
protected static final String KEY_ALIVE_DELAY = "ALIVE_delay";
protected static final String KEY_ALTERNATE_SUBTITLES_FOLDER = "alternate_subtitles_folder";
protected static final String KEY_ALTERNATE_THUMB_FOLDER = "alternate_thumb_folder";
protected static final String KEY_APPEND_PROFILE_NAME = "append_profile_name";
protected static final String KEY_ATZ_LIMIT = "atz_limit";
protected static final String KEY_AUTOMATIC_DISCOVER = "automatic_discover";
protected static final String KEY_AUTOMATIC_MAXIMUM_BITRATE = "automatic_maximum_bitrate";
protected static final String KEY_AUDIO_BITRATE = "audio_bitrate";
protected static final String KEY_AUDIO_CHANNEL_COUNT = "audio_channels";
protected static final String KEY_AUDIO_EMBED_DTS_IN_PCM = "audio_embed_dts_in_pcm";
protected static final String KEY_AUDIO_LANGUAGES = "audio_languages";
protected static final String KEY_AUDIO_REMUX_AC3 = "audio_remux_ac3";
protected static final String KEY_AUDIO_RESAMPLE = "audio_resample";
protected static final String KEY_AUDIO_SUB_LANGS = "audio_subtitles_languages";
protected static final String KEY_AUDIO_THUMBNAILS_METHOD = "audio_thumbnails_method";
protected static final String KEY_AUDIO_USE_PCM = "audio_use_pcm";
protected static final String KEY_AUTO_UPDATE = "auto_update";
protected static final String KEY_AUTOLOAD_SUBTITLES = "autoload_external_subtitles";
protected static final String KEY_AVISYNTH_CONVERT_FPS = "avisynth_convert_fps";
protected static final String KEY_AVISYNTH_INTERFRAME = "avisynth_interframe";
protected static final String KEY_AVISYNTH_INTERFRAME_GPU = "avisynth_interframegpu";
protected static final String KEY_AVISYNTH_MULTITHREADING = "avisynth_multithreading";
protected static final String KEY_AVISYNTH_SCRIPT = "avisynth_script";
protected static final String KEY_ASS_MARGIN = "subtitles_ass_margin";
protected static final String KEY_ASS_OUTLINE = "subtitles_ass_outline";
protected static final String KEY_ASS_SCALE = "subtitles_ass_scale";
protected static final String KEY_ASS_SHADOW = "subtitles_ass_shadow";
protected static final String KEY_BUFFER_MAX = "buffer_max";
protected static final String KEY_BUMP_ADDRESS = "bump";
protected static final String KEY_BUMP_IPS = "allowed_bump_ips";
protected static final String KEY_BUMP_JS = "bump.js";
protected static final String KEY_BUMP_SKIN_DIR = "bump.skin";
protected static final String KEY_CHAPTER_INTERVAL = "chapter_interval";
protected static final String KEY_CHAPTER_SUPPORT = "chapter_support";
protected static final String KEY_CHROMECAST_DBG = "chromecast_debug";
protected static final String KEY_CHROMECAST_EXT = "chromecast_extension";
protected static final String KEY_CODE_CHARS = "code_charset";
protected static final String KEY_CODE_THUMBS = "code_show_thumbs_no_code";
protected static final String KEY_CODE_TMO = "code_valid_timeout";
protected static final String KEY_CODE_USE = "code_enable";
protected static final String KEY_DISABLE_FAKESIZE = "disable_fakesize";
public static final String KEY_DISABLE_SUBTITLES = "disable_subtitles";
protected static final String KEY_DISABLE_TRANSCODE_FOR_EXTENSIONS = "disable_transcode_for_extensions";
protected static final String KEY_DISABLE_TRANSCODING = "disable_transcoding";
protected static final String KEY_DVDISO_THUMBNAILS = "dvd_isos_thumbnails";
protected static final String KEY_DYNAMIC_PLS = "dynamic_playlist";
protected static final String KEY_DYNAMIC_PLS_AUTO_SAVE = "dynamic_playlist_auto_save";
protected static final String KEY_DYNAMIC_PLS_HIDE = "dynamic_playlist_hide_folder";
protected static final String KEY_DYNAMIC_PLS_SAVE_PATH = "dynamic_playlist_save_path";
protected static final String KEY_ENCODED_AUDIO_PASSTHROUGH = "encoded_audio_passthrough";
protected static final String KEY_ENGINES = "engines";
protected static final String KEY_FFMPEG_ALTERNATIVE_PATH = "alternativeffmpegpath"; // TODO: FFmpegDVRMSRemux will be removed and DVR-MS will be transcoded
protected static final String KEY_FFMPEG_AVISYNTH_CONVERT_FPS = "ffmpeg_avisynth_convertfps";
protected static final String KEY_FFMPEG_AVISYNTH_INTERFRAME = "ffmpeg_avisynth_interframe";
protected static final String KEY_FFMPEG_AVISYNTH_INTERFRAME_GPU = "ffmpeg_avisynth_interframegpu";
protected static final String KEY_FFMPEG_AVISYNTH_MULTITHREADING = "ffmpeg_avisynth_multithreading";
protected static final String KEY_FFMPEG_FONTCONFIG = "ffmpeg_fontconfig";
protected static final String KEY_FFMPEG_MENCODER_PROBLEMATIC_SUBTITLES = "ffmpeg_mencoder_problematic_subtitles";
protected static final String KEY_FFMPEG_MULTITHREADING = "ffmpeg_multithreading";
protected static final String KEY_FFMPEG_MUX_TSMUXER_COMPATIBLE = "ffmpeg_mux_tsmuxer_compatible";
protected static final String KEY_FIX_25FPS_AV_MISMATCH = "fix_25fps_av_mismatch";
protected static final String KEY_FOLDER_LIMIT = "folder_limit";
protected static final String KEY_FOLDERS = "folders";
protected static final String KEY_FOLDERS_IGNORED = "folders_ignored";
protected static final String KEY_FOLDERS_MONITORED = "folders_monitored";
protected static final String KEY_FONT = "subtitles_font";
protected static final String KEY_FORCE_EXTERNAL_SUBTITLES = "force_external_subtitles";
protected static final String KEY_FORCE_TRANSCODE_FOR_EXTENSIONS = "force_transcode_for_extensions";
protected static final String KEY_FORCED_SUBTITLE_LANGUAGE = "forced_subtitle_language";
protected static final String KEY_FORCED_SUBTITLE_TAGS = "forced_subtitle_tags";
public static final String KEY_GPU_ACCELERATION = "gpu_acceleration";
protected static final String KEY_GUI_LOG_SEARCH_CASE_SENSITIVE = "gui_log_search_case_sensitive";
protected static final String KEY_GUI_LOG_SEARCH_MULTILINE = "gui_log_search_multiline";
protected static final String KEY_GUI_LOG_SEARCH_USE_REGEX = "gui_log_search_use_regex";
protected static final String KEY_HIDE_ADVANCED_OPTIONS = "hide_advanced_options";
protected static final String KEY_HIDE_EMPTY_FOLDERS = "hide_empty_folders";
protected static final String KEY_HIDE_ENGINENAMES = "hide_enginenames";
protected static final String KEY_HIDE_EXTENSIONS = "hide_extensions";
protected static final String KEY_HIDE_LIVE_SUBTITLES_FOLDER = "hide_live_subtitles_folder";
protected static final String KEY_HIDE_MEDIA_LIBRARY_FOLDER = "hide_media_library_folder";
protected static final String KEY_HIDE_NEW_MEDIA_FOLDER = "hide_new_media_folder";
protected static final String KEY_HIDE_RECENTLY_PLAYED_FOLDER = "hide_recently_played_folder";
protected static final String KEY_HIDE_SUBS_INFO = "hide_subs_info";
protected static final String KEY_HIDE_TRANSCODE_FOLDER = "hide_transcode_folder";
protected static final String KEY_HIDE_VIDEO_SETTINGS = "hide_video_settings";
protected static final String KEY_HTTP_ENGINE_V2 = "http_engine_v2";
protected static final String KEY_IGNORE_THE_WORD_A_AND_THE = "ignore_the_word_a_and_the";
protected static final String KEY_IMAGE_THUMBNAILS_ENABLED = "image_thumbnails";
protected static final String KEY_INFO_DB_RETRY = "infodb_retry";
protected static final String KEY_IP_FILTER = "ip_filter";
protected static final String KEY_ITUNES_LIBRARY_PATH = "itunes_library_path";
protected static final String KEY_LANGUAGE = "language";
protected static final String KEY_LIVE_SUBTITLES_KEEP = "live_subtitles_keep";
protected static final String KEY_LIVE_SUBTITLES_LIMIT = "live_subtitles_limit";
protected static final String KEY_LIVE_SUBTITLES_TMO = "live_subtitles_timeout";
protected static final String KEY_LOGGING_LOGFILE_NAME = "logging_logfile_name";
protected static final String KEY_LOGGING_BUFFERED = "logging_buffered";
protected static final String KEY_LOGGING_FILTER_CONSOLE = "logging_filter_console";
protected static final String KEY_LOGGING_FILTER_LOGS_TAB = "logging_filter_logs_tab";
protected static final String KEY_LOGGING_LOGS_TAB_LINEBUFFER = "logging_logs_tab_linebuffer";
protected static final String KEY_LOGGING_SYSLOG_FACILITY = "logging_syslog_facility";
protected static final String KEY_LOGGING_SYSLOG_HOST = "logging_syslog_host";
protected static final String KEY_LOGGING_SYSLOG_PORT = "logging_syslog_port";
protected static final String KEY_LOGGING_USE_SYSLOG = "logging_use_syslog";
protected static final String KEY_MAX_AUDIO_BUFFER = "maximum_audio_buffer_size";
protected static final String KEY_MAX_BITRATE = "maximum_bitrate";
protected static final String KEY_MAX_MEMORY_BUFFER_SIZE = "maximum_video_buffer_size";
protected static final String KEY_MEDIA_LIB_SORT = "media_lib_sort";
protected static final String KEY_MENCODER_ASS = "mencoder_ass";
protected static final String KEY_MENCODER_AC3_FIXED = "mencoder_ac3_fixed";
protected static final String KEY_MENCODER_CODEC_SPECIFIC_SCRIPT = "mencoder_codec_specific_script";
protected static final String KEY_MENCODER_CUSTOM_OPTIONS = "mencoder_custom_options";
protected static final String KEY_MENCODER_FONT_CONFIG = "mencoder_fontconfig";
protected static final String KEY_MENCODER_FORCE_FPS = "mencoder_forcefps";
protected static final String KEY_MENCODER_INTELLIGENT_SYNC = "mencoder_intelligent_sync";
protected static final String KEY_MENCODER_MAX_THREADS = "mencoder_max_threads";
protected static final String KEY_MENCODER_MUX_COMPATIBLE = "mencoder_mux_compatible";
protected static final String KEY_MENCODER_MT = "mencoder_mt";
protected static final String KEY_MENCODER_NO_OUT_OF_SYNC = "mencoder_nooutofsync";
protected static final String KEY_MENCODER_NOASS_BLUR = "mencoder_noass_blur";
protected static final String KEY_MENCODER_NOASS_OUTLINE = "mencoder_noass_outline";
protected static final String KEY_MENCODER_NOASS_SCALE = "mencoder_noass_scale";
protected static final String KEY_MENCODER_NOASS_SUBPOS = "mencoder_noass_subpos";
protected static final String KEY_MENCODER_NORMALIZE_VOLUME = "mencoder_normalize_volume";
protected static final String KEY_MENCODER_OVERSCAN_COMPENSATION_HEIGHT = "mencoder_overscan_compensation_height";
protected static final String KEY_MENCODER_OVERSCAN_COMPENSATION_WIDTH = "mencoder_overscan_compensation_width";
protected static final String KEY_MENCODER_REMUX_MPEG2 = "mencoder_remux_mpeg2";
protected static final String KEY_MENCODER_SCALER = "mencoder_scaler";
protected static final String KEY_MENCODER_SCALEX = "mencoder_scalex";
protected static final String KEY_MENCODER_SCALEY = "mencoder_scaley";
protected static final String KEY_MENCODER_SUB_FRIBIDI = "mencoder_subfribidi";
protected static final String KEY_MENCODER_USE_PCM_FOR_HQ_AUDIO_ONLY = "mencoder_usepcm_for_hq_audio_only";
protected static final String KEY_MENCODER_VOBSUB_SUBTITLE_QUALITY = "mencoder_vobsub_subtitle_quality";
protected static final String KEY_MENCODER_YADIF = "mencoder_yadif";
protected static final String KEY_MIN_MEMORY_BUFFER_SIZE = "minimum_video_buffer_size";
protected static final String KEY_MIN_PLAY_TIME = "minimum_watched_play_time";
protected static final String KEY_MIN_PLAY_TIME_FILE = "min_playtime_file";
protected static final String KEY_MIN_PLAY_TIME_WEB = "min_playtime_web";
protected static final String KEY_MIN_STREAM_BUFFER = "minimum_web_buffer_size";
protected static final String KEY_MINIMIZED = "minimized";
protected static final String KEY_MPEG2_MAIN_SETTINGS = "mpeg2_main_settings";
protected static final String KEY_MUX_ALLAUDIOTRACKS = "tsmuxer_mux_all_audiotracks";
protected static final String KEY_NETWORK_INTERFACE = "network_interface";
protected static final String KEY_NUMBER_OF_CPU_CORES = "number_of_cpu_cores";
protected static final String KEY_OPEN_ARCHIVES = "enable_archive_browsing";
protected static final String KEY_OVERSCAN = "mencoder_overscan";
protected static final String KEY_PING_PATH = "ping_path";
protected static final String KEY_PLAYLIST_AUTO_ADD_ALL= "playlist_auto_add_all";
protected static final String KEY_PLAYLIST_AUTO_CONT = "playlist_auto_continue";
protected static final String KEY_PLAYLIST_AUTO_PLAY= "playlist_auto_play";
protected static final String KEY_PLUGIN_DIRECTORY = "plugins";
protected static final String KEY_PLUGIN_PURGE_ACTION = "plugin_purge";
protected static final String KEY_PRETTIFY_FILENAMES = "prettify_filenames";
protected static final String KEY_PREVENTS_SLEEP = "prevents_sleep_mode";
protected static final String KEY_PROFILE_NAME = "name";
protected static final String KEY_PROXY_SERVER_PORT = "proxy";
protected static final String KEY_RENDERER_DEFAULT = "renderer_default";
protected static final String KEY_RENDERER_FORCE_DEFAULT = "renderer_force_default";
protected static final String KEY_RESUME = "resume";
protected static final String KEY_RESUME_BACK = "resume_back";
protected static final String KEY_RESUME_KEEP_TIME = "resume_keep_time";
protected static final String KEY_RESUME_REWIND = "resume_rewind";
protected static final String KEY_ROOT_LOG_LEVEL = "log_level";
protected static final String KEY_RUN_WIZARD = "run_wizard";
protected static final String KEY_SCREEN_SIZE = "screen_size";
protected static final String KEY_SCRIPT_DIR = "script_dir";
protected static final String KEY_SEARCH_FOLDER = "search_folder";
protected static final String KEY_SEARCH_IN_FOLDER = "search_in_folder";
protected static final String KEY_SEARCH_RECURSE = "search_recurse"; // legacy option
protected static final String KEY_SEARCH_RECURSE_DEPTH = "search_recurse_depth";
protected static final String KEY_SELECTED_RENDERERS = "selected_renderers";
protected static final String KEY_SERVER_HOSTNAME = "hostname";
protected static final String KEY_SERVER_NAME = "server_name";
protected static final String KEY_SERVER_PORT = "port";
protected static final String KEY_SHARES = "shares";
protected static final String KEY_SHOW_APERTURE_LIBRARY = "show_aperture_library";
protected static final String KEY_SHOW_IPHOTO_LIBRARY = "show_iphoto_library";
protected static final String KEY_SHOW_ITUNES_LIBRARY = "show_itunes_library";
protected static final String KEY_SHOW_SPLASH_SCREEN = "show_splash_screen";
protected static final String KEY_SINGLE = "single_instance";
protected static final String KEY_SKIP_LOOP_FILTER_ENABLED = "mencoder_skip_loop_filter";
protected static final String KEY_SKIP_NETWORK_INTERFACES = "skip_network_interfaces";
protected static final String KEY_SORT_METHOD = "sort_method";
protected static final String KEY_SORT_PATHS = "sort_paths";
protected static final String KEY_SPEED_DBG = "speed_debug";
protected static final String KEY_SUBS_COLOR = "subtitles_color";
protected static final String KEY_SUBTITLES_CODEPAGE = "subtitles_codepage";
protected static final String KEY_SUBTITLES_LANGUAGES = "subtitles_languages";
protected static final String KEY_TEMP_FOLDER_PATH = "temp_directory";
protected static final String KEY_THUMBNAIL_GENERATION_ENABLED = "generate_thumbnails";
protected static final String KEY_THUMBNAIL_SEEK_POS = "thumbnail_seek_position";
protected static final String KEY_TOOLTIP_BACKGROUND_COLOR = "tooltip_background";
protected static final String KEY_TOOLTIP_FOREGROUND_COLOR = "tooltip_foreground";
protected static final String KEY_TRANSCODE_BLOCKS_MULTIPLE_CONNECTIONS = "transcode_block_multiple_connections";
protected static final String KEY_TRANSCODE_FOLDER_NAME = "transcode_folder_name";
protected static final String KEY_TRANSCODE_KEEP_FIRST_CONNECTION = "transcode_keep_first_connection";
protected static final String KEY_TSMUXER_FORCEFPS = "tsmuxer_forcefps";
protected static final String KEY_UPNP_ENABLED = "upnp_enable";
protected static final String KEY_UPNP_PORT = "upnp_port";
protected static final String KEY_USE_CACHE = "use_cache";
protected static final String KEY_USE_EMBEDDED_SUBTITLES_STYLE = "use_embedded_subtitles_style";
protected static final String KEY_USE_IMDB_INFO = "use_imdb_info";
protected static final String KEY_USE_MPLAYER_FOR_THUMBS = "use_mplayer_for_video_thumbs";
protected static final String KEY_UUID = "uuid";
protected static final String KEY_VIDEOTRANSCODE_START_DELAY = "videotranscode_start_delay";
protected static final String KEY_VIRTUAL_FOLDERS = "virtual_folders";
protected static final String KEY_VIRTUAL_FOLDERS_FILE = "virtual_folders_file";
protected static final String KEY_VLC_AUDIO_SYNC_ENABLED = "vlc_audio_sync_enabled";
protected static final String KEY_VLC_SAMPLE_RATE = "vlc_sample_rate";
protected static final String KEY_VLC_SAMPLE_RATE_OVERRIDE = "vlc_sample_rate_override";
protected static final String KEY_VLC_SCALE = "vlc_scale";
protected static final String KEY_VLC_SUBTITLE_ENABLED = "vlc_subtitle_enabled";
protected static final String KEY_VLC_USE_EXPERIMENTAL_CODECS = "vlc_use_experimental_codecs";
protected static final String KEY_VLC_USE_HW_ACCELERATION = "vlc_use_hw_acceleration";
protected static final String KEY_FULLY_PLAYED_ACTION = "fully_played_action";
protected static final String KEY_FULLY_PLAYED_OUTPUT_DIRECTORY = "fully_played_output_directory";
protected static final String KEY_WEB_AUTHENTICATE = "web_authenticate";
protected static final String KEY_WEB_BROWSE_LANG = "web_use_browser_lang";
protected static final String KEY_WEB_BROWSE_SUB_LANG = "web_use_browser_sub_lang";
protected static final String KEY_WEB_CHROME_TRICK = "web_chrome_mkv_as_webm_spoof";
protected static final String KEY_WEB_CONF_PATH = "web_conf";
protected static final String KEY_WEB_CONT_AUDIO = "web_continue_audio";
protected static final String KEY_WEB_CONT_IMAGE = "web_continue_image";
protected static final String KEY_WEB_CONT_VIDEO = "web_continue_video";
protected static final String KEY_WEB_CONTROL = "web_control";
protected static final String KEY_WEB_ENABLE = "web_enable";
protected static final String KEY_WEB_FIREFOX_LINUX_MP4 = "web_firefox_linux_mp4";
protected static final String KEY_WEB_FLASH = "web_flash";
protected static final String KEY_WEB_HEIGHT = "web_height";
protected static final String KEY_WEB_IMAGE_SLIDE = "web_image_show_delay";
protected static final String KEY_WEB_LOOP_AUDIO = "web_loop_audio";
protected static final String KEY_WEB_LOOP_IMAGE = "web_loop_image";
protected static final String KEY_WEB_LOOP_VIDEO = "web_loop_video";
protected static final String KEY_WEB_LOW_SPEED = "web_low_speed";
protected static final String KEY_WEB_MP4_TRANS = "web_mp4_trans";
protected static final String KEY_WEB_PATH = "web_path";
protected static final String KEY_WEB_SIZE = "web_size";
protected static final String KEY_WEB_SUBS_TRANS = "web_subtitles_transcoded";
protected static final String KEY_WEB_THREADS = "web_threads";
protected static final String KEY_WEB_TRANSCODE = "web_transcode";
protected static final String KEY_WEB_WIDTH = "web_width";
protected static final String KEY_WINDOW_EXTENDED_STATE = "window_extended_state";
protected static final String KEY_WINDOW_GEOMETRY = "window_geometry";
protected static final String KEY_X264_CONSTANT_RATE_FACTOR = "x264_constant_rate_factor";
// Deprecated settings
@Deprecated
protected static final String KEY_MENCODER_ASS_DEFAULTSTYLE = "mencoder_ass_defaultstyle";
// The name of the subdirectory under which UMS config files are stored for this build (default: UMS).
// See Build for more details
protected static final String PROFILE_DIRECTORY_NAME = Build.getProfileDirectoryName();
// The default profile name displayed on the renderer
protected static String HOSTNAME;
protected static String DEFAULT_AVI_SYNTH_SCRIPT;
protected static final int MAX_MAX_MEMORY_DEFAULT_SIZE = 400;
protected static final int BUFFER_MEMORY_FACTOR = 368;
protected static int MAX_MAX_MEMORY_BUFFER_SIZE = MAX_MAX_MEMORY_DEFAULT_SIZE;
protected static final char LIST_SEPARATOR = ',';
public final String ALL_RENDERERS = "All renderers";
// Path to default logfile directory
protected String defaultLogFileDir = null;
public TempFolder tempFolder;
public ProgramPaths programPaths;
public IpFilter filter;
/**
* The set of keys defining when the HTTP server has to restarted due to a configuration change
*/
public static final Set<String> NEED_RELOAD_FLAGS = new HashSet<>(
Arrays.asList(
KEY_ALTERNATE_THUMB_FOLDER,
KEY_ATZ_LIMIT,
KEY_AUDIO_THUMBNAILS_METHOD,
KEY_CHAPTER_SUPPORT,
KEY_DISABLE_TRANSCODE_FOR_EXTENSIONS,
KEY_DISABLE_TRANSCODING,
KEY_ENGINES,
KEY_FOLDERS,
KEY_FORCE_TRANSCODE_FOR_EXTENSIONS,
KEY_HIDE_EMPTY_FOLDERS,
KEY_HIDE_ENGINENAMES,
KEY_HIDE_EXTENSIONS,
KEY_HIDE_LIVE_SUBTITLES_FOLDER,
KEY_HIDE_MEDIA_LIBRARY_FOLDER,
KEY_HIDE_SUBS_INFO,
KEY_HIDE_TRANSCODE_FOLDER,
KEY_HIDE_VIDEO_SETTINGS,
KEY_IGNORE_THE_WORD_A_AND_THE,
KEY_IP_FILTER,
KEY_NETWORK_INTERFACE,
KEY_OPEN_ARCHIVES,
KEY_PRETTIFY_FILENAMES,
KEY_SERVER_HOSTNAME,
KEY_SERVER_NAME,
KEY_SERVER_PORT,
KEY_SHOW_APERTURE_LIBRARY,
KEY_SHOW_IPHOTO_LIBRARY,
KEY_SHOW_ITUNES_LIBRARY,
KEY_SORT_METHOD,
KEY_USE_CACHE
)
);
/*
The following code enables a single setting - UMS_PROFILE - to be used to
initialize PROFILE_PATH i.e. the path to the current session's profile (AKA UMS.conf).
It also initializes PROFILE_DIRECTORY - i.e. the directory the profile is located in -
which is needed to detect the default WEB.conf location (anything else?).
While this convention - and therefore PROFILE_DIRECTORY - will remain,
adding more configurables - e.g. web_conf = ... - is on the TODO list.
UMS_PROFILE is read (in this order) from the property ums.profile.path or the
environment variable UMS_PROFILE. If UMS is launched with the command-line option
"profiles" (e.g. from a shortcut), it displays a file chooser dialog that
allows the ums.profile.path property to be set. This makes it easy to run UMS
under multiple profiles without fiddling with environment variables, properties or
command-line arguments.
1) if UMS_PROFILE is not set, UMS.conf is located in:
Windows: %ALLUSERSPROFILE%\$build
Mac OS X: $HOME/Library/Application Support/$build
Everything else: $HOME/.config/$build
- where $build is a subdirectory that ensures incompatible UMS builds don't target/clobber
the same configuration files. The default value for $build is "UMS". Other builds might use e.g.
"UMS Rendr Edition" or "ums-mlx".
2) if a relative or absolute *directory path* is supplied (the directory must exist),
it is used as the profile directory and the profile is located there under the default profile name (UMS.conf):
UMS_PROFILE = /absolute/path/to/dir
UMS_PROFILE = relative/path/to/dir # relative to the working directory
Amongst other things, this can be used to restore the legacy behaviour of locating UMS.conf in the current
working directory e.g.:
UMS_PROFILE=. ./UMS.sh
3) if a relative or absolute *file path* is supplied (the file doesn't have to exist),
it is taken to be the profile, and its parent dir is taken to be the profile (i.e. config file) dir:
UMS_PROFILE = UMS.conf # profile dir = .
UMS_PROFILE = folder/dev.conf # profile dir = folder
UMS_PROFILE = /path/to/some.file # profile dir = /path/to/
*/
protected static final String DEFAULT_PROFILE_FILENAME = "UMS.conf";
protected static final String ENV_PROFILE_PATH = "UMS_PROFILE";
protected static final String DEFAULT_WEB_CONF_FILENAME = "WEB.conf";
protected static final String DEFAULT_CREDENTIALS_FILENAME = "UMS.cred";
// Path to directory containing UMS config files
protected static final String PROFILE_DIRECTORY;
// Absolute path to profile file e.g. /path/to/UMS.conf
protected static final String PROFILE_PATH;
// Absolute path to WEB.conf file e.g. /path/to/WEB.conf
protected static String WEB_CONF_PATH;
// Absolute path to skel (default) profile file e.g. /etc/skel/.config/universalmediaserver/UMS.conf
// "project.skelprofile.dir" project property
protected static final String SKEL_PROFILE_PATH;
protected static final String PROPERTY_PROFILE_PATH = "ums.profile.path";
protected static final String SYSTEM_PROFILE_DIRECTORY;
static {
// first of all, set up the path to the default system profile directory
if (Platform.isWindows()) {
String programData = System.getenv("ALLUSERSPROFILE");
if (programData != null) {
SYSTEM_PROFILE_DIRECTORY = String.format("%s\\%s", programData, PROFILE_DIRECTORY_NAME);
} else {
SYSTEM_PROFILE_DIRECTORY = ""; // i.e. current (working) directory
}
} else if (Platform.isMac()) {
SYSTEM_PROFILE_DIRECTORY = String.format(
"%s/%s/%s",
System.getProperty("user.home"),
"/Library/Application Support",
PROFILE_DIRECTORY_NAME
);
} else {
String xdgConfigHome = System.getenv("XDG_CONFIG_HOME");
if (xdgConfigHome == null) {
SYSTEM_PROFILE_DIRECTORY = String.format("%s/.config/%s", System.getProperty("user.home"), PROFILE_DIRECTORY_NAME);
} else {
SYSTEM_PROFILE_DIRECTORY = String.format("%s/%s", xdgConfigHome, PROFILE_DIRECTORY_NAME);
}
}
// now set the profile path. first: check for a custom setting.
// try the system property, typically set via the profile chooser
String customProfilePath = System.getProperty(PROPERTY_PROFILE_PATH);
// failing that, try the environment variable
if (StringUtils.isBlank(customProfilePath)) {
customProfilePath = System.getenv(ENV_PROFILE_PATH);
}
// if customProfilePath is still blank, the default profile dir/filename is used
FileLocation profileLocation = FileUtil.getFileLocation(
customProfilePath,
SYSTEM_PROFILE_DIRECTORY,
DEFAULT_PROFILE_FILENAME
);
PROFILE_PATH = profileLocation.getFilePath();
PROFILE_DIRECTORY = profileLocation.getDirectoryPath();
// Set SKEL_PROFILE_PATH for Linux systems
String skelDir = PropertiesUtil.getProjectProperties().get("project.skelprofile.dir");
if (Platform.isLinux() && StringUtils.isNotBlank(skelDir)) {
SKEL_PROFILE_PATH = FilenameUtils.normalize(
new File(
new File(
skelDir,
PROFILE_DIRECTORY_NAME
).getAbsolutePath(),
DEFAULT_PROFILE_FILENAME
).getAbsolutePath()
);
} else {
SKEL_PROFILE_PATH = null;
}
}
/**
* Default constructor that will attempt to load the PMS configuration file
* from the profile path.
*
* @throws org.apache.commons.configuration.ConfigurationException
*/
public PmsConfiguration() throws ConfigurationException {
this(true);
}
/**
* Constructor that will initialize the PMS configuration.
*
* @param loadFile Set to true to attempt to load the PMS configuration
* file from the profile path. Set to false to skip
* loading.
*/
public PmsConfiguration(boolean loadFile) {
super(0);
if (loadFile) {
File pmsConfFile = new File(PROFILE_PATH);
try {
((PropertiesConfiguration)configuration).load(pmsConfFile);
} catch (ConfigurationException e) {
if (Platform.isLinux() && SKEL_PROFILE_PATH != null) {
LOGGER.debug("Failed to load {} ({}) - attempting to load skel profile", PROFILE_PATH, e.getMessage());
File skelConfigFile = new File(SKEL_PROFILE_PATH);
try {
// Load defaults from skel profile, save them later to PROFILE_PATH
((PropertiesConfiguration)configuration).load(skelConfigFile);
LOGGER.info("Default configuration loaded from {}", SKEL_PROFILE_PATH);
} catch (ConfigurationException ce) {
LOGGER.warn("Can't load neither {}: {} nor {}: {}", PROFILE_PATH, e.getMessage(), SKEL_PROFILE_PATH, ce.getMessage());
}
} else {
LOGGER.warn("Can't load {}: {}", PROFILE_PATH, e.getMessage());
}
}
}
((PropertiesConfiguration)configuration).setPath(PROFILE_PATH);
tempFolder = new TempFolder(getString(KEY_TEMP_FOLDER_PATH, null));
programPaths = createProgramPathsChain(configuration);
filter = new IpFilter();
PMS.setLocale(getLanguageLocale(true));
//TODO: The line below should be removed once all calls to Locale.getDefault() is replaced with PMS.getLocale()
Locale.setDefault(getLanguageLocale());
// Set DEFAULT_AVI_SYNTH_SCRIPT according to language
DEFAULT_AVI_SYNTH_SCRIPT = "<movie>\n<sub>\n";
long usableMemory = (Runtime.getRuntime().maxMemory() / 1048576) - BUFFER_MEMORY_FACTOR;
if (usableMemory > MAX_MAX_MEMORY_DEFAULT_SIZE) {
MAX_MAX_MEMORY_BUFFER_SIZE = (int) usableMemory;
}
}
/**
* The following 2 constructors are for minimal instantiation in the context of subclasses
* (i.e. DeviceConfiguration) that use our getters and setters on another Configuration object.
* Here our main purpose is to initialize RendererConfiguration as required.
*/
protected PmsConfiguration(int ignored) {
// Just instantiate
super(0);
tempFolder = null;
programPaths = null;
filter = null;
}
protected PmsConfiguration(File f, String uuid) throws ConfigurationException {
// Just initialize super
super(f, uuid);
tempFolder = null;
programPaths = null;
filter = null;
}
@Override
public void reset() {
// This is just to prevent super.reset() from being invoked. Actual resetting would
// require rebooting here, since all of the application settings are implicated.
}
/**
* Check if we have disabled something first, then check the config file,
* then the Windows registry, then check for a platform-specific
* default.
*/
protected static ProgramPaths createProgramPathsChain(Configuration configuration) {
return new ConfigurationProgramPaths(
configuration,
new WindowsRegistryProgramPaths(
new PlatformSpecificDefaultPathsFactory().get()
)
);
}
private String verifyLogFolder(File folder, String fallbackTo) {
try {
FilePermissions permissions = FileUtil.getFilePermissions(folder);
if (LOGGER.isTraceEnabled()) {
if (!permissions.isFolder()) {
LOGGER.trace("getDefaultLogFileFolder: \"{}\" is not a folder, falling back to {} for logging", folder.getAbsolutePath(), fallbackTo);
} else if (!permissions.isBrowsable()) {
LOGGER.trace("getDefaultLogFileFolder: \"{}\" is not browsable, falling back to {} for logging", folder.getAbsolutePath(), fallbackTo);
} else if (!permissions.isWritable()) {
LOGGER.trace("getDefaultLogFileFolder: \"{}\" is not writable, falling back to {} for logging", folder.getAbsolutePath(), fallbackTo);
}
}
if (permissions.isFolder() && permissions.isBrowsable() && permissions.isWritable()) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Default logfile folder set to: {}", folder.getAbsolutePath());
}
return folder.getAbsolutePath();
}
} catch (FileNotFoundException e) {
LOGGER.trace("getDefaultLogFileFolder: \"{}\" not found, falling back to {} for logging: {}", folder.getAbsolutePath(), fallbackTo, e.getMessage());
}
return null;
}
/**
* @return first writable folder in the following order:
* <p>
* 1. (On Linux only) path to {@code /var/log/ums/%USERNAME%/}.
* </p>
* <p>
* 2. Path to profile folder ({@code ~/.config/UMS/} on Linux, {@code %ALLUSERSPROFILE%\UMS} on Windows and
* {@code ~/Library/Application Support/UMS/} on Mac).
* </p>
* <p>
* 3. Path to user-defined temporary folder specified by {@code temp_directory} parameter in UMS.conf.
* </p>
* <p>
* 4. Path to system temporary folder.
* </p>
* <p>
* 5. Path to current working directory.
* </p>
*/
public synchronized String getDefaultLogFileFolder() {
if (defaultLogFileDir == null) {
if (Platform.isLinux()) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("getDefaultLogFileFolder: System is Linux, trying \"/var/log/UMS/{}/\"", System.getProperty("user.name"));
}
final File logDirectory = new File("/var/log/UMS/" + System.getProperty("user.name") + "/");
if (!logDirectory.exists()) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("getDefaultLogFileFolder: Trying to create: \"{}\"", logDirectory.getAbsolutePath());
}
try {
FileUtils.forceMkdir(logDirectory);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("getDefaultLogFileFolder: \"{}\" created", logDirectory.getAbsolutePath());
}
} catch (IOException e) {
LOGGER.debug("Could not create \"{}\": {}", logDirectory.getAbsolutePath(), e.getMessage());
}
}
defaultLogFileDir = verifyLogFolder(logDirectory, "profile folder");
}
if (defaultLogFileDir == null) {
// Log to profile directory if it is writable.
final File profileDirectory = new File(PROFILE_DIRECTORY);
defaultLogFileDir = verifyLogFolder(profileDirectory, "temporary folder");
}
if (defaultLogFileDir == null) {
// Try user-defined temporary folder or fall back to system temporary folder.
try {
defaultLogFileDir = verifyLogFolder(getTempFolder(), "working folder");
} catch (IOException e) {
LOGGER.error("Could not determine default logfile folder, falling back to working directory: {}", e.getMessage());
defaultLogFileDir = "";
}
}
}
return defaultLogFileDir;
}
public String getDefaultLogFileName() {
String s = getString(KEY_LOGGING_LOGFILE_NAME, "debug.log");
if (FileUtil.isValidFileName(s)) {
return s;
} else {
return "debug.log";
}
}
public String getDefaultLogFilePath() {
return FileUtil.appendPathSeparator(getDefaultLogFileFolder()) + getDefaultLogFileName();
}
public File getTempFolder() throws IOException {
return tempFolder.getTempFolder();
}
public String getVlcPath() {
return programPaths.getVlcPath();
}
public String getMencoderPath() {
return programPaths.getMencoderPath();
}
public int getMencoderMaxThreads() {
return Math.min(getInt(KEY_MENCODER_MAX_THREADS, getNumberOfCpuCores()), MENCODER_MAX_THREADS);
}
public String getDCRawPath() {
return programPaths.getDCRaw();
}
public String getFfmpegPath() {
return programPaths.getFfmpegPath();
}
public String getMplayerPath() {
return programPaths.getMplayerPath();
}
public String getTsmuxerPath() {
return programPaths.getTsmuxerPath();
}
public String getTsmuxerNewPath() {
return programPaths.getTsmuxerNewPath();
}
public String getFlacPath() {
return programPaths.getFlacPath();
}
public String getInterFramePath() {
return programPaths.getInterFramePath();
}
/**
* If the framerate is not recognized correctly and the video runs too fast or too
* slow, tsMuxeR can be forced to parse the fps from FFmpeg. Default value is true.
* @return True if tsMuxeR should parse fps from FFmpeg.
*/
public boolean isTsmuxerForceFps() {
return getBoolean(KEY_TSMUXER_FORCEFPS, true);
}
/**
* The AC-3 audio bitrate determines the quality of digital audio sound. An AV-receiver
* or amplifier has to be capable of playing this quality. Default value is 640.
* @return The AC-3 audio bitrate.
*/
public int getAudioBitrate() {
return getInt(KEY_AUDIO_BITRATE, 640);
}
/**
* If the framerate is not recognized correctly and the video runs too fast or too
* slow, tsMuxeR can be forced to parse the fps from FFmpeg.
* @param value Set to true if tsMuxeR should parse fps from FFmpeg.
*/
public void setTsmuxerForceFps(boolean value) {
configuration.setProperty(KEY_TSMUXER_FORCEFPS, value);
}
/**
* The server port where PMS listens for TCP/IP traffic. Default value is 5001.
* @return The port number.
*/
public int getServerPort() {
return getInt(KEY_SERVER_PORT, DEFAULT_SERVER_PORT);
}
/**
* Set the server port where PMS must listen for TCP/IP traffic.
* @param value The TCP/IP port number.
*/
public void setServerPort(int value) {
configuration.setProperty(KEY_SERVER_PORT, value);
}
/**
* The hostname of the server.
* @return The hostname if it is defined, otherwise <code>null</code>.
*/
public String getServerHostname() {
return getString(KEY_SERVER_HOSTNAME, null);
}
/**
* Set the hostname of the server.
* @param value The hostname.
*/
public void setHostname(String value) {
configuration.setProperty(KEY_SERVER_HOSTNAME, value);
}
public String getServerDisplayName() {
if (isAppendProfileName()) {
return String.format("%s [%s]", getString(KEY_SERVER_NAME, PMS.NAME), getProfileName());
} else {
return getString(KEY_SERVER_NAME, PMS.NAME);
}
}
/**
* The name of the server.
*
* @return The name of the server.
*/
public String getServerName() {
return getString(KEY_SERVER_NAME, PMS.NAME);
}
/**
* Set the name of the server.
*
* @param value The name.
*/
public void setServerName(String value) {
configuration.setProperty(KEY_SERVER_NAME, value);
}
/**
* The TCP/IP port number for a proxy server. Default value is -1.
*
* @return The proxy port number.
*/
// no longer used
@Deprecated
public int getProxyServerPort() {
return getInt(KEY_PROXY_SERVER_PORT, DEFAULT_PROXY_SERVER_PORT);
}
/**
* Gets the language {@link String} as stored in the {@link PmsConfiguration}.
* May return <code>null</code>.
* @return The language {@link String}
*/
public String getLanguageRawString() {
return configuration.getString(KEY_LANGUAGE);
}
/**
* Gets the {@link java.util.Locale} of the preferred language for the UMS
* user interface. The default is based on the default (OS) locale.
* @param log determines if any issues should be logged.
* @return The {@link java.util.Locale}.
*/
public Locale getLanguageLocale(boolean log) {
String languageCode = configuration.getString(KEY_LANGUAGE);
Locale locale = null;
if (languageCode != null && !languageCode.isEmpty()) {
locale = Languages.toLocale(Locale.forLanguageTag(languageCode));
if (log && locale == null) {
LOGGER.error("Invalid or unsupported language tag \"{}\", defaulting to OS language.", languageCode);
}
} else if (log) {
LOGGER.info("Language not specified, defaulting to OS language.");
}
if (locale == null) {
locale = Languages.toLocale(Locale.getDefault());
if (log && locale == null) {
LOGGER.error("Unsupported language tag \"{}\", defaulting to US English.", Locale.getDefault().toLanguageTag());
}
}
if (locale == null) {
locale = Locale.forLanguageTag("en-US"); // Default
}
return locale;
}
/**
* Gets the {@link java.util.Locale} of the preferred language for the UMS
* user interface. The default is based on the default (OS) locale. Doesn't
* log potential issues.
* @return The {@link java.util.Locale}.
*/
public Locale getLanguageLocale() {
return getLanguageLocale(false);
}
/**
* Gets the {@link java.util.Locale} compatible tag of the preferred
* language for the UMS user interface. The default is based on the default (OS) locale.
* @return The <a href="https://en.wikipedia.org/wiki/IETF_language_tag">IEFT BCP 47</a> language tag.
*/
public String getLanguageTag() {
return getLanguageLocale().toLanguageTag();
}
/**
* @deprecated Use {@link #getLanguageTag} or {@link #getLanguageLocale} instead
* @since 5.2.3
*/
public String getLanguage() {
return getLanguageTag();
}
/**
* Sets the preferred language for the UMS user interface.
* @param value The {@link java.net.Locale}.
*/
public void setLanguage(Locale locale) {
if (locale != null) {
if (Languages.isValid(locale)) {
configuration.setProperty(KEY_LANGUAGE, Languages.toLanguageTag(locale));
PMS.setLocale(Languages.toLocale(locale));
//TODO: The line below should be removed once all calls to Locale.getDefault() is replaced with PMS.getLocale()
Locale.setDefault(Languages.toLocale(locale));
} else {
LOGGER.error("setLanguage() aborted because of unsupported language tag \"{}\"", locale.toLanguageTag());
}
} else {
configuration.setProperty(KEY_LANGUAGE, "");
}
}
/**
* Sets the preferred language for the UMS user interface.
* @param value The <a href="https://en.wikipedia.org/wiki/IETF_language_tag">IEFT BCP 47</a> language tag.
*/
public void setLanguage(String value) {
if (value != null && !value.isEmpty()) {
setLanguage(Locale.forLanguageTag(value));
} else {
LOGGER.error("setLanguage() aborted because language tag is empty");
}
}
/**
* Returns the preferred minimum size for the transcoding memory buffer in megabytes.
* Default value is 12.
* @return The minimum memory buffer size.
*/
public int getMinMemoryBufferSize() {
return getInt(KEY_MIN_MEMORY_BUFFER_SIZE, 12);
}
/**
* Returns the preferred maximum size for the transcoding memory buffer in megabytes.
* The value returned has a top limit of {@link #MAX_MAX_MEMORY_BUFFER_SIZE}. Default
* value is 200.
*
* @return The maximum memory buffer size.
*/
public int getMaxMemoryBufferSize() {
return Math.max(0, Math.min(MAX_MAX_MEMORY_BUFFER_SIZE, getInt(KEY_MAX_MEMORY_BUFFER_SIZE, 200)));
}
/**
* Set the preferred maximum for the transcoding memory buffer in megabytes. The top
* limit for the value is {@link #MAX_MAX_MEMORY_BUFFER_SIZE}.
*
* @param value The maximum buffer size.
*/
public void setMaxMemoryBufferSize(int value) {
configuration.setProperty(KEY_MAX_MEMORY_BUFFER_SIZE, Math.max(0, Math.min(MAX_MAX_MEMORY_BUFFER_SIZE, value)));
}
/**
* Returns the font scale used for ASS subtitling. Default value is 1.4.
* @return The ASS font scale.
*/
public String getAssScale() {
return getString(KEY_ASS_SCALE, "1.4");
}
/**
* Some versions of MEncoder produce garbled audio because the "ac3" codec is used
* instead of the "ac3_fixed" codec. Returns true if "ac3_fixed" should be used.
* Default is false.
* See https://code.google.com/p/ps3mediaserver/issues/detail?id=1092#c1
* @return True if "ac3_fixed" should be used.
*/
public boolean isMencoderAc3Fixed() {
return getBoolean(KEY_MENCODER_AC3_FIXED, false);
}
/**
* Returns the margin used for ASS subtitling. Default value is 10.
* @return The ASS margin.
*/
public String getAssMargin() {
return getString(KEY_ASS_MARGIN, "10");
}
/**
* Returns the outline parameter used for ASS subtitling. Default value is 1.
* @return The ASS outline parameter.
*/
public String getAssOutline() {
return getString(KEY_ASS_OUTLINE, "1");
}
/**
* Returns the shadow parameter used for ASS subtitling. Default value is 1.
* @return The ASS shadow parameter.
*/
public String getAssShadow() {
return getString(KEY_ASS_SHADOW, "1");
}
/**
* Returns the subfont text scale parameter used for subtitling without ASS.
* Default value is 3.
* @return The subfont text scale parameter.
*/
public String getMencoderNoAssScale() {
return getString(KEY_MENCODER_NOASS_SCALE, "3");
}
/**
* Returns the subpos parameter used for subtitling without ASS.
* Default value is 2.
* @return The subpos parameter.
*/
public String getMencoderNoAssSubPos() {
return getString(KEY_MENCODER_NOASS_SUBPOS, "2");
}
/**
* Returns the subfont blur parameter used for subtitling without ASS.
* Default value is 1.
* @return The subfont blur parameter.
*/
public String getMencoderNoAssBlur() {
return getString(KEY_MENCODER_NOASS_BLUR, "1");
}
/**
* Returns the subfont outline parameter used for subtitling without ASS.
* Default value is 1.
* @return The subfont outline parameter.
*/
public String getMencoderNoAssOutline() {
return getString(KEY_MENCODER_NOASS_OUTLINE, "1");
}
/**
* Set the subfont outline parameter used for subtitling without ASS.
* @param value The subfont outline parameter value to set.
*/
public void setMencoderNoAssOutline(String value) {
configuration.setProperty(KEY_MENCODER_NOASS_OUTLINE, value);
}
/**
* Some versions of MEncoder produce garbled audio because the "ac3" codec is used
* instead of the "ac3_fixed" codec.
* See https://code.google.com/p/ps3mediaserver/issues/detail?id=1092#c1
* @param value Set to true if "ac3_fixed" should be used.
*/
public void setMencoderAc3Fixed(boolean value) {
configuration.setProperty(KEY_MENCODER_AC3_FIXED, value);
}
/**
* Set the margin used for ASS subtitling.
* @param value The ASS margin value to set.
*/
public void setAssMargin(String value) {
configuration.setProperty(KEY_ASS_MARGIN, value);
}
/**
* Set the outline parameter used for ASS subtitling.
* @param value The ASS outline parameter value to set.
*/
public void setAssOutline(String value) {
configuration.setProperty(KEY_ASS_OUTLINE, value);
}
/**
* Set the shadow parameter used for ASS subtitling.
* @param value The ASS shadow parameter value to set.
*/
public void setAssShadow(String value) {
configuration.setProperty(KEY_ASS_SHADOW, value);
}
/**
* Set the font scale used for ASS subtitling.
* @param value The ASS font scale value to set.
*/
public void setAssScale(String value) {
configuration.setProperty(KEY_ASS_SCALE, value);
}
/**
* Set the subfont text scale parameter used for subtitling without ASS.
* @param value The subfont text scale parameter value to set.
*/
public void setMencoderNoAssScale(String value) {
configuration.setProperty(KEY_MENCODER_NOASS_SCALE, value);
}
/**
* Set the subfont blur parameter used for subtitling without ASS.
* @param value The subfont blur parameter value to set.
*/
public void setMencoderNoAssBlur(String value) {
configuration.setProperty(KEY_MENCODER_NOASS_BLUR, value);
}
/**
* Set the subpos parameter used for subtitling without ASS.
* @param value The subpos parameter value to set.
*/
public void setMencoderNoAssSubPos(String value) {
configuration.setProperty(KEY_MENCODER_NOASS_SUBPOS, value);
}
/**
* Set the maximum number of concurrent MEncoder threads.
* XXX Currently unused.
* @param value The maximum number of concurrent threads.
*/
public void setMencoderMaxThreads(int value) {
configuration.setProperty(KEY_MENCODER_MAX_THREADS, value);
}
/**
* Returns the number of seconds from the start of a video file (the seek
* position) where the thumbnail image for the movie should be extracted
* from. Default is 4 seconds.
*
* @return The seek position in seconds.
*/
public int getThumbnailSeekPos() {
return getInt(KEY_THUMBNAIL_SEEK_POS, 4);
}
/**
* Sets the number of seconds from the start of a video file (the seek
* position) where the thumbnail image for the movie should be extracted
* from.
*
* @param value The seek position in seconds.
*/
public void setThumbnailSeekPos(int value) {
configuration.setProperty(KEY_THUMBNAIL_SEEK_POS, value);
}
/**
* Returns whether the user wants ASS/SSA subtitle support. Default is
* true.
*
* @return True if MEncoder should use ASS/SSA support.
*/
public boolean isMencoderAss() {
return getBoolean(KEY_MENCODER_ASS, true);
}
/**
* Returns whether or not subtitles should be disabled for all
* transcoding engines. Default is false, meaning subtitles should not
* be disabled.
*
* @return True if subtitles should be disabled, false otherwise.
*/
public boolean isDisableSubtitles() {
return getBoolean(KEY_DISABLE_SUBTITLES, false);
}
/**
* Set whether or not subtitles should be disabled for
* all transcoding engines.
*
* @param value Set to true if subtitles should be disabled.
*/
public void setDisableSubtitles(boolean value) {
configuration.setProperty(KEY_DISABLE_SUBTITLES, value);
}
/**
* Returns whether or not the Pulse Code Modulation audio format should be
* forced. The default is false.
* @return True if PCM should be forced, false otherwise.
*/
public boolean isAudioUsePCM() {
return getBoolean(KEY_AUDIO_USE_PCM, false);
}
/**
* Returns whether or not the Pulse Code Modulation audio format should be
* used only for HQ audio codecs. The default is false.
* @return True if PCM should be used only for HQ audio codecs, false otherwise.
*/
public boolean isMencoderUsePcmForHQAudioOnly() {
return getBoolean(KEY_MENCODER_USE_PCM_FOR_HQ_AUDIO_ONLY, false);
}
/**
* Returns the name of a TrueType font to use for subtitles.
* Default is <code>""</code>.
* @return The font name.
*/
public String getFont() {
return getString(KEY_FONT, "");
}
/**
* Returns the audio language priority as a comma separated
* string. For example: <code>"eng,fre,jpn,ger,und"</code>, where "und"
* stands for "undefined".
* Can be a blank string.
* Default value is "loc,eng,fre,jpn,ger,und".
*
* @return The audio language priority string.
*/
public String getAudioLanguages() {
return configurationReader.getPossiblyBlankConfigurationString(
KEY_AUDIO_LANGUAGES,
Messages.getString("MEncoderVideo.126")
);
}
/**
* Returns the subtitle language priority as a comma-separated
* string. For example: <code>"eng,fre,jpn,ger,und"</code>, where "und"
* stands for "undefined".
* Can be a blank string.
* Default value is a localized list (e.g. "eng,fre,jpn,ger,und").
*
* @return The subtitle language priority string.
*/
public String getSubtitlesLanguages() {
return configurationReader.getPossiblyBlankConfigurationString(
KEY_SUBTITLES_LANGUAGES,
Messages.getString("MEncoderVideo.127")
);
}
/**
* Returns the ISO 639 language code for the subtitle language that should
* be forced.
* Can be a blank string.
* @return The subtitle language code.
*/
public String getForcedSubtitleLanguage() {
return configurationReader.getPossiblyBlankConfigurationString(
KEY_FORCED_SUBTITLE_LANGUAGE,
PMS.getLocale().getLanguage()
);
}
/**
* Returns the tag string that identifies the subtitle language that
* should be forced.
* @return The tag string.
*/
public String getForcedSubtitleTags() {
return getString(KEY_FORCED_SUBTITLE_TAGS, "forced");
}
/**
* Returns a string of audio language and subtitle language pairs
* ordered by priority to try to match. Audio language
* and subtitle language should be comma-separated as a pair,
* individual pairs should be semicolon separated. "*" can be used to
* match any language. Subtitle language can be defined as "off".
* Default value is <code>"*,*"</code>.
*
* @return The audio and subtitle languages priority string.
*/
public String getAudioSubLanguages() {
return configurationReader.getPossiblyBlankConfigurationString(
KEY_AUDIO_SUB_LANGS,
Messages.getString("MEncoderVideo.128")
);
}
/**
* Sets a string of audio language and subtitle language pairs
* ordered by priority to try to match. Audio language
* and subtitle language should be comma-separated as a pair,
* individual pairs should be semicolon separated. "*" can be used to
* match any language. Subtitle language can be defined as "off".
*
* Example: <code>"en,off;jpn,eng;*,eng;*;*"</code>.
*
* @param value The audio and subtitle languages priority string.
*/
public void setAudioSubLanguages(String value) {
configuration.setProperty(KEY_AUDIO_SUB_LANGS, value);
}
/**
* Returns whether or not MEncoder should use FriBiDi mode, which
* is needed to display subtitles in languages that read from right to
* left, like Arabic, Farsi, Hebrew, Urdu, etc. Default value is false.
*
* @return True if FriBiDi mode should be used, false otherwise.
*/
public boolean isMencoderSubFribidi() {
return getBoolean(KEY_MENCODER_SUB_FRIBIDI, false);
}
/**
* Returns the character encoding (or code page) that should used
* for displaying non-Unicode external subtitles. Default is empty string
* (do not force encoding with -subcp key).
*
* @return The character encoding.
*/
public String getSubtitlesCodepage() {
return getString(KEY_SUBTITLES_CODEPAGE, "");
}
/**
* Whether MEncoder should use fontconfig for displaying subtitles.
*
* @return True if fontconfig should be used, false otherwise.
*/
public boolean isMencoderFontConfig() {
return getBoolean(KEY_MENCODER_FONT_CONFIG, true);
}
/**
* Set to true if MEncoder should be forced to use the framerate that is
* parsed by FFmpeg.
*
* @param value Set to true if the framerate should be forced, false
* otherwise.
*/
public void setMencoderForceFps(boolean value) {
configuration.setProperty(KEY_MENCODER_FORCE_FPS, value);
}
/**
* Whether MEncoder should be forced to use the framerate that is
* parsed by FFmpeg.
*
* @return True if the framerate should be forced, false otherwise.
*/
public boolean isMencoderForceFps() {
return getBoolean(KEY_MENCODER_FORCE_FPS, false);
}
/**
* Sets the audio language priority as a comma separated
* string. For example: <code>"eng,fre,jpn,ger,und"</code>, where "und"
* stands for "undefined".
* @param value The audio language priority string.
*/
public void setAudioLanguages(String value) {
configuration.setProperty(KEY_AUDIO_LANGUAGES, value);
}
/**
* Sets the subtitle language priority as a comma-separated string.
*
* Example: <code>"eng,fre,jpn,ger,und"</code>, where "und" stands for
* "undefined".
*
* @param value The subtitle language priority string.
*/
public void setSubtitlesLanguages(String value) {
configuration.setProperty(KEY_SUBTITLES_LANGUAGES, value);
}
/**
* Sets the ISO 639 language code for the subtitle language that should
* be forced.
*
* @param value The subtitle language code.
*/
public void setForcedSubtitleLanguage(String value) {
configuration.setProperty(KEY_FORCED_SUBTITLE_LANGUAGE, value);
}
/**
* Sets the tag string that identifies the subtitle language that
* should be forced.
*
* @param value The tag string.
*/
public void setForcedSubtitleTags(String value) {
configuration.setProperty(KEY_FORCED_SUBTITLE_TAGS, value);
}
/**
* Returns custom commandline options to pass on to MEncoder.
*
* @return The custom options string.
*/
public String getMencoderCustomOptions() {
return getString(KEY_MENCODER_CUSTOM_OPTIONS, "");
}
/**
* Sets custom commandline options to pass on to MEncoder.
*
* @param value The custom options string.
*/
public void setMencoderCustomOptions(String value) {
configuration.setProperty(KEY_MENCODER_CUSTOM_OPTIONS, value);
}
/**
* Sets the character encoding (or code page) that should be used
* for displaying non-Unicode external subtitles. Default is empty (autodetect).
*
* @param value The character encoding.
*/
public void setSubtitlesCodepage(String value) {
configuration.setProperty(KEY_SUBTITLES_CODEPAGE, value);
}
/**
* Sets whether or not MEncoder should use FriBiDi mode, which
* is needed to display subtitles in languages that read from right to
* left, like Arabic, Farsi, Hebrew, Urdu, etc. Default value is false.
*
* @param value Set to true if FriBiDi mode should be used.
*/
public void setMencoderSubFribidi(boolean value) {
configuration.setProperty(KEY_MENCODER_SUB_FRIBIDI, value);
}
/**
* Sets the name of a TrueType font to use for subtitles.
*
* @param value The font name.
*/
public void setFont(String value) {
configuration.setProperty(KEY_FONT, value);
}
/**
* Older versions of MEncoder do not support ASS/SSA subtitles on all
* platforms. Set to true if MEncoder supports them. Default should be
* true on Windows and OS X, false otherwise.
* See https://code.google.com/p/ps3mediaserver/issues/detail?id=1097
*
* @param value Set to true if MEncoder supports ASS/SSA subtitles.
*/
public void setMencoderAss(boolean value) {
configuration.setProperty(KEY_MENCODER_ASS, value);
}
/**
* Sets whether or not MEncoder should use fontconfig for displaying
* subtitles.
*
* @param value Set to true if fontconfig should be used.
*/
public void setMencoderFontConfig(boolean value) {
configuration.setProperty(KEY_MENCODER_FONT_CONFIG, value);
}
/**
* Sets whether or not the Pulse Code Modulation audio format should be
* forced.
*
* @param value Set to true if PCM should be forced.
*/
public void setAudioUsePCM(boolean value) {
configuration.setProperty(KEY_AUDIO_USE_PCM, value);
}
/**
* Sets whether or not the Pulse Code Modulation audio format should be
* used only for HQ audio codecs.
*
* @param value Set to true if PCM should be used only for HQ audio.
*/
public void setMencoderUsePcmForHQAudioOnly(boolean value) {
configuration.setProperty(KEY_MENCODER_USE_PCM_FOR_HQ_AUDIO_ONLY, value);
}
/**
* Whether archives (e.g. .zip or .rar) should be browsable.
*
* @return True if archives should be browsable.
*/
public boolean isArchiveBrowsing() {
return getBoolean(KEY_OPEN_ARCHIVES, false);
}
/**
* Sets whether archives (e.g. .zip or .rar) should be browsable.
*
* @param value Set to true if archives should be browsable.
*/
public void setArchiveBrowsing(boolean value) {
configuration.setProperty(KEY_OPEN_ARCHIVES, value);
}
/**
* Returns true if MEncoder should use the deinterlace filter, false
* otherwise.
*
* @return True if the deinterlace filter should be used.
*/
public boolean isMencoderYadif() {
return getBoolean(KEY_MENCODER_YADIF, false);
}
/**
* Set to true if MEncoder should use the deinterlace filter, false
* otherwise.
*
* @param value Set ot true if the deinterlace filter should be used.
*/
public void setMencoderYadif(boolean value) {
configuration.setProperty(KEY_MENCODER_YADIF, value);
}
/**
* Whether MEncoder should be used to upscale the video to an
* optimal resolution. Default value is false, meaning the renderer will
* upscale the video itself.
*
* @return True if MEncoder should be used, false otherwise.
* @see #getMencoderScaleX()
* @see #getMencoderScaleY()
*/
public boolean isMencoderScaler() {
return getBoolean(KEY_MENCODER_SCALER, false);
}
/**
* Set to true if MEncoder should be used to upscale the video to an
* optimal resolution. Set to false to leave upscaling to the renderer.
*
* @param value Set to true if MEncoder should be used to upscale.
* @see #setMencoderScaleX(int)
* @see #setMencoderScaleY(int)
*/
public void setMencoderScaler(boolean value) {
configuration.setProperty(KEY_MENCODER_SCALER, value);
}
/**
* Returns the width in pixels to which a video should be scaled when
* {@link #isMencoderScaler()} returns true.
*
* @return The width in pixels.
*/
public int getMencoderScaleX() {
return getInt(KEY_MENCODER_SCALEX, 0);
}
/**
* Sets the width in pixels to which a video should be scaled when
* {@link #isMencoderScaler()} returns true.
*
* @param value The width in pixels.
*/
public void setMencoderScaleX(int value) {
configuration.setProperty(KEY_MENCODER_SCALEX, value);
}
/**
* Returns the height in pixels to which a video should be scaled when
* {@link #isMencoderScaler()} returns true.
*
* @return The height in pixels.
*/
public int getMencoderScaleY() {
return getInt(KEY_MENCODER_SCALEY, 0);
}
/**
* Sets the height in pixels to which a video should be scaled when
* {@link #isMencoderScaler()} returns true.
*
* @param value The height in pixels.
*/
public void setMencoderScaleY(int value) {
configuration.setProperty(KEY_MENCODER_SCALEY, value);
}
/**
* Returns the number of audio channels that should be used for
* transcoding. Default value is 6 (for 5.1 audio).
*
* @return The number of audio channels.
*/
public int getAudioChannelCount() {
int valueFromUserConfig = getInt(KEY_AUDIO_CHANNEL_COUNT, 6);
if (valueFromUserConfig != 6 && valueFromUserConfig != 2) {
return 6;
}
return valueFromUserConfig;
}
/**
* Sets the number of audio channels that MEncoder should use for
* transcoding.
*
* @param value The number of audio channels.
*/
public void setAudioChannelCount(int value) {
if (value != 6 && value != 2) {
value = 6;
}
configuration.setProperty(KEY_AUDIO_CHANNEL_COUNT, value);
}
/**
* Sets the AC3 audio bitrate, which determines the quality of digital
* audio sound. An AV-receiver or amplifier has to be capable of playing
* this quality.
*
* @param value The AC3 audio bitrate.
*/
public void setAudioBitrate(int value) {
configuration.setProperty(KEY_AUDIO_BITRATE, value);
}
/**
* Returns the maximum video bitrate to be used by MEncoder and FFmpeg.
*
* @return The maximum video bitrate.
*/
public String getMaximumBitrate() {
String maximumBitrate = getMaximumBitrateDisplay();
if ("0".equals(maximumBitrate)) {
maximumBitrate = "1000";
}
return maximumBitrate;
}
/**
* The same as getMaximumBitrate() but this value is displayed to the user
* because for our own uses we turn the value "0" into the value "1000" but
* that can be confusing for the user.
*
* @return The maximum video bitrate to display in the GUI.
*/
public String getMaximumBitrateDisplay() {
return getString(KEY_MAX_BITRATE, "90");
}
/**
* Sets the maximum video bitrate to be used by MEncoder.
*
* @param value The maximum video bitrate.
*/
public void setMaximumBitrate(String value) {
configuration.setProperty(KEY_MAX_BITRATE, value);
}
/**
* @return The selected renderers as a list.
*/
public List<String> getSelectedRenderers() {
return getStringList(KEY_SELECTED_RENDERERS, ALL_RENDERERS);
}
/**
* @param value The comma-separated list of selected renderers.
*/
public void setSelectedRenderers(String value) {
if (value.isEmpty()) {
value = "None";
}
configuration.setProperty(KEY_SELECTED_RENDERERS, value);
}
/**
* @param value a string list of renderers.
*/
public void setSelectedRenderers(List<String> value) {
setStringList(KEY_SELECTED_RENDERERS, value);
}
/**
* Returns true if thumbnail generation is enabled, false otherwise.
*
* @return boolean indicating whether thumbnail generation is enabled.
*/
public boolean isThumbnailGenerationEnabled() {
return getBoolean(KEY_THUMBNAIL_GENERATION_ENABLED, true);
}
/**
* Sets the thumbnail generation option.
*/
public void setThumbnailGenerationEnabled(boolean value) {
configuration.setProperty(KEY_THUMBNAIL_GENERATION_ENABLED, value);
}
/**
* Returns true if PMS should generate thumbnails for images. Default value
* is true.
*
* @return True if image thumbnails should be generated.
*/
public boolean getImageThumbnailsEnabled() {
return getBoolean(KEY_IMAGE_THUMBNAILS_ENABLED, true);
}
/**
* Set to true if PMS should generate thumbnails for images.
*
* @param value True if image thumbnails should be generated.
*/
public void setImageThumbnailsEnabled(boolean value) {
configuration.setProperty(KEY_IMAGE_THUMBNAILS_ENABLED, value);
}
/**
* Returns the number of CPU cores that should be used for transcoding.
*
* @return The number of CPU cores.
*/
public int getNumberOfCpuCores() {
int nbcores = Runtime.getRuntime().availableProcessors();
if (nbcores < 1) {
nbcores = 1;
}
return getInt(KEY_NUMBER_OF_CPU_CORES, nbcores);
}
/**
* Sets the number of CPU cores that should be used for transcoding. The
* maximum value depends on the physical available count of "real processor
* cores". That means hyperthreading virtual CPU cores do not count! If you
* are not sure, analyze your CPU with the free tool CPU-z on Windows
* systems. On Linux have a look at the virtual proc-filesystem: in the
* file "/proc/cpuinfo" you will find more details about your CPU. You also
* get much information about CPUs from AMD and Intel from their Wikipedia
* articles.
* <p>
* PMS will detect and set the correct amount of cores as the default value.
*
* @param value The number of CPU cores.
*/
public void setNumberOfCpuCores(int value) {
configuration.setProperty(KEY_NUMBER_OF_CPU_CORES, value);
}
/**
* Returns true if PMS should start minimized, i.e. without its window
* opened. Default value false: to start with a window.
*
* @return True if PMS should start minimized, false otherwise.
*/
public boolean isMinimized() {
return getBoolean(KEY_MINIMIZED, false);
}
/**
* Set to true if PMS should start minimized, i.e. without its window
* opened.
*
* @param value True if PMS should start minimized, false otherwise.
*/
public void setMinimized(boolean value) {
configuration.setProperty(KEY_MINIMIZED, value);
}
/**
* Returns true if UMS should automatically start on Windows.
*
* @return True if UMS should start automatically, false otherwise.
*/
public boolean isAutoStart() {
if (Platform.isWindows()) {
File f = new File(WindowsRegistry.readRegistry("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Common Startup") + "\\Universal Media Server.lnk");
if (f.exists()) {
return true;
}
}
return false;
}
/**
* Set to true if UMS should automatically start on Windows.
*
* @param value True if UMS should start automatically, false otherwise.
*/
public void setAutoStart(boolean value) {
File sourceFile = new File(WindowsRegistry.readRegistry("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Common Programs") + "\\Universal Media Server.lnk");
File destinationFile = new File(WindowsRegistry.readRegistry("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Common Startup") + "\\Universal Media Server.lnk");
if (value) {
try {
FileUtils.copyFile(sourceFile, destinationFile);
if (destinationFile.exists()) {
LOGGER.info("UMS will start automatically with Windows");
} else {
LOGGER.info("An error occurred while trying to make UMS start automatically with Windows");
}
} catch (IOException e) {
if (!FileUtil.isAdmin()) {
try {
JOptionPane.showMessageDialog(
SwingUtilities.getWindowAncestor((Component) PMS.get().getFrame()),
Messages.getString("NetworkTab.58"),
Messages.getString("Dialog.PermissionsError"),
JOptionPane.ERROR_MESSAGE
);
} catch (NullPointerException e2) {
// This happens on the initial program load, ignore it
}
} else {
LOGGER.info("An error occurred while trying to make UMS start automatically with Windows");
}
}
} else {
if (destinationFile.delete()) {
LOGGER.info("UMS will not start automatically with Windows");
} else {
LOGGER.info("An error occurred while trying to make UMS not start automatically with Windows");
}
}
}
/**
* Whether we should check for external subtitle files with the same
* name as the media (*.srt, *.sub, *.ass, etc.).
*
* Note: This will return true if either the autoload external subtitles
* setting is enabled or the force external subtitles setting is enabled
*
* @return Whether we should check for external subtitle files.
*/
public boolean isAutoloadExternalSubtitles() {
return getBoolean(KEY_AUTOLOAD_SUBTITLES, true) || isForceExternalSubtitles();
}
/**
* Whether we should check for external subtitle files with the same
* name as the media (*.srt, *.sub, *.ass etc.).
*
* @param value Whether we should check for external subtitle files.
*/
public void setAutoloadExternalSubtitles(boolean value) {
configuration.setProperty(KEY_AUTOLOAD_SUBTITLES, value);
}
/**
* Whether we should force external subtitles with the same name as the
* media (*.srt, *.sub, *.ass, etc.) to display, regardless of whether
* language preferences disable them.
*
* @return Whether we should force external subtitle files.
*/
public boolean isForceExternalSubtitles() {
return getBoolean(KEY_FORCE_EXTERNAL_SUBTITLES, true);
}
/**
* Whether we should force external subtitles with the same name as the
* media (*.srt, *.sub, *.ass, etc.) to display, regardless of whether
* language preferences disable them.
*
* @param value Whether we should force external subtitle files.
*/
public void setForceExternalSubtitles(boolean value) {
configuration.setProperty(KEY_FORCE_EXTERNAL_SUBTITLES, value);
}
/**
* Returns true if PMS should hide the "# Videosettings #" folder on the
* DLNA device. The default value is false: PMS will display the folder.
*
* @return True if PMS should hide the folder, false othewise.
*/
public boolean getHideVideoSettings() {
return getBoolean(KEY_HIDE_VIDEO_SETTINGS, true);
}
/**
* Set to true if PMS should hide the "# Videosettings #" folder on the
* DLNA device, or set to false to make PMS display the folder.
*
* @param value True if PMS should hide the folder.
*/
public void setHideVideoSettings(boolean value) {
configuration.setProperty(KEY_HIDE_VIDEO_SETTINGS, value);
}
/**
* Gets the {@link FullyPlayedAction}.
*
* @return What to do with a file after it has been fully played
*/
public FullyPlayedAction getFullyPlayedAction() {
return FullyPlayedAction.toFullyPlayedAction(getInt(KEY_FULLY_PLAYED_ACTION, 1));
}
/**
* Sets the {@link FullyPlayedAction}.
*
* @param value what to do with a file after it has been fully played
*/
public void setFullyPlayedAction(FullyPlayedAction action) {
configuration.setProperty(KEY_FULLY_PLAYED_ACTION, action.toInt());
}
/**
* Returns the folder to move fully played files to.
*
* @see #getFullyPlayedAction()
* @return The folder to move fully played files to
*/
public String getFullyPlayedOutputDirectory() {
return getString(KEY_FULLY_PLAYED_OUTPUT_DIRECTORY, "");
}
/**
* Sets the folder to move fully played files to.
*
* @see #getFullyPlayedAction()
* @param value the folder to move fully played files to
*/
public void setFullyPlayedOutputDirectory(String value) {
configuration.setProperty(KEY_FULLY_PLAYED_OUTPUT_DIRECTORY, value);
}
/**
* Returns true if PMS should cache scanned media in its internal database,
* speeding up later retrieval. When false is returned, PMS will not use
* cache and media will have to be rescanned.
*
* @return True if PMS should cache media.
*/
public boolean getUseCache() {
return getBoolean(KEY_USE_CACHE, true);
}
/**
* Set to true if PMS should cache scanned media in its internal database,
* speeding up later retrieval.
*
* @param value True if PMS should cache media.
*/
public void setUseCache(boolean value) {
configuration.setProperty(KEY_USE_CACHE, value);
}
/**
* Whether we should pass the flag "convertfps=true" to AviSynth.
*
* @param value True if we should pass the flag.
*/
public void setAvisynthConvertFps(boolean value) {
configuration.setProperty(KEY_AVISYNTH_CONVERT_FPS, value);
}
/**
* Returns true if we should pass the flag "convertfps=true" to AviSynth.
*
* @return True if we should pass the flag.
*/
public boolean getAvisynthConvertFps() {
return getBoolean(KEY_AVISYNTH_CONVERT_FPS, true);
}
public void setAvisynthInterFrame(boolean value) {
configuration.setProperty(KEY_AVISYNTH_INTERFRAME, value);
}
public boolean getAvisynthInterFrame() {
return getBoolean(KEY_AVISYNTH_INTERFRAME, false);
}
public void setAvisynthInterFrameGPU(boolean value) {
configuration.setProperty(KEY_AVISYNTH_INTERFRAME_GPU, value);
}
public boolean getAvisynthInterFrameGPU() {
return getBoolean(KEY_AVISYNTH_INTERFRAME_GPU, false);
}
public void setAvisynthMultiThreading(boolean value) {
configuration.setProperty(KEY_AVISYNTH_MULTITHREADING, value);
}
public boolean getAvisynthMultiThreading() {
return getBoolean(KEY_AVISYNTH_MULTITHREADING, false);
}
/**
* Returns the template for the AviSynth script. The script string can
* contain the character "\u0001", which should be treated as the newline
* separator character.
*
* @return The AviSynth script template.
*/
public String getAvisynthScript() {
return getString(KEY_AVISYNTH_SCRIPT, DEFAULT_AVI_SYNTH_SCRIPT);
}
/**
* Sets the template for the AviSynth script. The script string may contain
* the character "\u0001", which will be treated as newline character.
*
* @param value The AviSynth script template.
*/
public void setAvisynthScript(String value) {
configuration.setProperty(KEY_AVISYNTH_SCRIPT, value);
}
/**
* Returns additional codec specific configuration options for MEncoder.
*
* @return The configuration options.
*/
public String getMencoderCodecSpecificConfig() {
return getString(KEY_MENCODER_CODEC_SPECIFIC_SCRIPT, "");
}
/**
* Sets additional codec specific configuration options for MEncoder.
*
* @param value The additional configuration options.
*/
public void setMencoderCodecSpecificConfig(String value) {
configuration.setProperty(KEY_MENCODER_CODEC_SPECIFIC_SCRIPT, value);
}
/**
* Returns the maximum size (in MB) that PMS should use for buffering
* audio.
*
* @return The maximum buffer size.
*/
public int getMaxAudioBuffer() {
return getInt(KEY_MAX_AUDIO_BUFFER, 100);
}
/**
* Returns the minimum size (in MB) that PMS should use for the buffer used
* for streaming media.
*
* @return The minimum buffer size.
*/
public int getMinStreamBuffer() {
return getInt(KEY_MIN_STREAM_BUFFER, 1);
}
/**
* Converts the getMPEG2MainSettings() from MEncoder's format to FFmpeg's.
*
* @return MPEG-2 settings formatted for FFmpeg.
*/
public String getMPEG2MainSettingsFFmpeg() {
String mpegSettings = getMPEG2MainSettings();
if (StringUtils.isBlank(mpegSettings) || mpegSettings.contains("Automatic")) {
return mpegSettings;
}
return convertMencoderSettingToFFmpegFormat(mpegSettings);
}
public void setFfmpegMultithreading(boolean value) {
configuration.setProperty(KEY_FFMPEG_MULTITHREADING, value);
}
public boolean isFfmpegMultithreading() {
boolean isMultiCore = getNumberOfCpuCores() > 1;
return getBoolean(KEY_FFMPEG_MULTITHREADING, isMultiCore);
}
public void setFfmpegAviSynthMultithreading(boolean value) {
configuration.setProperty(KEY_FFMPEG_AVISYNTH_MULTITHREADING, value);
}
public boolean isFfmpegAviSynthMultithreading() {
boolean isMultiCore = getNumberOfCpuCores() > 1;
return getBoolean(KEY_FFMPEG_AVISYNTH_MULTITHREADING, isMultiCore);
}
/**
* Whether we should pass the flag "convertfps=true" to AviSynth.
*
* @param value True if we should pass the flag.
*/
public void setFfmpegAvisynthConvertFps(boolean value) {
configuration.setProperty(KEY_AVISYNTH_CONVERT_FPS, value);
}
/**
* Returns true if we should pass the flag "convertfps=true" to AviSynth.
*
* @return True if we should pass the flag.
*/
public boolean getFfmpegAvisynthConvertFps() {
return getBoolean(KEY_FFMPEG_AVISYNTH_CONVERT_FPS, true);
}
public void setFfmpegAvisynthInterFrame(boolean value) {
configuration.setProperty(KEY_FFMPEG_AVISYNTH_INTERFRAME, value);
}
public boolean getFfmpegAvisynthInterFrame() {
return getBoolean(KEY_FFMPEG_AVISYNTH_INTERFRAME, false);
}
public void setFfmpegAvisynthInterFrameGPU(boolean value) {
configuration.setProperty(KEY_FFMPEG_AVISYNTH_INTERFRAME_GPU, value);
}
public boolean getFfmpegAvisynthInterFrameGPU() {
return getBoolean(KEY_FFMPEG_AVISYNTH_INTERFRAME_GPU, false);
}
public boolean isMencoderNoOutOfSync() {
return getBoolean(KEY_MENCODER_NO_OUT_OF_SYNC, true);
}
public void setMencoderNoOutOfSync(boolean value) {
configuration.setProperty(KEY_MENCODER_NO_OUT_OF_SYNC, value);
}
public boolean getTrancodeBlocksMultipleConnections() {
return getBoolean(KEY_TRANSCODE_BLOCKS_MULTIPLE_CONNECTIONS, false);
}
public void setTranscodeBlocksMultipleConnections(boolean value) {
configuration.setProperty(KEY_TRANSCODE_BLOCKS_MULTIPLE_CONNECTIONS, value);
}
public boolean getTrancodeKeepFirstConnections() {
return getBoolean(KEY_TRANSCODE_KEEP_FIRST_CONNECTION, true);
}
public void setTrancodeKeepFirstConnections(boolean value) {
configuration.setProperty(KEY_TRANSCODE_KEEP_FIRST_CONNECTION, value);
}
public boolean isMencoderIntelligentSync() {
return getBoolean(KEY_MENCODER_INTELLIGENT_SYNC, true);
}
public void setMencoderIntelligentSync(boolean value) {
configuration.setProperty(KEY_MENCODER_INTELLIGENT_SYNC, value);
}
public String getFfmpegAlternativePath() {
return getString(KEY_FFMPEG_ALTERNATIVE_PATH, null);
}
public void setFfmpegAlternativePath(String value) {
configuration.setProperty(KEY_FFMPEG_ALTERNATIVE_PATH, value);
}
public boolean getSkipLoopFilterEnabled() {
return getBoolean(KEY_SKIP_LOOP_FILTER_ENABLED, false);
}
/**
* The list of network interfaces that should be skipped when checking
* for an available network interface. Entries should be comma separated
* and typically exclude the number at the end of the interface name.
* <p>
* Default is to skip the interfaces created by Virtualbox, OpenVPN and
* Parallels: "tap,vmnet,vnic,virtualbox".
* @return The string of network interface names to skip.
*/
public List<String> getSkipNetworkInterfaces() {
return getStringList(KEY_SKIP_NETWORK_INTERFACES, "tap,vmnet,vnic,virtualbox");
}
public void setSkipLoopFilterEnabled(boolean value) {
configuration.setProperty(KEY_SKIP_LOOP_FILTER_ENABLED, value);
}
public String getMPEG2MainSettings() {
return getString(KEY_MPEG2_MAIN_SETTINGS, "Automatic (Wired)");
}
public void setMPEG2MainSettings(String value) {
configuration.setProperty(KEY_MPEG2_MAIN_SETTINGS, value);
}
public String getx264ConstantRateFactor() {
return getString(KEY_X264_CONSTANT_RATE_FACTOR, "Automatic (Wired)");
}
public void setx264ConstantRateFactor(String value) {
configuration.setProperty(KEY_X264_CONSTANT_RATE_FACTOR, value);
}
public String getMencoderVobsubSubtitleQuality() {
return getString(KEY_MENCODER_VOBSUB_SUBTITLE_QUALITY, "3");
}
public void setMencoderVobsubSubtitleQuality(String value) {
configuration.setProperty(KEY_MENCODER_VOBSUB_SUBTITLE_QUALITY, value);
}
public String getMencoderOverscanCompensationWidth() {
return getString(KEY_MENCODER_OVERSCAN_COMPENSATION_WIDTH, "0");
}
public void setMencoderOverscanCompensationWidth(String value) {
if (value.trim().length() == 0) {
value = "0";
}
configuration.setProperty(KEY_MENCODER_OVERSCAN_COMPENSATION_WIDTH, value);
}
public String getMencoderOverscanCompensationHeight() {
return getString(KEY_MENCODER_OVERSCAN_COMPENSATION_HEIGHT, "0");
}
public void setMencoderOverscanCompensationHeight(String value) {
if (value.trim().length() == 0) {
value = "0";
}
configuration.setProperty(KEY_MENCODER_OVERSCAN_COMPENSATION_HEIGHT, value);
}
public void setEnginesAsList(ArrayList<String> enginesAsList) {
configuration.setProperty(KEY_ENGINES, listToString(enginesAsList));
}
/**
* TODO look at the changes that were made to this in PMS and if they seem
* stable, merge them.
*/
public List<String> getEnginesAsList(SystemUtils registry) {
String defaultEngines = StringUtils.join(
new String[] {
"ffmpegvideo",
"mencoder",
"tsmuxer",
"ffmpegaudio",
"tsmuxeraudio",
"ffmpegwebvideo",
"vlcwebvideo", // (VLCWebVideo)
"vlcvideo", // (VideoLanVideoStreaming) TODO (legacy web video engine): remove
"mencoderwebvideo",
"vlcaudio", // (VideoLanAudioStreaming) TODO (legacy web audio engine): remove
"ffmpegdvrmsremux",
"dcraw"
},
","
);
List<String> engines = stringToList(
// Possibly blank: An empty string means: disable all engines
// http://www.ps3mediaserver.org/forum/viewtopic.php?f=6&t=15416
configurationReader.getPossiblyBlankConfigurationString(
KEY_ENGINES,
defaultEngines
)
);
engines = hackAvs(registry, engines);
// Backwards compatibility, can be removed when sufficient time has passed - 2017-01
int i = engines.indexOf("rawthumbs");
if (i >= 0) {
engines.set(i, "dcraw");
}
return engines;
}
private static String listToString(List<String> enginesAsList) {
return StringUtils.join(enginesAsList, LIST_SEPARATOR);
}
private static List<String> stringToList(String input) {
List<String> output = new ArrayList<>();
Collections.addAll(output, StringUtils.split(input, LIST_SEPARATOR));
return output;
}
// TODO: Get this out of here
private static List<String> hackAvs(SystemUtils registry, List<String> input) {
List<String> toBeRemoved = new ArrayList<>();
for (String engineId : input) {
if (engineId.startsWith("avs") && !registry.isAvis() && Platform.isWindows()) {
if (!avsHackLogged) {
LOGGER.info("AviSynth is not installed. You cannot use " + engineId + " as a transcoding engine.");
avsHackLogged = true;
}
toBeRemoved.add(engineId);
}
}
List<String> output = new ArrayList<>();
output.addAll(input);
output.removeAll(toBeRemoved);
return output;
}
public void save() throws ConfigurationException {
((PropertiesConfiguration)configuration).save();
LOGGER.info("Configuration saved to: " + PROFILE_PATH);
}
public String getFolders(ArrayList<String> tags) {
return tagLoop(tags, ".folders", KEY_FOLDERS);
}
public String getFoldersIgnored(ArrayList<String> tags) {
return tagLoop(tags, ".ignore", KEY_FOLDERS_IGNORED);
}
public void setFolders(String value) {
configuration.setProperty(KEY_FOLDERS, value);
}
public String getFoldersMonitored() {
return getString(KEY_FOLDERS_MONITORED, "");
}
public void setFoldersMonitored(String value) {
configuration.setProperty(KEY_FOLDERS_MONITORED, value);
}
public String getNetworkInterface() {
return getString(KEY_NETWORK_INTERFACE, "");
}
public void setNetworkInterface(String value) {
configuration.setProperty(KEY_NETWORK_INTERFACE, value);
}
public boolean isHideEngineNames() {
return getBoolean(KEY_HIDE_ENGINENAMES, true);
}
public void setHideEngineNames(boolean value) {
configuration.setProperty(KEY_HIDE_ENGINENAMES, value);
}
public boolean isHideExtensions() {
return getBoolean(KEY_HIDE_EXTENSIONS, true);
}
public void setHideExtensions(boolean value) {
configuration.setProperty(KEY_HIDE_EXTENSIONS, value);
}
public String getShares() {
return getString(KEY_SHARES, "");
}
public void setShares(String value) {
configuration.setProperty(KEY_SHARES, value);
}
public String getDisableTranscodeForExtensions() {
return getString(KEY_DISABLE_TRANSCODE_FOR_EXTENSIONS, "");
}
public void setDisableTranscodeForExtensions(String value) {
configuration.setProperty(KEY_DISABLE_TRANSCODE_FOR_EXTENSIONS, value);
}
public boolean isDisableTranscoding() {
return getBoolean(KEY_DISABLE_TRANSCODING, false);
}
public String getForceTranscodeForExtensions() {
return getString(KEY_FORCE_TRANSCODE_FOR_EXTENSIONS, "");
}
public void setForceTranscodeForExtensions(String value) {
configuration.setProperty(KEY_FORCE_TRANSCODE_FOR_EXTENSIONS, value);
}
public void setMencoderMT(boolean value) {
configuration.setProperty(KEY_MENCODER_MT, value);
}
public boolean getMencoderMT() {
boolean isMultiCore = getNumberOfCpuCores() > 1;
return getBoolean(KEY_MENCODER_MT, isMultiCore);
}
public void setAudioRemuxAC3(boolean value) {
configuration.setProperty(KEY_AUDIO_REMUX_AC3, value);
}
public boolean isAudioRemuxAC3() {
return getBoolean(KEY_AUDIO_REMUX_AC3, true);
}
public void setMencoderRemuxMPEG2(boolean value) {
configuration.setProperty(KEY_MENCODER_REMUX_MPEG2, value);
}
public boolean isMencoderRemuxMPEG2() {
return getBoolean(KEY_MENCODER_REMUX_MPEG2, true);
}
public void setDisableFakeSize(boolean value) {
configuration.setProperty(KEY_DISABLE_FAKESIZE, value);
}
public boolean isDisableFakeSize() {
return getBoolean(KEY_DISABLE_FAKESIZE, false);
}
/**
* Whether the style rules defined by styled subtitles (ASS/SSA) should
* be followed (true) or overridden by our style rules (false) when
* using MEncoder.
*
* @see #setUseEmbeddedSubtitlesStyle(boolean)
* @param value whether to use the embedded styles or ours
* @deprecated
*/
@Deprecated
public void setMencoderAssDefaultStyle(boolean value) {
configuration.setProperty(KEY_MENCODER_ASS_DEFAULTSTYLE, value);
}
/**
* Whether the style rules defined by styled subtitles (ASS/SSA) should
* be followed (true) or overridden by our style rules (false) when
* using MEncoder.
*
* @see #isUseEmbeddedSubtitlesStyle()
* @return whether to use the embedded styles or ours
* @deprecated
*/
@Deprecated
public boolean isMencoderAssDefaultStyle() {
return getBoolean(KEY_MENCODER_ASS_DEFAULTSTYLE, true);
}
/**
* Whether the style rules defined by styled subtitles (ASS/SSA) should
* be followed (true) or overridden by our style rules (false).
*
* @param value whether to use the embedded styles or ours
*/
public void setUseEmbeddedSubtitlesStyle(boolean value) {
configuration.setProperty(KEY_USE_EMBEDDED_SUBTITLES_STYLE, value);
}
/**
* Whether the style rules defined by styled subtitles (ASS/SSA) should
* be followed (true) or overridden by our style rules (false).
*
* @return whether to use the embedded styles or ours
*/
public boolean isUseEmbeddedSubtitlesStyle() {
return getBoolean(KEY_USE_EMBEDDED_SUBTITLES_STYLE, true);
}
public int getMEncoderOverscan() {
return getInt(KEY_OVERSCAN, 0);
}
public void setMEncoderOverscan(int value) {
configuration.setProperty(KEY_OVERSCAN, value);
}
/**
* Returns sort method to use for ordering lists of files. One of the
* following values is returned:
* <ul>
* <li>0: Locale-sensitive A-Z</li>
* <li>1: Sort by modified date, newest first</li>
* <li>2: Sort by modified date, oldest first</li>
* <li>3: Case-insensitive ASCIIbetical sort</li>
* <li>4: Locale-sensitive natural sort</li>
* <li>5: Random</li>
* </ul>
* Default value is 4.
* @return The sort method
*/
private int findPathSort(String[] paths, String path) throws NumberFormatException{
for (String path1 : paths) {
String[] kv = path1.split(",");
if (kv.length < 2) {
continue;
}
if (kv[0].equals(path)) {
return Integer.parseInt(kv[1]);
}
}
return -1;
}
public int getSortMethod(File path) {
int cnt = 0;
String raw = getString(KEY_SORT_PATHS, null);
if (StringUtils.isEmpty(raw)) {
return getInt(KEY_SORT_METHOD, UMSUtils.SORT_LOC_NAT);
}
if (Platform.isWindows()) {
// windows is crap
raw = raw.toLowerCase();
}
String[] paths = raw.split(" ");
while (path != null && (cnt++ < 100)) {
String key = path.getAbsolutePath();
if (Platform.isWindows()) {
key = key.toLowerCase();
}
try {
int ret = findPathSort(paths, key);
if (ret != -1) {
return ret;
}
} catch (NumberFormatException e) {
// just ignore
}
path = path.getParentFile();
}
return getInt(KEY_SORT_METHOD, UMSUtils.SORT_LOC_NAT);
}
/**
* Set the sort method to use for ordering lists of files. The following
* values are recognized:
* <ul>
* <li>0: Locale-sensitive A-Z</li>
* <li>1: Sort by modified date, newest first</li>
* <li>2: Sort by modified date, oldest first</li>
* <li>3: Case-insensitive ASCIIbetical sort</li>
* <li>4: Locale-sensitive natural sort</li>
* <li>5: Random</li>
* </ul>
* @param value The sort method to use
*/
public void setSortMethod(int value) {
configuration.setProperty(KEY_SORT_METHOD, value);
}
public CoverSupplier getAudioThumbnailMethod() {
return CoverSupplier.toCoverSupplier(getInt(KEY_AUDIO_THUMBNAILS_METHOD, 1));
}
public void setAudioThumbnailMethod(CoverSupplier value) {
configuration.setProperty(KEY_AUDIO_THUMBNAILS_METHOD, value.toInt());
}
public String getAlternateThumbFolder() {
return getString(KEY_ALTERNATE_THUMB_FOLDER, "");
}
public void setAlternateThumbFolder(String value) {
configuration.setProperty(KEY_ALTERNATE_THUMB_FOLDER, value);
}
public String getAlternateSubtitlesFolder() {
return getString(KEY_ALTERNATE_SUBTITLES_FOLDER, "");
}
public void setAlternateSubtitlesFolder(String value) {
configuration.setProperty(KEY_ALTERNATE_SUBTITLES_FOLDER, value);
}
public void setAudioEmbedDtsInPcm(boolean value) {
configuration.setProperty(KEY_AUDIO_EMBED_DTS_IN_PCM, value);
}
public boolean isAudioEmbedDtsInPcm() {
return getBoolean(KEY_AUDIO_EMBED_DTS_IN_PCM, false);
}
public void setEncodedAudioPassthrough(boolean value) {
configuration.setProperty(KEY_ENCODED_AUDIO_PASSTHROUGH, value);
}
public boolean isEncodedAudioPassthrough() {
return getBoolean(KEY_ENCODED_AUDIO_PASSTHROUGH, false);
}
public void setMencoderMuxWhenCompatible(boolean value) {
configuration.setProperty(KEY_MENCODER_MUX_COMPATIBLE, value);
}
public boolean isMencoderMuxWhenCompatible() {
return getBoolean(KEY_MENCODER_MUX_COMPATIBLE, false);
}
public void setMEncoderNormalizeVolume(boolean value) {
configuration.setProperty(KEY_MENCODER_NORMALIZE_VOLUME, value);
}
public boolean isMEncoderNormalizeVolume() {
return getBoolean(KEY_MENCODER_NORMALIZE_VOLUME, false);
}
public void setFFmpegMuxWithTsMuxerWhenCompatible(boolean value) {
configuration.setProperty(KEY_FFMPEG_MUX_TSMUXER_COMPATIBLE, value);
}
public boolean isFFmpegMuxWithTsMuxerWhenCompatible() {
return getBoolean(KEY_FFMPEG_MUX_TSMUXER_COMPATIBLE, false);
}
/**
* @see #setFFmpegDeferToMEncoderForEmbeddedSubtitles(boolean)
* @deprecated
*/
@Deprecated
public void setFFmpegDeferToMEncoderForSubtitles(boolean value) {
setFFmpegDeferToMEncoderForProblematicSubtitles(value);
}
/**
* @see #isFFmpegDeferToMEncoderForEmbeddedSubtitles()
* @deprecated
*/
@Deprecated
public boolean isFFmpegDeferToMEncoderForSubtitles() {
return isFFmpegDeferToMEncoderForProblematicSubtitles();
}
/**
* Whether FFmpegVideo should defer to MEncoderVideo when there are
* subtitles that need to be transcoded which FFmpeg will need to
* initially parse, which can cause timeouts.
*
* @param value
*/
public void setFFmpegDeferToMEncoderForProblematicSubtitles(boolean value) {
configuration.setProperty(KEY_FFMPEG_MENCODER_PROBLEMATIC_SUBTITLES, value);
}
/**
* Whether FFmpegVideo should defer to MEncoderVideo when there are
* subtitles that need to be transcoded which FFmpeg will need to
* initially parse, which can cause timeouts.
*
* @return
*/
public boolean isFFmpegDeferToMEncoderForProblematicSubtitles() {
return getBoolean(KEY_FFMPEG_MENCODER_PROBLEMATIC_SUBTITLES, true);
}
public void setFFmpegFontConfig(boolean value) {
configuration.setProperty(KEY_FFMPEG_FONTCONFIG, value);
}
public boolean isFFmpegFontConfig() {
return getBoolean(KEY_FFMPEG_FONTCONFIG, false);
}
public void setMuxAllAudioTracks(boolean value) {
configuration.setProperty(KEY_MUX_ALLAUDIOTRACKS, value);
}
public boolean isMuxAllAudioTracks() {
return getBoolean(KEY_MUX_ALLAUDIOTRACKS, false);
}
public void setUseMplayerForVideoThumbs(boolean value) {
configuration.setProperty(KEY_USE_MPLAYER_FOR_THUMBS, value);
}
public boolean isUseMplayerForVideoThumbs() {
return getBoolean(KEY_USE_MPLAYER_FOR_THUMBS, false);
}
public String getIpFilter() {
return getString(KEY_IP_FILTER, "");
}
public synchronized IpFilter getIpFiltering() {
filter.setRawFilter(getIpFilter());
return filter;
}
public void setIpFilter(String value) {
configuration.setProperty(KEY_IP_FILTER, value);
}
public void setPreventsSleep(boolean value) {
configuration.setProperty(KEY_PREVENTS_SLEEP, value);
}
public boolean isPreventsSleep() {
return getBoolean(KEY_PREVENTS_SLEEP, true);
}
public void setHTTPEngineV2(boolean value) {
configuration.setProperty(KEY_HTTP_ENGINE_V2, value);
}
public boolean isHTTPEngineV2() {
return getBoolean(KEY_HTTP_ENGINE_V2, true);
}
public boolean isShowIphotoLibrary() {
return getBoolean(KEY_SHOW_IPHOTO_LIBRARY, false);
}
public void setShowIphotoLibrary(boolean value) {
configuration.setProperty(KEY_SHOW_IPHOTO_LIBRARY, value);
}
public boolean isShowApertureLibrary() {
return getBoolean(KEY_SHOW_APERTURE_LIBRARY, false);
}
public void setShowApertureLibrary(boolean value) {
configuration.setProperty(KEY_SHOW_APERTURE_LIBRARY, value);
}
public boolean isShowItunesLibrary() {
return getBoolean(KEY_SHOW_ITUNES_LIBRARY, false);
}
public String getItunesLibraryPath() {
return getString(KEY_ITUNES_LIBRARY_PATH, "");
}
public void setShowItunesLibrary(boolean value) {
configuration.setProperty(KEY_SHOW_ITUNES_LIBRARY, value);
}
public boolean isHideAdvancedOptions() {
return getBoolean(PmsConfiguration.KEY_HIDE_ADVANCED_OPTIONS, true);
}
public void setHideAdvancedOptions(final boolean value) {
this.configuration.setProperty(PmsConfiguration.KEY_HIDE_ADVANCED_OPTIONS, value);
}
public boolean isHideEmptyFolders() {
return getBoolean(PmsConfiguration.KEY_HIDE_EMPTY_FOLDERS, false);
}
public void setHideEmptyFolders(final boolean value) {
this.configuration.setProperty(PmsConfiguration.KEY_HIDE_EMPTY_FOLDERS, value);
}
public boolean isHideMediaLibraryFolder() {
return getBoolean(PmsConfiguration.KEY_HIDE_MEDIA_LIBRARY_FOLDER, true);
}
public void setHideMediaLibraryFolder(final boolean value) {
this.configuration.setProperty(PmsConfiguration.KEY_HIDE_MEDIA_LIBRARY_FOLDER, value);
}
// TODO (breaking change): rename to e.g. isTranscodeFolderEnabled
// (and return true by default)
public boolean getHideTranscodeEnabled() {
return getBoolean(KEY_HIDE_TRANSCODE_FOLDER, false);
}
// TODO (breaking change): rename to e.g. setTranscodeFolderEnabled
// (and negate the value in the caller)
public void setHideTranscodeEnabled(boolean value) {
configuration.setProperty(KEY_HIDE_TRANSCODE_FOLDER, value);
}
public boolean isDvdIsoThumbnails() {
return getBoolean(KEY_DVDISO_THUMBNAILS, false);
}
public void setDvdIsoThumbnails(boolean value) {
configuration.setProperty(KEY_DVDISO_THUMBNAILS, value);
}
public Object getCustomProperty(String property) {
return configurationReader.getCustomProperty(property);
}
public void setCustomProperty(String property, Object value) {
configuration.setProperty(property, value);
}
public boolean isChapterSupport() {
return getBoolean(KEY_CHAPTER_SUPPORT, false);
}
public void setChapterSupport(boolean value) {
configuration.setProperty(KEY_CHAPTER_SUPPORT, value);
}
public int getChapterInterval() {
return getInt(KEY_CHAPTER_INTERVAL, 5);
}
public void setChapterInterval(int value) {
configuration.setProperty(KEY_CHAPTER_INTERVAL, value);
}
public SubtitleColor getSubsColor() {
String colorString = getString(KEY_SUBS_COLOR, null);
if (StringUtils.isNotBlank(colorString)) {
try {
return new SubtitleColor(colorString);
} catch (InvalidArgumentException e) {
LOGGER.error("Using default subtitle color: {}", e.getMessage());
LOGGER.trace("", e);
}
}
return new SubtitleColor(0xFF, 0xFF, 0xFF);
}
public void setSubsColor(Color color) {
setSubsColor(new SubtitleColor(color));
}
public void setSubsColor(SubtitleColor color) {
if (color.getAlpha() != 0xFF) {
configuration.setProperty(KEY_SUBS_COLOR, color.get0xRRGGBBAA());
} else {
configuration.setProperty(KEY_SUBS_COLOR, color.get0xRRGGBB());
}
}
public boolean isFix25FPSAvMismatch() {
return getBoolean(KEY_FIX_25FPS_AV_MISMATCH, false);
}
public void setFix25FPSAvMismatch(boolean value) {
configuration.setProperty(KEY_FIX_25FPS_AV_MISMATCH, value);
}
public int getVideoTranscodeStartDelay() {
return getInt(KEY_VIDEOTRANSCODE_START_DELAY, 6);
}
public void setVideoTranscodeStartDelay(int value) {
configuration.setProperty(KEY_VIDEOTRANSCODE_START_DELAY, value);
}
public boolean isAudioResample() {
return getBoolean(KEY_AUDIO_RESAMPLE, true);
}
public void setAudioResample(boolean value) {
configuration.setProperty(KEY_AUDIO_RESAMPLE, value);
}
public boolean isIgnoreTheWordAandThe() {
return getBoolean(KEY_IGNORE_THE_WORD_A_AND_THE, true);
}
public void setIgnoreTheWordAandThe(boolean value) {
configuration.setProperty(KEY_IGNORE_THE_WORD_A_AND_THE, value);
}
public boolean isPrettifyFilenames() {
return getBoolean(KEY_PRETTIFY_FILENAMES, false);
}
public void setPrettifyFilenames(boolean value) {
configuration.setProperty(KEY_PRETTIFY_FILENAMES, value);
}
public boolean isUseInfoFromIMDb() {
return getBoolean(KEY_USE_IMDB_INFO, false) && isPrettifyFilenames();
}
public void setUseInfoFromIMDb(boolean value) {
configuration.setProperty(KEY_USE_IMDB_INFO, value);
}
public boolean isRunWizard() {
return getBoolean(KEY_RUN_WIZARD, true);
}
public void setRunWizard(boolean value) {
configuration.setProperty(KEY_RUN_WIZARD, value);
}
public boolean isHideNewMediaFolder() {
return getBoolean(KEY_HIDE_NEW_MEDIA_FOLDER, false);
}
public void setHideNewMediaFolder(final boolean value) {
this.configuration.setProperty(KEY_HIDE_NEW_MEDIA_FOLDER, value);
}
public boolean isHideRecentlyPlayedFolder() {
return getBoolean(PmsConfiguration.KEY_HIDE_RECENTLY_PLAYED_FOLDER, false);
}
public void setHideRecentlyPlayedFolder(final boolean value) {
this.configuration.setProperty(PmsConfiguration.KEY_HIDE_RECENTLY_PLAYED_FOLDER, value);
}
/**
* Returns the name of the renderer to fall back on when header matching
* fails. PMS will recognize the configured renderer instead of "Unknown
* renderer". Default value is "", which means PMS will return the unknown
* renderer when no match can be made.
*
* @return The name of the renderer PMS should fall back on when header
* matching fails.
* @see #isRendererForceDefault()
*/
public String getRendererDefault() {
return getString(KEY_RENDERER_DEFAULT, "");
}
/**
* Sets the name of the renderer to fall back on when header matching
* fails. PMS will recognize the configured renderer instead of "Unknown
* renderer". Set to "" to make PMS return the unknown renderer when no
* match can be made.
*
* @param value The name of the renderer to fall back on. This has to be
* <code>""</code> or a case insensitive match with the name
* used in any render configuration file.
* @see #setRendererForceDefault(boolean)
*/
public void setRendererDefault(String value) {
configuration.setProperty(KEY_RENDERER_DEFAULT, value);
}
/**
* Returns true when PMS should not try to guess connecting renderers
* and instead force picking the defined fallback renderer. Default
* value is false, which means PMS will attempt to recognize connecting
* renderers by their headers.
*
* @return True when the fallback renderer should always be picked.
* @see #getRendererDefault()
*/
public boolean isRendererForceDefault() {
return getBoolean(KEY_RENDERER_FORCE_DEFAULT, false);
}
/**
* Set to true when PMS should not try to guess connecting renderers
* and instead force picking the defined fallback renderer. Set to false
* to make PMS attempt to recognize connecting renderers by their headers.
*
* @param value True when the fallback renderer should always be picked.
* @see #setRendererDefault(String)
*/
public void setRendererForceDefault(boolean value) {
configuration.setProperty(KEY_RENDERER_FORCE_DEFAULT, value);
}
public String getVirtualFolders(ArrayList<String> tags) {
return tagLoop(tags, ".vfolders", KEY_VIRTUAL_FOLDERS);
}
public String getVirtualFoldersFile(ArrayList<String> tags) {
return tagLoop(tags, ".vfolders.file", KEY_VIRTUAL_FOLDERS_FILE);
}
public String getProfilePath() {
return PROFILE_PATH;
}
public String getProfileDirectory() {
return PROFILE_DIRECTORY;
}
/**
* Returns the absolute path to the WEB.conf file. By default
* this is <pre>PROFILE_DIRECTORY + File.pathSeparator + WEB.conf</pre>,
* but it can be overridden via the <pre>web_conf</pre> profile option.
* The existence of the file is not checked.
*
* @return the path to the WEB.conf file.
*/
public String getWebConfPath() {
// Initialise this here rather than in the constructor
// or statically so that custom settings are logged
// to the logfile/Logs tab.
if (WEB_CONF_PATH == null) {
WEB_CONF_PATH = FileUtil.getFileLocation(
getString(KEY_WEB_CONF_PATH, null),
PROFILE_DIRECTORY,
DEFAULT_WEB_CONF_FILENAME
).getFilePath();
}
return getString(KEY_WEB_CONF_PATH, WEB_CONF_PATH);
}
public String getPluginDirectory() {
return getString(KEY_PLUGIN_DIRECTORY, "plugins");
}
public void setPluginDirectory(String value) {
configuration.setProperty(KEY_PLUGIN_DIRECTORY, value);
}
public String getProfileName() {
if (HOSTNAME == null) { // Initialise this lazily
try {
HOSTNAME = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
LOGGER.info("Can't determine hostname");
HOSTNAME = "unknown host";
}
}
return getString(KEY_PROFILE_NAME, HOSTNAME);
}
public boolean isAutoUpdate() {
return Build.isUpdatable() && getBoolean(KEY_AUTO_UPDATE, false);
}
public void setAutoUpdate(boolean value) {
configuration.setProperty(KEY_AUTO_UPDATE, value);
}
public int getUpnpPort() {
return getInt(KEY_UPNP_PORT, 1900);
}
public String getUuid() {
return getString(KEY_UUID, null);
}
public void setUuid(String value){
configuration.setProperty(KEY_UUID, value);
}
public void addConfigurationListener(ConfigurationListener l) {
((PropertiesConfiguration)configuration).addConfigurationListener(l);
}
public void removeConfigurationListener(ConfigurationListener l) {
((PropertiesConfiguration)configuration).removeConfigurationListener(l);
}
public boolean getFolderLimit() {
return getBoolean(KEY_FOLDER_LIMIT, false);
}
public String getScriptDir() {
return getString(KEY_SCRIPT_DIR, null);
}
public String getPluginPurgeAction() {
return getString(KEY_PLUGIN_PURGE_ACTION, "delete");
}
public boolean getSearchFolder() {
return getBoolean(KEY_SEARCH_FOLDER, false);
}
public boolean getSearchInFolder() {
return getBoolean(KEY_SEARCH_IN_FOLDER, false) && getSearchFolder();
}
public int getSearchDepth() {
int ret = (getBoolean(KEY_SEARCH_RECURSE, true) ? 100 : 2);
return getInt(KEY_SEARCH_RECURSE_DEPTH, ret);
}
public void reload() {
try {
((PropertiesConfiguration)configuration).refresh();
} catch (ConfigurationException e) {
LOGGER.error(null, e);
}
}
/**
* Retrieve the name of the folder used to select subtitles, audio channels, chapters, engines &c.
* Defaults to the localized version of <pre>#--TRANSCODE--#</pre>.
* @return The folder name.
*/
public String getTranscodeFolderName() {
return getString(KEY_TRANSCODE_FOLDER_NAME, Messages.getString("TranscodeVirtualFolder.0"));
}
/**
* Set a custom name for the <pre>#--TRANSCODE--#</pre> folder.
* @param name The folder name.
*/
public void setTranscodeFolderName(String name) {
configuration.setProperty(KEY_TRANSCODE_FOLDER_NAME, name);
}
/**
* State if the video hardware acceleration is allowed
* @return true if hardware acceleration is allowed, false otherwise
*/
public boolean isGPUAcceleration() {
return getBoolean(KEY_GPU_ACCELERATION, false);
}
/**
* Set the video hardware acceleration enable/disable
* @param value true if hardware acceleration is allowed, false otherwise
*/
public void setGPUAcceleration(boolean value) {
configuration.setProperty(KEY_GPU_ACCELERATION, value);
}
/**
* Get the state of the GUI log tab "Case sensitive" check box
* @return true if enabled, false if disabled
*/
public boolean getGUILogSearchCaseSensitive() {
return getBoolean(KEY_GUI_LOG_SEARCH_CASE_SENSITIVE, false);
}
/**
* Set the state of the GUI log tab "Case sensitive" check box
* @param value true if enabled, false if disabled
*/
public void setGUILogSearchCaseSensitive(boolean value) {
configuration.setProperty(KEY_GUI_LOG_SEARCH_CASE_SENSITIVE, value);
}
/**
* Get the state of the GUI log tab "Multiline" check box
* @return true if enabled, false if disabled
*/
public boolean getGUILogSearchMultiLine() {
return getBoolean(KEY_GUI_LOG_SEARCH_MULTILINE, false);
}
/**
* Set the state of the GUI log tab "Multiline" check box
* @param value true if enabled, false if disabled
*/
public void setGUILogSearchMultiLine(boolean value) {
configuration.setProperty(KEY_GUI_LOG_SEARCH_MULTILINE, value);
}
/**
* Get the state of the GUI log tab "RegEx" check box
* @return true if enabled, false if disabled
*/
public boolean getGUILogSearchRegEx() {
return getBoolean(KEY_GUI_LOG_SEARCH_USE_REGEX, false);
}
/**
* Set the state of the GUI log tab "RegEx" check box
* @param value true if enabled, false if disabled
*/
public void setGUILogSearchRegEx(boolean value) {
configuration.setProperty(KEY_GUI_LOG_SEARCH_USE_REGEX, value);
}
/* Start without external netowrk (increase startup speed) */
public static final String KEY_EXTERNAL_NETWORK = "external_network";
public boolean getExternalNetwork() {
return getBoolean(KEY_EXTERNAL_NETWORK, true);
}
public void setExternalNetwork(boolean b) {
configuration.setProperty(KEY_EXTERNAL_NETWORK, b);
}
/* Credential path handling */
public static final String KEY_CRED_PATH = "cred.path";
public void initCred() throws IOException {
File credFile = getCredFile();
if (!credFile.exists()) {
// Create an empty file and save the path if needed
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(credFile), StandardCharsets.UTF_8))) {
writer.write("# Add credentials to the file");
writer.newLine();
writer.write("# on the format tag=user,password");
writer.newLine();
writer.write("# For example:");
writer.newLine();
writer.write("# channels.xxx=name,secret");
writer.newLine();
}
// Save the path if we got here
configuration.setProperty(KEY_CRED_PATH, credFile.getAbsolutePath());
try {
((PropertiesConfiguration)configuration).save();
} catch (ConfigurationException e) {
LOGGER.warn("An error occurred while saving configuration: {}", e.getMessage());
}
}
}
/**
* @deprecated Use {@link #getCredFile()} instead.
*/
public String getCredPath() {
return getCredFile().getAbsolutePath();
}
public File getCredFile() {
String path = getString(KEY_CRED_PATH, "");
if (path != null && !path.trim().isEmpty()) {
return new File(path);
}
return new File(getProfileDirectory(), DEFAULT_CREDENTIALS_FILENAME);
}
public int getATZLimit() {
int tmp = getInt(KEY_ATZ_LIMIT, 10000);
if (tmp <= 2) {
// this is silly, ignore
tmp = 10000;
}
return tmp;
}
public void setATZLimit(int val) {
if (val <= 2) {
// clear prop
configuration.clearProperty(KEY_ATZ_LIMIT);
return;
}
configuration.setProperty(KEY_ATZ_LIMIT, val);
}
public void setATZLimit(String str) {
try {
setATZLimit(Integer.parseInt(str));
} catch (Exception e) {
setATZLimit(0);
}
}
public String getDataDir() {
return getProfileDirectory() + File.separator + "data";
}
public String getDataFile(String str) {
return getDataDir() + File.separator + str;
}
private String KEY_URL_RES_ORDER = "url_resolve_order";
public String[] getURLResolveOrder() {
return getString(KEY_URL_RES_ORDER, "").split(",");
}
public boolean isHideLiveSubtitlesFolder() {
return getBoolean(KEY_HIDE_LIVE_SUBTITLES_FOLDER, true);
}
public void setHideLiveSubtitlesFolder(boolean value) {
configuration.setProperty(KEY_HIDE_LIVE_SUBTITLES_FOLDER, value);
}
public int liveSubtitlesLimit() {
return getInt(KEY_LIVE_SUBTITLES_LIMIT, 20);
}
public boolean isLiveSubtitlesKeep() {
return getBoolean(KEY_LIVE_SUBTITLES_KEEP, false);
}
public int getLiveSubtitlesTimeout() {
return getInt(KEY_LIVE_SUBTITLES_TMO, 0) * 24 * 3600 * 1000;
}
public void setLiveSubtitlesTimeout(int t) {
configuration.setProperty(KEY_LIVE_SUBTITLES_TMO, t);
}
public boolean getLoggingBuffered() {
return getBoolean(KEY_LOGGING_BUFFERED, false);
}
public void setLoggingBuffered(boolean value) {
configuration.setProperty(KEY_LOGGING_BUFFERED, value);
}
public Level getLoggingFilterConsole() {
return Level.toLevel(getString(KEY_LOGGING_FILTER_CONSOLE, "INFO"),Level.INFO);
}
public void setLoggingFilterConsole(Level value) {
configuration.setProperty(KEY_LOGGING_FILTER_CONSOLE, value.levelStr);
}
public Level getLoggingFilterLogsTab() {
return Level.toLevel(getString(KEY_LOGGING_FILTER_LOGS_TAB, "INFO"),Level.INFO);
}
public void setLoggingFilterLogsTab(Level value) {
configuration.setProperty(KEY_LOGGING_FILTER_LOGS_TAB, value.levelStr);
}
public int getLoggingLogsTabLinebuffer() {
return Math.min(Math.max(getInt(KEY_LOGGING_LOGS_TAB_LINEBUFFER, 1000), LOGGING_LOGS_TAB_LINEBUFFER_MIN),LOGGING_LOGS_TAB_LINEBUFFER_MAX);
}
public void setLoggingLogsTabLinebuffer(int value) {
value = Math.min(Math.max(value, LOGGING_LOGS_TAB_LINEBUFFER_MIN),LOGGING_LOGS_TAB_LINEBUFFER_MAX);
configuration.setProperty(KEY_LOGGING_LOGS_TAB_LINEBUFFER, value);
}
public String getLoggingSyslogFacility() {
return getString(KEY_LOGGING_SYSLOG_FACILITY, "USER");
}
public void setLoggingSyslogFacility(String value) {
configuration.setProperty(KEY_LOGGING_SYSLOG_FACILITY, value);
}
public void setLoggingSyslogFacilityDefault() {
setLoggingSyslogFacility("USER");
}
public String getLoggingSyslogHost() {
return getString(KEY_LOGGING_SYSLOG_HOST, "");
}
public void setLoggingSyslogHost(String value) {
configuration.setProperty(KEY_LOGGING_SYSLOG_HOST, value);
}
public int getLoggingSyslogPort() {
int i = getInt(KEY_LOGGING_SYSLOG_PORT, 514);
if (i < 1 || i > 65535) {
return 514;
} else {
return i;
}
}
public void setLoggingSyslogPort(int value) {
if (value < 1 || value > 65535) {
setLoggingSyslogPortDefault();
} else {
configuration.setProperty(KEY_LOGGING_SYSLOG_PORT, value);
}
}
public void setLoggingSyslogPortDefault() {
setLoggingSyslogPort(514);
}
public boolean getLoggingUseSyslog() {
return getBoolean(KEY_LOGGING_USE_SYSLOG, false);
}
public void setLoggingUseSyslog(boolean value) {
configuration.setProperty(KEY_LOGGING_USE_SYSLOG, value);
}
public boolean isVlcUseHardwareAccel() {
return getBoolean(KEY_VLC_USE_HW_ACCELERATION, false);
}
public void setVlcUseHardwareAccel(boolean value) {
configuration.setProperty(KEY_VLC_USE_HW_ACCELERATION, value);
}
public boolean isVlcExperimentalCodecs() {
return getBoolean(KEY_VLC_USE_EXPERIMENTAL_CODECS, false);
}
public void setVlcExperimentalCodecs(boolean value) {
configuration.setProperty(KEY_VLC_USE_EXPERIMENTAL_CODECS, value);
}
public boolean isVlcAudioSyncEnabled() {
return getBoolean(KEY_VLC_AUDIO_SYNC_ENABLED, false);
}
public void setVlcAudioSyncEnabled(boolean value) {
configuration.setProperty(KEY_VLC_AUDIO_SYNC_ENABLED, value);
}
public boolean isVlcSubtitleEnabled() {
return getBoolean(KEY_VLC_SUBTITLE_ENABLED, true);
}
public void setVlcSubtitleEnabled(boolean value) {
configuration.setProperty(KEY_VLC_SUBTITLE_ENABLED, value);
}
public String getVlcScale() {
return getString(KEY_VLC_SCALE, "1.0");
}
public void setVlcScale(String value) {
configuration.setProperty(KEY_VLC_SCALE, value);
}
public boolean getVlcSampleRateOverride() {
return getBoolean(KEY_VLC_SAMPLE_RATE_OVERRIDE, false);
}
public void setVlcSampleRateOverride(boolean value) {
configuration.setProperty(KEY_VLC_SAMPLE_RATE_OVERRIDE, value);
}
public String getVlcSampleRate() {
return getString(KEY_VLC_SAMPLE_RATE, "48000");
}
public void setVlcSampleRate(String value) {
configuration.setProperty(KEY_VLC_SAMPLE_RATE, value);
}
public boolean isResumeEnabled() {
return getBoolean(KEY_RESUME, true);
}
public void setResume(boolean value) {
configuration.setProperty(KEY_RESUME, value);
}
@Deprecated
public int getMinPlayTime() {
return getMinimumWatchedPlayTime();
}
public int getMinimumWatchedPlayTime() {
return getInt(KEY_MIN_PLAY_TIME, 30000);
}
public int getMinimumWatchedPlayTimeSeconds() {
return getMinimumWatchedPlayTime() / 1000;
}
public int getMinPlayTimeWeb() {
return getInt(KEY_MIN_PLAY_TIME_WEB, getMinimumWatchedPlayTime());
}
public int getMinPlayTimeFile() {
return getInt(KEY_MIN_PLAY_TIME_FILE, getMinimumWatchedPlayTime());
}
public int getResumeRewind() {
return getInt(KEY_RESUME_REWIND, 17000);
}
public double getResumeBackFactor() {
int percent = getInt(KEY_RESUME_BACK, 92);
if (percent > 97) {
percent = 97;
}
if (percent < 10) {
percent = 10;
}
return (percent / 100.0);
}
public int getResumeKeepTime() {
return getInt(KEY_RESUME_KEEP_TIME, 0);
}
public boolean hideSubsInfo() {
return getBoolean(KEY_HIDE_SUBS_INFO, false);
}
public String getPlugins(ArrayList<String> tags) {
return tagLoop(tags, ".plugins", "dummy");
}
public boolean isHideWebFolder(ArrayList<String> tags) {
return tagLoopBool(tags, ".web", "dummy", false);
}
private String tagLoop(ArrayList<String> tags, String suff, String fallback) {
if (tags == null || tags.isEmpty()) {
// no tags use fallback
return getString(fallback, "");
}
for (String tag : tags) {
String x = (tag.toLowerCase() + suff).replaceAll(" ", "_");
String res = getString(x, "");
if (StringUtils.isNotBlank(res)) {
// use first tag found
return res;
}
}
// down here no matching tag was found
// return fallback
return getString(fallback, "");
}
private boolean tagLoopBool(ArrayList<String> tags, String suff, String fallback, boolean def) {
String b = tagLoop(tags, suff, fallback);
if (StringUtils.isBlank(b)) {
return def;
}
return b.trim().equalsIgnoreCase("true");
}
/**
* Whether the profile name should be appended to the server name when
* displayed on the renderer
*
* @return True if the profile name should be appended.
*/
public boolean isAppendProfileName() {
return getBoolean(KEY_APPEND_PROFILE_NAME, false);
}
/**
* Set whether the profile name should be appended to the server name
* when displayed on the renderer
*
* @param value Set to true if the profile name should be appended.
*/
public void setAppendProfileName(boolean value) {
configuration.setProperty(KEY_APPEND_PROFILE_NAME, value);
}
public int getDepth3D() {
return getInt(KEY_3D_SUBTITLES_DEPTH, 0);
}
public void setDepth3D(int value) {
configuration.setProperty(KEY_3D_SUBTITLES_DEPTH, value);
}
/**
* @deprecated
* @see #setRunSingleInstance(boolean)
*/
@Deprecated
public void setSingle(boolean value) {
setRunSingleInstance(value);
}
/**
* Set whether UMS should allow only one instance by shutting down
* the first one when a second one is launched.
*
* @param value whether to kill the old UMS instance
*/
public void setRunSingleInstance(boolean value) {
configuration.setProperty(KEY_SINGLE, value);
}
/**
* @deprecated
* @see #isRunSingleInstance()
*/
@Deprecated
public boolean getSingle() {
return isRunSingleInstance();
}
/**
* Whether UMS should allow only one instance by shutting down
* the first one when a second one is launched.
*
* @return value whether to kill the old UMS instance
*/
public boolean isRunSingleInstance() {
return getBoolean(KEY_SINGLE, true);
}
/**
* Web stuff
*/
protected static final String KEY_NO_FOLDERS = "no_shared";
protected static final String KEY_WEB_HTTPS = "use_https";
protected static final String KEY_WEB_PORT = "web_port";
protected static final int WEB_MAX_THREADS = 100;
public boolean getNoFolders(String tag) {
if (tag == null) {
return getBoolean(KEY_NO_FOLDERS, false);
}
String x = (tag.toLowerCase() + ".no_shared").replaceAll(" ", "_");
return getBoolean(x, false);
}
public boolean getWebHttps() {
return getBoolean(KEY_WEB_HTTPS, false);
}
public File getWebPath() {
File path = new File(getString(KEY_WEB_PATH, "web"));
if (!path.exists()) {
path.mkdirs();
}
return path;
}
public File getWebFile(String file) {
return new File(getWebPath().getAbsolutePath() + File.separator + file);
}
public boolean isWebAuthenticate() {
return getBoolean(KEY_WEB_AUTHENTICATE, false);
}
public int getWebThreads() {
int x = getInt(KEY_WEB_THREADS, 30);
return (x > WEB_MAX_THREADS ? WEB_MAX_THREADS : x);
}
public boolean isWebMp4Trans() {
return getBoolean(KEY_WEB_MP4_TRANS, false);
}
public String getBumpAddress() {
return getString(KEY_BUMP_ADDRESS, "");
}
public void setBumpAddress(String value) {
configuration.setProperty(KEY_BUMP_ADDRESS, value);
}
public String getBumpJS(String fallback) {
return getString(KEY_BUMP_JS, fallback);
}
public String getBumpSkinDir(String fallback) {
return getString(KEY_BUMP_SKIN_DIR, fallback);
}
/**
* Default port for the WEB interface.
*/
public int getWebPort() {
return getInt(KEY_WEB_PORT, 9001);
}
public boolean useWebInterface() {
return getBoolean(KEY_WEB_ENABLE, true);
}
public boolean isAutomaticMaximumBitrate() {
return getBoolean(KEY_AUTOMATIC_MAXIMUM_BITRATE, false);
}
public void setAutomaticMaximumBitrate(boolean b) {
if (!isAutomaticMaximumBitrate() && b) {
// get all bitrates from renderers
RendererConfiguration.calculateAllSpeeds();
}
configuration.setProperty(KEY_AUTOMATIC_MAXIMUM_BITRATE, b);
}
public String pingPath() {
return getString(KEY_PING_PATH, null);
}
public boolean isSpeedDbg() {
return getBoolean(KEY_SPEED_DBG, false);
}
public boolean getAutoDiscover() {
return getBoolean(KEY_AUTOMATIC_DISCOVER, false);
}
public int mediaLibrarySort() {
return getInt(KEY_MEDIA_LIB_SORT, UMSUtils.SORT_NO_SORT);
}
public boolean getWebAutoCont(Format f) {
String key = KEY_WEB_CONT_VIDEO;
boolean def = false;
if (f.isAudio()) {
key = KEY_WEB_CONT_AUDIO;
def = true;
}
if (f.isImage()) {
key = KEY_WEB_CONT_IMAGE;
def = false;
}
return getBoolean(key, def);
}
public boolean getWebAutoLoop(Format f) {
String key = KEY_WEB_LOOP_VIDEO;
if (f.isAudio()) {
key = KEY_WEB_LOOP_AUDIO;
}
if (f.isImage()) {
key = KEY_WEB_LOOP_IMAGE;
}
return getBoolean(key, false);
}
public int getWebImgSlideDelay() {
return getInt(KEY_WEB_IMAGE_SLIDE, 0);
}
public String getWebSize() {
return getString(KEY_WEB_SIZE, "");
}
public int getWebHeight() {
return getInt(KEY_WEB_HEIGHT, 0);
}
public int getWebWidth() {
return getInt(KEY_WEB_WIDTH, 0);
}
public boolean getWebFlash() {
return getBoolean(KEY_WEB_FLASH, false);
}
public boolean getWebChrome() {
return getBoolean(KEY_WEB_CHROME_TRICK, false);
}
public boolean getWebFirefoxLinuxMp4() {
return getBoolean(KEY_WEB_FIREFOX_LINUX_MP4, false);
}
public boolean getWebSubs() {
return getBoolean(KEY_WEB_SUBS_TRANS, false);
}
public String getBumpAllowedIps() {
return getString(KEY_BUMP_IPS, "");
}
public String getWebTranscode() {
return getString(KEY_WEB_TRANSCODE, null);
}
public int getWebLowSpeed() {
return getInt(KEY_WEB_LOW_SPEED, 0);
}
public boolean useWebLang() {
return getBoolean(KEY_WEB_BROWSE_LANG, false);
}
public boolean useWebSubLang() {
return getBoolean(KEY_WEB_BROWSE_SUB_LANG, false);
}
public boolean useWebControl() {
return getBoolean(KEY_WEB_CONTROL, true);
}
public boolean useCode() {
return getBoolean(KEY_CODE_USE, true);
}
public int getCodeValidTmo() {
return (getInt(KEY_CODE_TMO, 4 * 60) * 60 * 1000);
}
public boolean isShowCodeThumbs() {
return getBoolean(KEY_CODE_THUMBS, true);
}
public int getCodeCharSet() {
int cs = getInt(KEY_CODE_CHARS, CodeEnter.DIGITS);
if (cs < CodeEnter.DIGITS || cs > CodeEnter.BOTH) {
// ensure we go a legal value
cs = CodeEnter.DIGITS;
}
return cs;
}
public boolean isDynamicPls() {
return getBoolean(KEY_DYNAMIC_PLS, false);
}
public boolean isDynamicPlsAutoSave() {
return getBoolean(KEY_DYNAMIC_PLS_AUTO_SAVE, false);
}
public String getDynamicPlsSavePath() {
String path = getString(KEY_DYNAMIC_PLS_SAVE_PATH, "");
if (StringUtils.isEmpty(path)) {
path = getDataFile("dynpls");
// ensure that this path exists
new File(path).mkdirs();
}
return path;
}
public String getDynamicPlsSaveFile(String str) {
return getDynamicPlsSavePath() + File.separator + str;
}
public boolean isHideSavedPlaylistFolder() {
return getBoolean(KEY_DYNAMIC_PLS_HIDE, false);
}
public boolean isAutoContinue() {
return getBoolean(KEY_PLAYLIST_AUTO_CONT, false);
}
public boolean isAutoAddAll() {
return getBoolean(KEY_PLAYLIST_AUTO_ADD_ALL, false);
}
public String getAutoPlay() {
return getString(KEY_PLAYLIST_AUTO_PLAY, null);
}
public boolean useChromecastExt() {
return getBoolean(KEY_CHROMECAST_EXT, true);
}
public boolean isChromecastDbg() {
return getBoolean(KEY_CHROMECAST_DBG, false);
}
public Color getToolTipForegroundColor() {
return getColor(KEY_TOOLTIP_FOREGROUND_COLOR, "255,255,255");
}
public Color getToolTipBackgroundColor() {
return getColor(KEY_TOOLTIP_BACKGROUND_COLOR, "125,184,47");
}
/**
* Enable the automatically saving of modified properties to the disk.
*/
public void setAutoSave() {
((PropertiesConfiguration) configuration).setAutoSave(true);
}
public boolean isUpnpEnabled() {
return getBoolean(KEY_UPNP_ENABLED, true);
}
public String getRootLogLevel() {
String level = getString(KEY_ROOT_LOG_LEVEL, "DEBUG").toUpperCase();
return "ALL TRACE DEBUG INFO WARN ERROR OFF".contains(level) ? level : "DEBUG";
}
public void setRootLogLevel(ch.qos.logback.classic.Level level) {
configuration.setProperty(KEY_ROOT_LOG_LEVEL, level.toString());
}
public void setWindowGeometry(String value) {
configuration.setProperty(KEY_WINDOW_GEOMETRY, value);
}
public String getWindowGeometry() {
return getString(KEY_WINDOW_GEOMETRY, "x=-1,y=-1,width=1000,height=750");
}
public void setScreenSize(String value) {
configuration.setProperty(KEY_SCREEN_SIZE, value);
}
public String getScreenSize() {
return getString(KEY_SCREEN_SIZE, "-1x-1");
}
public void setWindowExtendedState(int value) {
configuration.setProperty(KEY_WINDOW_EXTENDED_STATE, value);
}
public int getWindowExtendedState() {
return getInt(KEY_WINDOW_EXTENDED_STATE, Frame.NORMAL);
}
public boolean isShowSplashScreen() {
return getBoolean(KEY_SHOW_SPLASH_SCREEN, false);
}
public void setShowSplashScreen(boolean value) {
configuration.setProperty(KEY_SHOW_SPLASH_SCREEN, value);
}
public boolean isInfoDbRetry() {
return getBoolean(KEY_INFO_DB_RETRY, false);
}
public int getAliveDelay() {
return getInt(KEY_ALIVE_DELAY, 0);
}
}