moved resolvers to implementations, trimmed nuget package a bit

This commit is contained in:
LukePulverenti
2013-03-03 01:58:04 -05:00
parent 627b8370a8
commit ac3a94f5a1
35 changed files with 543 additions and 518 deletions

View File

@@ -1,39 +0,0 @@
using MediaBrowser.Controller.Library;
namespace MediaBrowser.Controller.Resolvers.Audio
{
/// <summary>
/// Class AudioResolver
/// </summary>
public class AudioResolver : BaseItemResolver<Entities.Audio.Audio>
{
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override ResolverPriority Priority
{
get { return ResolverPriority.Last; }
}
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>Entities.Audio.Audio.</returns>
protected override Entities.Audio.Audio Resolve(ItemResolveArgs args)
{
// Return audio if the path is a file and has a matching extension
if (!args.IsDirectory)
{
if (EntityResolutionHelper.IsAudioFile(args))
{
return new Entities.Audio.Audio();
}
}
return null;
}
}
}

View File

@@ -1,37 +0,0 @@
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
namespace MediaBrowser.Controller.Resolvers.Audio
{
/// <summary>
/// Class MusicAlbumResolver
/// </summary>
public class MusicAlbumResolver : BaseItemResolver<MusicAlbum>
{
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override ResolverPriority Priority
{
get { return ResolverPriority.Third; } // we need to be ahead of the generic folder resolver but behind the movie one
}
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>MusicAlbum.</returns>
protected override MusicAlbum Resolve(ItemResolveArgs args)
{
if (!args.IsDirectory) return null;
//Avoid mis-identifying top folders
if (args.Parent == null) return null;
if (args.Parent.IsRoot) return null;
return EntityResolutionHelper.IsMusicAlbum(args) ? new MusicAlbum() : null;
}
}
}

View File

@@ -1,39 +0,0 @@
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using System.Linq;
namespace MediaBrowser.Controller.Resolvers.Audio
{
/// <summary>
/// Class MusicArtistResolver
/// </summary>
public class MusicArtistResolver : BaseItemResolver<MusicArtist>
{
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override ResolverPriority Priority
{
get { return ResolverPriority.Third; } // we need to be ahead of the generic folder resolver but behind the movie one
}
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>MusicArtist.</returns>
protected override MusicArtist Resolve(ItemResolveArgs args)
{
if (!args.IsDirectory) return null;
//Avoid mis-identifying top folders
if (args.Parent == null) return null;
if (args.Parent.IsRoot) return null;
// If we contain an album assume we are an artist folder
return args.FileSystemChildren.Any(EntityResolutionHelper.IsMusicAlbum) ? new MusicArtist() : null;
}
}
}

View File

