Moved the http server to it's own assembly. added comments and made other minor re-organizations.

This commit is contained in:
LukePulverenti Luke Pulverenti luke pulverenti 2012-07-19 22:22:44 -04:00
parent 6fbd5cf464
commit 80b3ad7bd2
67 changed files with 806 additions and 964 deletions

View file

@ -1,10 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using MediaBrowser.Controller;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Api
{
/// <summary>
/// Contains some helpers for the api
/// </summary>
public static class ApiService
{
public static BaseItem GetItemById(string id)
@ -14,86 +20,29 @@ namespace MediaBrowser.Api
return Kernel.Instance.GetItemById(guid);
}
public static IEnumerable<CategoryInfo> GetAllStudios(Folder parent, Guid userId)
/// <summary>
/// Takes a BaseItem and returns the actual object that will be serialized by the api
/// </summary>
public static ApiBaseItemWrapper<BaseItem> GetSerializationObject(BaseItem item, bool includeChildren, Guid userId)
{
Dictionary<string, int> data = new Dictionary<string, int>();
IEnumerable<BaseItem> allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId);
foreach (var item in allItems)
ApiBaseItemWrapper<BaseItem> wrapper = new ApiBaseItemWrapper<BaseItem>()
{
if (item.Studios == null)
{
continue;
}
Item = item,
UserItemData = Kernel.Instance.GetUserItemData(userId, item.Id),
ItemType = item.GetType()
};
foreach (string val in item.Studios)
if (includeChildren)
{
var folder = item as Folder;
if (folder != null)
{
if (!data.ContainsKey(val))
{
data.Add(val, 1);
}
else
{
data[val]++;
}
wrapper.Children = Kernel.Instance.GetParentalAllowedChildren(folder, userId).Select(c => GetSerializationObject(c, false, userId));
}
}
List<CategoryInfo> list = new List<CategoryInfo>();
foreach (string key in data.Keys)
{
list.Add(new CategoryInfo()
{
Name = key,
ItemCount = data[key]
});
}
return list;
}
public static IEnumerable<CategoryInfo> GetAllGenres(Folder parent, Guid userId)
{
Dictionary<string, int> data = new Dictionary<string, int>();
IEnumerable<BaseItem> allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId);
foreach (var item in allItems)
{
if (item.Genres == null)
{
continue;
}
foreach (string val in item.Genres)
{
if (!data.ContainsKey(val))
{
data.Add(val, 1);
}
else
{
data[val]++;
}
}
}
List<CategoryInfo> list = new List<CategoryInfo>();
foreach (string key in data.Keys)
{
list.Add(new CategoryInfo()
{
Name = key,
ItemCount = data[key]
});
}
return list;
return wrapper;
}
}
}

View file

