add more sync buttons

This commit is contained in:
Luke Pulverenti 2014-12-18 23:20:07 -05:00
parent e3484bdcc2
commit e55ab989d2
46 changed files with 380 additions and 872 deletions

View File

@ -185,7 +185,9 @@ namespace MediaBrowser.Api
CompletionPercentage = percentComplete,
Width = state.OutputWidth,
Height = state.OutputHeight,
AudioChannels = state.OutputAudioChannels
AudioChannels = state.OutputAudioChannels,
IsAudioDirect = string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase),
IsVideoDirect = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)
});
}
}

View File

@ -302,6 +302,21 @@ namespace MediaBrowser.Api.Playback
}
}
protected string H264Encoder
{
get
{
var lib = ServerConfigurationManager.Configuration.H264Encoder;
if (!string.IsNullOrWhiteSpace(lib))
{
return lib;
}
return "libx264";
}
}
/// <summary>
/// Gets the video bitrate to specify on the command line
/// </summary>
@ -318,7 +333,7 @@ namespace MediaBrowser.Api.Playback
var qualitySetting = GetQualitySetting();
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
if (string.Equals(videoCodec, H264Encoder, StringComparison.OrdinalIgnoreCase))
{
switch (qualitySetting)
{
@ -761,7 +776,7 @@ namespace MediaBrowser.Api.Playback
{
if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase))
{
return "libx264";
return H264Encoder;
}
if (string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase))
{
@ -1562,9 +1577,6 @@ namespace MediaBrowser.Api.Playback
mediaStreams = new List<MediaStream>();
state.DeInterlace = true;
state.OutputAudioSync = "1000";
state.InputVideoSync = "-1";
state.InputAudioSync = "1";
// Just to prevent this from being null and causing other methods to fail
state.MediaPath = string.Empty;
@ -1696,6 +1708,13 @@ namespace MediaBrowser.Api.Playback
state.InputFileSize = mediaSource.Size;
state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate;
if (state.ReadInputAtNativeFramerate)
{
state.OutputAudioSync = "1000";
state.InputVideoSync = "-1";
state.InputAudioSync = "1";
}
AttachMediaStreamInfo(state, mediaSource.MediaStreams, videoRequest, requestedUrl);
}

View File

@ -1,4 +1,5 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
@ -6,7 +7,6 @@ using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.IO;
using System;
using System.Collections.Generic;
@ -119,11 +119,7 @@ namespace MediaBrowser.Api.Playback.Hls
if (isLive)
{
//var file = request.PlaylistId + Path.GetExtension(Request.PathInfo);
//file = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, file);
return ResultFactory.GetStaticFileResult(Request, playlist, FileShare.ReadWrite);
return ResultFactory.GetResult(GetLivePlaylistText(playlist, state.SegmentLength), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
var audioBitrate = state.OutputAudioBitrate ?? 0;
@ -144,6 +140,22 @@ namespace MediaBrowser.Api.Playback.Hls
return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
private string GetLivePlaylistText(string path, int segmentLength)
{
using (var stream = FileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var reader = new StreamReader(stream))
{
var text = reader.ReadToEnd();
var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(UsCulture) + Environment.NewLine + "#EXT-X-ALLOW-CACHE:NO";
// ffmpeg pads the reported length by a full second
return text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(UsCulture), newDuration, StringComparison.OrdinalIgnoreCase);
}
}
}
private string GetMasterPlaylistFileText(string firstPlaylist, int bitrate, bool includeBaselineStream, int baselineStreamBitrate)
{
var builder = new StringBuilder();

View File

@ -651,7 +651,7 @@ namespace MediaBrowser.Api.Playback.Hls
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg;
var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, H264Encoder, true) + keyFrameArg;
// Add resolution params, if specified
if (!hasGraphicalSubs)

View File

@ -594,7 +594,7 @@ namespace MediaBrowser.Api.Playback.Hls
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg;
var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, H264Encoder, true) + keyFrameArg;
args += " -r 24 -g 24";

View File

@ -9,8 +9,6 @@ using MediaBrowser.Model.IO;
using ServiceStack;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Api.Playback.Hls
{
@ -147,7 +145,7 @@ namespace MediaBrowser.Api.Playback.Hls
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg;
var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, H264Encoder, true) + keyFrameArg;
// Add resolution params, if specified
if (!hasGraphicalSubs)

View File