@@ -1,165 +0,0 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using System.IO;
using System.Text.RegularExpressions;
namespace MediaBrowser.Controller.Resolvers
{
/// <summary>
/// Class BaseItemResolver
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class BaseItemResolver<T> : IBaseItemResolver
where T : BaseItem, new()
{
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>`0.</returns>
protected virtual T Resolve(ItemResolveArgs args)
{
return null;
}
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public virtual ResolverPriority Priority
{
get
{
return ResolverPriority.First;
}
}
/// <summary>
/// Sets initial values on the newly resolved item
/// </summary>
/// <param name="item">The item.</param>
/// <param name="args">The args.</param>
protected virtual void SetInitialItemValues(T item, ItemResolveArgs args)
{
// If the subclass didn't specify this
if (string.IsNullOrEmpty(item.Path))
{
item.Path = args.Path;
}
// If the subclass didn't specify this
if (args.Parent != null)
{
item.Parent = args.Parent;
}
item.Id = item.Path.GetMBId(item.GetType());
item.DisplayMediaType = item.GetType().Name;
}
/// <summary>
/// Resolves the path.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>BaseItem.</returns>
public BaseItem ResolvePath(ItemResolveArgs args)
{
T item = Resolve(args);
if (item != null)
{
// Set the args on the item
item.ResolveArgs = args;
// Set initial values on the newly resolved item
SetInitialItemValues(item, args);
// Make sure the item has a name
EnsureName(item);
// Make sure DateCreated and DateModified have values
EntityResolutionHelper.EnsureDates(item, args);
}
return item;
}
/// <summary>
/// Ensures the name.
/// </summary>
/// <param name="item">The item.</param>
private void EnsureName(T item)
{
// If the subclass didn't supply a name, add it here
if (string.IsNullOrEmpty(item.Name) && !string.IsNullOrEmpty(item.Path))
{
//we use our resolve args name here to get the name of the containg folder, not actual video file
item.Name = GetMBName(item.ResolveArgs.FileInfo.cFileName, item.ResolveArgs.FileInfo.IsDirectory);
}
}
/// <summary>
/// The MB name regex
/// </summary>
private static readonly Regex MBNameRegex = new Regex("(\\[.*\\])", RegexOptions.Compiled);
/// <summary>
/// Strip out attribute items and return just the name we will use for items
/// </summary>
/// <param name="path">Assumed to be a file or directory path</param>
/// <param name="isDirectory">if set to <c>true</c> [is directory].</param>
/// <returns>The cleaned name</returns>
private static string GetMBName(string path, bool isDirectory)
{
//first just get the file or directory name
var fn = isDirectory ? Path.GetFileName(path) : Path.GetFileNameWithoutExtension(path);
//now - strip out anything inside brackets
fn = MBNameRegex.Replace(fn, string.Empty);
return fn;
}
}
/// <summary>
/// Weed this to keep a list of resolvers, since Resolvers are built with generics
/// </summary>
public interface IBaseItemResolver
{
/// <summary>
/// Resolves the path.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>BaseItem.</returns>
BaseItem ResolvePath(ItemResolveArgs args);
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
ResolverPriority Priority { get; }
}
/// <summary>
/// Enum ResolverPriority
/// </summary>
public enum ResolverPriority
{
/// <summary>
/// The first
/// </summary>
First = 1,
/// <summary>
/// The second
/// </summary>
Second = 2,
/// <summary>
/// The third
/// </summary>
Third = 3,
/// <summary>
/// The last
/// </summary>
Last = 4
}
}

View File

@@ -1,55 +0,0 @@
using MediaBrowser.Controller.Library;
using System;
using System.Collections.Generic;
using System.Linq;
namespace MediaBrowser.Controller.Resolvers
{
/// <summary>
/// Provides the core resolver ignore rules
/// </summary>
public class CoreResolutionIgnoreRule : IResolutionIgnoreRule
{
/// <summary>
/// Any folder named in this list will be ignored - can be added to at runtime for extensibility
/// </summary>
private static readonly List<string> IgnoreFolders = new List<string>
{
"trailers",
"metadata",
"certificate",
"backup",
"ps3_update",
"ps3_vprm",
"adv_obj",
"extrafanart"
};
/// <summary>
/// Shoulds the ignore.
/// </summary>
/// <param name="args">The args.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public bool ShouldIgnore(ItemResolveArgs args)
{
// Ignore hidden files and folders
if (args.IsHidden)
{
return true;
}
if (args.IsDirectory)
{
var filename = args.FileInfo.cFileName;
// Ignore any folders in our list
if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
}
}

View File

@@ -1,210 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace MediaBrowser.Controller.Resolvers
{
/// <summary>
/// Class EntityResolutionHelper
/// </summary>
public static class EntityResolutionHelper
{
/// <summary>
/// Any extension in this list is considered a metadata file - can be added to at runtime for extensibility
/// </summary>
public static List<string> MetaExtensions = new List<string>
{
".xml",
".jpg",
".png",
".json",
".data"
};
/// <summary>
/// Any extension in this list is considered a video file - can be added to at runtime for extensibility
/// </summary>
public static List<string> VideoFileExtensions = new List<string>
{
".mkv",
".m2t",
".m2ts",
".img",
".iso",
".ts",
".rmvb",
".mov",
".avi",
".mpg",
".mpeg",
".wmv",
".mp4",
".divx",
".dvr-ms",
".wtv",
".ogm",
".ogv",
".asf",
".m4v",
".flv",
".f4v",
".3gp",
".webm"
};
/// <summary>
/// Determines whether [is video file] [the specified path].
/// </summary>
/// <param name="path">The path.</param>
/// <returns><c>true</c> if [is video file] [the specified path]; otherwise, <c>false</c>.</returns>
public static bool IsVideoFile(string path)
{
var extension = Path.GetExtension(path) ?? string.Empty;
return VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// The audio file extensions
/// </summary>
public static readonly string[] AudioFileExtensions = new[] {
".mp3",
".flac",
".wma",
".aac",
".acc",
".m4a",
".m4b",
".wav",
".ape",
".ogg",
".oga"
};
/// <summary>
/// Determines whether [is audio file] [the specified args].
/// </summary>
/// <param name="args">The args.</param>
/// <returns><c>true</c> if [is audio file] [the specified args]; otherwise, <c>false</c>.</returns>
public static bool IsAudioFile(ItemResolveArgs args)
{
return AudioFileExtensions.Contains(Path.GetExtension(args.Path), StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// Determines whether [is audio file] [the specified file].
/// </summary>
/// <param name="file">The file.</param>
/// <returns><c>true</c> if [is audio file] [the specified file]; otherwise, <c>false</c>.</returns>
public static bool IsAudioFile(WIN32_FIND_DATA file)
{
return AudioFileExtensions.Contains(Path.GetExtension(file.Path), StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// Determine if the supplied file data points to a music album
/// </summary>
/// <param name="data">The data.</param>
/// <returns><c>true</c> if [is music album] [the specified data]; otherwise, <c>false</c>.</returns>
public static bool IsMusicAlbum(WIN32_FIND_DATA data)
{
return ContainsMusic(FileSystem.GetFiles(data.Path));
}
/// <summary>
/// Determine if the supplied reslove args should be considered a music album
/// </summary>
/// <param name="args">The args.</param>
/// <returns><c>true</c> if [is music album] [the specified args]; otherwise, <c>false</c>.</returns>
public static bool IsMusicAlbum(ItemResolveArgs args)
{
// Args points to an album if parent is an Artist folder or it directly contains music
if (args.IsDirectory)
{
//if (args.Parent is MusicArtist) return true; //saves us from testing children twice
if (ContainsMusic(args.FileSystemChildren)) return true;
}
return false;
}
/// <summary>
/// Determine if the supplied list contains what we should consider music
/// </summary>
/// <param name="list">The list.</param>
/// <returns><c>true</c> if the specified list contains music; otherwise, <c>false</c>.</returns>
public static bool ContainsMusic(IEnumerable<WIN32_FIND_DATA> list)
{
// If list contains at least 2 audio files or at least one and no video files consider it to contain music
var foundAudio = 0;
var foundVideo = 0;
foreach (var file in list)
{
if (IsAudioFile(file)) foundAudio++;
if (foundAudio >= 2)
{
return true;
}
if (IsVideoFile(file.Path)) foundVideo++;
}
// or a single audio file and no video files
if (foundAudio > 0 && foundVideo == 0) return true;
return false;
}
/// <summary>
/// Determines whether a path should be ignored based on its contents - called after the contents have been read
/// </summary>
/// <param name="args">The args.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public static bool ShouldResolvePathContents(ItemResolveArgs args)
{
// Ignore any folders containing a file called .ignore
return !args.ContainsFileSystemEntryByName(".ignore");
}
/// <summary>
/// Ensures DateCreated and DateModified have values
/// </summary>
/// <param name="item">The item.</param>
/// <param name="args">The args.</param>
public static void EnsureDates(BaseItem item, ItemResolveArgs args)
{
if (!Path.IsPathRooted(item.Path))
{
return;
}
// See if a different path came out of the resolver than what went in
if (!args.Path.Equals(item.Path, StringComparison.OrdinalIgnoreCase))
{
var childData = args.IsDirectory ? args.GetFileSystemEntryByPath(item.Path) : null;
if (childData.HasValue)
{
item.DateCreated = childData.Value.CreationTimeUtc;
item.DateModified = childData.Value.LastWriteTimeUtc;
}
else
{
var fileData = FileSystem.GetFileData(item.Path);
if (fileData.HasValue)
{
item.DateCreated = fileData.Value.CreationTimeUtc;
item.DateModified = fileData.Value.LastWriteTimeUtc;
}
}
}
else
{
item.DateCreated = args.FileInfo.CreationTimeUtc;
item.DateModified = args.FileInfo.LastWriteTimeUtc;
}
}
}
}

View File

@@ -1,69 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
namespace MediaBrowser.Controller.Resolvers
{
/// <summary>
/// Class FolderResolver
/// </summary>
public class FolderResolver : BaseFolderResolver<Folder>
{
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override ResolverPriority Priority
{
get { return ResolverPriority.Last; }
}
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>Folder.</returns>
protected override Folder Resolve(ItemResolveArgs args)
{
if (args.IsDirectory)
{
if (args.IsPhysicalRoot)
{
return new AggregateFolder();
}
if (args.IsRoot)
{
return new UserRootFolder(); //if we got here and still a root - must be user root
}
if (args.IsVf)
{
return new CollectionFolder();
}
return new Folder();
}
return null;
}
}
/// <summary>
/// Class BaseFolderResolver
/// </summary>
/// <typeparam name="TItemType">The type of the T item type.</typeparam>
public abstract class BaseFolderResolver<TItemType> : BaseItemResolver<TItemType>
where TItemType : Folder, new()
{
/// <summary>
/// Sets the initial item values.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="args">The args.</param>
protected override void SetInitialItemValues(TItemType item, ItemResolveArgs args)
{
base.SetInitialItemValues(item, args);
item.IsRoot = args.Parent == null;
item.IsPhysicalRoot = args.IsPhysicalRoot;
}
}
}

View File

@@ -1,12 +0,0 @@
using MediaBrowser.Controller.Library;
namespace MediaBrowser.Controller.Resolvers
{
/// <summary>
/// Provides a base "rule" that anyone can use to have paths ignored by the resolver
/// </summary>
public interface IResolutionIgnoreRule
{
bool ShouldIgnore(ItemResolveArgs args);
}
}

View File

@@ -1,38 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using System;
using System.IO;
namespace MediaBrowser.Controller.Resolvers
{
/// <summary>
/// Class LocalTrailerResolver
/// </summary>
public class LocalTrailerResolver : BaseVideoResolver<Trailer>
{
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>Trailer.</returns>
protected override Trailer Resolve(ItemResolveArgs args)
{
// Trailers are not Children, therefore this can never happen
if (args.Parent != null)
{
return null;
}
// If the file is within a trailers folder, see if the VideoResolver returns something
if (!args.IsDirectory)
{
if (string.Equals(Path.GetFileName(Path.GetDirectoryName(args.Path)), BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase))
{
return base.Resolve(args);
}
}
return null;
}
}
}

View File

@@ -1,41 +0,0 @@
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using System;
using System.IO;
namespace MediaBrowser.Controller.Resolvers.Movies
{
/// <summary>
/// Class BoxSetResolver
/// </summary>
public class BoxSetResolver : BaseFolderResolver<BoxSet>
{
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>BoxSet.</returns>
protected override BoxSet Resolve(ItemResolveArgs args)
{
// It's a boxset if all of the following conditions are met:
// Is a Directory
// Contains [boxset] in the path
if (args.IsDirectory)
{
var filename = Path.GetFileName(args.Path);
if (string.IsNullOrEmpty(filename))
{
return null;
}
if (filename.IndexOf("[boxset]", StringComparison.OrdinalIgnoreCase) != -1)
{
return new BoxSet();
}
}
return null;
}
}
}

View File

@@ -1,208 +0,0 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers.Movies;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.IO;
namespace MediaBrowser.Controller.Resolvers.Movies
{
/// <summary>
/// Class MovieResolver
/// </summary>
public class MovieResolver : BaseVideoResolver<Movie>
{
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override ResolverPriority Priority
{
get
{
// Give plugins a chance to catch iso's first
// Also since we have to loop through child files looking for videos,
// see if we can avoid some of that by letting other resolvers claim folders first
return ResolverPriority.Second;
}
}
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>Movie.</returns>
protected override Movie Resolve(ItemResolveArgs args)
{
// Must be a directory and under a 'Movies' VF
if (args.IsDirectory)
{
// Avoid expensive tests against VF's and all their children by not allowing this
if (args.Parent == null || args.Parent.IsRoot)
{
return null;
}
// If the parent is not a boxset, the only other allowed parent type is Folder
if (!(args.Parent is BoxSet))
{
if (args.Parent.GetType() != typeof(Folder))
{
return null;
}
}
// Optimization to avoid running all these tests against Top folders
if (args.Parent != null && args.Parent.IsRoot)
{
return null;
}
// The movie must be a video file
return FindMovie(args);
}
return null;
}
/// <summary>
/// Sets the initial item values.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="args">The args.</param>
protected override void SetInitialItemValues(Movie item, ItemResolveArgs args)
{
base.SetInitialItemValues(item, args);
SetProviderIdFromPath(item);
}
/// <summary>
/// Sets the provider id from path.
/// </summary>
/// <param name="item">The item.</param>
private void SetProviderIdFromPath(Movie item)
{
//we need to only look at the name of this actual item (not parents)
var justName = item.Path.Substring(item.Path.LastIndexOf(Path.DirectorySeparatorChar));
var id = justName.GetAttributeValue("tmdbid");
if (!string.IsNullOrEmpty(id))
{
item.SetProviderId(MetadataProviders.Tmdb, id);
}
}
/// <summary>
/// Finds a movie based on a child file system entries
/// </summary>
/// <param name="args">The args.</param>
/// <returns>Movie.</returns>
private Movie FindMovie(ItemResolveArgs args)
{
// Since the looping is expensive, this is an optimization to help us avoid it
if (args.ContainsMetaFileByName("series.xml") || args.Path.IndexOf("[tvdbid", StringComparison.OrdinalIgnoreCase) != -1)
{
return null;
}
// Optimization to avoid having to resolve every file
bool? isKnownMovie = null;
var movies = new List<Movie>();
// Loop through each child file/folder and see if we find a video
foreach (var child in args.FileSystemChildren)
{
if (child.IsDirectory)
{
if (IsDvdDirectory(child.cFileName))
{
return new Movie
{
Path = args.Path,
VideoType = VideoType.Dvd
};
}
if (IsBluRayDirectory(child.cFileName))
{
return new Movie
{
Path = args.Path,
VideoType = VideoType.BluRay
};
}
if (IsHdDvdDirectory(child.cFileName))
{
return new Movie
{
Path = args.Path,
VideoType = VideoType.HdDvd
};
}
continue;
}
var childArgs = new ItemResolveArgs
{
FileInfo = child,
Path = child.Path
};
var item = base.Resolve(childArgs);
if (item != null)
{
// If we already know it's a movie, we can stop looping
if (!isKnownMovie.HasValue)
{
isKnownMovie = args.ContainsMetaFileByName("movie.xml") || args.ContainsMetaFileByName(MovieDbProvider.LOCAL_META_FILE_NAME) || args.Path.IndexOf("[tmdbid", StringComparison.OrdinalIgnoreCase) != -1;
}
if (isKnownMovie.Value)
{
return item;
}
movies.Add(item);
}
}
// If there are multiple video files, return null, and let the VideoResolver catch them later as plain videos
return movies.Count == 1 ? movies[0] : null;
}
/// <summary>
/// Determines whether [is DVD directory] [the specified directory name].
/// </summary>
/// <param name="directoryName">Name of the directory.</param>
/// <returns><c>true</c> if [is DVD directory] [the specified directory name]; otherwise, <c>false</c>.</returns>
private bool IsDvdDirectory(string directoryName)
{
return directoryName.Equals("video_ts", StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Determines whether [is hd DVD directory] [the specified directory name].
/// </summary>
/// <param name="directoryName">Name of the directory.</param>
/// <returns><c>true</c> if [is hd DVD directory] [the specified directory name]; otherwise, <c>false</c>.</returns>
private bool IsHdDvdDirectory(string directoryName)
{
return directoryName.Equals("hvdvd_ts", StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Determines whether [is blu ray directory] [the specified directory name].
/// </summary>
/// <param name="directoryName">Name of the directory.</param>
/// <returns><c>true</c> if [is blu ray directory] [the specified directory name]; otherwise, <c>false</c>.</returns>
private bool IsBluRayDirectory(string directoryName)
{
return directoryName.Equals("bdmv", StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@@ -1,76 +0,0 @@
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using System;
namespace MediaBrowser.Controller.Resolvers.TV
{
/// <summary>
/// Class EpisodeResolver
/// </summary>
public class EpisodeResolver : BaseVideoResolver<Episode>
{
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>Episode.</returns>
protected override Episode Resolve(ItemResolveArgs args)
{
// If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something
if (args.Parent is Season || args.Parent is Series)
{
if (args.IsDirectory)
{
if (args.ContainsFileSystemEntryByName("video_ts"))
{
return new Episode
{
Path = args.Path,
VideoType = VideoType.Dvd
};
}
if (args.ContainsFileSystemEntryByName("bdmv"))
{
return new Episode
{
Path = args.Path,
VideoType = VideoType.BluRay
};
}
}
return base.Resolve(args);
}
return null;
}
/// <summary>
/// Sets the initial item values.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="args">The args.</param>
protected override void SetInitialItemValues(Episode item, ItemResolveArgs args)
{
base.SetInitialItemValues(item, args);
//fill in our season and series ids
var season = args.Parent as Season;
if (season != null)
{
item.SeasonItemId = season.Id;
var series = season.Parent as Series;
if (series != null)
{
item.SeriesItemId = series.Id;
}
}
else
{
var series = args.Parent as Series;
item.SeriesItemId = series != null ? series.Id : Guid.Empty;
}
}
}
}

View File

@@ -1,45 +0,0 @@
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using System;
namespace MediaBrowser.Controller.Resolvers.TV
{
/// <summary>
/// Class SeasonResolver
/// </summary>
public class SeasonResolver : BaseFolderResolver<Season>
{
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>Season.</returns>
protected override Season Resolve(ItemResolveArgs args)
{
if (args.Parent is Series && args.IsDirectory)
{
return new Season
{
IndexNumber = TVUtils.GetSeasonNumberFromPath(args.Path)
};
}
return null;
}
/// <summary>
/// Sets the initial item values.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="args">The args.</param>
protected override void SetInitialItemValues(Season item, ItemResolveArgs args)
{
base.SetInitialItemValues(item, args);
var series = args.Parent as Series;
item.SeriesItemId = series != null ? series.Id : Guid.Empty;
Season.AddMetadataFiles(args);
}
}
}

View File

@@ -1,98 +0,0 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using System;
using System.IO;
namespace MediaBrowser.Controller.Resolvers.TV
{
/// <summary>
/// Class SeriesResolver
/// </summary>
public class SeriesResolver : BaseFolderResolver<Series>
{
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override ResolverPriority Priority
{
get
{
return ResolverPriority.Second;
}
}
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>Series.</returns>
protected override Series Resolve(ItemResolveArgs args)
{
if (args.IsDirectory)
{
// Avoid expensive tests against VF's and all their children by not allowing this
if (args.Parent == null || args.Parent.IsRoot)
{
return null;
}
// Optimization to avoid running these tests against Seasons
if (args.Parent is Series)
{
return null;
}
// It's a Series if any of the following conditions are met:
// series.xml exists
// [tvdbid= is present in the path
// TVUtils.IsSeriesFolder returns true
var filename = Path.GetFileName(args.Path);
if (string.IsNullOrEmpty(filename))
{
return null;
}
if (args.ContainsMetaFileByName("series.xml") || filename.IndexOf("[tvdbid=", StringComparison.OrdinalIgnoreCase) != -1 || TVUtils.IsSeriesFolder(args.Path, args.FileSystemChildren))
{
return new Series();
}
}
return null;
}
/// <summary>
/// Sets the initial item values.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="args">The args.</param>
protected override void SetInitialItemValues(Series item, ItemResolveArgs args)
{
base.SetInitialItemValues(item, args);
Season.AddMetadataFiles(args);
SetProviderIdFromPath(item);
}
/// <summary>
/// Sets the provider id from path.
/// </summary>
/// <param name="item">The item.</param>
private void SetProviderIdFromPath(Series item)
{
var justName = item.Path.Substring(item.Path.LastIndexOf(Path.DirectorySeparatorChar));
var id = justName.GetAttributeValue("tvdbid");
if (!string.IsNullOrEmpty(id))
{
item.SetProviderId(MetadataProviders.Tvdb, id);
}
}
}
}

View File

@@ -1,286 +0,0 @@
using MediaBrowser.Controller.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace MediaBrowser.Controller.Resolvers.TV
{
/// <summary>
/// Class TVUtils
/// </summary>
public static class TVUtils
{
/// <summary>
/// The TVDB API key
/// </summary>
public static readonly string TVDBApiKey = "B89CE93890E9419B";
/// <summary>
/// The banner URL
/// </summary>
public static readonly string BannerUrl = "http://www.thetvdb.com/banners/";
/// <summary>
/// A season folder must contain one of these somewhere in the name
/// </summary>
private static readonly string[] SeasonFolderNames = new[]
{
"season",
"sæson",
"temporada",
"saison",
"staffel"
};
/// <summary>
/// Used to detect paths that represent episodes, need to make sure they don't also
/// match movie titles like "2001 A Space..."
/// Currently we limit the numbers here to 2 digits to try and avoid this
/// </summary>
private static readonly Regex[] EpisodeExpressions = new[]
{
new Regex(
@".*\\[s|S]?(?<seasonnumber>\d{1,2})[x|X](?<epnumber>\d{1,3})[^\\]*$",
RegexOptions.Compiled),
// 01x02 blah.avi S01x01 balh.avi
new Regex(
@".*\\[s|S](?<seasonnumber>\d{1,2})x?[e|E](?<epnumber>\d{1,3})[^\\]*$",
RegexOptions.Compiled),
// S01E02 blah.avi, S01xE01 blah.avi
new Regex(
@".*\\(?<seriesname>[^\\]*)[s|S]?(?<seasonnumber>\d{1,2})[x|X](?<epnumber>\d{1,3})[^\\]*$",
RegexOptions.Compiled),
// 01x02 blah.avi S01x01 balh.avi
new Regex(
@".*\\(?<seriesname>[^\\]*)[s|S](?<seasonnumber>\d{1,2})[x|X|\.]?[e|E](?<epnumber>\d{1,3})[^\\]*$",
RegexOptions.Compiled)
// S01E02 blah.avi, S01xE01 blah.avi
};
/// <summary>
/// To avoid the following matching movies they are only valid when contained in a folder which has been matched as a being season
/// </summary>
private static readonly Regex[] EpisodeExpressionsInASeasonFolder = new[]
{
new Regex(
@".*\\(?<epnumber>\d{1,2})\s?-\s?[^\\]*$",
RegexOptions.Compiled),
// 01 - blah.avi, 01-blah.avi
new Regex(
@".*\\(?<epnumber>\d{1,2})[^\d\\]*[^\\]*$",
RegexOptions.Compiled),
// 01.avi, 01.blah.avi "01 - 22 blah.avi"
new Regex(
@".*\\(?<seasonnumber>\d)(?<epnumber>\d{1,2})[^\d\\]+[^\\]*$",
RegexOptions.Compiled),
// 01.avi, 01.blah.avi
new Regex(
@".*\\\D*\d+(?<epnumber>\d{2})",
RegexOptions.Compiled)
// hell0 - 101 - hello.avi
};
/// <summary>
/// Gets the season number from path.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>System.Nullable{System.Int32}.</returns>
public static int? GetSeasonNumberFromPath(string path)
{
// Look for one of the season folder names
foreach (var name in SeasonFolderNames)
{
int index = path.IndexOf(name, StringComparison.OrdinalIgnoreCase);
if (index != -1)
{
return GetSeasonNumberFromPathSubstring(path.Substring(index + name.Length));
}
}
return null;
}
/// <summary>
/// Extracts the season number from the second half of the Season folder name (everything after "Season", or "Staffel")
/// </summary>
/// <param name="path">The path.</param>
/// <returns>System.Nullable{System.Int32}.</returns>
private static int? GetSeasonNumberFromPathSubstring(string path)
{
int numericStart = -1;
int length = 0;
// Find out where the numbers start, and then keep going until they end
for (int i = 0; i < path.Length; i++)
{
if (char.IsNumber(path, i))
{
if (numericStart == -1)
{
numericStart = i;
}
length++;
}
else if (numericStart != -1)
{
break;
}
}
if (numericStart == -1)
{
return null;
}
return int.Parse(path.Substring(numericStart, length));
}
/// <summary>
/// Determines whether [is season folder] [the specified path].
/// </summary>
/// <param name="path">The path.</param>
/// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns>
public static bool IsSeasonFolder(string path)
{
return GetSeasonNumberFromPath(path) != null;
}
/// <summary>
/// Determines whether [is series folder] [the specified path].
/// </summary>
/// <param name="path">The path.</param>
/// <param name="fileSystemChildren">The file system children.</param>
/// <returns><c>true</c> if [is series folder] [the specified path]; otherwise, <c>false</c>.</returns>
public static bool IsSeriesFolder(string path, IEnumerable<WIN32_FIND_DATA> fileSystemChildren)
{
// A folder with more than 3 non-season folders in will not becounted as a series
var nonSeriesFolders = 0;
foreach (var child in fileSystemChildren)
{
if (child.IsHidden || child.IsSystemFile)
{
continue;
}
if (child.IsDirectory)
{
if (IsSeasonFolder(child.Path))
{
return true;
}
nonSeriesFolders++;
if (nonSeriesFolders >= 3)
{
return false;
}
}
else
{
if (EntityResolutionHelper.IsVideoFile(child.Path) &&
!string.IsNullOrEmpty(EpisodeNumberFromFile(child.Path, false)))
{
return true;
}
}
}
return false;
}
/// <summary>
/// Episodes the number from file.
/// </summary>
/// <param name="fullPath">The full path.</param>
/// <param name="isInSeason">if set to <c>true</c> [is in season].</param>
/// <returns>System.String.</returns>
public static string EpisodeNumberFromFile(string fullPath, bool isInSeason)
{
string fl = fullPath.ToLower();
foreach (var r in EpisodeExpressions)
{
Match m = r.Match(fl);
if (m.Success)
return m.Groups["epnumber"].Value;
}
if (isInSeason)
{
var match = EpisodeExpressionsInASeasonFolder.Select(r => r.Match(fl))
.FirstOrDefault(m => m.Success);
if (match != null)
{
return match.Value;
}
}
return null;
}
/// <summary>
/// Seasons the number from episode file.
/// </summary>
/// <param name="fullPath">The full path.</param>
/// <returns>System.String.</returns>
public static string SeasonNumberFromEpisodeFile(string fullPath)
{
string fl = fullPath.ToLower();
foreach (var r in EpisodeExpressions)
{
Match m = r.Match(fl);
if (m.Success)
{
Group g = m.Groups["seasonnumber"];
if (g != null)
return g.Value;
return null;
}
}
return null;
}
/// <summary>
/// Gets the air days.
/// </summary>
/// <param name="day">The day.</param>
/// <returns>List{DayOfWeek}.</returns>
public static List<DayOfWeek> GetAirDays(string day)
{
if (!string.IsNullOrWhiteSpace(day))
{
if (day.Equals("Daily", StringComparison.OrdinalIgnoreCase))
{
return new List<DayOfWeek>
{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
}
DayOfWeek value;
if (Enum.TryParse(day, true, out value))
{
return new List<DayOfWeek>
{
value
};
}
return new List<DayOfWeek>
{
};
}
return null;
}
}
}

View File

@@ -1,71 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using System;
using System.IO;
namespace MediaBrowser.Controller.Resolvers
{
/// <summary>
/// Resolves a Path into a Video
/// </summary>
public class VideoResolver : BaseVideoResolver<Video>
{
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override ResolverPriority Priority
{
get { return ResolverPriority.Last; }
}
}
/// <summary>
/// Resolves a Path into a Video or Video subclass
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class BaseVideoResolver<T> : BaseItemResolver<T>
where T : Video, new()
{
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>`0.</returns>
protected override T Resolve(ItemResolveArgs args)
{
// If the path is a file check for a matching extensions
if (!args.IsDirectory)
{
if (EntityResolutionHelper.IsVideoFile(args.Path))
{
var extension = Path.GetExtension(args.Path);
var type = string.Equals(extension, ".iso", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".img", StringComparison.OrdinalIgnoreCase) ?
VideoType.Iso : VideoType.VideoFile;
return new T
{
VideoType = type,
Path = args.Path
};
}
}
return null;
}
/// <summary>
/// Sets the initial item values.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="args">The args.</param>
protected override void SetInitialItemValues(T item, ItemResolveArgs args)
{
base.SetInitialItemValues(item, args);
item.VideoFormat = item.Path.IndexOf("[3d]", StringComparison.OrdinalIgnoreCase) != -1 ? VideoFormat.Digital3D : item.Path.IndexOf("[sbs3d]", StringComparison.OrdinalIgnoreCase) != -1 ? VideoFormat.Sbs3D : VideoFormat.Standard;
}
}
}