@ -1,5 +1,4 @@
using System.Collections.Generic;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Model.Entities;
@ -10,11 +9,6 @@ namespace MediaBrowser.Api.HttpHandlers
/// </summary>
public class GenreHandler : ItemListHandler
{
public GenreHandler(RequestContext ctx)
: base(ctx)
{
}
protected override IEnumerable<BaseItem> ItemsToSerialize
{
get

View file

@ -1,17 +1,11 @@
using System;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Controller;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Api.HttpHandlers
{
public class GenresHandler : JsonHandler
{
public GenresHandler(RequestContext ctx)
: base(ctx)
{
}
protected sealed override object ObjectToSerialize
{
get
@ -19,7 +13,7 @@ namespace MediaBrowser.Api.HttpHandlers
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
Guid userId = Guid.Parse(QueryString["userid"]);
return ApiService.GetAllGenres(parent, userId);
return Kernel.Instance.GetAllGenres(parent, userId);
}
}
}

View file

@ -1,27 +1,14 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Model.Entities;
using MediaBrowser.Net.Handlers;
namespace MediaBrowser.Api.HttpHandlers
{
public class ImageHandler : Response
public class ImageHandler : BaseHandler
{
public ImageHandler(RequestContext ctx)
: base(ctx)
{
Headers["Content-Encoding"] = "gzip";
WriteStream = s =>
{
WriteReponse(s);
s.Close();
};
}
private string _ImagePath = string.Empty;
private string ImagePath
{
@ -149,12 +136,9 @@ namespace MediaBrowser.Api.HttpHandlers
}
}
private void WriteReponse(Stream stream)
protected override void WriteResponseToOutputStream(Stream stream)
{
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, false))
{
ImageProcessor.ProcessImage(ImagePath, gzipStream, Width, Height, MaxWidth, MaxHeight, Quality);
}
ImageProcessor.ProcessImage(ImagePath, stream, Width, Height, MaxWidth, MaxHeight, Quality);
}
private string GetImagePath()

View file

@ -1,5 +1,4 @@
using System.Collections.Generic;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Model.Entities;
@ -7,11 +6,6 @@ namespace MediaBrowser.Api.HttpHandlers
{
class InProgressItemsHandler : ItemListHandler
{
public InProgressItemsHandler(RequestContext ctx)
: base(ctx)
{
}
protected override IEnumerable<BaseItem> ItemsToSerialize
{
get

View file

@ -1,50 +1,21 @@
using System;
using MediaBrowser.Api.Model;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Controller;
using MediaBrowser.Net.Handlers;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Api.HttpHandlers
{
public class ItemHandler : JsonHandler
{
public ItemHandler(RequestContext ctx)
: base(ctx)
{
}
protected sealed override object ObjectToSerialize
{
get
{
Guid userId = Guid.Parse(QueryString["userid"]);
return GetSerializationObject(ItemToSerialize, true, userId);
return ApiService.GetSerializationObject(ItemToSerialize, true, userId);
}
}
public static object GetSerializationObject(BaseItem item, bool includeChildren, Guid userId)
{
BaseItemInfo wrapper = new BaseItemInfo()
{
Item = item,
UserItemData = Kernel.Instance.GetUserItemData(userId, item.Id)
};
if (includeChildren)
{
var folder = item as Folder;
if (folder != null)
{
wrapper.Children = Kernel.Instance.GetParentalAllowedChildren(folder, userId);
}
}
return wrapper;
}
protected virtual BaseItem ItemToSerialize
{
get

View file

@ -1,26 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Net.Handlers;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Api.HttpHandlers
{
public abstract class ItemListHandler : JsonHandler
{
public ItemListHandler(RequestContext ctx)
: base(ctx)
{
}
protected sealed override object ObjectToSerialize
{
get
{
return ItemsToSerialize.Select(i =>
{
return ItemHandler.GetSerializationObject(i, false, UserId);
return ApiService.GetSerializationObject(i, false, UserId);
});
}

View file

@ -0,0 +1,16 @@
using System.IO;
using MediaBrowser.Common.Json;
using MediaBrowser.Net.Handlers;
namespace MediaBrowser.Api.HttpHandlers
{
public abstract class JsonHandler : BaseJsonHandler
{
protected abstract object ObjectToSerialize { get; }
protected override void WriteResponseToOutputStream(Stream stream)
{
JsonSerializer.SerializeToStream(ObjectToSerialize, stream);
}
}
}

View file

@ -1,23 +1,12 @@
using System;
using System.IO;
using System.IO.Compression;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Net.Handlers;
namespace MediaBrowser.Api.HttpHandlers
{
class MediaHandler : Response
class MediaHandler : BaseHandler
{
public MediaHandler(RequestContext ctx)
: base(ctx)
{
WriteStream = s =>
{
WriteReponse(s);
s.Close();
};
}
private string _MediaPath = string.Empty;
private string MediaPath
{
@ -46,6 +35,14 @@ namespace MediaBrowser.Api.HttpHandlers
return item.Path;
}
public override bool GzipResponse
{
get
{
return false;
}
}
public override string ContentType
{
get
@ -87,7 +84,7 @@ namespace MediaBrowser.Api.HttpHandlers
}
}
private void WriteReponse(Stream stream)
protected override void WriteResponseToOutputStream(Stream stream)
{
try
{
@ -100,6 +97,5 @@ namespace MediaBrowser.Api.HttpHandlers
{
}
}
}
}

View file

@ -1,16 +1,10 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Api.HttpHandlers
{
public class PersonHandler : ItemHandler
{
public PersonHandler(RequestContext ctx)
: base(ctx)
{
}
protected override BaseItem ItemToSerialize
{
get

View file

@ -1,5 +1,4 @@
using System.Collections.Generic;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Model.Entities;
@ -7,11 +6,6 @@ namespace MediaBrowser.Api.HttpHandlers
{
class RecentlyAddedItemsHandler : ItemListHandler
{
public RecentlyAddedItemsHandler(RequestContext ctx)
: base(ctx)
{
}
protected override IEnumerable<BaseItem> ItemsToSerialize
{
get

View file

@ -1,5 +1,4 @@
using System.Collections.Generic;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Model.Entities;
@ -10,11 +9,6 @@ namespace MediaBrowser.Api.HttpHandlers
/// </summary>
public class StudioHandler : ItemListHandler
{
public StudioHandler(RequestContext ctx)
: base(ctx)
{
}
protected override IEnumerable<BaseItem> ItemsToSerialize
{
get

View file

@ -1,17 +1,12 @@
using System;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Net.Handlers;
using MediaBrowser.Controller;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Api.HttpHandlers
{
public class StudiosHandler : JsonHandler
{
public StudiosHandler(RequestContext ctx)
: base(ctx)
{
}
protected sealed override object ObjectToSerialize
{
get
@ -19,7 +14,7 @@ namespace MediaBrowser.Api.HttpHandlers
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
Guid userId = Guid.Parse(QueryString["userid"]);
return ApiService.GetAllStudios(parent, userId);
return Kernel.Instance.GetAllStudios(parent, userId);
}
}
}

View file

@ -1,16 +1,10 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Net.Handlers;
using MediaBrowser.Controller;
namespace MediaBrowser.Api.HttpHandlers
{
class UsersHandler : JsonHandler
{
public UsersHandler(RequestContext ctx)
: base(ctx)
{
}
protected override object ObjectToSerialize
{
get

View file

@ -37,6 +37,7 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@ -51,6 +52,7 @@
<Compile Include="HttpHandlers\InProgressItemsHandler.cs" />
<Compile Include="HttpHandlers\ItemHandler.cs" />
<Compile Include="HttpHandlers\ItemListHandler.cs" />
<Compile Include="HttpHandlers\JsonHandler.cs" />
<Compile Include="HttpHandlers\PersonHandler.cs" />
<Compile Include="HttpHandlers\RecentlyAddedItemsHandler.cs" />
<Compile Include="HttpHandlers\StudioHandler.cs" />
@ -58,7 +60,6 @@
<Compile Include="HttpHandlers\UsersHandler.cs" />
<Compile Include="ImageProcessor.cs" />
<Compile Include="HttpHandlers\MediaHandler.cs" />
<Compile Include="Model\BaseItemInfo.cs" />
<Compile Include="Plugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
@ -75,6 +76,10 @@
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Net\MediaBrowser.Net.csproj">
<Project>{5da08d1c-0d52-4b1b-aa66-e4a171d938f6}</Project>
<Name>MediaBrowser.Net</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View file

@ -1,15 +0,0 @@
using System.Collections.Generic;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Api.Model
{
public class BaseItemInfo
{
public BaseItem Item { get; set; }
public UserItemData UserItemData { get; set; }
public IEnumerable<BaseItem> Children { get; set; }
}
}

View file

@ -3,6 +3,8 @@ using System.Reactive.Linq;
using MediaBrowser.Api.HttpHandlers;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Controller;
using MediaBrowser.Net;
using MediaBrowser.Net.Handlers;
namespace MediaBrowser.Api
{
@ -12,25 +14,70 @@ namespace MediaBrowser.Api
{
var httpServer = Kernel.Instance.HttpServer;
httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/users", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new UsersHandler(ctx)));
httpServer.Where(ctx => ctx.LocalPath.IndexOf("/api/", StringComparison.OrdinalIgnoreCase) != -1).Subscribe(ctx =>
{
BaseHandler handler = GetHandler(ctx);
httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/media", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new MediaHandler(ctx)));
if (handler != null)
{
ctx.Respond(handler);
}
});
}
httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/item", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new ItemHandler(ctx)));
private BaseHandler GetHandler(RequestContext ctx)
{
BaseHandler handler = null;
httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/image", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new ImageHandler(ctx)));
string localPath = ctx.LocalPath;
httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/genre", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new GenreHandler(ctx)));
if (localPath.EndsWith("/api/item", StringComparison.OrdinalIgnoreCase))
{
handler = new ItemHandler();
}
else if (localPath.EndsWith("/api/image", StringComparison.OrdinalIgnoreCase))
{
handler = new ImageHandler();
}
else if (localPath.EndsWith("/api/users", StringComparison.OrdinalIgnoreCase))
{
handler = new UsersHandler();
}
else if (localPath.EndsWith("/api/media", StringComparison.OrdinalIgnoreCase))
{
handler = new MediaHandler();
}
else if (localPath.EndsWith("/api/genre", StringComparison.OrdinalIgnoreCase))
{
handler = new GenreHandler();
}
else if (localPath.EndsWith("/api/genres", StringComparison.OrdinalIgnoreCase))
{
handler = new GenresHandler();
}
else if (localPath.EndsWith("/api/studio", StringComparison.OrdinalIgnoreCase))
{
handler = new StudioHandler();
}
else if (localPath.EndsWith("/api/studios", StringComparison.OrdinalIgnoreCase))
{
handler = new StudiosHandler();
}
else if (localPath.EndsWith("/api/recentlyaddeditems", StringComparison.OrdinalIgnoreCase))
{
handler = new RecentlyAddedItemsHandler();
}
else if (localPath.EndsWith("/api/inprogressitems", StringComparison.OrdinalIgnoreCase))
{
handler = new InProgressItemsHandler();
}
httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/genres", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new GenresHandler(ctx)));
if (handler != null)
{
handler.RequestContext = ctx;
}
httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/studio", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new StudioHandler(ctx)));
httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/studios", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new StudiosHandler(ctx)));
httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/recentlyaddeditems", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new RecentlyAddedItemsHandler(ctx)));
httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/inprogressitems", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new InProgressItemsHandler(ctx)));
return handler;
}
}
}

View file

@ -2,11 +2,12 @@
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using MediaBrowser.Common.Json;
using MediaBrowser.Model.Users;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Common.ApiInteraction
{
@ -21,19 +22,20 @@ namespace MediaBrowser.Common.ApiInteraction
WebClient = new WebClient();
}
public async Task<DictionaryBaseItem> GetRootItem(Guid userId)
public async Task<ApiBaseItemWrapper<ApiBaseItem>> GetRootItem(Guid userId)
{
string url = ApiUrl + "/item?userId=" + userId.ToString();
Stream stream = await WebClient.OpenReadTaskAsync(url);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (Stream stream = await WebClient.OpenReadTaskAsync(url))
{
return DictionaryBaseItem.FromApiOutput(gzipStream);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
{
return DeserializeBaseItemWrapper(gzipStream);
}
}
}
public async Task<DictionaryBaseItem> GetItem(Guid id, Guid userId)
public async Task<ApiBaseItemWrapper<ApiBaseItem>> GetItem(Guid id, Guid userId)
{
string url = ApiUrl + "/item?userId=" + userId.ToString();
@ -42,11 +44,12 @@ namespace MediaBrowser.Common.ApiInteraction
url += "&id=" + id.ToString();
}
Stream stream = await WebClient.OpenReadTaskAsync(url);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (Stream stream = await WebClient.OpenReadTaskAsync(url))
{
return DictionaryBaseItem.FromApiOutput(gzipStream);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
{
return DeserializeBaseItemWrapper(gzipStream);
}
}
}
@ -54,11 +57,12 @@ namespace MediaBrowser.Common.ApiInteraction
{
string url = ApiUrl + "/users";
Stream stream = await WebClient.OpenReadTaskAsync(url);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (Stream stream = await WebClient.OpenReadTaskAsync(url))
{
return JsonSerializer.DeserializeFromStream<IEnumerable<User>>(gzipStream);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
{
return JsonSerializer.DeserializeFromStream<IEnumerable<User>>(gzipStream);
}
}
}
@ -66,11 +70,12 @@ namespace MediaBrowser.Common.ApiInteraction
{
string url = ApiUrl + "/genres?userId=" + userId.ToString();
Stream stream = await WebClient.OpenReadTaskAsync(url);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (Stream stream = await WebClient.OpenReadTaskAsync(url))
{
return JsonSerializer.DeserializeFromStream<IEnumerable<CategoryInfo>>(gzipStream);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
{
return JsonSerializer.DeserializeFromStream<IEnumerable<CategoryInfo>>(gzipStream);
}
}
}
@ -78,11 +83,12 @@ namespace MediaBrowser.Common.ApiInteraction
{
string url = ApiUrl + "/genre?userId=" + userId.ToString() + "&name=" + name;
Stream stream = await WebClient.OpenReadTaskAsync(url);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (Stream stream = await WebClient.OpenReadTaskAsync(url))
{
return JsonSerializer.DeserializeFromStream<CategoryInfo>(gzipStream);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
{
return JsonSerializer.DeserializeFromStream<CategoryInfo>(gzipStream);
}
}
}
@ -90,11 +96,12 @@ namespace MediaBrowser.Common.ApiInteraction
{
string url = ApiUrl + "/studios?userId=" + userId.ToString();
Stream stream = await WebClient.OpenReadTaskAsync(url);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (Stream stream = await WebClient.OpenReadTaskAsync(url))
{
return JsonSerializer.DeserializeFromStream<IEnumerable<CategoryInfo>>(gzipStream);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
{
return JsonSerializer.DeserializeFromStream<IEnumerable<CategoryInfo>>(gzipStream);
}
}
}
@ -102,12 +109,20 @@ namespace MediaBrowser.Common.ApiInteraction
{
string url = ApiUrl + "/studio?userId=" + userId.ToString() + "&name=" + name;
Stream stream = await WebClient.OpenReadTaskAsync(url);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (Stream stream = await WebClient.OpenReadTaskAsync(url))
{
return JsonSerializer.DeserializeFromStream<CategoryInfo>(gzipStream);
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
{
return JsonSerializer.DeserializeFromStream<CategoryInfo>(gzipStream);
}
}
}
private static ApiBaseItemWrapper<ApiBaseItem> DeserializeBaseItemWrapper(Stream stream)
{
ApiBaseItemWrapper<ApiBaseItem> data = JsonSerializer.DeserializeFromStream<ApiBaseItemWrapper<ApiBaseItem>>(stream);
return data;
}
}
}

View file

@ -1,412 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using MediaBrowser.Common.Json;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
using System.Linq;
namespace MediaBrowser.Common.ApiInteraction
{
public class DictionaryBaseItem : BaseItem
{
private Dictionary<string, object> Dictionary { get; set; }
public UserItemData UserItemData { get; set; }
public IEnumerable<DictionaryBaseItem> Children { get; set; }
public DictionaryBaseItem(Dictionary<string, object> dictionary)
{
Dictionary = dictionary;
}
public override string Name
{
get
{
return GetString("Name");
}
set
{
SetValue("Name", value);
}
}
public override string ArtImagePath
{
get
{
return GetString("ArtImagePath");
}
set
{
SetValue("ArtImagePath", value);
}
}
public override string AspectRatio
{
get
{
return GetString("AspectRatio");
}
set
{
SetValue("AspectRatio", value);
}
}
public override string BannerImagePath
{
get
{
return GetString("BannerImagePath");
}
set
{
SetValue("BannerImagePath", value);
}
}
public override string CustomPin
{
get
{
return GetString("CustomPin");
}
set
{
SetValue("CustomPin", value);
}
}
public override string CustomRating
{
get
{
return GetString("CustomRating");
}
set
{
SetValue("CustomRating", value);
}
}
public override string DisplayMediaType
{
get
{
return GetString("DisplayMediaType");
}
set
{
SetValue("DisplayMediaType", value);
}
}
public override string LogoImagePath
{
get
{
return GetString("LogoImagePath");
}
set
{
SetValue("LogoImagePath", value);
}
}
public override string OfficialRating
{
get
{
return GetString("OfficialRating");
}
set
{
SetValue("OfficialRating", value);
}
}
public override string Overview
{
get
{
return GetString("Overview");
}
set
{
SetValue("Overview", value);
}
}
public override string Path
{
get
{
return GetString("Path");
}
set
{
SetValue("Path", value);
}
}
public override string PrimaryImagePath
{
get
{
return GetString("PrimaryImagePath");
}
set
{
SetValue("PrimaryImagePath", value);
}
}
public override string SortName
{
get
{
return GetString("SortName");
}
set
{
SetValue("SortName", value);
}
}
public override string Tagline
{
get
{
return GetString("Tagline");
}
set
{
SetValue("Tagline", value);
}
}
public override string TrailerUrl
{
get
{
return GetString("TrailerUrl");
}
set
{
SetValue("TrailerUrl", value);
}
}
public override DateTime DateCreated
{
get
{
return GetDateTime("DateCreated");
}
set
{
SetValue("DateCreated", value);
}
}
public override DateTime DateModified
{
get
{
return GetDateTime("DateModified");
}
set
{
SetValue("DateModified", value);
}
}
public override float? UserRating
{
get
{
return GetNullableFloat("UserRating");
}
set
{
SetValue("UserRating", value);
}
}
public override string ThumbnailImagePath
{
get
{
return GetString("ThumbnailImagePath");
}
set
{
SetValue("ThumbnailImagePath", value);
}
}
public override int? ProductionYear
{
get
{
return GetNullableInt("ProductionYear");
}
set
{
SetValue("ProductionYear", value);
}
}
public override TimeSpan? RunTime
{
get
{
return GetNullableTimeSpan("RunTime");
}
set
{
SetValue("RunTime", value);
}
}
public bool IsFolder
{
get
{
return GetBool("IsFolder");
}
}
public override Guid Id
{
get
{
return GetGuid("Id");
}
set
{
SetValue("Id", value);
}
}
public TimeSpan? GetNullableTimeSpan(string name)
{
string val = Dictionary[name] as string;
if (string.IsNullOrEmpty(val))
{
return null;
}
return TimeSpan.Parse(val);
}
public int? GetNullableInt(string name)
{
string val = Dictionary[name] as string;
if (string.IsNullOrEmpty(val))
{
return null;
}
return int.Parse(val);
}
public float? GetNullableFloat(string name)
{
string val = Dictionary[name] as string;
if (string.IsNullOrEmpty(val))
{
return null;
}
return float.Parse(val);
}
public DateTime? GetNullableDateTime(string name)
{
string val = Dictionary[name] as string;
if (string.IsNullOrEmpty(val))
{
return null;
}
return DateTime.Parse(val);
}
public DateTime GetDateTime(string name)
{
DateTime? val = GetNullableDateTime(name);
return val ?? DateTime.MinValue;
}
public bool? GetNullableBool(string name)
{
string val = Dictionary[name] as string;
if (string.IsNullOrEmpty(val))
{
return null;
}
return val != "false";
}
public Guid GetGuid(string name)
{
string val = GetString(name);
if (string.IsNullOrEmpty(val))
{
return Guid.Empty;
}
return Guid.Parse(val);
}
public bool GetBool(string name)
{
bool? val = GetNullableBool(name);
return val ?? false;
}
public string GetString(string name)
{
return Dictionary[name] as string;
}
private void SetValue<T>(string name, T value)
{
Dictionary[name] = value;
}
public static DictionaryBaseItem FromApiOutput(Stream stream)
{
Dictionary<string, object> data = JsonSerializer.DeserializeFromStream<Dictionary<string, object>>(stream);
string baseItem = data["Item"] as string;
DictionaryBaseItem item = new DictionaryBaseItem(JsonSerializer.DeserializeFromString<Dictionary<string, object>>(baseItem));
if (data.ContainsKey("UserItemData"))
{
item.UserItemData = JsonSerializer.DeserializeFromString<UserItemData>(data["UserItemData"].ToString());
}
if (data.ContainsKey("Children"))
{
item.Children = JsonSerializer.DeserializeFromString<IEnumerable<Dictionary<string, object>>>(data["Children"].ToString()).Select(c => new DictionaryBaseItem(c));
}
return item;
}
}
}

View file

@ -1,23 +1,24 @@
using System.IO;
using System;
namespace MediaBrowser.Common.Json
{
public class JsonSerializer
{
public static void SerializeToStream<T>(T o, Stream stream)
public static void SerializeToStream<T>(T obj, Stream stream)
{
Configure();
ServiceStack.Text.JsonSerializer.SerializeToStream<T>(o, stream);
ServiceStack.Text.JsonSerializer.SerializeToStream<T>(obj, stream);
}
public static void SerializeToFile<T>(T o, string file)
public static void SerializeToFile<T>(T obj, string file)
{
Configure();
using (StreamWriter streamWriter = new StreamWriter(file))
{
ServiceStack.Text.JsonSerializer.SerializeToWriter<T>(o, streamWriter);
ServiceStack.Text.JsonSerializer.SerializeToWriter<T>(obj, streamWriter);
}
}
@ -44,12 +45,11 @@ namespace MediaBrowser.Common.Json
return ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(data);
}
private static void Configure()
{
ServiceStack.Text.JsConfig.ExcludeTypeInfo = true;
ServiceStack.Text.JsConfig.IncludeNullValues = false;
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.JsonDateHandler.ISO8601;
}
}
}

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MediaBrowser.Common.Logging
{

View file

@ -35,9 +35,6 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Reactive">
<HintPath>..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@ -48,15 +45,6 @@
<Compile Include="ApiInteraction\ApiController.cs" />
<Compile Include="Events\GenericItemEventArgs.cs" />
<Compile Include="Json\JsonSerializer.cs" />
<Compile Include="ApiInteraction\DictionaryBaseItem.cs" />
<Compile Include="Net\CollectionExtensions.cs" />
<Compile Include="Net\Handlers\BaseEmbeddedResourceHandler.cs" />
<Compile Include="Net\Handlers\JsonHandler.cs" />
<Compile Include="Net\HttpServer.cs" />
<Compile Include="Net\Request.cs" />
<Compile Include="Net\RequestContext.cs" />
<Compile Include="Net\Response.cs" />
<Compile Include="Net\StreamExtensions.cs" />
<Compile Include="Plugins\BasePluginConfiguration.cs" />
<Compile Include="Logging\BaseLogger.cs" />
<Compile Include="Logging\FileLogger.cs" />

View file

@ -1,36 +0,0 @@
using System.IO;
using System.IO.Compression;
using MediaBrowser.Common.Json;
namespace MediaBrowser.Common.Net.Handlers
{
public abstract class JsonHandler : Response
{
public JsonHandler(RequestContext ctx)
: base(ctx)
{
Headers["Content-Encoding"] = "gzip";
WriteStream = s =>
{
WriteReponse(s);
s.Close();
};
}
public override string ContentType
{
get { return "application/json"; }
}
protected abstract object ObjectToSerialize { get; }
private void WriteReponse(Stream stream)
{
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, false))
{
JsonSerializer.SerializeToStream(ObjectToSerialize, gzipStream);
}
}
}
}

View file

@ -1,77 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
namespace MediaBrowser.Common.Net
{
public abstract class Response
{
protected RequestContext RequestContext { get; private set; }
protected NameValueCollection QueryString
{
get
{
return RequestContext.Request.QueryString;
}
}
public Response(RequestContext ctx)
{
RequestContext = ctx;
WriteStream = s => { };
Headers = new Dictionary<string, string>();
}
public abstract string ContentType { get; }
public virtual int StatusCode
{
get
{
return 200;
}
}
public virtual TimeSpan CacheDuration
{
get
{
return TimeSpan.FromTicks(0);
}
}
public virtual DateTime? LastDateModified
{
get
{
return null;
}
}
public IDictionary<string, string> Headers { get; set; }
public Action<Stream> WriteStream { get; set; }
}
/*public class ByteResponse : Response
{
public ByteResponse(byte[] bytes)
{
WriteStream = async s =>
{
await s.WriteAsync(bytes, 0, bytes.Length);
s.Close();
};
}
}
public class StringResponse : ByteResponse
{
public StringResponse(string message)
: base(Encoding.UTF8.GetBytes(message))
{
}
}*/
}

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.IO;
using MediaBrowser.Common.Json;
namespace MediaBrowser.Common.Plugins

View file

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MediaBrowser.Common.Plugins
{
public class BasePluginConfiguration

View file

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Rx-Main" version="1.0.11226" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.8.5" targetFramework="net45" />
</packages>

View file

@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using MediaBrowser.Model.Entities;
using System.IO;
using System.Linq;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Events
{
/// <summary>
/// This is an EventArgs object used when resolving a Path into a BaseItem
/// </summary>
public class ItemResolveEventArgs : PreBeginResolveEventArgs
{
public IEnumerable<KeyValuePair<string, FileAttributes>> FileSystemChildren { get; set; }
@ -57,6 +59,11 @@ namespace MediaBrowser.Controller.Events
}
}
/// <summary>
/// This is an EventArgs object used before we begin resolving a Path into a BaseItem
/// File system children have not been collected yet, but consuming events will
/// have a chance to cancel resolution based on the Path, Parent and FileAttributes
/// </summary>
public class PreBeginResolveEventArgs : EventArgs
{
public string Path { get; set; }

View file

@ -24,9 +24,9 @@ namespace MediaBrowser.Controller.IO
pathsToWatch.Add(rootFolder.Path);
foreach (Folder folder in rootFolder.FolderChildren)
foreach (Folder folder in rootFolder.Children.OfType<Folder>())
{
foreach (Folder subFolder in folder.FolderChildren)
foreach (Folder subFolder in folder.Children.OfType<Folder>())
{
if (Path.IsPathRooted(subFolder.Path))
{

View file

@ -5,6 +5,9 @@ using System.Text;
namespace MediaBrowser.Controller.IO
{
/// <summary>
/// Contains helpers to interact with shortcut files (.lnk)
/// </summary>
public static class Shortcut
{
#region Signitures were imported from http://pinvoke.net

View file

@ -7,7 +7,6 @@ using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Common.Json;
using MediaBrowser.Common.Logging;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Controller.Events;
using MediaBrowser.Controller.IO;
@ -16,6 +15,7 @@ using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
using MediaBrowser.Net;
namespace MediaBrowser.Controller
{
@ -79,7 +79,7 @@ namespace MediaBrowser.Controller
ReloadHttpServer();
ReloadPlugins();
LoadPlugins();
// Get users from users folder
// Load root media folder
@ -94,7 +94,7 @@ namespace MediaBrowser.Controller
Logger.LoggerInstance.LogSeverity = Configuration.LogSeverity;
}
private void ReloadPlugins()
private void LoadPlugins()
{
// Find plugins
Plugins = PluginController.GetAllPlugins();
@ -261,7 +261,7 @@ namespace MediaBrowser.Controller
/// </summary>
public IEnumerable<BaseItem> GetParentalAllowedChildren(Folder folder, Guid userId)
{
return folder.Children.ToList().Where(i => IsParentalAllowed(i, userId));
return folder.Children.Where(i => IsParentalAllowed(i, userId));
}
/// <summary>
@ -307,7 +307,7 @@ namespace MediaBrowser.Controller
{
DateTime now = DateTime.Now;
return GetParentalAllowedRecursiveChildren(parent, userId).Where(i => (now - i.DateCreated).TotalDays < Configuration.RecentItemDays);
return GetParentalAllowedRecursiveChildren(parent, userId).Where(i => !(i is Folder) && (now - i.DateCreated).TotalDays < Configuration.RecentItemDays);
}
/// <summary>
@ -330,6 +330,11 @@ namespace MediaBrowser.Controller
{
return GetParentalAllowedRecursiveChildren(parent, userId).Where(i =>
{
if (i is Folder)
{
return false;
}
var userdata = GetUserItemData(userId, i.Id);
return userdata != null && userdata.PlaybackPosition.Ticks > 0;
@ -359,5 +364,116 @@ namespace MediaBrowser.Controller
{
return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.People != null && f.People.Any(s => s.Name.Equals(personName, StringComparison.OrdinalIgnoreCase)));
}
/// <summary>
/// Gets all studios from all recursive children of a folder
/// The CategoryInfo class is used to keep track of the number of times each studio appears
/// </summary>
public IEnumerable<CategoryInfo> GetAllStudios(Folder parent, Guid userId)
{
Dictionary<string, int> data = new Dictionary<string, int>();
// Get all the allowed recursive children
IEnumerable<BaseItem> allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId);
foreach (var item in allItems)
{
// Add each studio from the item to the data dictionary
// If the studio already exists, increment the count
if (item.Studios == null)
{
continue;
}
foreach (string val in item.Studios)
{
if (!data.ContainsKey(val))
{
data.Add(val, 1);
}
else
{
data[val]++;
}
}
}
// Now go through the dictionary and create a Category for each studio
List<CategoryInfo> list = new List<CategoryInfo>();
foreach (string key in data.Keys)
{
// Get the original entity so that we can also supply the PrimaryImagePath
Studio entity = Kernel.Instance.ItemController.GetStudio(key);
if (entity != null)
{
list.Add(new CategoryInfo()
{
Name = entity.Name,
ItemCount = data[key],
PrimaryImagePath = entity.PrimaryImagePath
});
}
}
return list;
}
/// <summary>
/// Gets all genres from all recursive children of a folder
/// The CategoryInfo class is used to keep track of the number of times each genres appears
/// </summary>
public IEnumerable<CategoryInfo> GetAllGenres(Folder parent, Guid userId)
{
Dictionary<string, int> data = new Dictionary<string, int>();
// Get all the allowed recursive children
IEnumerable<BaseItem> allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId);
foreach (var item in allItems)
{
// Add each genre from the item to the data dictionary
// If the genre already exists, increment the count
if (item.Genres == null)
{
continue;
}
foreach (string val in item.Genres)
{
if (!data.ContainsKey(val))
{
data.Add(val, 1);
}
else
{
data[val]++;
}
}
}
// Now go through the dictionary and create a Category for each genre
List<CategoryInfo> list = new List<CategoryInfo>();
foreach (string key in data.Keys)
{
// Get the original entity so that we can also supply the PrimaryImagePath
Genre entity = Kernel.Instance.ItemController.GetGenre(key);
if (entity != null)
{
list.Add(new CategoryInfo()
{
Name = entity.Name,
ItemCount = data[key],
PrimaryImagePath = entity.PrimaryImagePath
});
}
}
return list;
}
}
}

View file

@ -323,6 +323,12 @@ namespace MediaBrowser.Controller.Library
return null;
}
public Genre GetGenre(string name)
{
// not yet implemented
return null;
}
public Year GetYear(int value)
{
// not yet implemented

View file

@ -66,6 +66,10 @@
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Net\MediaBrowser.Net.csproj">
<Project>{5da08d1c-0d52-4b1b-aa66-e4a171d938f6}</Project>
<Name>MediaBrowser.Net</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View file

@ -8,6 +8,8 @@ namespace MediaBrowser.Controller.Resolvers
{
protected override Audio Resolve(ItemResolveEventArgs args)
{
// Return audio if the path is a file and has a matching extension
if (!args.IsFolder)
{
if (IsAudioFile(args.Path))

View file

@ -15,6 +15,9 @@ namespace MediaBrowser.Controller.Resolvers
return null;
}
/// <summary>
/// Sets initial values on the newly resolved item
/// </summary>
protected virtual void SetItemValues(T item, ItemResolveEventArgs args)
{
// If the subclass didn't specify this
@ -23,6 +26,7 @@ namespace MediaBrowser.Controller.Resolvers
item.Path = args.Path;
}
// If the subclass didn't specify this
if (args.Parent != null)
{
item.Parent = args.Parent;
@ -40,9 +44,14 @@ namespace MediaBrowser.Controller.Resolvers
if (item != null)
{
// Set initial values on the newly resolved item
SetItemValues(item, args);
// Make sure the item has a name
EnsureName(item);
// Make sure DateCreated and DateModified have values
EnsureDates(item);
}
@ -59,6 +68,9 @@ namespace MediaBrowser.Controller.Resolvers
}
/// <summary>
/// Ensures DateCreated and DateModified have values
/// </summary>
private void EnsureDates(T item)
{
// If the subclass didn't supply dates, add them here
@ -73,6 +85,9 @@ namespace MediaBrowser.Controller.Resolvers
}
}
/// <summary>
/// Fills in image paths based on files win the folder
/// </summary>
protected virtual void PopulateImages(T item, ItemResolveEventArgs args)
{
List<string> backdropFiles = new List<string>();
@ -88,6 +103,7 @@ namespace MediaBrowser.Controller.Resolvers
string ext = Path.GetExtension(filePath);
// Only support png and jpg files
if (!ext.EndsWith("png", StringComparison.OrdinalIgnoreCase) && !ext.EndsWith("jpg", StringComparison.OrdinalIgnoreCase))
{
continue;
@ -137,6 +153,9 @@ namespace MediaBrowser.Controller.Resolvers
}
}
/// <summary>
/// Weed this to keep a list of resolvers, since Resolvers are built with generics
/// </summary>
public interface IBaseItemResolver
{
BaseItem ResolvePath(ItemResolveEventArgs args);

View file

@ -29,6 +29,7 @@ namespace MediaBrowser.Controller.Resolvers
item.IsRoot = args.Parent == null;
// Read data from folder.xml, if it exists
PopulateFolderMetadata(item, args);
}

View file

@ -1,20 +1,26 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
using MediaBrowser.Controller.Events;
using MediaBrowser.Model.Entities;
using System.Linq;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Resolvers
{
/// <summary>
/// Resolves a Path into a Video
/// </summary>
public class VideoResolver : BaseVideoResolver<Video>
{
}
/// <summary>
/// Resolves a Path into a Video or Video subclass
/// </summary>
public abstract class BaseVideoResolver<T> : BaseItemResolver<T>
where T : Video, new()
{
protected override T Resolve(ItemResolveEventArgs args)
{
// If the path is a file check for a matching extensions
if (!args.IsFolder)
{
if (IsVideoFile(args.Path))
@ -29,6 +35,7 @@ namespace MediaBrowser.Controller.Resolvers
else
{
// If the path is a folder, check if it's bluray or dvd
T item = ResolveFromFolderName(args.Path);
if (item != null)
@ -36,6 +43,7 @@ namespace MediaBrowser.Controller.Resolvers
return item;
}
// Also check the subfolders for bluray or dvd
foreach (KeyValuePair<string, FileAttributes> folder in args.FileSystemChildren)
{
if (!folder.Value.HasFlag(FileAttributes.Directory))

View file

@ -6,8 +6,14 @@ using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller
{
/// <summary>
/// Manages users within the system
/// </summary>
public class UserController
{
/// <summary>
/// Gets or sets the path to folder that contains data for all the users
/// </summary>
public string UsersPath { get; set; }
public UserController(string usersPath)
@ -15,6 +21,9 @@ namespace MediaBrowser.Controller
UsersPath = usersPath;
}
/// <summary>
/// Gets all users within the system
/// </summary>
public IEnumerable<User> GetAllUsers()
{
if (!Directory.Exists(UsersPath))
@ -37,6 +46,9 @@ namespace MediaBrowser.Controller
return list;
}
/// <summary>
/// Gets a User from it's directory
/// </summary>
private User GetFromDirectory(string path)
{
string file = Path.Combine(path, "user.js");
@ -44,17 +56,28 @@ namespace MediaBrowser.Controller
return JsonSerializer.DeserializeFromFile<User>(file);
}
public void CreateUser(User user)
/// <summary>
/// Creates a User with a given name
/// </summary>
public User CreateUser(string name)
{
user.Id = Guid.NewGuid();
var now = DateTime.Now;
user.DateCreated = user.DateModified = DateTime.Now;
User user = new User()
{
Name = name,
Id = Guid.NewGuid(),
DateCreated = now,
DateModified = now
};
string userFolder = Path.Combine(UsersPath, user.Id.ToString());
user.Path = Path.Combine(UsersPath, user.Id.ToString());
Directory.CreateDirectory(userFolder);
Directory.CreateDirectory(user.Path);
JsonSerializer.SerializeToFile(user, Path.Combine(userFolder, "user.js"));
JsonSerializer.SerializeToFile(user, Path.Combine(user.Path, "user.js"));
return user;
}
}
}

View file

@ -7,15 +7,23 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Xml
{
public class BaseItemXmlParser<T>
/// <summary>
/// Provides a base class for parsing metadata xml
/// </summary>
public abstract class BaseItemXmlParser<T>
where T : BaseItem, new()
{
/// <summary>
/// Fetches metadata for an item from one xml file
/// </summary>
public virtual void Fetch(T item, string metadataFile)
{
// Use XmlReader for best performance
using (XmlReader reader = XmlReader.Create(metadataFile))
{
reader.MoveToContent();
// Loop through each element
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
@ -25,7 +33,7 @@ namespace MediaBrowser.Controller.Xml
}
}
// If dates weren't supplied in metadata, use values from the file
// If dates weren't supplied in metadata, use values from the xml file
if (item.DateCreated == DateTime.MinValue)
{
item.DateCreated = File.GetCreationTime(metadataFile);
@ -37,10 +45,14 @@ namespace MediaBrowser.Controller.Xml
}
}
/// <summary>
/// Fetches metadata from one Xml Element
/// </summary>
protected virtual void FetchDataFromXmlNode(XmlReader reader, T item)
{
switch (reader.Name)
{
// DateCreated
case "Added":
DateTime added;
if (DateTime.TryParse(reader.ReadElementContentAsString() ?? string.Empty, out added))
@ -49,6 +61,7 @@ namespace MediaBrowser.Controller.Xml
}
break;
// DisplayMediaType
case "Type":
{
item.DisplayMediaType = reader.ReadElementContentAsString() ?? string.Empty;
@ -69,6 +82,7 @@ namespace MediaBrowser.Controller.Xml
break;
}
// TODO: Do we still need this?
case "banner":
item.BannerImagePath = reader.ReadElementContentAsString() ?? string.Empty;
break;
@ -172,7 +186,7 @@ namespace MediaBrowser.Controller.Xml
string rating = reader.ReadElementContentAsString();
if (!string.IsNullOrEmpty(rating))
if (!string.IsNullOrWhiteSpace(rating))
{
float val;
@ -428,7 +442,7 @@ namespace MediaBrowser.Controller.Xml
{
string genre = reader.ReadElementContentAsString();
if (!string.IsNullOrEmpty(genre))
if (!string.IsNullOrWhiteSpace(genre))
{
list.Add(genre);
}
@ -461,7 +475,7 @@ namespace MediaBrowser.Controller.Xml
{
string genre = reader.ReadElementContentAsString();
if (!string.IsNullOrEmpty(genre))
if (!string.IsNullOrWhiteSpace(genre))
{
list.Add(genre);
}
@ -522,7 +536,7 @@ namespace MediaBrowser.Controller.Xml
{
string studio = reader.ReadElementContentAsString();
if (!string.IsNullOrEmpty(studio))
if (!string.IsNullOrWhiteSpace(studio))
{
list.Add(studio);
}
@ -555,7 +569,7 @@ namespace MediaBrowser.Controller.Xml
int rating = 7;
if (!string.IsNullOrEmpty(ratingString))
if (!string.IsNullOrWhiteSpace(ratingString))
{
int.TryParse(ratingString, out rating);
}
@ -646,7 +660,7 @@ namespace MediaBrowser.Controller.Xml
{
value = (value ?? string.Empty).Trim(deliminator);
return string.IsNullOrEmpty(value) ? new string[] { } : value.Split(deliminator);
return string.IsNullOrWhiteSpace(value) ? new string[] { } : value.Split(deliminator);
}
}
}

View file

@ -2,6 +2,10 @@
namespace MediaBrowser.Controller.Xml
{
/// <summary>
/// Fetches metadata fro a folder.
/// Since folder.xml contains no folder-specific values, no overrides are needed
/// </summary>
public class FolderXmlParser : BaseItemXmlParser<Folder>
{
}

View file

@ -1,5 +1,4 @@
using System;
using System.Globalization;
using System.Globalization;
using System.Xml;
namespace MediaBrowser.Controller.Xml
@ -8,13 +7,16 @@ namespace MediaBrowser.Controller.Xml
{
private static CultureInfo _usCulture = new CultureInfo("en-US");
/// <summary>
/// Reads a float from the current element of an XmlReader
/// </summary>
public static float ReadFloatSafe(this XmlReader reader)
{
string valueString = reader.ReadElementContentAsString();
float value = 0;
if (!string.IsNullOrEmpty(valueString))
if (!string.IsNullOrWhiteSpace(valueString))
{
// float.TryParse is local aware, so it can be probamatic, force us culture
float.TryParse(valueString, NumberStyles.AllowDecimalPoint, _usCulture, out value);
@ -23,13 +25,16 @@ namespace MediaBrowser.Controller.Xml
return value;
}
/// <summary>
/// Reads an int from the current element of an XmlReader
/// </summary>
public static int ReadIntSafe(this XmlReader reader)
{
string valueString = reader.ReadElementContentAsString();
int value = 0;
if (!string.IsNullOrEmpty(valueString))
if (!string.IsNullOrWhiteSpace(valueString))
{
int.TryParse(valueString, out value);

View file

@ -1,14 +1,14 @@
using System.IO;
using System.Reflection;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Net;
using MediaBrowser.Net.Handlers;
namespace MediaBrowser.HtmlBrowser.Handlers
{
class EmbeddedResourceHandler : BaseEmbeddedResourceHandler
{
public EmbeddedResourceHandler(RequestContext ctx, string resourcePath)
: base(ctx, resourcePath)
public EmbeddedResourceHandler(string resourcePath)
: base(resourcePath)
{
}

View file

@ -59,6 +59,10 @@
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Net\MediaBrowser.Net.csproj">
<Project>{5da08d1c-0d52-4b1b-aa66-e4a171d938f6}</Project>
<Name>MediaBrowser.Net</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View file

@ -1,6 +1,6 @@
using System;
using System.Reactive.Linq;
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Net.Handlers;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Controller;
using MediaBrowser.HtmlBrowser.Handlers;
@ -13,7 +13,7 @@ namespace MediaBrowser.HtmlBrowser
{
var httpServer = Kernel.Instance.HttpServer;
httpServer.Where(ctx => ctx.LocalPath.IndexOf("/browser/", StringComparison.OrdinalIgnoreCase) != -1).Subscribe(ctx =>
/*httpServer.Where(ctx => ctx.LocalPath.IndexOf("/browser/", StringComparison.OrdinalIgnoreCase) != -1).Subscribe(ctx =>
{
string localPath = ctx.LocalPath;
string srch = "/browser/";
@ -24,7 +24,7 @@ namespace MediaBrowser.HtmlBrowser
ctx.Respond(new EmbeddedResourceHandler(ctx, resource));
});
});*/
}
}
}

View file

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Model.Entities
{
/// <summary>
/// This is a concrete class that the UI can use to deserialize
/// It is flat in the sense that it will be used regardless of the type of BaseItem involved
/// </summary>
public class ApiBaseItem : BaseItem
{
}
/// <summary>
/// This is the full return object when requesting an Item
/// </summary>
public class ApiBaseItemWrapper<T>
where T : BaseItem
{
public T Item { get; set; }
public UserItemData UserItemData { get; set; }
public IEnumerable<ApiBaseItemWrapper<T>> Children { get; set; }
[IgnoreDataMember]
public Type ItemType { get; set; }
public string Type
{
get
{
return ItemType.Name;
}
}
}
}

View file

@ -6,70 +6,70 @@ namespace MediaBrowser.Model.Entities
{
public abstract class BaseItem
{
public virtual string Name { get; set; }
public virtual string SortName { get; set; }
public string Name { get; set; }
public string SortName { get; set; }
public virtual Guid Id { get; set; }
public Guid Id { get; set; }
public virtual DateTime DateCreated { get; set; }
public DateTime DateCreated { get; set; }
public virtual DateTime DateModified { get; set; }
public DateTime DateModified { get; set; }
public virtual string Path { get; set; }
/// <summary>
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired
/// </summary>
public DateTime? PremiereDate { get; set; }
public string Path { get; set; }
[IgnoreDataMember]
public Folder Parent { get; set; }
public virtual string PrimaryImagePath { get; set; }
public virtual string LogoImagePath { get; set; }
public virtual string ArtImagePath { get; set; }
public virtual string ThumbnailImagePath { get; set; }
public virtual string BannerImagePath { get; set; }
public string PrimaryImagePath { get; set; }
public string LogoImagePath { get; set; }
public string ArtImagePath { get; set; }
public string ThumbnailImagePath { get; set; }
public string BannerImagePath { get; set; }
public virtual IEnumerable<string> BackdropImagePaths { get; set; }
public IEnumerable<string> BackdropImagePaths { get; set; }
public virtual string OfficialRating { get; set; }
public string OfficialRating { get; set; }
public virtual string CustomRating { get; set; }
public virtual string CustomPin { get; set; }
public string CustomRating { get; set; }
public string CustomPin { get; set; }
public virtual string Overview { get; set; }
public virtual string Tagline { get; set; }
public string Overview { get; set; }
public string Tagline { get; set; }
[IgnoreDataMember]
public virtual IEnumerable<PersonInfo> People { get; set; }
public IEnumerable<PersonInfo> People { get; set; }
public virtual IEnumerable<string> Studios { get; set; }
public IEnumerable<string> Studios { get; set; }
public virtual IEnumerable<string> Genres { get; set; }
public IEnumerable<string> Genres { get; set; }
public virtual string DisplayMediaType { get; set; }
public string DisplayMediaType { get; set; }
public virtual float? UserRating { get; set; }
public virtual TimeSpan? RunTime { get; set; }
public float? UserRating { get; set; }
public TimeSpan? RunTime { get; set; }
public virtual string AspectRatio { get; set; }
public virtual int? ProductionYear { get; set; }
public string AspectRatio { get; set; }
public int? ProductionYear { get; set; }
/// <summary>
/// If the item is part of a series, this is it's number in the series.
/// This could be episode number, album track number, etc.
/// </summary>
public int? IndexNumber { get; set; }
[IgnoreDataMember]
public virtual IEnumerable<Video> LocalTrailers { get; set; }
public IEnumerable<Video> LocalTrailers { get; set; }
public string TrailerUrl { get; set; }
public virtual string TrailerUrl { get; set; }
public override string ToString()
{
return Name;
}
/// <summary>
/// This is strictly to enhance json output, until I can find a way to customize service stack to add this without having to use a property
/// </summary>
public string Type
{
get
{
return GetType().Name;
}
}
}
}

View file

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
namespace MediaBrowser.Model.Entities
@ -21,9 +18,6 @@ namespace MediaBrowser.Model.Entities
[IgnoreDataMember]
public BaseItem[] Children { get; set; }
[IgnoreDataMember]
public IEnumerable<Folder> FolderChildren { get { return Children.OfType<Folder>(); } }
/// <summary>
/// Finds an item by ID, recursively
/// </summary>
@ -36,17 +30,18 @@ namespace MediaBrowser.Model.Entities
foreach (BaseItem item in Children)
{
if (item.Id == id)
var folder = item as Folder;
if (folder != null)
{
return item;
var foundItem = folder.FindById(id);
if (foundItem != null)
{
return foundItem;
}
}
}
foreach (Folder folder in FolderChildren)
{
BaseItem item = folder.FindById(id);
if (item != null)
else if (item.Id == id)
{
return item;
}
@ -67,17 +62,18 @@ namespace MediaBrowser.Model.Entities
foreach (BaseItem item in Children)
{
if (item.Path.Equals(path, StringComparison.OrdinalIgnoreCase))
var folder = item as Folder;
if (folder != null)
{
return item;
var foundItem = folder.FindByPath(path);
if (foundItem != null)
{
return foundItem;
}
}
}
foreach (Folder folder in FolderChildren)
{
BaseItem item = folder.FindByPath(path);
if (item != null)
else if (item.Path.Equals(path, StringComparison.OrdinalIgnoreCase))
{
return item;
}

View file

@ -36,6 +36,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Configuration\Configuration.cs" />
<Compile Include="Entities\ApiBaseItem.cs" />
<Compile Include="Entities\Audio.cs" />
<Compile Include="Entities\BaseItem.cs" />
<Compile Include="Entities\CategoryInfo.cs" />

View file

@ -6,7 +6,6 @@ namespace MediaBrowser.Model.Users
{
public class User : BaseItem
{
public string Password { get; set; }
public string MaxParentalRating { get; set; }
private Dictionary<Guid, UserItemData> _ItemData = new Dictionary<Guid, UserItemData>();

View file

@ -1,6 +1,6 @@
using System.Collections.Generic;
using MediaBrowser.Model.Entities;
using System.Runtime.Serialization;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Movies.Entities
{

View file

@ -17,7 +17,7 @@ namespace MediaBrowser.Movies.Metadata
case "IMDB":
case "IMDbId":
string IMDbId = reader.ReadElementContentAsString() ?? string.Empty;
if (!string.IsNullOrEmpty(IMDbId))
if (!string.IsNullOrWhiteSpace(IMDbId))
{
item.ImdbId = IMDbId;
}

View file

@ -2,7 +2,7 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
namespace MediaBrowser.Common.Net
namespace MediaBrowser.Net
{
public static class CollectionExtensions
{

View file

@ -1,23 +1,14 @@
using System.IO;
using System.IO.Compression;
using System;
using System;
using System.IO;
namespace MediaBrowser.Common.Net.Handlers
namespace MediaBrowser.Net.Handlers
{
public abstract class BaseEmbeddedResourceHandler : Response
public abstract class BaseEmbeddedResourceHandler : BaseHandler
{
public BaseEmbeddedResourceHandler(RequestContext ctx, string resourcePath)
: base(ctx)
public BaseEmbeddedResourceHandler(string resourcePath)
: base()
{
ResourcePath = resourcePath;
Headers["Content-Encoding"] = "gzip";
WriteStream = s =>
{
WriteReponse(s);
s.Close();
};
}
protected string ResourcePath { get; set; }
@ -57,12 +48,9 @@ namespace MediaBrowser.Common.Net.Handlers
}
}
private void WriteReponse(Stream stream)
protected override void WriteResponseToOutputStream(Stream stream)
{
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, false))
{
GetEmbeddedResourceStream().CopyTo(gzipStream);
}
GetEmbeddedResourceStream().CopyTo(stream);
}
protected abstract Stream GetEmbeddedResourceStream();

View file

@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.IO.Compression;
namespace MediaBrowser.Net.Handlers
{
public abstract class BaseHandler
{
/// <summary>
/// Response headers
/// </summary>
public IDictionary<string, string> Headers = new Dictionary<string, string>();
/// <summary>
/// The action to write the response to the output stream
/// </summary>
public Action<Stream> WriteStream { get; set; }
/// <summary>
/// The original RequestContext
/// </summary>
public RequestContext RequestContext { get; set; }
/// <summary>
/// The original QueryString
/// </summary>
protected NameValueCollection QueryString
{
get
{
return RequestContext.Request.QueryString;
}
}
/// <summary>
/// Gets the MIME type to include in the response headers
/// </summary>
public abstract string ContentType { get; }
/// <summary>
/// Gets the status code to include in the response headers
/// </summary>
public virtual int StatusCode
{
get
{
return 200;
}
}
/// <summary>
/// Gets the cache duration to include in the response headers
/// </summary>
public virtual TimeSpan CacheDuration
{
get
{
return TimeSpan.FromTicks(0);
}
}
/// <summary>
/// Gets the last date modified of the content being returned, if this can be determined.
/// This will be used to invalidate the cache, so it's not needed if CacheDuration is 0.
/// </summary>
public virtual DateTime? LastDateModified
{
get
{
return null;
}
}
public virtual bool GzipResponse
{
get
{
return true;
}
}
public BaseHandler()
{
WriteStream = s =>
{
WriteReponse(s);
s.Close();
};
}
private void WriteReponse(Stream stream)
{
if (GzipResponse)
{
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, false))
{
WriteResponseToOutputStream(gzipStream);
}
}
else
{
WriteResponseToOutputStream(stream);
}
}
protected abstract void WriteResponseToOutputStream(Stream stream);
}
}

View file

@ -0,0 +1,11 @@

namespace MediaBrowser.Net.Handlers
{
public abstract class BaseJsonHandler : BaseHandler
{
public override string ContentType
{
get { return "application/json"; }
}
}
}

View file

@ -2,7 +2,7 @@ using System;
using System.Net;
using System.Reactive.Linq;
namespace MediaBrowser.Common.Net
namespace MediaBrowser.Net
{
public class HttpServer : IObservable<RequestContext>, IDisposable
{

View file

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MediaBrowser.Net</RootNamespace>
<AssemblyName>MediaBrowser.Net</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Reactive">
<HintPath>..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CollectionExtensions.cs" />
<Compile Include="Handlers\BaseEmbeddedResourceHandler.cs" />
<Compile Include="Handlers\BaseJsonHandler.cs" />
<Compile Include="HttpServer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Request.cs" />
<Compile Include="RequestContext.cs" />
<Compile Include="Handlers\BaseHandler.cs" />
<Compile Include="StreamExtensions.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MediaBrowser.Net")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MediaBrowser.Net")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("eacc40b5-e24e-4467-8000-f40874048d45")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -2,7 +2,7 @@
using System.IO;
using System.Linq;
namespace MediaBrowser.Common.Net
namespace MediaBrowser.Net
{
public class Request
{

View file

@ -1,8 +1,9 @@
using System;
using System.Linq;
using System.Net;
using MediaBrowser.Net.Handlers;
namespace MediaBrowser.Common.Net
namespace MediaBrowser.Net
{
public class RequestContext
{
@ -23,7 +24,7 @@ namespace MediaBrowser.Common.Net
Request = context.Request;
}
public void Respond(Response handler)
public void Respond(BaseHandler handler)
{
Response.AddHeader("Access-Control-Allow-Origin", "*");
@ -58,6 +59,11 @@ namespace MediaBrowser.Common.Net
if (statusCode != 304)
{
if (handler.GzipResponse)
{
Response.AddHeader("Content-Encoding", "gzip");
}
if (cacheDuration.Ticks > 0)
{
CacheResponse(Response, cacheDuration, handler.LastDateModified);

View file

@ -2,7 +2,7 @@ using System;
using System.IO;
using System.Reactive.Linq;
namespace MediaBrowser.Common.Net
namespace MediaBrowser.Net
{
public static class StreamExtensions
{

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Rx-Main" version="1.0.11226" targetFramework="net45" />
</packages>

View file

@ -1,13 +1,9 @@
using System;
using System.Collections.Generic;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.TV.Entities
{
public class Episode : Video
{
public string SeasonNumber { get; set; }
public string EpisodeNumber { get; set; }
public DateTime? FirstAired { get; set; }
}
}

View file

@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.TV.Entities
{
public class Series : Folder
{
public string TVDBSeriesId { get; set; }
public string TvdbId { get; set; }
public string Status { get; set; }
}
}

View file

@ -16,7 +16,7 @@ namespace MediaBrowser.TV.Metadata
{
string filename = reader.ReadElementContentAsString();
if (!string.IsNullOrEmpty(filename))
if (!string.IsNullOrWhiteSpace(filename))
{
string metadataFolder = Path.GetDirectoryName(item.Path);
item.PrimaryImagePath = Path.Combine(metadataFolder, filename);
@ -24,7 +24,12 @@ namespace MediaBrowser.TV.Metadata
break;
}
case "EpisodeNumber":
item.EpisodeNumber = reader.ReadElementContentAsString() ?? string.Empty;
string number = reader.ReadElementContentAsString() ?? string.Empty;
if (!string.IsNullOrWhiteSpace(number))
{
item.IndexNumber = int.Parse(number);
}
break;
case "SeasonNumber":
@ -39,13 +44,13 @@ namespace MediaBrowser.TV.Metadata
{
string firstAired = reader.ReadElementContentAsString() ?? string.Empty;
if (!string.IsNullOrEmpty(firstAired))
if (!string.IsNullOrWhiteSpace(firstAired))
{
DateTime airDate;
if (DateTime.TryParse(firstAired, out airDate) && airDate.Year > 1850)
{
item.FirstAired = airDate;
item.PremiereDate = airDate;
item.ProductionYear = airDate.Year;
}
}

View file

@ -12,7 +12,7 @@ namespace MediaBrowser.TV.Metadata
switch (reader.Name)
{
case "id":
item.TVDBSeriesId = reader.ReadElementContentAsString() ?? string.Empty;
item.TvdbId = reader.ReadElementContentAsString() ?? string.Empty;
break;
case "SeriesName":
@ -26,7 +26,7 @@ namespace MediaBrowser.TV.Metadata
case "Runtime":
{
string text = reader.ReadElementContentAsString() ?? string.Empty;
if (!string.IsNullOrEmpty(text))
if (!string.IsNullOrWhiteSpace(text))
{
int runtime;

View file

@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Common", "Medi
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model", "MediaBrowser.Model\MediaBrowser.Model.csproj", "{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Net", "MediaBrowser.Net\MediaBrowser.Net.csproj", "{5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -43,6 +45,10 @@ Global
{5758B2C7-949A-421D-B268-70A950CF8741}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5758B2C7-949A-421D-B268-70A950CF8741}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5758B2C7-949A-421D-B268-70A950CF8741}.Release|Any CPU.Build.0 = Release|Any CPU
{5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Release|Any CPU.Build.0 = Release|Any CPU
{78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Release|Any CPU.ActiveCfg = Release|Any CPU