@ -55,8 +55,14 @@ namespace MediaBrowser.Api.Sync
[ApiMember(Name = "UserId", Description = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string UserId { get; set; }
[ApiMember(Name = "ItemIds", Description = "ItemIds", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
[ApiMember(Name = "ItemIds", Description = "ItemIds", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ItemIds { get; set; }
[ApiMember(Name = "ParentId", Description = "ParentId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ParentId { get; set; }
[ApiMember(Name = "Category", Description = "Category", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public SyncCategory? Category { get; set; }
}
[Route("/Sync/JobItems/{Id}/Transferred", "POST", Summary = "Reports that a sync job item has successfully been transferred.")]
@ -155,19 +161,26 @@ namespace MediaBrowser.Api.Sync
result.Targets = _syncManager.GetSyncTargets(request.UserId)
.ToList();
var dtos = request.ItemIds.Split(',')
.Select(_libraryManager.GetItemById)
.Where(i => i != null)
.Select(i => _dtoService.GetBaseItemDto(i, new DtoOptions
{
Fields = new List<ItemFields>
if (request.Category.HasValue)
{
result.Options = SyncHelper.GetSyncOptions(request.Category.Value);
}
else
{
var dtos = request.ItemIds.Split(',')
.Select(_libraryManager.GetItemById)
.Where(i => i != null)
.Select(i => _dtoService.GetBaseItemDto(i, new DtoOptions
{
Fields = new List<ItemFields>
{
ItemFields.SyncInfo
}
}))
.ToList();
}))
.ToList();
result.Options = SyncHelper.GetSyncOptions(dtos);
result.Options = SyncHelper.GetSyncOptions(dtos);
}
return ToOptimizedResult(result);
}

View File

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Connect;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Users;
@ -51,7 +52,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public Guid Id { get; set; }
public string Id { get; set; }
}
/// <summary>
@ -66,7 +67,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
public Guid Id { get; set; }
public string Id { get; set; }
}
/// <summary>
@ -80,7 +81,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public Guid Id { get; set; }
public string Id { get; set; }
/// <summary>
/// Gets or sets the password.
@ -125,7 +126,7 @@ namespace MediaBrowser.Api
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
public Guid Id { get; set; }
public string Id { get; set; }
/// <summary>
/// Gets or sets the password.
@ -155,6 +156,28 @@ namespace MediaBrowser.Api
{
}
/// <summary>
/// Class UpdateUser
/// </summary>
[Route("/Users/{Id}/Policy", "POST", Summary = "Updates a user policy")]
[Authenticated(Roles = "admin")]
public class UpdateUserPolicy : UserPolicy, IReturnVoid
{
[ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public string Id { get; set; }
}
/// <summary>
/// Class UpdateUser
/// </summary>
[Route("/Users/{Id}/Configuration", "POST", Summary = "Updates a user configuration")]
[Authenticated]
public class UpdateUserConfiguration : UserConfiguration, IReturnVoid
{
[ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public string Id { get; set; }
}
/// <summary>
/// Class CreateUser
/// </summary>
@ -196,12 +219,6 @@ namespace MediaBrowser.Api
public IAuthorizationContext AuthorizationContext { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="UserService" /> class.
/// </summary>
/// <param name="userManager">The user manager.</param>
/// <param name="dtoService">The dto service.</param>
/// <param name="sessionMananger">The session mananger.</param>
public UserService(IUserManager userManager, IDtoService dtoService, ISessionManager sessionMananger, IServerConfigurationManager config, INetworkManager networkManager)
{
_userManager = userManager;
@ -495,5 +512,17 @@ namespace MediaBrowser.Api
{
return _userManager.RedeemPasswordResetPin(request.Pin);
}
public void Post(UpdateUserConfiguration request)
{
var user = _userManager.GetUserById(request.Id);
user.UpdateConfiguration(request);
}
public void Post(UpdateUserPolicy request)
{
var task = _userManager.UpdateUserPolicy(request.Id, request);
Task.WaitAll(task);
}
}
}

View File

@ -45,6 +45,8 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".tbn" };
public static readonly List<string> SupportedImageExtensionsList = SupportedImageExtensions.ToList();
/// <summary>
/// The trailer folder name
/// </summary>

View File

@ -153,7 +153,14 @@ namespace MediaBrowser.Controller.Entities.Movies
public MovieInfo GetLookupInfo()
{
return GetItemLookupInfo<MovieInfo>();
var info = GetItemLookupInfo<MovieInfo>();
if (!IsInMixedFolder)
{
info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
}
return info;
}
public override bool BeforeMetadataRefresh()

View File

@ -1,5 +1,4 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using System;
@ -301,51 +300,9 @@ namespace MediaBrowser.Controller.Entities.TV
{
var hasChanges = base.BeforeMetadataRefresh();
var locationType = LocationType;
if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
if (LibraryManager.FillMissingEpisodeNumbersFromPath(this))
{
if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path))
{
IndexNumber = LibraryManager.GetEpisodeNumberFromFile(Path, true);
// If a change was made record it
if (IndexNumber.HasValue)
{
hasChanges = true;
}
}
if (!IndexNumberEnd.HasValue && !string.IsNullOrEmpty(Path))
{
IndexNumberEnd = LibraryManager.GetEndingEpisodeNumberFromFile(Path);
// If a change was made record it
if (IndexNumberEnd.HasValue)
{
hasChanges = true;
}
}
}
if (!ParentIndexNumber.HasValue)
{
var season = Season;
if (season != null)
{
ParentIndexNumber = season.IndexNumber;
}
if (!ParentIndexNumber.HasValue && !string.IsNullOrEmpty(Path))
{
ParentIndexNumber = LibraryManager.GetSeasonNumberFromEpisodeFile(Path);
}
// If a change was made record it
if (ParentIndexNumber.HasValue)
{
hasChanges = true;
}
hasChanges = true;
}
return hasChanges;

View File

@ -1,5 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Controller.Sorting;
@ -340,26 +341,11 @@ namespace MediaBrowser.Controller.Library
int? GetSeasonNumberFromPath(string path);
/// <summary>
/// Gets the season number from episode file.
/// Fills the missing episode numbers from path.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>System.Nullable&lt;System.Int32&gt;.</returns>
int? GetSeasonNumberFromEpisodeFile(string path);
/// <summary>
/// Gets the ending episode number from file.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>System.Nullable&lt;System.Int32&gt;.</returns>
int? GetEndingEpisodeNumberFromFile(string path);
/// <summary>
/// Gets the episode number from file.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="considerSeasonless">if set to <c>true</c> [consider seasonless].</param>
/// <returns>System.Nullable&lt;System.Int32&gt;.</returns>
int? GetEpisodeNumberFromFile(string path, bool considerSeasonless);
/// <param name="episode">The episode.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
bool FillMissingEpisodeNumbersFromPath(Episode episode);
/// <summary>
/// Parses the name.

View File

@ -76,11 +76,14 @@ namespace MediaBrowser.LocalMetadata.Images
{
return directoryService.GetFileSystemEntries(path)
.Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase) ||
(i.Attributes & FileAttributes.Directory) == FileAttributes.Directory);
(i.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
.OrderBy(i => BaseItem.SupportedImageExtensionsList.IndexOf(i.Extension ?? string.Empty));
}
return directoryService.GetFiles(path)
.Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase));
.Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
.OrderBy(i => BaseItem.SupportedImageExtensionsList.IndexOf(i.Extension ?? string.Empty));
}
public List<LocalImageInfo> GetImages(IHasImages item, IDirectoryService directoryService)
@ -109,6 +112,7 @@ namespace MediaBrowser.LocalMetadata.Images
return !string.IsNullOrEmpty(ext) &&
BaseItem.SupportedImageExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
})
.OrderBy(i => BaseItem.SupportedImageExtensionsList.IndexOf(i.Extension ?? string.Empty))
.ToList();
var list = new List<LocalImageInfo>();
@ -402,13 +406,7 @@ namespace MediaBrowser.LocalMetadata.Images
private FileSystemInfo GetImage(IEnumerable<FileSystemInfo> files, string name)
{
var candidates = files
.Where(i => string.Equals(name, _fileSystem.GetFileNameWithoutExtension(i), StringComparison.OrdinalIgnoreCase))
.ToList();
return BaseItem.SupportedImageExtensions
.Select(i => candidates.FirstOrDefault(c => string.Equals(c.Extension, i, StringComparison.OrdinalIgnoreCase)))
.FirstOrDefault(i => i != null);
return files.FirstOrDefault(i => ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) && string.Equals(name, _fileSystem.GetFileNameWithoutExtension(i), StringComparison.OrdinalIgnoreCase));
}
}
}

