From 36a02ff45749052886b79516c84e8fc6ac212189 Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Mon, 28 Mar 2016 01:32:12 +0000 Subject: [PATCH] New binding: {plex} => built-in Plex format defaults for Episode/Movie/Music objects --- .../net/filebot/format/MediaBindingBean.java | 12 +++ source/net/filebot/media/NamingStandard.java | 93 +++++++++++++++++++ .../net/filebot/similarity/Normalization.java | 5 + .../ui/rename/BindingDialog.properties | 2 +- .../net/filebot/ui/rename/FormatDialog.java | 2 +- .../filebot/ui/rename/FormatDialog.properties | 6 ++ website/naming.html | 5 + 7 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 source/net/filebot/media/NamingStandard.java diff --git a/source/net/filebot/format/MediaBindingBean.java b/source/net/filebot/format/MediaBindingBean.java index 8dc05876..332b4277 100644 --- a/source/net/filebot/format/MediaBindingBean.java +++ b/source/net/filebot/format/MediaBindingBean.java @@ -45,6 +45,7 @@ import net.filebot.Settings; import net.filebot.Settings.ApplicationFolder; import net.filebot.WebServices; import net.filebot.hash.HashType; +import net.filebot.media.NamingStandard; import net.filebot.mediainfo.MediaInfo; import net.filebot.mediainfo.MediaInfo.StreamKind; import net.filebot.mediainfo.MediaInfoException; @@ -914,6 +915,17 @@ public class MediaBindingBean { return 1 + identityIndexOf(duplicates, getInfoObject()); } + @Define("plex") + public File getPlexStandardPath() throws Exception { + String path = NamingStandard.Plex.getPath(infoObject); + try { + path = path.concat(getSubtitleTags()); + } catch (Exception e) { + // ignore => no language tags + } + return new File(path); + } + @Define("self") public AssociativeScriptObject getSelf() { return createBindingObject(mediaFile, infoObject, context); diff --git a/source/net/filebot/media/NamingStandard.java b/source/net/filebot/media/NamingStandard.java new file mode 100644 index 00000000..f7f9a388 --- /dev/null +++ b/source/net/filebot/media/NamingStandard.java @@ -0,0 +1,93 @@ +package net.filebot.media; + +import static java.util.Arrays.*; +import static java.util.stream.Collectors.*; +import static net.filebot.WebServices.*; +import static net.filebot.similarity.Normalization.*; +import static net.filebot.util.FileUtilities.*; +import static net.filebot.web.EpisodeFormat.*; + +import java.util.Objects; + +import net.filebot.web.AudioTrack; +import net.filebot.web.Episode; +import net.filebot.web.EpisodeFormat; +import net.filebot.web.Movie; +import net.filebot.web.MoviePart; +import net.filebot.web.MultiEpisode; + +public enum NamingStandard { + + Plex; + + public String getPath(Object o) { + if (o instanceof Episode) + return getPath((Episode) o); + if (o instanceof Movie) + return getPath((Movie) o); + if (o instanceof AudioTrack) + return getPath((AudioTrack) o); + + return null; + } + + public String getPath(Episode e) { + // enforce title length limit by default + String episodeTitle = truncateText(e instanceof MultiEpisode ? SeasonEpisode.formatMultiTitle(((MultiEpisode) e).getEpisodes()) : e.getTitle(), 150); + + // Anime + if (isAnime(e)) { + String primaryTitle = e.getSeriesInfo().getName(); + String episode = String.join(" - ", primaryTitle, EpisodeFormat.SeasonEpisode.formatSxE(e), episodeTitle); + return path("Anime", primaryTitle, episode); + } + + // TV Series + String episode = String.join(" - ", e.getSeriesName(), EpisodeFormat.SeasonEpisode.formatS00E00(e), episodeTitle); + String season = e.getSeason() == null ? null : e.getSpecial() == null ? String.format("Season %02d", e.getSeason()) : "Special"; + return path("TV Shows", e.getSeriesName(), season, episode); + } + + public String getPath(Movie m) { + // Movie + String name = m.getNameWithYear(); + + // Movie (multi-part) + if (m instanceof MoviePart) { + name = String.format("%s CD%d", name, ((MoviePart) m).getPartIndex()); + } + + return path("Movies", m.getNameWithYear(), name); + } + + public String getPath(AudioTrack a) { + // Music + String name = String.join(" - ", a.getArtist(), first(a.getTrackTitle(), a.getTitle())); + + // prepend track number + if (a.getTrack() != null) { + name = String.format("%02d. %s", a.getTrack(), name); + } + + return path("Music", first(a.getAlbumArtist(), a.getArtist()), a.getAlbum(), name); + } + + private static String path(String... name) { + return stream(name).filter(Objects::nonNull).map(s -> { + s = replacePathSeparators(s, " "); + s = replaceSpace(s, " "); + s = normalizeQuotationMarks(s); + s = trimTrailingPunctuation(s); + return s; + }).collect(joining("/")); + } + + private static String first(String... options) { + return stream(options).filter(Objects::nonNull).findFirst().get(); + } + + private static boolean isAnime(Episode e) { + return AniDB.getIdentifier().equals(e.getSeriesInfo().getDatabase()); + } + +} diff --git a/source/net/filebot/similarity/Normalization.java b/source/net/filebot/similarity/Normalization.java index ed92f9bb..e3699c69 100644 --- a/source/net/filebot/similarity/Normalization.java +++ b/source/net/filebot/similarity/Normalization.java @@ -14,6 +14,7 @@ public class Normalization { private static final Pattern[] brackets = new Pattern[] { compile("\\([^\\(]*\\)"), compile("\\[[^\\[]*\\]"), compile("\\{[^\\{]*\\}") }; private static final Pattern trailingParentheses = compile("(?season / episode numbers S01E01 + + plex + Plex Naming Standard + <path> + imdbid imdb id