View File

@ -185,6 +185,14 @@ namespace MediaBrowser.Model.ApiClient
/// <exception cref="ArgumentNullException">url</exception>
Task<Stream> GetImageStreamAsync(string url, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Updates the user configuration.
/// </summary>
/// <param name="userId">The user identifier.</param>
/// <param name="configuration">The configuration.</param>
/// <returns>Task.</returns>
Task UpdateUserConfiguration(string userId, UserConfiguration configuration);
/// <summary>
/// Gets a BaseItem
/// </summary>

View File

@ -144,12 +144,6 @@ namespace MediaBrowser.Model.Configuration
/// <value>The image saving convention.</value>
public ImageSavingConvention ImageSavingConvention { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable people prefix sub folders].
/// </summary>
/// <value><c>true</c> if [enable people prefix sub folders]; otherwise, <c>false</c>.</value>
public bool EnablePeoplePrefixSubFolders { get; set; }
/// <summary>
/// Gets or sets the encoding quality.
/// </summary>
@ -179,8 +173,7 @@ namespace MediaBrowser.Model.Configuration
public string[] InsecureApps7 { get; set; }
public bool SaveMetadataHidden { get; set; }
public bool PlaylistImagesDeleted { get; set; }
public string H264Encoder { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
@ -195,7 +188,6 @@ namespace MediaBrowser.Model.Configuration
EnableDashboardResponseCaching = true;
EnableAutomaticRestart = true;
EnablePeoplePrefixSubFolders = true;
EnableUPnP = true;
DownMixAudioBoost = 2;
@ -225,6 +217,7 @@ namespace MediaBrowser.Model.Configuration
EnableRealtimeMonitor = true;
UICulture = "en-us";
H264Encoder = "libx264";
PeopleMetadataOptions = new PeopleMetadataOptions();

View File

@ -549,7 +549,13 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets a value indicating whether [supports playlists].
/// </summary>
/// <value><c>true</c> if [supports playlists]; otherwise, <c>false</c>.</value>
public bool SupportsPlaylists { get; set; }
public bool SupportsPlaylists
{
get
{
return RunTimeTicks.HasValue || IsFolder || IsGenre || IsMusicGenre || IsArtist;
}
}
/// <summary>
/// Determines whether the specified type is type.

View File

@ -6,6 +6,11 @@ namespace MediaBrowser.Model.Querying
/// </summary>
public enum ItemFields
{
/// <summary>
/// The air time
/// </summary>
AirTime,
/// <summary>
/// The alternate episode numbers
/// </summary>
@ -151,6 +156,11 @@ namespace MediaBrowser.Model.Querying
/// </summary>
Revenue,
/// <summary>
/// The season name
/// </summary>
SeasonName,
/// <summary>
/// The short overview
/// </summary>
@ -181,6 +191,11 @@ namespace MediaBrowser.Model.Querying
/// </summary>
SortName,
/// <summary>
/// The special episode numbers
/// </summary>
SpecialEpisodeNumbers,
/// <summary>
/// The studios of the item
/// </summary>

View File

@ -5,6 +5,8 @@ namespace MediaBrowser.Model.Session
public string AudioCodec { get; set; }
public string VideoCodec { get; set; }
public string Container { get; set; }
public bool IsVideoDirect { get; set; }
public bool IsAudioDirect { get; set; }
public int? Bitrate { get; set; }
public float? Framerate { get; set; }

View File

@ -0,0 +1,9 @@
using MediaBrowser.Model.Dto;
namespace MediaBrowser.Model.Sync
{
public class SyncItem
{
public BaseItemDto Item { get; set; }
}
}

View File

@ -72,26 +72,29 @@ namespace MediaBrowser.Server.Implementations.Channels
var features = _channelManager.GetChannelFeatures(channelId);
const int currentRefreshLevel = 1;
var maxRefreshLevel = features.AutoRefreshLevels ?? 1;
var maxRefreshLevel = features.AutoRefreshLevels ?? 0;
var innerProgress = new ActionableProgress<double>();
if (maxRefreshLevel > 0)
{
var innerProgress = new ActionableProgress<double>();
var startingNumberComplete = numComplete;
innerProgress.RegisterAction(p =>
{
double innerPercent = startingNumberComplete;
innerPercent += (p / 100);
innerPercent /= numItems;
progress.Report(innerPercent * 100);
});
var startingNumberComplete = numComplete;
innerProgress.RegisterAction(p =>
{
double innerPercent = startingNumberComplete;
innerPercent += (p / 100);
innerPercent /= numItems;
progress.Report(innerPercent * 100);
});
try
{
await GetAllItems(user, channelId, null, currentRefreshLevel, maxRefreshLevel, innerProgress, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error getting channel content", ex);
try
{
await GetAllItems(user, channelId, null, currentRefreshLevel, maxRefreshLevel, innerProgress, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error getting channel content", ex);
}
}
numComplete++;

View File

@ -121,8 +121,6 @@ namespace MediaBrowser.Server.Implementations.Dto
ServerId = _appHost.SystemId
};
dto.SupportsPlaylists = item.SupportsAddingToPlaylist;
if (fields.Contains(ItemFields.People))
{
AttachPeople(dto, item);
@ -1132,15 +1130,22 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber;
}
dto.AirsAfterSeasonNumber = episode.AirsAfterSeasonNumber;
dto.AirsBeforeEpisodeNumber = episode.AirsBeforeEpisodeNumber;
dto.AirsBeforeSeasonNumber = episode.AirsBeforeSeasonNumber;
//if (fields.Contains(ItemFields.SpecialEpisodeNumbers))
{
dto.AirsAfterSeasonNumber = episode.AirsAfterSeasonNumber;
dto.AirsBeforeEpisodeNumber = episode.AirsBeforeEpisodeNumber;
dto.AirsBeforeSeasonNumber = episode.AirsBeforeSeasonNumber;
}
var episodeSeason = episode.Season;
if (episodeSeason != null)
{
dto.SeasonId = episodeSeason.Id.ToString("N");
dto.SeasonName = episodeSeason.Name;
if (fields.Contains(ItemFields.SeasonName))
{
dto.SeasonName = episodeSeason.Name;
}
}
if (fields.Contains(ItemFields.SeriesGenres))
@ -1180,7 +1185,11 @@ namespace MediaBrowser.Server.Implementations.Dto
{
dto.SeriesId = GetDtoId(series);
dto.SeriesName = series.Name;
dto.AirTime = series.AirTime;
if (fields.Contains(ItemFields.AirTime))
{
dto.AirTime = series.AirTime;
}
if (options.GetImageLimit(ImageType.Thumb) > 0)
{

View File

@ -4,11 +4,11 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Logging;
using MediaBrowser.Naming.Common;
using MediaBrowser.Naming.IO;
using System;
using System.Collections.Generic;
using System.Globalization;
@ -16,8 +16,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Server.Implementations.Library;
using MediaBrowser.Server.Implementations.Library.Resolvers.TV;
namespace MediaBrowser.Server.Implementations.FileOrganization
{
@ -57,18 +55,23 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
FileSize = new FileInfo(path).Length
};
var seriesName = SeriesResolver.GetSeriesNameFromEpisodeFile(path);
var resolver = new Naming.TV.EpisodeResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
var episodeInfo = resolver.Resolve(path, FileInfoType.File) ??
new Naming.TV.EpisodeInfo();
var seriesName = episodeInfo.SeriesName;
if (!string.IsNullOrEmpty(seriesName))
{
var season = SeriesResolver.GetSeasonNumberFromEpisodeFile(path);
var season = episodeInfo.SeasonNumber;
result.ExtractedSeasonNumber = season;
if (season.HasValue)
{
// Passing in true will include a few extra regex's
var episode = SeriesResolver.GetEpisodeNumberFromFile(path, true);
var episode = episodeInfo.EpisodeNumber;
result.ExtractedEpisodeNumber = episode;
@ -76,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
_logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, season, episode);
var endingEpisodeNumber = SeriesResolver.GetEndingEpisodeNumberFromFile(path);
var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber;
result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
@ -251,7 +254,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var folder = Path.GetDirectoryName(targetPath);
var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath);
try
{
var filesOfOtherExtensions = Directory.EnumerateFiles(folder, "*", SearchOption.TopDirectoryOnly)

View File

@ -18,8 +18,8 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Naming.Audio;
using MediaBrowser.Naming.Common;
using MediaBrowser.Naming.IO;
using MediaBrowser.Naming.TV;
using MediaBrowser.Naming.Video;
using MediaBrowser.Server.Implementations.Library.Resolvers.TV;
using MediaBrowser.Server.Implementations.Library.Validators;
using MediaBrowser.Server.Implementations.ScheduledTasks;
using System;
@ -862,7 +862,7 @@ namespace MediaBrowser.Server.Implementations.Library
var type = typeof(T);
if (type == typeof(Person) && ConfigurationManager.Configuration.EnablePeoplePrefixSubFolders)
if (type == typeof(Person))
{
subFolderPrefix = validFilename.Substring(0, 1);
}
@ -1708,22 +1708,69 @@ namespace MediaBrowser.Server.Implementations.Library
public int? GetSeasonNumberFromPath(string path)
{
return SeriesResolver.GetSeasonNumberFromPath(path, CollectionType.TvShows);
return new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(path, true).SeasonNumber;
}
public int? GetSeasonNumberFromEpisodeFile(string path)
public bool FillMissingEpisodeNumbersFromPath(Episode episode)
{
return SeriesResolver.GetSeasonNumberFromEpisodeFile(path);
}
var resolver = new EpisodeResolver(new ExtendedNamingOptions(),
new Naming.Logging.NullLogger());
public int? GetEndingEpisodeNumberFromFile(string path)
{
return SeriesResolver.GetEndingEpisodeNumberFromFile(path);
}
var locationType = episode.LocationType;
var fileType = /*args.IsDirectory ? FileInfoType.Directory :*/ FileInfoType.File;
var episodeInfo = locationType == LocationType.FileSystem || locationType == LocationType.Offline ?
resolver.Resolve(episode.Path, fileType) :
new Naming.TV.EpisodeInfo();
public int? GetEpisodeNumberFromFile(string path, bool considerSeasonless)
{
return SeriesResolver.GetEpisodeNumberFromFile(path, considerSeasonless);
if (episodeInfo == null)
{
episodeInfo = new Naming.TV.EpisodeInfo();
}
var changed = false;
if (!episode.IndexNumber.HasValue)
{
episode.IndexNumber = episodeInfo.EpisodeNumber;
if (episode.IndexNumber.HasValue)
{
changed = true;
}
}
if (!episode.IndexNumberEnd.HasValue)
{
episode.IndexNumberEnd = episodeInfo.EndingEpsiodeNumber;
if (episode.IndexNumberEnd.HasValue)
{
changed = true;
}
}
if (!episode.ParentIndexNumber.HasValue)
{
episode.ParentIndexNumber = episodeInfo.SeasonNumber;
if (!episode.ParentIndexNumber.HasValue)
{
var season = episode.Season;
if (season != null)
{
episode.ParentIndexNumber = season.IndexNumber;
}
}
if (episode.ParentIndexNumber.HasValue)
{
changed = true;
}
}
return changed;
}
public ItemLookupInfo ParseName(string name)

View File

@ -82,8 +82,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
return ResolveVideos<Movie>(parent, files, directoryService, collectionType);
}
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
return ResolveVideos<Movie>(parent, files, directoryService, collectionType);
}
@ -117,7 +116,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
FullName = i.FullName,
Type = FileInfoType.File
}).ToList()).ToList();
}).ToList(), false).ToList();
var result = new MultiItemResolverResult
{
@ -168,12 +167,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
{
return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType, false);
return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
}
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
{
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType, false);
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
}
if (string.IsNullOrEmpty(collectionType))
@ -193,8 +192,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
}
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
}
@ -216,8 +214,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
}
// To find a movie file, the collection type must be movies or boxsets
else if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
else if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
item = ResolveVideo<Movie>(args, true);
}
@ -277,9 +274,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
/// <param name="fileSystemEntries">The file system entries.</param>
/// <param name="directoryService">The directory service.</param>
/// <param name="collectionType">Type of the collection.</param>
/// <param name="supportMultiVersion">if set to <c>true</c> [support multi version].</param>
/// <returns>Movie.</returns>
private T FindMovie<T>(string path, Folder parent, List<FileSystemInfo> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool supportMultiVersion = true)
private T FindMovie<T>(string path, Folder parent, List<FileSystemInfo> fileSystemEntries, IDirectoryService directoryService, string collectionType)
where T : Video, new()
{
var multiDiscFolders = new List<FileSystemInfo>();
@ -328,8 +324,11 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, collectionType);
var supportsMultiVersion = !string.Equals(collectionType, CollectionType.HomeVideos) &&
!string.Equals(collectionType, CollectionType.MusicVideos);
// Test for multi-editions
if (result.Items.Count > 1 && supportMultiVersion)
if (result.Items.Count > 1 && supportsMultiVersion)
{
var filenamePrefix = Path.GetFileName(path);
@ -474,7 +473,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
CollectionType.Movies,
CollectionType.HomeVideos,
CollectionType.MusicVideos,
CollectionType.BoxSets,
CollectionType.Movies
};

View File

@ -1,5 +1,7 @@
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Naming.Common;
using MediaBrowser.Naming.IO;
using System.Linq;
namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
@ -37,23 +39,10 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
}
// If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something
if (season != null || parent is Series || parent.Parents.OfType<Series>().Any())
if (season != null || args.HasParent<Series>())
{
var episode = ResolveVideo<Episode>(args, false);
if (episode != null)
{
if (season != null)
{
episode.ParentIndexNumber = season.IndexNumber;
}
if (episode.ParentIndexNumber == null)
{
episode.ParentIndexNumber = SeriesResolver.GetSeasonNumberFromEpisodeFile(args.Path);
}
}
return episode;
}

View File

@ -1,7 +1,8 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Naming.Common;
using MediaBrowser.Naming.TV;
namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
@ -35,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
var season = new Season
{
IndexNumber = SeriesResolver.GetSeasonNumberFromPath(args.Path, CollectionType.TvShows)
IndexNumber = new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(args.Path, true).SeasonNumber
};
if (season.IndexNumber.HasValue && season.IndexNumber.Value == 0)

View File

@ -1,5 +1,4 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
@ -9,10 +8,10 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using MediaBrowser.Naming.Common;
using MediaBrowser.Naming.IO;
using MediaBrowser.Naming.TV;
namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
@ -67,13 +66,11 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
var collectionType = args.GetCollectionType();
var isTvShowsFolder = string.Equals(collectionType, CollectionType.TvShows,
StringComparison.OrdinalIgnoreCase);
var isTvShowsFolder = string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase);
// If there's a collection type and it's not tv, it can't be a series
if (!string.IsNullOrEmpty(collectionType) &&
!isTvShowsFolder &&
!string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
!isTvShowsFolder)
{
return null;
}
@ -123,7 +120,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
{
if (IsSeasonFolder(child.FullName, collectionType, directoryService, fileSystem))
if (IsSeasonFolder(child.FullName, collectionType))
{
//logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
return true;
@ -137,7 +134,17 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
var isTvShowsFolder = string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase);
if (GetEpisodeNumberFromFile(fullName, isTvShowsFolder).HasValue)
// We can fast track this for known tv folders
if (isTvShowsFolder)
{
return true;
}
var resolver = new Naming.TV.EpisodeResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
var episodeInfo = resolver.Resolve(fullName, FileInfoType.File, isTvShowsFolder, false);
if (episodeInfo != null && (episodeInfo.EpisodeNumber.HasValue || episodeInfo.IsByDate))
{
return true;
}
@ -172,351 +179,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
/// </summary>
/// <param name="path">The path.</param>
/// <param name="collectionType">Type of the collection.</param>
/// <param name="directoryService">The directory service.</param>
/// <param name="fileSystem">The file system.</param>
/// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns>
private static bool IsSeasonFolder(string path, string collectionType, IDirectoryService directoryService, IFileSystem fileSystem)
private static bool IsSeasonFolder(string path, string collectionType)
{
var seasonNumber = GetSeasonNumberFromPath(path, collectionType);
var hasSeasonNumber = seasonNumber != null;
var isTvFolder = string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase);
var seasonNumber = new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(path, isTvFolder).SeasonNumber;
if (!hasSeasonNumber)
{
return false;
}
//// It's a season folder if it's named as such and does not contain any audio files, apart from theme.mp3
//foreach (var fileSystemInfo in directoryService.GetFileSystemEntries(path))
//{
// var attributes = fileSystemInfo.Attributes;
// if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
// {
// continue;
// }
// // Can't enforce this because files saved by Bitcasa are always marked System
// //if ((attributes & FileAttributes.System) == FileAttributes.System)
// //{
// // continue;
// //}
// if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
// {
// //if (IsBadFolder(fileSystemInfo.Name))
// //{
// // return false;
// //}
// }
// else
// {
// if (EntityResolutionHelper.IsAudioFile(fileSystemInfo.FullName) &&
// !string.Equals(fileSystem.GetFileNameWithoutExtension(fileSystemInfo), BaseItem.ThemeSongFilename))
// {
// return false;
// }
// }
//}
return true;
}
/// <summary>
/// A season folder must contain one of these somewhere in the name
/// </summary>
private static readonly string[] SeasonFolderNames =
{
"season",
"sæson",
"temporada",
"saison",
"staffel",
"series",
"сезон"
};
/// <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 Regex(
@".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)[sS](?<seasonnumber>\d{1,4})[x,X]?[eE](?<epnumber>\d{1,3})[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})[^\\\/]*$",
RegexOptions.Compiled)
};
private static readonly Regex[] MultipleEpisodeExpressions =
{
new Regex(
@".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[eExX](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})(-[xE]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
RegexOptions.Compiled),
new Regex(
@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
RegexOptions.Compiled)
};
/// <summary>
/// To avoid the following matching movies they are only valid when contained in a folder which has been matched as a being season, or the media type is TV series
/// </summary>
private static readonly Regex[] EpisodeExpressionsWithoutSeason =
{
new Regex(
@".*[\\\/](?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\.\w+$",
RegexOptions.Compiled),
// "01.avi"
new Regex(
@".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\s?-\s?[^\\\/]*$",
RegexOptions.Compiled),
// "01 - blah.avi", "01-blah.avi"
new Regex(
@".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\.[^\\\/]+$",
RegexOptions.Compiled),
// "01.blah.avi"
new Regex(
@".*[\\\/][^\\\/]* - (?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*[^\\\/]*$",
RegexOptions.Compiled),
// "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi", "blah 2 - 01 - blah"
};
public static int? GetSeasonNumberFromPath(string path)
{
return GetSeasonNumberFromPath(path, CollectionType.TvShows);
}
/// <summary>
/// Gets the season number from path.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="collectionType">Type of the collection.</param>
/// <returns>System.Nullable{System.Int32}.</returns>
public static int? GetSeasonNumberFromPath(string path, string collectionType)
{
var filename = Path.GetFileName(path);
if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
{
if (string.Equals(filename, "specials", StringComparison.OrdinalIgnoreCase))
{
return 0;
}
}
int val;
if (int.TryParse(filename, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
{
return val;
}
if (filename.StartsWith("s", StringComparison.OrdinalIgnoreCase))
{
var testFilename = filename.Substring(1);
if (int.TryParse(testFilename, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
{
return val;
}
}
// Look for one of the season folder names
foreach (var name in SeasonFolderNames)
{
var index = filename.IndexOf(name, StringComparison.OrdinalIgnoreCase);
if (index != -1)
{
return GetSeasonNumberFromPathSubstring(filename.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)
{
var numericStart = -1;
var length = 0;
// Find out where the numbers start, and then keep going until they end
for (var 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), CultureInfo.InvariantCulture);
}
/// <summary>
/// Episodes the number from file.
/// </summary>
/// <param name="fullPath">The full path.</param>
/// <param name="considerSeasonlessNames">if set to <c>true</c> [is in season].</param>
/// <returns>System.String.</returns>
public static int? GetEpisodeNumberFromFile(string fullPath, bool considerSeasonlessNames)
{
string fl = fullPath.ToLower();
foreach (var r in EpisodeExpressions)
{
Match m = r.Match(fl);
if (m.Success)
return ParseEpisodeNumber(m.Groups["epnumber"].Value);
}
if (considerSeasonlessNames)
{
var match = EpisodeExpressionsWithoutSeason.Select(r => r.Match(fl))
.FirstOrDefault(m => m.Success);
if (match != null)
{
return ParseEpisodeNumber(match.Groups["epnumber"].Value);
}
}
return null;
}
public static int? GetEndingEpisodeNumberFromFile(string fullPath)
{
var fl = fullPath.ToLower();
foreach (var r in MultipleEpisodeExpressions)
{
var m = r.Match(fl);
if (m.Success && !string.IsNullOrEmpty(m.Groups["endingepnumber"].Value))
return ParseEpisodeNumber(m.Groups["endingepnumber"].Value);
}
foreach (var r in EpisodeExpressionsWithoutSeason)
{
var m = r.Match(fl);
if (m.Success && !string.IsNullOrEmpty(m.Groups["endingepnumber"].Value))
return ParseEpisodeNumber(m.Groups["endingepnumber"].Value);
}
return null;
}
/// <summary>
/// Seasons the number from episode file.
/// </summary>
/// <param name="fullPath">The full path.</param>
/// <returns>System.String.</returns>
public static int? GetSeasonNumberFromEpisodeFile(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)
{
var val = g.Value;
if (!string.IsNullOrWhiteSpace(val))
{
int num;
if (int.TryParse(val, NumberStyles.Integer, UsCulture, out num))
{
return num;
}
}
}
return null;
}
}
return null;
}
public static string GetSeriesNameFromEpisodeFile(string fullPath)
{
var fl = fullPath.ToLower();
foreach (var r in EpisodeExpressions)
{
var m = r.Match(fl);
if (m.Success)
{
var g = m.Groups["seriesname"];
if (g != null)
{
var val = g.Value;
if (!string.IsNullOrWhiteSpace(val))
{
return val;
}
}
return null;
}
}
return null;
}
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private static int? ParseEpisodeNumber(string val)
{
int num;
if (!string.IsNullOrEmpty(val) && int.TryParse(val, NumberStyles.Integer, UsCulture, out num))
{
return num;
}
return null;
return seasonNumber.HasValue;
}
/// <summary>

View File

@ -781,20 +781,29 @@ namespace MediaBrowser.Server.Implementations.Library
{
lock (_policySyncLock)
{
return (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), path);
return (UserPolicy) _xmlSerializer.DeserializeFromFile(typeof (UserPolicy), path);
}
}
catch (FileNotFoundException)
{
return GetDefaultPolicy(user);
}
catch (Exception ex)
{
_logger.ErrorException("Error reading policy file: {0}", ex, path);
return new UserPolicy
{
EnableSync = !user.ConnectLinkType.HasValue || user.ConnectLinkType.Value != UserLinkType.Guest
};
return GetDefaultPolicy(user);
}
}
private UserPolicy GetDefaultPolicy(User user)
{
return new UserPolicy
{
EnableSync = true
};
}
private readonly object _policySyncLock = new object();
public async Task UpdateUserPolicy(string userId, UserPolicy userPolicy)
{

View File

@ -650,7 +650,7 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
"OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
"OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
"OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
"LabelItemLimit": "Item limit:",

View File

@ -1295,5 +1295,6 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
"TitleSync": "Sync"
"TitleSync": "Sync",
"OptionAllowSyncContent": "Allow syncing media to devices"
}

View File

@ -51,7 +51,7 @@
</Reference>
<Reference Include="MediaBrowser.Naming, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.18\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.21\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
</Reference>
<Reference Include="Mono.Nat, Version=1.2.21.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>

View File

@ -61,7 +61,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public bool IsHidden
{
get { return true; }
get { return false; }
}
public bool IsEnabled

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.Naming" version="1.0.0.18" targetFramework="net45" />
<package id="MediaBrowser.Naming" version="1.0.0.21" targetFramework="net45" />
<package id="Mono.Nat" version="1.2.21.0" targetFramework="net45" />
<package id="morelinq" version="1.1.0" targetFramework="net45" />
</packages>

View File

@ -363,7 +363,6 @@ namespace MediaBrowser.Server.Startup.Common
var migrations = new List<IVersionMigration>
{
new MigrateUserFolders(ApplicationPaths),
new PlaylistImages(ServerConfigurationManager),
new RenameXbmcOptions(ServerConfigurationManager),
new RenameXmlOptions(ServerConfigurationManager),
new DeprecatePlugins(ApplicationPaths),

View File

@ -67,7 +67,6 @@
<Compile Include="Migrations\DeprecatePlugins.cs" />
<Compile Include="Migrations\IVersionMigration.cs" />
<Compile Include="Migrations\MigrateUserFolders.cs" />
<Compile Include="Migrations\PlaylistImages.cs" />
<Compile Include="Migrations\RenameXbmcOptions.cs" />
<Compile Include="Migrations\RenameXmlOptions.cs" />
<Compile Include="NativeEnvironment.cs" />

View File

@ -1,55 +0,0 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using System.IO;
using System.Linq;
namespace MediaBrowser.Server.Startup.Common.Migrations
{
public class PlaylistImages : IVersionMigration
{
private readonly IServerConfigurationManager _config;
public PlaylistImages(IServerConfigurationManager config)
{
_config = config;
}
public void Run()
{
if (!_config.Configuration.PlaylistImagesDeleted)
{
DeletePlaylistImages();
_config.Configuration.PlaylistImagesDeleted = true;
_config.SaveConfiguration();
}
}
private void DeletePlaylistImages()
{
try
{
var path = Path.Combine(_config.ApplicationPaths.DataPath, "playlists");
var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories)
.Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i) ?? string.Empty))
.ToList();
foreach (var file in files)
{
try
{
File.Delete(file);
}
catch (IOException)
{
}
}
}
catch (IOException)
{
}
}
}
}

View File

@ -53,7 +53,6 @@
<Compile Include="MediaEncoding\Subtitles\AssParserTests.cs" />
<Compile Include="MediaEncoding\Subtitles\SrtParserTests.cs" />
<Compile Include="MediaEncoding\Subtitles\VttWriterTest.cs" />
<Compile Include="Resolvers\TvUtilTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -1,246 +0,0 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Server.Implementations.Library.Resolvers.TV;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MediaBrowser.Tests.Resolvers
{
[TestClass]
public class TvUtilTests
{
[TestMethod]
public void TestGetEpisodeNumberFromFile()
{
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\S02E03 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\01x02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\S01x02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\S01E02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\S01xE02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\seriesname 01x02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\seriesname S01x02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\seriesname S01E02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\seriesname S01xE02 blah.avi", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\Elementary - 02x03 - 02x04 - 02x15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\02x03 - 02x04 - 02x15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\02x03-04-15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\Elementary - 02x03-04-15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\02x03-E15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\Elementary - 02x03-E15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\02x03 - x04 - x15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\Elementary - 02x03 - x04 - x15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\02x03x04x15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\Elementary - 02x03x04x15 - Ep Name.ext", true));
Assert.AreEqual(23, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\Elementary - S01E23-E24-E26 - The Woman.mp4", true));
Assert.AreEqual(23, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\S01E23-E24-E26 - The Woman.mp4", true));
Assert.AreEqual(9, SeriesResolver.GetEpisodeNumberFromFile(@"Season 25\The Simpsons.S25E09.Steal this episode.mp4", true));
Assert.AreEqual(8, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons.S25E08.Steal this episode.mp4", false));
Assert.AreEqual(136, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\[HorribleSubs] Hunter X Hunter - 136 [720p].mkv",true));
//Four Digits seasons
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\S2009x02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\S2009E02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\S2009xE02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\seriesname 2009x02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\seriesname S2009x02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\seriesname S2009E02 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\seriesname S2009xE02 blah.avi", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x03 - 2009x04 - 2009x15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x03-04-15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03-04-15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x03-E15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03-E15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x03 - x04 - x15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03 - x04 - x15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x03x04x15 - Ep Name.ext", true));
Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03x04x15 - Ep Name.ext", true));
Assert.AreEqual(23, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - S2009E23-E24-E26 - The Woman.mp4", true));
Assert.AreEqual(23, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\S2009E23-E24-E26 - The Woman.mp4", true));
//Without season number
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\02 - blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\02 - blah 14 blah.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\02 - blah-02 a.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\02.avi", true));
//Without seasons
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\02.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\02 - Ep Name.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\02-Ep Name.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\02.EpName.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons - 02.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons - 02 - Ep Name.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons - 02 Ep Name.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons 5 - 02 - Ep Name.avi", true));
Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons 5 - 02 Ep Name.avi", true));
}
[TestMethod]
public void TestGetEndingEpisodeNumberFromFile()
{
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\4x01 20 Hours in America (1).mkv"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\01x02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\S01x02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\S01E02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\S01xE02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\seriesname 01x02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\seriesname S01x02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\seriesname S01E02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\seriesname S01xE02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02x03 - 04 Ep Name.ext"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\My show name 02x03 - 04 Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\Elementary - 02x03 - 02x04 - 02x15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02x03 - 02x04 - 02x15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02x03-04-15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\Elementary - 02x03-04-15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\02x03-E15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\Elementary - 02x03-E15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\02x03 - x04 - x15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\Elementary - 02x03 - x04 - x15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\02x03x04x15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\Elementary - 02x03x04x15 - Ep Name.ext"));
Assert.AreEqual(26, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\Elementary - S01E23-E24-E26 - The Woman.mp4"));
Assert.AreEqual(26, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\S01E23-E24-E26 - The Woman.mp4"));
//Four Digits seasons
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\S2009x02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\S2009E02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\S2009xE02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\seriesname 2009x02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\seriesname S2009x02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\seriesname S2009E02 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\seriesname S2009xE02 blah.avi"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x03 - 2009x04 - 2009x15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x03-04-15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03-04-15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x03-E15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03-E15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x03 - x04 - x15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03 - x04 - x15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x03x04x15 - Ep Name.ext"));
Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03x04x15 - Ep Name.ext"));
Assert.AreEqual(26, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - S2009E23-E24-E26 - The Woman.mp4"));
Assert.AreEqual(26, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\S2009E23-E24-E26 - The Woman.mp4"));
//Without season number
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\02 - blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02 - blah 14 blah.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\02 - blah-02 a.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02.avi"));
Assert.AreEqual(3, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\02-03 - blah.avi"));
Assert.AreEqual(4, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02-04 - blah 14 blah.avi"));
Assert.AreEqual(5, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\02-05 - blah-02 a.avi"));
Assert.AreEqual(4, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02-04.avi"));
Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\[HorribleSubs] Hunter X Hunter - 136 [720p].mkv"));
}
[TestMethod]
public void TestGetSeasonNumberFromPath() {
Assert.AreEqual(02, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"\Show\Season 02\S02E03 blah.avi"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Seinfeld\S02"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Seinfeld\2"));
//Four Digits seasons
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
}
[TestMethod]
public void TestGetSeasonNumberFromEpisodeFile()
{
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\01x02 blah.avi"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\S01x02 blah.avi"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\S01E02 blah.avi"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\S01xE02 blah.avi"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\seriesname 01x02 blah.avi"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\seriesname S01x02 blah.avi"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\seriesname S01E02 blah.avi"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\seriesname S01xE02 blah.avi"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2\Elementary - 02x03 - 02x04 - 02x15 - Ep Name.ext"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2\02x03 - 02x04 - 02x15 - Ep Name.ext"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2\02x03-04-15 - Ep Name.ext"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2\Elementary - 02x03-04-15 - Ep Name.ext"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\02x03-E15 - Ep Name.ext"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\Elementary - 02x03-E15 - Ep Name.ext"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\02x03 - x04 - x15 - Ep Name.ext"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\Elementary - 02x03 - x04 - x15 - Ep Name.ext"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\02x03x04x15 - Ep Name.ext"));
Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\Elementary - 02x03x04x15 - Ep Name.ext"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\Elementary - S01E23-E24-E26 - The Woman.mp4"));
Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\S01E23-E24-E26 - The Woman.mp4"));
//Four Digits seasons
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x02 blah.avi"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\S2009x02 blah.avi"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\S2009E02 blah.avi"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\S2009xE02 blah.avi"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\seriesname 2009x02 blah.avi"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\seriesname S2009x02 blah.avi"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\seriesname S2009E02 blah.avi"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\seriesname S2009xE02 blah.avi"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.ext"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x03 - 2009x04 - 2009x15 - Ep Name.ext"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x03-04-15 - Ep Name.ext"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - 2009x03-04-15 - Ep Name.ext"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x03-E15 - Ep Name.ext"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - 2009x03-E15 - Ep Name.ext"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x03 - x04 - x15 - Ep Name.ext"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - 2009x03 - x04 - x15 - Ep Name.ext"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x03x04x15 - Ep Name.ext"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - 2009x03x04x15 - Ep Name.ext"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - S2009E23-E24-E26 - The Woman.mp4"));
Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\S2009E23-E24-E26 - The Woman.mp4"));
Assert.AreEqual(25, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 25\The Simpsons.S25E09.Steal this episode.mp4"));
Assert.AreEqual(25, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"The Simpsons\The Simpsons.S25E09.Steal this episode.mp4"));
}
}
}

View File

@ -197,6 +197,7 @@ namespace MediaBrowser.WebDashboard.Api
{
"thirdparty/jquerymobile-1.4.5/jquery.mobile-1.4.5.min.css",
"thirdparty/swipebox-master/css/swipebox.min.css" + versionString,
"thirdparty/fontawesome/css/font-awesome.min.css" + versionString,
"css/all.css" + versionString
};

View File

@ -963,6 +963,15 @@
<Content Include="dashboard-ui\thirdparty\cast_sender.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\thirdparty\fontawesome\css\font-awesome.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\thirdparty\fontawesome\css\font-awesome.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\thirdparty\fontawesome\fonts\fontawesome-webfont.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\thirdparty\jquery-2.1.1.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -2917,6 +2926,18 @@
<None Include="dashboard-ui\css\fonts\RobotoThin.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="dashboard-ui\thirdparty\fontawesome\fonts\fontawesome-webfont.eot">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="dashboard-ui\thirdparty\fontawesome\fonts\fontawesome-webfont.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="dashboard-ui\thirdparty\fontawesome\fonts\fontawesome-webfont.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="dashboard-ui\thirdparty\fontawesome\fonts\FontAwesome.otf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\jquery.mobile-1.4.3.min.map">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View File

@ -7,7 +7,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{F0E0E6
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8C5D6ABC-D277-407B-8061-3AA04251D539}"
ProjectSection(SolutionItems) = preProject
Performance1.psess = Performance1.psess
Performance19.psess = Performance19.psess
Performance2.psess = Performance2.psess
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget (2)", ".nuget (2)", "{E60FB157-87E2-4A41-8B04-27EA49B63B4D}"
@ -516,4 +518,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
EndGlobal

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
<version>3.0.521</version>
<version>3.0.522</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.521" />
<dependency id="MediaBrowser.Common" version="3.0.522" />
<dependency id="NLog" version="3.1.0.0" />
<dependency id="SimpleInjector" version="2.6.1" />
<dependency id="sharpcompress" version="0.10.2" />

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
<version>3.0.521</version>
<version>3.0.522</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Model.Signed</id>
<version>3.0.521</version>
<version>3.0.522</version>
<title>MediaBrowser.Model - Signed Edition</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
<version>3.0.521</version>
<version>3.0.522</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.521" />
<dependency id="MediaBrowser.Common" version="3.0.522" />
</dependencies>
</metadata>
<files>

View File

@ -1,4 +1,4 @@
using System.Reflection;
//[assembly: AssemblyVersion("3.0.*")]
[assembly: AssemblyVersion("3.0.5464.40000")]
[assembly: AssemblyVersion("3.0.*")]
//[assembly: AssemblyVersion("3.0.5464.40000")]