mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
commit
f3ee129bd9
@ -10,7 +10,6 @@ using MediaBrowser.Model.Dlna;
|
|||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
using MediaBrowser.Controller.TV;
|
using MediaBrowser.Controller.TV;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
@ -129,9 +128,20 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No configuration so it's going to be pretty arbitrary
|
foreach (var user in _userManager.Users)
|
||||||
return _userManager.Users.FirstOrDefault(i => i.Policy.IsAdministrator) ??
|
{
|
||||||
_userManager.Users.First();
|
if (user.Policy.IsAdministrator)
|
||||||
|
{
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var user in _userManager.Users)
|
||||||
|
{
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -487,6 +487,11 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
return GetMusicArtistItems(item, null, user, sort, startIndex, limit);
|
return GetMusicArtistItems(item, null, user, sort, startIndex, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item is Genre)
|
||||||
|
{
|
||||||
|
return GetGenreItems(item, null, user, sort, startIndex, limit);
|
||||||
|
}
|
||||||
|
|
||||||
var collectionFolder = item as ICollectionFolder;
|
var collectionFolder = item as ICollectionFolder;
|
||||||
if (collectionFolder != null && string.Equals(CollectionType.Music, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
|
if (collectionFolder != null && string.Equals(CollectionType.Music, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@ -503,23 +508,6 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
|
|
||||||
if (stubType.HasValue)
|
if (stubType.HasValue)
|
||||||
{
|
{
|
||||||
if (stubType.Value == StubType.People)
|
|
||||||
{
|
|
||||||
var items = _libraryManager.GetPeopleItems(new InternalPeopleQuery
|
|
||||||
{
|
|
||||||
ItemId = item.Id
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var result = new QueryResult<ServerItem>
|
|
||||||
{
|
|
||||||
Items = items.Select(i => new ServerItem(i)).ToArray(items.Count),
|
|
||||||
TotalRecordCount = items.Count
|
|
||||||
};
|
|
||||||
|
|
||||||
return ApplyPaging(result, startIndex, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
var person = item as Person;
|
var person = item as Person;
|
||||||
if (person != null)
|
if (person != null)
|
||||||
{
|
{
|
||||||
@ -1173,6 +1161,26 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
return ToResult(result);
|
return ToResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private QueryResult<ServerItem> GetGenreItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
|
||||||
|
{
|
||||||
|
var query = new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
Recursive = true,
|
||||||
|
ParentId = parentId,
|
||||||
|
GenreIds = new[] { item.Id.ToString("N") },
|
||||||
|
IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name },
|
||||||
|
Limit = limit,
|
||||||
|
StartIndex = startIndex,
|
||||||
|
DtoOptions = GetDtoOptions()
|
||||||
|
};
|
||||||
|
|
||||||
|
SetSorting(query, sort, false);
|
||||||
|
|
||||||
|
var result = _libraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
|
return ToResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
private QueryResult<ServerItem> GetMusicGenreItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
|
private QueryResult<ServerItem> GetMusicGenreItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
|
||||||
{
|
{
|
||||||
var query = new InternalItemsQuery(user)
|
var query = new InternalItemsQuery(user)
|
||||||
@ -1331,7 +1339,6 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
public enum StubType
|
public enum StubType
|
||||||
{
|
{
|
||||||
Folder = 0,
|
Folder = 0,
|
||||||
People = 1,
|
|
||||||
Latest = 2,
|
Latest = 2,
|
||||||
Playlists = 3,
|
Playlists = 3,
|
||||||
Albums = 4,
|
Albums = 4,
|
||||||
|
@ -198,7 +198,7 @@ namespace Emby.Dlna.Didl
|
|||||||
streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions
|
streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions
|
||||||
{
|
{
|
||||||
ItemId = GetClientId(video),
|
ItemId = GetClientId(video),
|
||||||
MediaSources = sources,
|
MediaSources = sources.ToArray(sources.Count),
|
||||||
Profile = _profile,
|
Profile = _profile,
|
||||||
DeviceId = deviceId,
|
DeviceId = deviceId,
|
||||||
MaxBitrate = _profile.MaxStreamingBitrate
|
MaxBitrate = _profile.MaxStreamingBitrate
|
||||||
@ -236,7 +236,7 @@ namespace Emby.Dlna.Didl
|
|||||||
AddVideoResource(writer, video, deviceId, filter, contentFeature, streamInfo);
|
AddVideoResource(writer, video, deviceId, filter, contentFeature, streamInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
var subtitleProfiles = streamInfo.GetSubtitleProfiles(false, _serverAddress, _accessToken)
|
var subtitleProfiles = streamInfo.GetSubtitleProfiles(_mediaEncoder, false, _serverAddress, _accessToken)
|
||||||
.Where(subtitle => subtitle.DeliveryMethod == SubtitleDeliveryMethod.External)
|
.Where(subtitle => subtitle.DeliveryMethod == SubtitleDeliveryMethod.External)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@ -391,14 +391,6 @@ namespace Emby.Dlna.Didl
|
|||||||
|
|
||||||
private string GetDisplayName(BaseItem item, StubType? itemStubType, BaseItem context)
|
private string GetDisplayName(BaseItem item, StubType? itemStubType, BaseItem context)
|
||||||
{
|
{
|
||||||
if (itemStubType.HasValue && itemStubType.Value == StubType.People)
|
|
||||||
{
|
|
||||||
if (item is Video)
|
|
||||||
{
|
|
||||||
return _localization.GetLocalizedString("HeaderCastCrew");
|
|
||||||
}
|
|
||||||
return _localization.GetLocalizedString("HeaderPeople");
|
|
||||||
}
|
|
||||||
if (itemStubType.HasValue && itemStubType.Value == StubType.Latest)
|
if (itemStubType.HasValue && itemStubType.Value == StubType.Latest)
|
||||||
{
|
{
|
||||||
return _localization.GetLocalizedString("ViewTypeMusicLatest");
|
return _localization.GetLocalizedString("ViewTypeMusicLatest");
|
||||||
@ -513,7 +505,7 @@ namespace Emby.Dlna.Didl
|
|||||||
streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions
|
streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions
|
||||||
{
|
{
|
||||||
ItemId = GetClientId(audio),
|
ItemId = GetClientId(audio),
|
||||||
MediaSources = sources,
|
MediaSources = sources.ToArray(sources.Count),
|
||||||
Profile = _profile,
|
Profile = _profile,
|
||||||
DeviceId = deviceId
|
DeviceId = deviceId
|
||||||
});
|
});
|
||||||
@ -961,12 +953,6 @@ namespace Emby.Dlna.Didl
|
|||||||
|
|
||||||
private void AddCover(BaseItem item, BaseItem context, StubType? stubType, XmlWriter writer)
|
private void AddCover(BaseItem item, BaseItem context, StubType? stubType, XmlWriter writer)
|
||||||
{
|
{
|
||||||
if (stubType.HasValue && stubType.Value == StubType.People)
|
|
||||||
{
|
|
||||||
AddEmbeddedImageAsCover("people", writer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageDownloadInfo imageInfo = null;
|
ImageDownloadInfo imageInfo = null;
|
||||||
|
|
||||||
if (context is UserView)
|
if (context is UserView)
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
using MediaBrowser.Model.Extensions;
|
using MediaBrowser.Model.Extensions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Emby.Dlna.Didl
|
namespace Emby.Dlna.Didl
|
||||||
{
|
{
|
||||||
public class Filter
|
public class Filter
|
||||||
{
|
{
|
||||||
private readonly List<string> _fields;
|
private readonly string[] _fields;
|
||||||
private readonly bool _all;
|
private readonly bool _all;
|
||||||
|
|
||||||
public Filter()
|
public Filter()
|
||||||
@ -20,9 +19,7 @@ namespace Emby.Dlna.Didl
|
|||||||
{
|
{
|
||||||
_all = StringHelper.EqualsIgnoreCase(filter, "*");
|
_all = StringHelper.EqualsIgnoreCase(filter, "*");
|
||||||
|
|
||||||
var list = (filter ?? string.Empty).Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList();
|
_fields = (filter ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
_fields = list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Contains(string field)
|
public bool Contains(string field)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -13,13 +13,13 @@ using MediaBrowser.Model.System;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
|
using MediaBrowser.Model.Extensions;
|
||||||
|
|
||||||
namespace Emby.Dlna.PlayTo
|
namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
@ -48,7 +48,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var lastDateKnownActivity = new[] { _creationTime, _device.DateLastActivity }.Max();
|
var lastDateKnownActivity = _creationTime > _device.DateLastActivity ? _creationTime : _device.DateLastActivity;
|
||||||
|
|
||||||
if (DateTime.UtcNow >= lastDateKnownActivity.AddSeconds(120))
|
if (DateTime.UtcNow >= lastDateKnownActivity.AddSeconds(120))
|
||||||
{
|
{
|
||||||
@ -564,7 +564,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
streamInfo.TargetVideoCodecTag,
|
streamInfo.TargetVideoCodecTag,
|
||||||
streamInfo.IsTargetAVC);
|
streamInfo.IsTargetAVC);
|
||||||
|
|
||||||
return list.FirstOrDefault();
|
return list.Count == 0 ? null : list[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -589,7 +589,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildVideoItem(new VideoOptions
|
StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildVideoItem(new VideoOptions
|
||||||
{
|
{
|
||||||
ItemId = item.Id.ToString("N"),
|
ItemId = item.Id.ToString("N"),
|
||||||
MediaSources = mediaSources,
|
MediaSources = mediaSources.ToArray(mediaSources.Count),
|
||||||
Profile = profile,
|
Profile = profile,
|
||||||
DeviceId = deviceId,
|
DeviceId = deviceId,
|
||||||
MaxBitrate = profile.MaxStreamingBitrate,
|
MaxBitrate = profile.MaxStreamingBitrate,
|
||||||
@ -609,7 +609,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions
|
StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions
|
||||||
{
|
{
|
||||||
ItemId = item.Id.ToString("N"),
|
ItemId = item.Id.ToString("N"),
|
||||||
MediaSources = mediaSources,
|
MediaSources = mediaSources.ToArray(mediaSources.Count),
|
||||||
Profile = profile,
|
Profile = profile,
|
||||||
DeviceId = deviceId,
|
DeviceId = deviceId,
|
||||||
MaxBitrate = profile.MaxStreamingBitrate,
|
MaxBitrate = profile.MaxStreamingBitrate,
|
||||||
|
@ -182,7 +182,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
{
|
{
|
||||||
PlayableMediaTypes = profile.GetSupportedMediaTypes(),
|
PlayableMediaTypes = profile.GetSupportedMediaTypes(),
|
||||||
|
|
||||||
SupportedCommands = new List<string>
|
SupportedCommands = new string[]
|
||||||
{
|
{
|
||||||
GeneralCommandType.VolumeDown.ToString(),
|
GeneralCommandType.VolumeDown.ToString(),
|
||||||
GeneralCommandType.VolumeUp.ToString(),
|
GeneralCommandType.VolumeUp.ToString(),
|
||||||
|
@ -16,14 +16,14 @@ namespace Emby.Dlna.Profiles
|
|||||||
Manufacturer = "Panasonic",
|
Manufacturer = "Panasonic",
|
||||||
|
|
||||||
Headers = new[]
|
Headers = new[]
|
||||||
{
|
{
|
||||||
new HttpHeaderInfo
|
new HttpHeaderInfo
|
||||||
{
|
{
|
||||||
Name = "User-Agent",
|
Name = "User-Agent",
|
||||||
Value = "Panasonic MIL DLNA",
|
Value = "Panasonic MIL DLNA",
|
||||||
Match = HeaderMatchType.Substring
|
Match = HeaderMatchType.Substring
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AddXmlRootAttribute("xmlns:pv", "http://www.pv.com/pvns/");
|
AddXmlRootAttribute("xmlns:pv", "http://www.pv.com/pvns/");
|
||||||
@ -31,105 +31,105 @@ namespace Emby.Dlna.Profiles
|
|||||||
TimelineOffsetSeconds = 10;
|
TimelineOffsetSeconds = 10;
|
||||||
|
|
||||||
TranscodingProfiles = new[]
|
TranscodingProfiles = new[]
|
||||||
{
|
{
|
||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
Container = "mp3",
|
Container = "mp3",
|
||||||
AudioCodec = "mp3",
|
AudioCodec = "mp3",
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio
|
||||||
},
|
},
|
||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
Container = "ts",
|
Container = "ts",
|
||||||
AudioCodec = "ac3",
|
AudioCodec = "ac3",
|
||||||
VideoCodec = "h264",
|
VideoCodec = "h264",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
Container = "jpeg",
|
Container = "jpeg",
|
||||||
Type = DlnaProfileType.Photo
|
Type = DlnaProfileType.Photo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
DirectPlayProfiles = new[]
|
DirectPlayProfiles = new[]
|
||||||
{
|
{
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mpeg,mpg",
|
Container = "mpeg,mpg",
|
||||||
VideoCodec = "mpeg2video,mpeg4",
|
VideoCodec = "mpeg2video,mpeg4",
|
||||||
AudioCodec = "ac3,mp3,pcm_dvd",
|
AudioCodec = "ac3,mp3,pcm_dvd",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mkv",
|
Container = "mkv",
|
||||||
VideoCodec = "h264,mpeg2video",
|
VideoCodec = "h264,mpeg2video",
|
||||||
AudioCodec = "aac,ac3,dca,mp3,mp2,pcm,dts",
|
AudioCodec = "aac,ac3,dca,mp3,mp2,pcm,dts",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "ts",
|
Container = "ts",
|
||||||
VideoCodec = "h264,mpeg2video",
|
VideoCodec = "h264,mpeg2video",
|
||||||
AudioCodec = "aac,mp3,mp2",
|
AudioCodec = "aac,mp3,mp2",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4,m4v",
|
Container = "mp4,m4v",
|
||||||
VideoCodec = "h264",
|
VideoCodec = "h264",
|
||||||
AudioCodec = "aac,ac3,mp3,pcm",
|
AudioCodec = "aac,ac3,mp3,pcm",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mov",
|
Container = "mov",
|
||||||
VideoCodec = "h264",
|
VideoCodec = "h264",
|
||||||
AudioCodec = "aac,pcm",
|
AudioCodec = "aac,pcm",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "avi",
|
Container = "avi",
|
||||||
VideoCodec = "mpeg4",
|
VideoCodec = "mpeg4",
|
||||||
AudioCodec = "pcm",
|
AudioCodec = "pcm",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "flv",
|
Container = "flv",
|
||||||
VideoCodec = "h264",
|
VideoCodec = "h264",
|
||||||
AudioCodec = "aac",
|
AudioCodec = "aac",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp3",
|
Container = "mp3",
|
||||||
AudioCodec = "mp3",
|
AudioCodec = "mp3",
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4",
|
Container = "mp4",
|
||||||
AudioCodec = "aac",
|
AudioCodec = "aac",
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "jpeg",
|
Container = "jpeg",
|
||||||
Type = DlnaProfileType.Photo
|
Type = DlnaProfileType.Photo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ContainerProfiles = new[]
|
ContainerProfiles = new[]
|
||||||
{
|
{
|
||||||
@ -156,35 +156,35 @@ namespace Emby.Dlna.Profiles
|
|||||||
};
|
};
|
||||||
|
|
||||||
CodecProfiles = new[]
|
CodecProfiles = new[]
|
||||||
{
|
{
|
||||||
new CodecProfile
|
new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.Video,
|
Type = CodecType.Video,
|
||||||
|
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
{
|
{
|
||||||
new ProfileCondition
|
new ProfileCondition
|
||||||
{
|
{
|
||||||
Condition = ProfileConditionType.LessThanEqual,
|
Condition = ProfileConditionType.LessThanEqual,
|
||||||
Property = ProfileConditionValue.Width,
|
Property = ProfileConditionValue.Width,
|
||||||
Value = "1920"
|
Value = "1920"
|
||||||
},
|
},
|
||||||
new ProfileCondition
|
new ProfileCondition
|
||||||
{
|
{
|
||||||
Condition = ProfileConditionType.LessThanEqual,
|
Condition = ProfileConditionType.LessThanEqual,
|
||||||
Property = ProfileConditionValue.Height,
|
Property = ProfileConditionValue.Height,
|
||||||
Value = "1080"
|
Value = "1080"
|
||||||
},
|
},
|
||||||
new ProfileCondition
|
new ProfileCondition
|
||||||
{
|
{
|
||||||
Condition = ProfileConditionType.LessThanEqual,
|
Condition = ProfileConditionType.LessThanEqual,
|
||||||
Property = ProfileConditionValue.VideoBitDepth,
|
Property = ProfileConditionValue.VideoBitDepth,
|
||||||
Value = "8",
|
Value = "8",
|
||||||
IsRequired = false
|
IsRequired = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SubtitleProfiles = new[]
|
SubtitleProfiles = new[]
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
@ -24,10 +23,12 @@ namespace Emby.Dlna.Ssdp
|
|||||||
|
|
||||||
public static string GetDescendantValue(this XElement container, XName name)
|
public static string GetDescendantValue(this XElement container, XName name)
|
||||||
{
|
{
|
||||||
var node = container.Descendants(name)
|
foreach (var node in container.Descendants(name))
|
||||||
.FirstOrDefault();
|
{
|
||||||
|
return node.Value;
|
||||||
|
}
|
||||||
|
|
||||||
return node == null ? null : node.Value;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,13 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
{
|
{
|
||||||
internal static class ImageHelpers
|
internal static class ImageHelpers
|
||||||
{
|
{
|
||||||
internal static List<string> ProjectPaths(List<string> paths, int count)
|
internal static List<string> ProjectPaths(string[] paths, int count)
|
||||||
{
|
{
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("count");
|
throw new ArgumentOutOfRangeException("count");
|
||||||
}
|
}
|
||||||
if (paths.Count == 0)
|
if (paths.Length == 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("paths");
|
throw new ArgumentOutOfRangeException("paths");
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
return list.Take(count).ToList();
|
return list.Take(count).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddToList(List<string> list, List<string> paths, int count)
|
private static void AddToList(List<string> list, string[] paths, int count)
|
||||||
{
|
{
|
||||||
while (list.Count < count)
|
while (list.Count < count)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,6 @@ using MediaBrowser.Model.Drawing;
|
|||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.System;
|
using MediaBrowser.Model.System;
|
||||||
|
|
||||||
@ -306,15 +305,15 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
|
|
||||||
if (ratio >= 1.4)
|
if (ratio >= 1.4)
|
||||||
{
|
{
|
||||||
new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height);
|
new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
|
||||||
}
|
}
|
||||||
else if (ratio >= .9)
|
else if (ratio >= .9)
|
||||||
{
|
{
|
||||||
new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height);
|
new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height);
|
new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BuildPosterCollage(List<string> paths, string outputPath, int width, int height)
|
public void BuildPosterCollage(string[] paths, string outputPath, int width, int height)
|
||||||
{
|
{
|
||||||
using (var wand = BuildPosterCollageWand(paths, width, height))
|
using (var wand = BuildPosterCollageWand(paths, width, height))
|
||||||
{
|
{
|
||||||
@ -27,7 +27,7 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BuildSquareCollage(List<string> paths, string outputPath, int width, int height)
|
public void BuildSquareCollage(string[] paths, string outputPath, int width, int height)
|
||||||
{
|
{
|
||||||
using (var wand = BuildSquareCollageWand(paths, width, height))
|
using (var wand = BuildSquareCollageWand(paths, width, height))
|
||||||
{
|
{
|
||||||
@ -35,7 +35,7 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BuildThumbCollage(List<string> paths, string outputPath, int width, int height)
|
public void BuildThumbCollage(string[] paths, string outputPath, int width, int height)
|
||||||
{
|
{
|
||||||
using (var wand = BuildThumbCollageWand(paths, width, height))
|
using (var wand = BuildThumbCollageWand(paths, width, height))
|
||||||
{
|
{
|
||||||
@ -43,7 +43,7 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MagickWand BuildPosterCollageWand(List<string> paths, int width, int height)
|
private MagickWand BuildPosterCollageWand(string[] paths, int width, int height)
|
||||||
{
|
{
|
||||||
var inputPaths = ImageHelpers.ProjectPaths(paths, 3);
|
var inputPaths = ImageHelpers.ProjectPaths(paths, 3);
|
||||||
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
||||||
@ -108,7 +108,7 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MagickWand BuildThumbCollageWand(List<string> paths, int width, int height)
|
private MagickWand BuildThumbCollageWand(string[] paths, int width, int height)
|
||||||
{
|
{
|
||||||
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
||||||
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
||||||
@ -173,7 +173,7 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MagickWand BuildSquareCollageWand(List<string> paths, int width, int height)
|
private MagickWand BuildSquareCollageWand(string[] paths, int width, int height)
|
||||||
{
|
{
|
||||||
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
||||||
var outputWand = new MagickWand(width, height, new PixelWand("none", 1));
|
var outputWand = new MagickWand(width, height, new PixelWand("none", 1));
|
||||||
|
@ -18,6 +18,7 @@ using System.Threading.Tasks;
|
|||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using Emby.Drawing.Common;
|
using Emby.Drawing.Common;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
using MediaBrowser.Model.Extensions;
|
using MediaBrowser.Model.Extensions;
|
||||||
@ -44,7 +45,7 @@ namespace Emby.Drawing
|
|||||||
/// Image processors are specialized metadata providers that run after the normal ones
|
/// Image processors are specialized metadata providers that run after the normal ones
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The image enhancers.</value>
|
/// <value>The image enhancers.</value>
|
||||||
public IEnumerable<IImageEnhancer> ImageEnhancers { get; private set; }
|
public IImageEnhancer[] ImageEnhancers { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _logger
|
/// The _logger
|
||||||
@ -56,22 +57,24 @@ namespace Emby.Drawing
|
|||||||
private readonly IServerApplicationPaths _appPaths;
|
private readonly IServerApplicationPaths _appPaths;
|
||||||
private IImageEncoder _imageEncoder;
|
private IImageEncoder _imageEncoder;
|
||||||
private readonly Func<ILibraryManager> _libraryManager;
|
private readonly Func<ILibraryManager> _libraryManager;
|
||||||
|
private readonly Func<IMediaEncoder> _mediaEncoder;
|
||||||
|
|
||||||
public ImageProcessor(ILogger logger,
|
public ImageProcessor(ILogger logger,
|
||||||
IServerApplicationPaths appPaths,
|
IServerApplicationPaths appPaths,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IJsonSerializer jsonSerializer,
|
IJsonSerializer jsonSerializer,
|
||||||
IImageEncoder imageEncoder,
|
IImageEncoder imageEncoder,
|
||||||
Func<ILibraryManager> libraryManager, ITimerFactory timerFactory)
|
Func<ILibraryManager> libraryManager, ITimerFactory timerFactory, Func<IMediaEncoder> mediaEncoder)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
_imageEncoder = imageEncoder;
|
_imageEncoder = imageEncoder;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
_mediaEncoder = mediaEncoder;
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
|
|
||||||
ImageEnhancers = new List<IImageEnhancer>();
|
ImageEnhancers = new IImageEnhancer[] { };
|
||||||
_saveImageSizeTimer = timerFactory.Create(SaveImageSizeCallback, null, Timeout.Infinite, Timeout.Infinite);
|
_saveImageSizeTimer = timerFactory.Create(SaveImageSizeCallback, null, Timeout.Infinite, Timeout.Infinite);
|
||||||
ImageHelper.ImageProcessor = this;
|
ImageHelper.ImageProcessor = this;
|
||||||
|
|
||||||
@ -120,7 +123,36 @@ namespace Emby.Drawing
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _imageEncoder.SupportedInputFormats;
|
return new string[]
|
||||||
|
{
|
||||||
|
"tiff",
|
||||||
|
"jpeg",
|
||||||
|
"jpg",
|
||||||
|
"png",
|
||||||
|
"aiff",
|
||||||
|
"cr2",
|
||||||
|
"crw",
|
||||||
|
"dng",
|
||||||
|
|
||||||
|
// Remove until supported
|
||||||
|
//"nef",
|
||||||
|
"orf",
|
||||||
|
"pef",
|
||||||
|
"arw",
|
||||||
|
"webp",
|
||||||
|
"gif",
|
||||||
|
"bmp",
|
||||||
|
"erf",
|
||||||
|
"raf",
|
||||||
|
"rw2",
|
||||||
|
"nrw",
|
||||||
|
"dng",
|
||||||
|
"ico",
|
||||||
|
"astc",
|
||||||
|
"ktx",
|
||||||
|
"pkm",
|
||||||
|
"wbmp"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +235,10 @@ namespace Emby.Drawing
|
|||||||
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false);
|
||||||
|
originalImagePath = supportedImageInfo.Item1;
|
||||||
|
dateModified = supportedImageInfo.Item2;
|
||||||
|
|
||||||
if (options.Enhancers.Count > 0)
|
if (options.Enhancers.Count > 0)
|
||||||
{
|
{
|
||||||
if (item == null)
|
if (item == null)
|
||||||
@ -618,7 +654,7 @@ namespace Emby.Drawing
|
|||||||
|
|
||||||
var supportedEnhancers = GetSupportedEnhancers(item, image.Type);
|
var supportedEnhancers = GetSupportedEnhancers(item, image.Type);
|
||||||
|
|
||||||
return GetImageCacheTag(item, image, supportedEnhancers.ToList());
|
return GetImageCacheTag(item, image, supportedEnhancers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -663,6 +699,42 @@ namespace Emby.Drawing
|
|||||||
return string.Join("|", cacheKeys.ToArray(cacheKeys.Count)).GetMD5().ToString("N");
|
return string.Join("|", cacheKeys.ToArray(cacheKeys.Count)).GetMD5().ToString("N");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<Tuple<string, DateTime>> GetSupportedImage(string originalImagePath, DateTime dateModified)
|
||||||
|
{
|
||||||
|
var inputFormat = (Path.GetExtension(originalImagePath) ?? string.Empty)
|
||||||
|
.TrimStart('.')
|
||||||
|
.Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (!_imageEncoder.SupportedInputFormats.Contains(inputFormat, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filename = (originalImagePath + dateModified.Ticks.ToString(UsCulture)).GetMD5().ToString("N");
|
||||||
|
|
||||||
|
var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + ".webp");
|
||||||
|
|
||||||
|
var file = _fileSystem.GetFileInfo(outputPath);
|
||||||
|
if (!file.Exists)
|
||||||
|
{
|
||||||
|
await _mediaEncoder().ConvertImage(originalImagePath, outputPath).ConfigureAwait(false);
|
||||||
|
dateModified = _fileSystem.GetLastWriteTimeUtc(outputPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dateModified = file.LastWriteTimeUtc;
|
||||||
|
}
|
||||||
|
|
||||||
|
originalImagePath = outputPath;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Image conversion failed for {0}", ex, originalImagePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Tuple<string, DateTime>(originalImagePath, dateModified);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the enhanced image.
|
/// Gets the enhanced image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -672,7 +744,7 @@ namespace Emby.Drawing
|
|||||||
/// <returns>Task{System.String}.</returns>
|
/// <returns>Task{System.String}.</returns>
|
||||||
public async Task<string> GetEnhancedImage(IHasMetadata item, ImageType imageType, int imageIndex)
|
public async Task<string> GetEnhancedImage(IHasMetadata item, ImageType imageType, int imageIndex)
|
||||||
{
|
{
|
||||||
var enhancers = GetSupportedEnhancers(item, imageType).ToList();
|
var enhancers = GetSupportedEnhancers(item, imageType);
|
||||||
|
|
||||||
var imageInfo = item.GetImageInfo(imageType, imageIndex);
|
var imageInfo = item.GetImageInfo(imageType, imageIndex);
|
||||||
|
|
||||||
@ -866,21 +938,25 @@ namespace Emby.Drawing
|
|||||||
_logger.Info("Completed creation of image collage and saved to {0}", options.OutputPath);
|
_logger.Info("Completed creation of image collage and saved to {0}", options.OutputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IImageEnhancer> GetSupportedEnhancers(IHasMetadata item, ImageType imageType)
|
public List<IImageEnhancer> GetSupportedEnhancers(IHasMetadata item, ImageType imageType)
|
||||||
{
|
{
|
||||||
return ImageEnhancers.Where(i =>
|
var list = new List<IImageEnhancer>();
|
||||||
|
|
||||||
|
foreach (var i in ImageEnhancers)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return i.Supports(item, imageType);
|
if (i.Supports(item, imageType))
|
||||||
|
{
|
||||||
|
list.Add(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.ErrorException("Error in image enhancer: {0}", ex, i.GetType().Name);
|
_logger.ErrorException("Error in image enhancer: {0}", ex, i.GetType().Name);
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
@ -444,11 +444,11 @@ namespace Emby.Server.Implementations.Activity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void CreateLogEntry(ActivityLogEntry entry)
|
private void CreateLogEntry(ActivityLogEntry entry)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _activityManager.Create(entry).ConfigureAwait(false);
|
_activityManager.Create(entry);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -25,12 +25,12 @@ namespace Emby.Server.Implementations.Activity
|
|||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Create(ActivityLogEntry entry)
|
public void Create(ActivityLogEntry entry)
|
||||||
{
|
{
|
||||||
entry.Id = Guid.NewGuid().ToString("N");
|
entry.Id = Guid.NewGuid().ToString("N");
|
||||||
entry.Date = DateTime.UtcNow;
|
entry.Date = DateTime.UtcNow;
|
||||||
|
|
||||||
await _repo.Create(entry).ConfigureAwait(false);
|
_repo.Create(entry);
|
||||||
|
|
||||||
EventHelper.FireEventIfNotNull(EntryCreated, this, new GenericEventArgs<ActivityLogEntry>(entry), _logger);
|
EventHelper.FireEventIfNotNull(EntryCreated, this, new GenericEventArgs<ActivityLogEntry>(entry), _logger);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Emby.Server.Implementations.Data;
|
using Emby.Server.Implementations.Data;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.Activity;
|
using MediaBrowser.Model.Activity;
|
||||||
@ -41,12 +40,12 @@ namespace Emby.Server.Implementations.Activity
|
|||||||
|
|
||||||
private const string BaseActivitySelectText = "select Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity from ActivityLogEntries";
|
private const string BaseActivitySelectText = "select Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity from ActivityLogEntries";
|
||||||
|
|
||||||
public Task Create(ActivityLogEntry entry)
|
public void Create(ActivityLogEntry entry)
|
||||||
{
|
{
|
||||||
return Update(entry);
|
Update(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Update(ActivityLogEntry entry)
|
public void Update(ActivityLogEntry entry)
|
||||||
{
|
{
|
||||||
if (entry == null)
|
if (entry == null)
|
||||||
{
|
{
|
||||||
|
@ -227,6 +227,8 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
protected IEnvironmentInfo EnvironmentInfo { get; set; }
|
protected IEnvironmentInfo EnvironmentInfo { get; set; }
|
||||||
|
|
||||||
|
private IBlurayExaminer BlurayExaminer { get; set; }
|
||||||
|
|
||||||
public PackageVersionClass SystemUpdateLevel
|
public PackageVersionClass SystemUpdateLevel
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -424,11 +426,6 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
SetBaseExceptionMessage();
|
SetBaseExceptionMessage();
|
||||||
|
|
||||||
if (environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows)
|
|
||||||
{
|
|
||||||
fileSystem.AddShortcutHandler(new LnkShortcutHandler());
|
|
||||||
}
|
|
||||||
|
|
||||||
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
|
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -866,7 +863,7 @@ namespace Emby.Server.Implementations
|
|||||||
SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, LogManager, FileSystemManager, CryptographyProvider);
|
SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, LogManager, FileSystemManager, CryptographyProvider);
|
||||||
RegisterSingleInstance(SecurityManager);
|
RegisterSingleInstance(SecurityManager);
|
||||||
|
|
||||||
InstallationManager = new InstallationManager(LogManager.GetLogger("InstallationManager"), this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ConfigurationManager, FileSystemManager, CryptographyProvider);
|
InstallationManager = new InstallationManager(LogManager.GetLogger("InstallationManager"), this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ConfigurationManager, FileSystemManager, CryptographyProvider, PackageRuntime);
|
||||||
RegisterSingleInstance(InstallationManager);
|
RegisterSingleInstance(InstallationManager);
|
||||||
|
|
||||||
ZipClient = new ZipClient(FileSystemManager);
|
ZipClient = new ZipClient(FileSystemManager);
|
||||||
@ -889,7 +886,8 @@ namespace Emby.Server.Implementations
|
|||||||
ITextEncoding textEncoding = new TextEncoding.TextEncoding(FileSystemManager, LogManager.GetLogger("TextEncoding"), JsonSerializer);
|
ITextEncoding textEncoding = new TextEncoding.TextEncoding(FileSystemManager, LogManager.GetLogger("TextEncoding"), JsonSerializer);
|
||||||
RegisterSingleInstance(textEncoding);
|
RegisterSingleInstance(textEncoding);
|
||||||
Utilities.EncodingHelper = textEncoding;
|
Utilities.EncodingHelper = textEncoding;
|
||||||
RegisterSingleInstance<IBlurayExaminer>(() => new BdInfoExaminer(FileSystemManager, textEncoding));
|
BlurayExaminer = new BdInfoExaminer(FileSystemManager, textEncoding);
|
||||||
|
RegisterSingleInstance(BlurayExaminer);
|
||||||
|
|
||||||
RegisterSingleInstance<IXmlReaderSettingsFactory>(new XmlReaderSettingsFactory());
|
RegisterSingleInstance<IXmlReaderSettingsFactory>(new XmlReaderSettingsFactory());
|
||||||
|
|
||||||
@ -1050,7 +1048,15 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
SetStaticProperties();
|
SetStaticProperties();
|
||||||
|
|
||||||
await ((UserManager)UserManager).Initialize().ConfigureAwait(false);
|
((UserManager)UserManager).Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual string PackageRuntime
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "netframework";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths, bool isStartup)
|
public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths, bool isStartup)
|
||||||
@ -1199,7 +1205,7 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
private IImageProcessor GetImageProcessor()
|
private IImageProcessor GetImageProcessor()
|
||||||
{
|
{
|
||||||
return new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, ImageEncoder, () => LibraryManager, TimerFactory);
|
return new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, ImageEncoder, () => LibraryManager, TimerFactory, () => MediaEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual FFMpegInstallInfo GetFfmpegInstallInfo()
|
protected virtual FFMpegInstallInfo GetFfmpegInstallInfo()
|
||||||
@ -1332,7 +1338,8 @@ namespace Emby.Server.Implementations
|
|||||||
ProcessFactory,
|
ProcessFactory,
|
||||||
(Environment.ProcessorCount > 2 ? 14000 : 40000),
|
(Environment.ProcessorCount > 2 ? 14000 : 40000),
|
||||||
EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows,
|
EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows,
|
||||||
EnvironmentInfo);
|
EnvironmentInfo,
|
||||||
|
BlurayExaminer);
|
||||||
|
|
||||||
MediaEncoder = mediaEncoder;
|
MediaEncoder = mediaEncoder;
|
||||||
RegisterSingleInstance(MediaEncoder);
|
RegisterSingleInstance(MediaEncoder);
|
||||||
@ -1858,9 +1865,9 @@ namespace Emby.Server.Implementations
|
|||||||
HasPendingRestart = HasPendingRestart,
|
HasPendingRestart = HasPendingRestart,
|
||||||
Version = ApplicationVersion.ToString(),
|
Version = ApplicationVersion.ToString(),
|
||||||
WebSocketPortNumber = HttpPort,
|
WebSocketPortNumber = HttpPort,
|
||||||
FailedPluginAssemblies = FailedAssemblies.ToList(),
|
FailedPluginAssemblies = FailedAssemblies.ToArray(),
|
||||||
InProgressInstallations = InstallationManager.CurrentInstallations.Select(i => i.Item1).ToList(),
|
InProgressInstallations = InstallationManager.CurrentInstallations.Select(i => i.Item1).ToArray(),
|
||||||
CompletedInstallations = InstallationManager.CompletedInstallations.ToList(),
|
CompletedInstallations = InstallationManager.CompletedInstallations.ToArray(),
|
||||||
Id = SystemId,
|
Id = SystemId,
|
||||||
ProgramDataPath = ApplicationPaths.ProgramDataPath,
|
ProgramDataPath = ApplicationPaths.ProgramDataPath,
|
||||||
LogPath = ApplicationPaths.LogDirectoryPath,
|
LogPath = ApplicationPaths.LogDirectoryPath,
|
||||||
|
@ -182,10 +182,8 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
|
var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
var returnItems = returnList
|
|
||||||
.ToArray(returnList.Count);
|
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
@ -431,7 +429,7 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
{
|
{
|
||||||
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
_libraryManager.CreateItem(item, cancellationToken);
|
||||||
}
|
}
|
||||||
else if (forceUpdate)
|
else if (forceUpdate)
|
||||||
{
|
{
|
||||||
@ -464,14 +462,14 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
return _libraryManager.GetItemById(id) as Channel;
|
return _libraryManager.GetItemById(id) as Channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ChannelFeatures> GetAllChannelFeatures()
|
public ChannelFeatures[] GetAllChannelFeatures()
|
||||||
{
|
{
|
||||||
return _libraryManager.GetItemIds(new InternalItemsQuery
|
return _libraryManager.GetItemIds(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Channel).Name },
|
IncludeItemTypes = new[] { typeof(Channel).Name },
|
||||||
SortBy = new[] { ItemSortBy.SortName }
|
SortBy = new[] { ItemSortBy.SortName }
|
||||||
|
|
||||||
}).Select(i => GetChannelFeatures(i.ToString("N")));
|
}).Select(i => GetChannelFeatures(i.ToString("N"))).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelFeatures GetChannelFeatures(string id)
|
public ChannelFeatures GetChannelFeatures(string id)
|
||||||
@ -511,10 +509,10 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
{
|
{
|
||||||
CanFilter = !features.MaxPageSize.HasValue,
|
CanFilter = !features.MaxPageSize.HasValue,
|
||||||
CanSearch = provider is ISearchableChannel,
|
CanSearch = provider is ISearchableChannel,
|
||||||
ContentTypes = features.ContentTypes,
|
ContentTypes = features.ContentTypes.ToArray(),
|
||||||
DefaultSortFields = features.DefaultSortFields,
|
DefaultSortFields = features.DefaultSortFields.ToArray(),
|
||||||
MaxPageSize = features.MaxPageSize,
|
MaxPageSize = features.MaxPageSize,
|
||||||
MediaTypes = features.MediaTypes,
|
MediaTypes = features.MediaTypes.ToArray(),
|
||||||
SupportsSortOrderToggle = features.SupportsSortOrderToggle,
|
SupportsSortOrderToggle = features.SupportsSortOrderToggle,
|
||||||
SupportsLatestMedia = supportsLatest,
|
SupportsLatestMedia = supportsLatest,
|
||||||
Name = channel.Name,
|
Name = channel.Name,
|
||||||
@ -566,12 +564,10 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
|
|
||||||
var dtoOptions = new DtoOptions()
|
var dtoOptions = new DtoOptions()
|
||||||
{
|
{
|
||||||
Fields = query.Fields.ToList()
|
Fields = query.Fields
|
||||||
};
|
};
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(items, dtoOptions, user).ConfigureAwait(false));
|
var returnItems = (await _dtoService.GetBaseItemDtos(items, dtoOptions, user).ConfigureAwait(false));
|
||||||
var returnItems = returnList
|
|
||||||
.ToArray(returnList.Count);
|
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
@ -833,13 +829,11 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
|
|
||||||
var dtoOptions = new DtoOptions()
|
var dtoOptions = new DtoOptions()
|
||||||
{
|
{
|
||||||
Fields = query.Fields.ToList()
|
Fields = query.Fields
|
||||||
};
|
};
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
|
var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
var returnItems = returnList
|
|
||||||
.ToArray(returnList.Count);
|
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
@ -987,13 +981,11 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
|
|
||||||
var dtoOptions = new DtoOptions()
|
var dtoOptions = new DtoOptions()
|
||||||
{
|
{
|
||||||
Fields = query.Fields.ToList()
|
Fields = query.Fields
|
||||||
};
|
};
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
|
var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
var returnItems = returnList
|
|
||||||
.ToArray(returnList.Count);
|
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
@ -1338,7 +1330,7 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
var hasArtists = item as IHasArtist;
|
var hasArtists = item as IHasArtist;
|
||||||
if (hasArtists != null)
|
if (hasArtists != null)
|
||||||
{
|
{
|
||||||
hasArtists.Artists = info.Artists;
|
hasArtists.Artists = info.Artists.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasAlbumArtists = item as IHasAlbumArtist;
|
var hasAlbumArtists = item as IHasAlbumArtist;
|
||||||
@ -1396,11 +1388,11 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
{
|
{
|
||||||
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
_libraryManager.CreateItem(item, cancellationToken);
|
||||||
|
|
||||||
if (info.People != null && info.People.Count > 0)
|
if (info.People != null && info.People.Count > 0)
|
||||||
{
|
{
|
||||||
await _libraryManager.UpdatePeople(item, info.People ?? new List<PersonInfo>()).ConfigureAwait(false);
|
_libraryManager.UpdatePeople(item, info.People ?? new List<PersonInfo>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (forceUpdate)
|
else if (forceUpdate)
|
||||||
|
@ -84,15 +84,15 @@ namespace Emby.Server.Implementations.Collections
|
|||||||
ProviderIds = options.ProviderIds,
|
ProviderIds = options.ProviderIds,
|
||||||
Shares = options.UserIds.Select(i => new Share
|
Shares = options.UserIds.Select(i => new Share
|
||||||
{
|
{
|
||||||
UserId = i.ToString("N"),
|
UserId = i,
|
||||||
CanEdit = true
|
CanEdit = true
|
||||||
|
|
||||||
}).ToList()
|
}).ToList()
|
||||||
};
|
};
|
||||||
|
|
||||||
await parentFolder.AddChild(collection, CancellationToken.None).ConfigureAwait(false);
|
parentFolder.AddChild(collection, CancellationToken.None);
|
||||||
|
|
||||||
if (options.ItemIdList.Count > 0)
|
if (options.ItemIdList.Length > 0)
|
||||||
{
|
{
|
||||||
await AddToCollection(collection.Id, options.ItemIdList, false, new MetadataRefreshOptions(_fileSystem)
|
await AddToCollection(collection.Id, options.ItemIdList, false, new MetadataRefreshOptions(_fileSystem)
|
||||||
{
|
{
|
||||||
@ -149,12 +149,17 @@ namespace Emby.Server.Implementations.Collections
|
|||||||
return GetCollectionsFolder(string.Empty);
|
return GetCollectionsFolder(string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
|
public Task AddToCollection(Guid collectionId, IEnumerable<string> ids)
|
||||||
{
|
{
|
||||||
return AddToCollection(collectionId, ids, true, new MetadataRefreshOptions(_fileSystem));
|
return AddToCollection(collectionId, ids, true, new MetadataRefreshOptions(_fileSystem));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent, MetadataRefreshOptions refreshOptions)
|
public Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
|
||||||
|
{
|
||||||
|
return AddToCollection(collectionId, ids.Select(i => i.ToString("N")), true, new MetadataRefreshOptions(_fileSystem));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AddToCollection(Guid collectionId, IEnumerable<string> ids, bool fireEvent, MetadataRefreshOptions refreshOptions)
|
||||||
{
|
{
|
||||||
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
|
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
|
||||||
|
|
||||||
@ -165,11 +170,12 @@ namespace Emby.Server.Implementations.Collections
|
|||||||
|
|
||||||
var list = new List<LinkedChild>();
|
var list = new List<LinkedChild>();
|
||||||
var itemList = new List<BaseItem>();
|
var itemList = new List<BaseItem>();
|
||||||
var currentLinkedChildren = collection.GetLinkedChildren().ToList();
|
var currentLinkedChildrenIds = collection.GetLinkedChildren().Select(i => i.Id).ToList();
|
||||||
|
|
||||||
foreach (var itemId in ids)
|
foreach (var id in ids)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(itemId);
|
var guidId = new Guid(id);
|
||||||
|
var item = _libraryManager.GetItemById(guidId);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(item.Path))
|
if (string.IsNullOrWhiteSpace(item.Path))
|
||||||
{
|
{
|
||||||
@ -183,7 +189,7 @@ namespace Emby.Server.Implementations.Collections
|
|||||||
|
|
||||||
itemList.Add(item);
|
itemList.Add(item);
|
||||||
|
|
||||||
if (currentLinkedChildren.All(i => i.Id != itemId))
|
if (!currentLinkedChildrenIds.Contains(guidId))
|
||||||
{
|
{
|
||||||
list.Add(LinkedChild.Create(item));
|
list.Add(LinkedChild.Create(item));
|
||||||
}
|
}
|
||||||
@ -213,6 +219,11 @@ namespace Emby.Server.Implementations.Collections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task RemoveFromCollection(Guid collectionId, IEnumerable<string> itemIds)
|
||||||
|
{
|
||||||
|
return RemoveFromCollection(collectionId, itemIds.Select(i => new Guid(i)));
|
||||||
|
}
|
||||||
|
|
||||||
public async Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds)
|
public async Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds)
|
||||||
{
|
{
|
||||||
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
|
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
|
||||||
@ -225,11 +236,11 @@ namespace Emby.Server.Implementations.Collections
|
|||||||
var list = new List<LinkedChild>();
|
var list = new List<LinkedChild>();
|
||||||
var itemList = new List<BaseItem>();
|
var itemList = new List<BaseItem>();
|
||||||
|
|
||||||
foreach (var itemId in itemIds)
|
foreach (var guidId in itemIds)
|
||||||
{
|
{
|
||||||
var childItem = _libraryManager.GetItemById(itemId);
|
var childItem = _libraryManager.GetItemById(guidId);
|
||||||
|
|
||||||
var child = collection.LinkedChildren.FirstOrDefault(i => (i.ItemId.HasValue && i.ItemId.Value == itemId) || (childItem != null && string.Equals(childItem.Path, i.Path, StringComparison.OrdinalIgnoreCase)));
|
var child = collection.LinkedChildren.FirstOrDefault(i => (i.ItemId.HasValue && i.ItemId.Value == guidId) || (childItem != null && string.Equals(childItem.Path, i.Path, StringComparison.OrdinalIgnoreCase)));
|
||||||
|
|
||||||
if (child == null)
|
if (child == null)
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
@ -75,7 +74,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">item</exception>
|
/// <exception cref="System.ArgumentNullException">item</exception>
|
||||||
public async Task SaveDisplayPreferences(DisplayPreferences displayPreferences, Guid userId, string client, CancellationToken cancellationToken)
|
public void SaveDisplayPreferences(DisplayPreferences displayPreferences, Guid userId, string client, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (displayPreferences == null)
|
if (displayPreferences == null)
|
||||||
{
|
{
|
||||||
@ -123,7 +122,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">item</exception>
|
/// <exception cref="System.ArgumentNullException">item</exception>
|
||||||
public async Task SaveAllDisplayPreferences(IEnumerable<DisplayPreferences> displayPreferences, Guid userId, CancellationToken cancellationToken)
|
public void SaveAllDisplayPreferences(IEnumerable<DisplayPreferences> displayPreferences, Guid userId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (displayPreferences == null)
|
if (displayPreferences == null)
|
||||||
{
|
{
|
||||||
@ -226,9 +225,9 @@ namespace Emby.Server.Implementations.Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SaveDisplayPreferences(DisplayPreferences displayPreferences, string userId, string client, CancellationToken cancellationToken)
|
public void SaveDisplayPreferences(DisplayPreferences displayPreferences, string userId, string client, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return SaveDisplayPreferences(displayPreferences, new Guid(userId), client, cancellationToken);
|
SaveDisplayPreferences(displayPreferences, new Guid(userId), client, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DisplayPreferences GetDisplayPreferences(string displayPreferencesId, string userId, string client)
|
public DisplayPreferences GetDisplayPreferences(string displayPreferencesId, string userId, string client)
|
||||||
|
@ -132,8 +132,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the connection to the database
|
/// Opens the connection to the database
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task.</returns>
|
public void Initialize(SqliteUserDataRepository userDataRepo)
|
||||||
public async Task Initialize(SqliteUserDataRepository userDataRepo)
|
|
||||||
{
|
{
|
||||||
using (var connection = CreateConnection())
|
using (var connection = CreateConnection())
|
||||||
{
|
{
|
||||||
@ -149,7 +148,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
|
|
||||||
"create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))",
|
"create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))",
|
||||||
"create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)",
|
"create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)",
|
||||||
"create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)",
|
"create index if not exists idx_AncestorIds5 on AncestorIds(AncestorIdText,ItemId)",
|
||||||
|
|
||||||
"create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT, CleanValue TEXT)",
|
"create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT, CleanValue TEXT)",
|
||||||
|
|
||||||
@ -308,6 +307,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
"drop index if exists idx_TypeSeriesPresentationUniqueKey2",
|
"drop index if exists idx_TypeSeriesPresentationUniqueKey2",
|
||||||
"drop index if exists idx_AncestorIds3",
|
"drop index if exists idx_AncestorIds3",
|
||||||
"drop index if exists idx_AncestorIds4",
|
"drop index if exists idx_AncestorIds4",
|
||||||
|
"drop index if exists idx_AncestorIds2",
|
||||||
|
|
||||||
"create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)",
|
"create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)",
|
||||||
"create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)",
|
"create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)",
|
||||||
@ -599,16 +599,15 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
|
||||||
/// <exception cref="System.ArgumentNullException">item</exception>
|
/// <exception cref="System.ArgumentNullException">item</exception>
|
||||||
public Task SaveItem(BaseItem item, CancellationToken cancellationToken)
|
public void SaveItem(BaseItem item, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("item");
|
throw new ArgumentNullException("item");
|
||||||
}
|
}
|
||||||
|
|
||||||
return SaveItems(new List<BaseItem> { item }, cancellationToken);
|
SaveItems(new List<BaseItem> { item }, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -616,13 +615,12 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
|
||||||
/// <exception cref="System.ArgumentNullException">
|
/// <exception cref="System.ArgumentNullException">
|
||||||
/// items
|
/// items
|
||||||
/// or
|
/// or
|
||||||
/// cancellationToken
|
/// cancellationToken
|
||||||
/// </exception>
|
/// </exception>
|
||||||
public async Task SaveItems(List<BaseItem> items, CancellationToken cancellationToken)
|
public void SaveItems(List<BaseItem> items, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (items == null)
|
if (items == null)
|
||||||
{
|
{
|
||||||
@ -1027,9 +1025,9 @@ namespace Emby.Server.Implementations.Data
|
|||||||
var hasArtists = item as IHasArtist;
|
var hasArtists = item as IHasArtist;
|
||||||
if (hasArtists != null)
|
if (hasArtists != null)
|
||||||
{
|
{
|
||||||
if (hasArtists.Artists.Count > 0)
|
if (hasArtists.Artists.Length > 0)
|
||||||
{
|
{
|
||||||
artists = string.Join("|", hasArtists.Artists.ToArray());
|
artists = string.Join("|", hasArtists.Artists);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
saveItemStatement.TryBind("@Artists", artists);
|
saveItemStatement.TryBind("@Artists", artists);
|
||||||
@ -1907,7 +1905,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
var hasArtists = item as IHasArtist;
|
var hasArtists = item as IHasArtist;
|
||||||
if (hasArtists != null && !reader.IsDBNull(index))
|
if (hasArtists != null && !reader.IsDBNull(index))
|
||||||
{
|
{
|
||||||
hasArtists.Artists = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
|
hasArtists.Artists = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
@ -1958,22 +1956,18 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// Gets the critic reviews.
|
/// Gets the critic reviews.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="itemId">The item id.</param>
|
/// <param name="itemId">The item id.</param>
|
||||||
/// <returns>Task{IEnumerable{ItemReview}}.</returns>
|
|
||||||
public List<ItemReview> GetCriticReviews(Guid itemId)
|
public List<ItemReview> GetCriticReviews(Guid itemId)
|
||||||
{
|
{
|
||||||
return new List<ItemReview>();
|
return new List<ItemReview>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Task _cachedTask = Task.FromResult(true);
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the critic reviews.
|
/// Saves the critic reviews.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="itemId">The item id.</param>
|
/// <param name="itemId">The item id.</param>
|
||||||
/// <param name="criticReviews">The critic reviews.</param>
|
/// <param name="criticReviews">The critic reviews.</param>
|
||||||
/// <returns>Task.</returns>
|
public void SaveCriticReviews(Guid itemId, IEnumerable<ItemReview> criticReviews)
|
||||||
public Task SaveCriticReviews(Guid itemId, IEnumerable<ItemReview> criticReviews)
|
|
||||||
{
|
{
|
||||||
return _cachedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -2078,7 +2072,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the chapters.
|
/// Saves the chapters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task SaveChapters(Guid id, List<ChapterInfo> chapters)
|
public void SaveChapters(Guid id, List<ChapterInfo> chapters)
|
||||||
{
|
{
|
||||||
CheckDisposed();
|
CheckDisposed();
|
||||||
|
|
||||||
@ -4653,12 +4647,12 @@ namespace Emby.Server.Implementations.Data
|
|||||||
typeof(AggregateFolder)
|
typeof(AggregateFolder)
|
||||||
};
|
};
|
||||||
|
|
||||||
public async Task UpdateInheritedValues(CancellationToken cancellationToken)
|
public void UpdateInheritedValues(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await UpdateInheritedTags(cancellationToken).ConfigureAwait(false);
|
UpdateInheritedTags(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateInheritedTags(CancellationToken cancellationToken)
|
private void UpdateInheritedTags(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var newValues = new List<Tuple<Guid, string[]>>();
|
var newValues = new List<Tuple<Guid, string[]>>();
|
||||||
|
|
||||||
@ -4753,7 +4747,7 @@ limit 100";
|
|||||||
return new[] { value }.Where(IsValidType);
|
return new[] { value }.Where(IsValidType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteItem(Guid id, CancellationToken cancellationToken)
|
public void DeleteItem(Guid id, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (id == Guid.Empty)
|
if (id == Guid.Empty)
|
||||||
{
|
{
|
||||||
@ -5484,7 +5478,7 @@ limit 100";
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdatePeople(Guid itemId, List<PersonInfo> people)
|
public void UpdatePeople(Guid itemId, List<PersonInfo> people)
|
||||||
{
|
{
|
||||||
if (itemId == Guid.Empty)
|
if (itemId == Guid.Empty)
|
||||||
{
|
{
|
||||||
@ -5614,7 +5608,7 @@ limit 100";
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SaveMediaStreams(Guid id, List<MediaStream> streams, CancellationToken cancellationToken)
|
public void SaveMediaStreams(Guid id, List<MediaStream> streams, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
CheckDisposed();
|
CheckDisposed();
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
@ -153,7 +152,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// userId
|
/// userId
|
||||||
/// or
|
/// or
|
||||||
/// userDataId</exception>
|
/// userDataId</exception>
|
||||||
public Task SaveUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken)
|
public void SaveUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (userData == null)
|
if (userData == null)
|
||||||
{
|
{
|
||||||
@ -168,10 +167,10 @@ namespace Emby.Server.Implementations.Data
|
|||||||
throw new ArgumentNullException("key");
|
throw new ArgumentNullException("key");
|
||||||
}
|
}
|
||||||
|
|
||||||
return PersistUserData(userId, key, userData, cancellationToken);
|
PersistUserData(userId, key, userData, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SaveAllUserData(Guid userId, IEnumerable<UserItemData> userData, CancellationToken cancellationToken)
|
public void SaveAllUserData(Guid userId, UserItemData[] userData, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (userData == null)
|
if (userData == null)
|
||||||
{
|
{
|
||||||
@ -182,7 +181,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
throw new ArgumentNullException("userId");
|
throw new ArgumentNullException("userId");
|
||||||
}
|
}
|
||||||
|
|
||||||
return PersistAllUserData(userId, userData.ToList(), cancellationToken);
|
PersistAllUserData(userId, userData, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -193,7 +192,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// <param name="userData">The user data.</param>
|
/// <param name="userData">The user data.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public async Task PersistUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken)
|
public void PersistUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@ -264,7 +263,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Persist all user data for the specified user
|
/// Persist all user data for the specified user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PersistAllUserData(Guid userId, List<UserItemData> userDataList, CancellationToken cancellationToken)
|
private void PersistAllUserData(Guid userId, UserItemData[] userDataList, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@ -349,7 +348,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId"></param>
|
/// <param name="userId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public IEnumerable<UserItemData> GetAllUserData(Guid userId)
|
public List<UserItemData> GetAllUserData(Guid userId)
|
||||||
{
|
{
|
||||||
if (userId == Guid.Empty)
|
if (userId == Guid.Empty)
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
@ -72,7 +71,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">user</exception>
|
/// <exception cref="System.ArgumentNullException">user</exception>
|
||||||
public async Task SaveUser(User user, CancellationToken cancellationToken)
|
public void SaveUser(User user, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
@ -139,7 +138,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">user</exception>
|
/// <exception cref="System.ArgumentNullException">user</exception>
|
||||||
public async Task DeleteUser(User user, CancellationToken cancellationToken)
|
public void DeleteUser(User user, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,7 @@ using MediaBrowser.Model.IO;
|
|||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
|
using MediaBrowser.Model.Extensions;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Devices
|
namespace Emby.Server.Implementations.Devices
|
||||||
{
|
{
|
||||||
@ -199,7 +200,10 @@ namespace Emby.Server.Implementations.Devices
|
|||||||
}
|
}
|
||||||
|
|
||||||
history.DeviceId = deviceId;
|
history.DeviceId = deviceId;
|
||||||
history.FilesUploaded.Add(file);
|
|
||||||
|
var list = history.FilesUploaded.ToList();
|
||||||
|
list.Add(file);
|
||||||
|
history.FilesUploaded = list.ToArray(list.Count);
|
||||||
|
|
||||||
_json.SerializeToFile(history, path);
|
_json.SerializeToFile(history, path);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
/// <param name="owner">The owner.</param>
|
/// <param name="owner">The owner.</param>
|
||||||
/// <returns>Task{DtoBaseItem}.</returns>
|
/// <returns>Task{DtoBaseItem}.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">item</exception>
|
/// <exception cref="System.ArgumentNullException">item</exception>
|
||||||
public BaseItemDto GetBaseItemDto(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null)
|
public BaseItemDto GetBaseItemDto(BaseItem item, ItemFields[] fields, User user = null, BaseItem owner = null)
|
||||||
{
|
{
|
||||||
var options = new DtoOptions
|
var options = new DtoOptions
|
||||||
{
|
{
|
||||||
@ -87,7 +87,17 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
return GetBaseItemDto(item, options, user, owner);
|
return GetBaseItemDto(item, options, user, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<BaseItemDto>> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
|
public Task<BaseItemDto[]> GetBaseItemDtos(List<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
|
||||||
|
{
|
||||||
|
return GetBaseItemDtos(items, items.Count, options, user, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<BaseItemDto[]> GetBaseItemDtos(BaseItem[] items, DtoOptions options, User user = null, BaseItem owner = null)
|
||||||
|
{
|
||||||
|
return GetBaseItemDtos(items, items.Length, options, user, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<BaseItemDto[]> GetBaseItemDtos(IEnumerable<BaseItem> items, int itemCount, DtoOptions options, User user = null, BaseItem owner = null)
|
||||||
{
|
{
|
||||||
if (items == null)
|
if (items == null)
|
||||||
{
|
{
|
||||||
@ -101,17 +111,14 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
|
|
||||||
var syncDictionary = GetSyncedItemProgress(options);
|
var syncDictionary = GetSyncedItemProgress(options);
|
||||||
|
|
||||||
var list = new List<BaseItemDto>();
|
var returnItems = new BaseItemDto[itemCount];
|
||||||
var programTuples = new List<Tuple<BaseItem, BaseItemDto>>();
|
var programTuples = new List<Tuple<BaseItem, BaseItemDto>>();
|
||||||
var channelTuples = new List<Tuple<BaseItemDto, LiveTvChannel>>();
|
var channelTuples = new List<Tuple<BaseItemDto, LiveTvChannel>>();
|
||||||
|
|
||||||
var refreshQueue = options.Fields.Contains(ItemFields.RefreshState)
|
var index = 0;
|
||||||
? _providerManager.GetRefreshQueue()
|
|
||||||
: null;
|
|
||||||
|
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user, owner);
|
var dto = GetBaseItemDtoInternal(item, options, user, owner);
|
||||||
|
|
||||||
var tvChannel = item as LiveTvChannel;
|
var tvChannel = item as LiveTvChannel;
|
||||||
if (tvChannel != null)
|
if (tvChannel != null)
|
||||||
@ -144,7 +151,8 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
|
|
||||||
FillSyncInfo(dto, item, options, user, syncDictionary);
|
FillSyncInfo(dto, item, options, user, syncDictionary);
|
||||||
|
|
||||||
list.Add(dto);
|
returnItems[index] = dto;
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (programTuples.Count > 0)
|
if (programTuples.Count > 0)
|
||||||
@ -157,18 +165,14 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
await _livetvManager().AddChannelInfo(channelTuples, options, user).ConfigureAwait(false);
|
await _livetvManager().AddChannelInfo(channelTuples, options, user).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return returnItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
|
public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
|
||||||
{
|
{
|
||||||
var syncDictionary = GetSyncedItemProgress(options);
|
var syncDictionary = GetSyncedItemProgress(options);
|
||||||
|
|
||||||
var refreshQueue = options.Fields.Contains(ItemFields.RefreshState)
|
var dto = GetBaseItemDtoInternal(item, options, user, owner);
|
||||||
? _providerManager.GetRefreshQueue()
|
|
||||||
: null;
|
|
||||||
|
|
||||||
var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user, owner);
|
|
||||||
var tvChannel = item as LiveTvChannel;
|
var tvChannel = item as LiveTvChannel;
|
||||||
if (tvChannel != null)
|
if (tvChannel != null)
|
||||||
{
|
{
|
||||||
@ -300,7 +304,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, Dictionary<Guid, Guid> currentRefreshQueue, User user = null, BaseItem owner = null)
|
private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
|
||||||
{
|
{
|
||||||
var fields = options.Fields;
|
var fields = options.Fields;
|
||||||
|
|
||||||
@ -365,6 +369,8 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
{
|
{
|
||||||
dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user);
|
dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NormalizeMediaSourceContainers(dto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,25 +406,72 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
dto.Etag = item.GetEtag(user);
|
dto.Etag = item.GetEtag(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentRefreshQueue != null)
|
var liveTvManager = _livetvManager();
|
||||||
{
|
|
||||||
//dto.RefreshState = item.GetRefreshState(currentRefreshQueue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item is ILiveTvRecording)
|
if (item is ILiveTvRecording)
|
||||||
{
|
{
|
||||||
_livetvManager().AddInfoToRecordingDto(item, dto, user);
|
liveTvManager.AddInfoToRecordingDto(item, dto, user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var activeRecording = liveTvManager.GetActiveRecordingInfo(item.Path);
|
||||||
|
if (activeRecording != null)
|
||||||
|
{
|
||||||
|
dto.Type = "Recording";
|
||||||
|
dto.CanDownload = false;
|
||||||
|
if (!string.IsNullOrWhiteSpace(dto.SeriesName))
|
||||||
|
{
|
||||||
|
dto.EpisodeTitle = dto.Name;
|
||||||
|
dto.Name = dto.SeriesName;
|
||||||
|
}
|
||||||
|
liveTvManager.AddInfoToRecordingDto(item, dto, activeRecording, user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void NormalizeMediaSourceContainers(BaseItemDto dto)
|
||||||
|
{
|
||||||
|
foreach (var mediaSource in dto.MediaSources)
|
||||||
|
{
|
||||||
|
var container = mediaSource.Container;
|
||||||
|
if (string.IsNullOrWhiteSpace(container))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var containers = container.Split(new[] { ',' });
|
||||||
|
if (containers.Length < 2)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = mediaSource.Path;
|
||||||
|
string fileExtensionContainer = null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(path))
|
||||||
|
{
|
||||||
|
path = Path.GetExtension(path);
|
||||||
|
if (!string.IsNullOrWhiteSpace(path))
|
||||||
|
{
|
||||||
|
path = Path.GetExtension(path);
|
||||||
|
if (!string.IsNullOrWhiteSpace(path))
|
||||||
|
{
|
||||||
|
path = path.TrimStart('.');
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(path) && containers.Contains(path, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
fileExtensionContainer = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaSource.Container = fileExtensionContainer ?? containers[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, Dictionary<string, SyncedItemProgress> syncProgress, User user = null)
|
public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, Dictionary<string, SyncedItemProgress> syncProgress, User user = null)
|
||||||
{
|
{
|
||||||
var refreshQueue = options.Fields.Contains(ItemFields.RefreshState)
|
var dto = GetBaseItemDtoInternal(item, options, user);
|
||||||
? _providerManager.GetRefreshQueue()
|
|
||||||
: null;
|
|
||||||
var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user);
|
|
||||||
|
|
||||||
if (taggedItems != null && options.Fields.Contains(ItemFields.ItemCounts))
|
if (taggedItems != null && options.Fields.Contains(ItemFields.ItemCounts))
|
||||||
{
|
{
|
||||||
@ -992,7 +1045,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
{
|
{
|
||||||
dto.RemoteTrailers = hasTrailers != null ?
|
dto.RemoteTrailers = hasTrailers != null ?
|
||||||
hasTrailers.RemoteTrailers :
|
hasTrailers.RemoteTrailers :
|
||||||
new MediaUrl[] {};
|
new MediaUrl[] { };
|
||||||
}
|
}
|
||||||
|
|
||||||
dto.Name = item.Name;
|
dto.Name = item.Name;
|
||||||
@ -1053,7 +1106,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
|
|
||||||
if (dto.Taglines == null)
|
if (dto.Taglines == null)
|
||||||
{
|
{
|
||||||
dto.Taglines = new string[]{};
|
dto.Taglines = new string[] { };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1243,17 +1296,17 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
|
|
||||||
if (iHasMediaSources != null)
|
if (iHasMediaSources != null)
|
||||||
{
|
{
|
||||||
List<MediaStream> mediaStreams;
|
MediaStream[] mediaStreams;
|
||||||
|
|
||||||
if (dto.MediaSources != null && dto.MediaSources.Count > 0)
|
if (dto.MediaSources != null && dto.MediaSources.Count > 0)
|
||||||
{
|
{
|
||||||
mediaStreams = dto.MediaSources.Where(i => new Guid(i.Id) == item.Id)
|
mediaStreams = dto.MediaSources.Where(i => new Guid(i.Id) == item.Id)
|
||||||
.SelectMany(i => i.MediaStreams)
|
.SelectMany(i => i.MediaStreams)
|
||||||
.ToList();
|
.ToArray();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mediaStreams = _mediaSourceManager().GetStaticMediaSources(iHasMediaSources, true).First().MediaStreams;
|
mediaStreams = _mediaSourceManager().GetStaticMediaSources(iHasMediaSources, true).First().MediaStreams.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
dto.MediaStreams = mediaStreams;
|
dto.MediaStreams = mediaStreams;
|
||||||
@ -1564,7 +1617,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary).ToList();
|
var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary);
|
||||||
|
|
||||||
ImageSize size;
|
ImageSize size;
|
||||||
|
|
||||||
|
@ -133,7 +133,6 @@
|
|||||||
<Compile Include="IO\FileRefresher.cs" />
|
<Compile Include="IO\FileRefresher.cs" />
|
||||||
<Compile Include="IO\IsoManager.cs" />
|
<Compile Include="IO\IsoManager.cs" />
|
||||||
<Compile Include="IO\LibraryMonitor.cs" />
|
<Compile Include="IO\LibraryMonitor.cs" />
|
||||||
<Compile Include="IO\LnkShortcutHandler.cs" />
|
|
||||||
<Compile Include="IO\ManagedFileSystem.cs" />
|
<Compile Include="IO\ManagedFileSystem.cs" />
|
||||||
<Compile Include="IO\MbLinkShortcutHandler.cs" />
|
<Compile Include="IO\MbLinkShortcutHandler.cs" />
|
||||||
<Compile Include="IO\MemoryStreamProvider.cs" />
|
<Compile Include="IO\MemoryStreamProvider.cs" />
|
||||||
@ -662,8 +661,9 @@
|
|||||||
<Reference Include="Emby.XmlTv, Version=1.0.6387.29335, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Emby.XmlTv, Version=1.0.6387.29335, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Emby.XmlTv.1.0.10\lib\portable-net45+netstandard2.0+win8\Emby.XmlTv.dll</HintPath>
|
<HintPath>..\packages\Emby.XmlTv.1.0.10\lib\portable-net45+netstandard2.0+win8\Emby.XmlTv.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="MediaBrowser.Naming, Version=1.0.6437.24226, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="MediaBrowser.Naming, Version=1.0.6447.2217, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\MediaBrowser.Naming.1.0.6\lib\portable-net45+netstandard2.0+win8\MediaBrowser.Naming.dll</HintPath>
|
<HintPath>..\packages\MediaBrowser.Naming.1.0.7\lib\portable-net45+netstandard2.0+win8\MediaBrowser.Naming.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ServiceStack.Text, Version=4.5.8.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="ServiceStack.Text, Version=4.5.8.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll</HintPath>
|
<HintPath>..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll</HintPath>
|
||||||
@ -699,7 +699,6 @@
|
|||||||
<EmbeddedResource Include="Localization\Core\ar.json" />
|
<EmbeddedResource Include="Localization\Core\ar.json" />
|
||||||
<EmbeddedResource Include="Localization\Core\bg-BG.json" />
|
<EmbeddedResource Include="Localization\Core\bg-BG.json" />
|
||||||
<EmbeddedResource Include="Localization\Core\ca.json" />
|
<EmbeddedResource Include="Localization\Core\ca.json" />
|
||||||
<EmbeddedResource Include="Localization\Core\core.json" />
|
|
||||||
<EmbeddedResource Include="Localization\Core\cs.json" />
|
<EmbeddedResource Include="Localization\Core\cs.json" />
|
||||||
<EmbeddedResource Include="Localization\Core\da.json" />
|
<EmbeddedResource Include="Localization\Core\da.json" />
|
||||||
<EmbeddedResource Include="Localization\Core\de.json" />
|
<EmbeddedResource Include="Localization\Core\de.json" />
|
||||||
|
@ -367,15 +367,15 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
|
|
||||||
return new LibraryUpdateInfo
|
return new LibraryUpdateInfo
|
||||||
{
|
{
|
||||||
ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
|
ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
|
||||||
|
|
||||||
ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
|
ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
|
||||||
|
|
||||||
ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, true)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
|
ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, true)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
|
||||||
|
|
||||||
FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
|
FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
|
||||||
|
|
||||||
FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList()
|
FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
dto.ItemId = i.Id.ToString("N");
|
dto.ItemId = i.Id.ToString("N");
|
||||||
return dto;
|
return dto;
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToArray();
|
||||||
|
|
||||||
var info = new UserDataChangeInfo
|
var info = new UserDataChangeInfo
|
||||||
{
|
{
|
||||||
|
@ -162,7 +162,7 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
return serviceType;
|
return serviceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddServiceInfo(Type serviceType, Type requestType, Type responseType)
|
public void AddServiceInfo(Type serviceType, Type requestType)
|
||||||
{
|
{
|
||||||
ServiceOperationsMap[requestType] = serviceType;
|
ServiceOperationsMap[requestType] = serviceType;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ namespace Emby.Server.Implementations.IO
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Any file name ending in any of these will be ignored by the watchers
|
/// Any file name ending in any of these will be ignored by the watchers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IReadOnlyList<string> _alwaysIgnoreFiles = new List<string>
|
private readonly string[] _alwaysIgnoreFiles = new string[]
|
||||||
{
|
{
|
||||||
"small.jpg",
|
"small.jpg",
|
||||||
"albumart.jpg",
|
"albumart.jpg",
|
||||||
@ -45,7 +45,7 @@ namespace Emby.Server.Implementations.IO
|
|||||||
"TempSBE"
|
"TempSBE"
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly IReadOnlyList<string> _alwaysIgnoreSubstrings = new List<string>
|
private readonly string[] _alwaysIgnoreSubstrings = new string[]
|
||||||
{
|
{
|
||||||
// Synology
|
// Synology
|
||||||
"eaDir",
|
"eaDir",
|
||||||
@ -54,7 +54,7 @@ namespace Emby.Server.Implementations.IO
|
|||||||
".actors"
|
".actors"
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly IReadOnlyList<string> _alwaysIgnoreExtensions = new List<string>
|
private readonly string[] _alwaysIgnoreExtensions = new string[]
|
||||||
{
|
{
|
||||||
// thumbs.db
|
// thumbs.db
|
||||||
".db",
|
".db",
|
||||||
@ -85,6 +85,8 @@ namespace Emby.Server.Implementations.IO
|
|||||||
|
|
||||||
public bool IsPathLocked(string path)
|
public bool IsPathLocked(string path)
|
||||||
{
|
{
|
||||||
|
// This method is not used by the core but it used by auto-organize
|
||||||
|
|
||||||
var lockedPaths = _tempIgnoredPaths.Keys.ToList();
|
var lockedPaths = _tempIgnoredPaths.Keys.ToList();
|
||||||
return lockedPaths.Any(i => _fileSystem.AreEqual(i, path) || _fileSystem.ContainsSubPath(i, path));
|
return lockedPaths.Any(i => _fileSystem.AreEqual(i, path) || _fileSystem.ContainsSubPath(i, path));
|
||||||
}
|
}
|
||||||
|
@ -353,7 +353,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (item is Photo)
|
if (!(item is Video))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -461,10 +461,10 @@ namespace Emby.Server.Implementations.Library
|
|||||||
parent.RemoveChild(item);
|
parent.RemoveChild(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
await ItemRepository.DeleteItem(item.Id, CancellationToken.None).ConfigureAwait(false);
|
ItemRepository.DeleteItem(item.Id, CancellationToken.None);
|
||||||
foreach (var child in children)
|
foreach (var child in children)
|
||||||
{
|
{
|
||||||
await ItemRepository.DeleteItem(child.Id, CancellationToken.None).ConfigureAwait(false);
|
ItemRepository.DeleteItem(child.Id, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseItem removed;
|
BaseItem removed;
|
||||||
@ -599,18 +599,16 @@ namespace Emby.Server.Implementations.Library
|
|||||||
// When resolving the root, we need it's grandchildren (children of user views)
|
// When resolving the root, we need it's grandchildren (children of user views)
|
||||||
var flattenFolderDepth = isPhysicalRoot ? 2 : 0;
|
var flattenFolderDepth = isPhysicalRoot ? 2 : 0;
|
||||||
|
|
||||||
var fileSystemDictionary = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, _fileSystem, _logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
|
var files = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, _fileSystem, _logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
|
||||||
|
|
||||||
// Need to remove subpaths that may have been resolved from shortcuts
|
// Need to remove subpaths that may have been resolved from shortcuts
|
||||||
// Example: if \\server\movies exists, then strip out \\server\movies\action
|
// Example: if \\server\movies exists, then strip out \\server\movies\action
|
||||||
if (isPhysicalRoot)
|
if (isPhysicalRoot)
|
||||||
{
|
{
|
||||||
var paths = NormalizeRootPathList(fileSystemDictionary.Values);
|
files = NormalizeRootPathList(files).ToArray();
|
||||||
|
|
||||||
fileSystemDictionary = paths.ToDictionary(i => i.FullName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args.FileSystemDictionary = fileSystemDictionary;
|
args.FileSystemChildren = files;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if we should resolve based on our contents
|
// Check to see if we should resolve based on our contents
|
||||||
@ -656,7 +654,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths)
|
public List<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths)
|
||||||
{
|
{
|
||||||
var originalList = paths.ToList();
|
var originalList = paths.ToList();
|
||||||
|
|
||||||
@ -999,8 +997,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
Path = path
|
Path = path
|
||||||
};
|
};
|
||||||
|
|
||||||
var task = CreateItem(item, CancellationToken.None);
|
CreateItem(item, CancellationToken.None);
|
||||||
Task.WaitAll(task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
@ -1172,7 +1169,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
progress.Report(percent * 100);
|
progress.Report(percent * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
await ItemRepository.UpdateInheritedValues(cancellationToken).ConfigureAwait(false);
|
ItemRepository.UpdateInheritedValues(cancellationToken);
|
||||||
|
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
@ -1208,7 +1205,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
.Where(i => string.Equals(ShortcutFileExtension, Path.GetExtension(i), StringComparison.OrdinalIgnoreCase))
|
.Where(i => string.Equals(ShortcutFileExtension, Path.GetExtension(i), StringComparison.OrdinalIgnoreCase))
|
||||||
.Select(_fileSystem.ResolveShortcut)
|
.Select(_fileSystem.ResolveShortcut)
|
||||||
.OrderBy(i => i)
|
.OrderBy(i => i)
|
||||||
.ToList(),
|
.ToArray(),
|
||||||
|
|
||||||
CollectionType = GetCollectionType(dir)
|
CollectionType = GetCollectionType(dir)
|
||||||
};
|
};
|
||||||
@ -1554,7 +1551,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
IncludeHidden = true,
|
IncludeHidden = true,
|
||||||
IncludeExternalContent = allowExternalContent
|
IncludeExternalContent = allowExternalContent
|
||||||
|
|
||||||
}, CancellationToken.None).Result.ToList();
|
}, CancellationToken.None).Result;
|
||||||
|
|
||||||
query.TopParentIds = userViews.SelectMany(i => GetTopParentIdsForQuery(i, user)).Select(i => i.ToString("N")).ToArray();
|
query.TopParentIds = userViews.SelectMany(i => GetTopParentIdsForQuery(i, user)).Select(i => i.ToString("N")).ToArray();
|
||||||
}
|
}
|
||||||
@ -1814,9 +1811,9 @@ namespace Emby.Server.Implementations.Library
|
|||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public Task CreateItem(BaseItem item, CancellationToken cancellationToken)
|
public void CreateItem(BaseItem item, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return CreateItems(new[] { item }, cancellationToken);
|
CreateItems(new[] { item }, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1825,11 +1822,11 @@ namespace Emby.Server.Implementations.Library
|
|||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public async Task CreateItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken)
|
public void CreateItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var list = items.ToList();
|
var list = items.ToList();
|
||||||
|
|
||||||
await ItemRepository.SaveItems(list, cancellationToken).ConfigureAwait(false);
|
ItemRepository.SaveItems(list, cancellationToken);
|
||||||
|
|
||||||
foreach (var item in list)
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
@ -1872,7 +1869,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
var logName = item.LocationType == LocationType.Remote ? item.Name ?? item.Path : item.Path ?? item.Name;
|
var logName = item.LocationType == LocationType.Remote ? item.Name ?? item.Path : item.Path ?? item.Name;
|
||||||
_logger.Debug("Saving {0} to database.", logName);
|
_logger.Debug("Saving {0} to database.", logName);
|
||||||
|
|
||||||
await ItemRepository.SaveItem(item, cancellationToken).ConfigureAwait(false);
|
ItemRepository.SaveItem(item, cancellationToken);
|
||||||
|
|
||||||
RegisterItem(item);
|
RegisterItem(item);
|
||||||
|
|
||||||
@ -2069,7 +2066,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromHours(24);
|
private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromHours(24);
|
||||||
//private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromMinutes(1);
|
//private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromMinutes(1);
|
||||||
|
|
||||||
public Task<UserView> GetNamedView(User user,
|
public UserView GetNamedView(User user,
|
||||||
string name,
|
string name,
|
||||||
string viewType,
|
string viewType,
|
||||||
string sortName,
|
string sortName,
|
||||||
@ -2107,7 +2104,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
ForcedSortName = sortName
|
ForcedSortName = sortName
|
||||||
};
|
};
|
||||||
|
|
||||||
await CreateItem(item, cancellationToken).ConfigureAwait(false);
|
CreateItem(item, cancellationToken);
|
||||||
|
|
||||||
refresh = true;
|
refresh = true;
|
||||||
}
|
}
|
||||||
@ -2138,7 +2135,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UserView> GetNamedView(User user,
|
public UserView GetNamedView(User user,
|
||||||
string name,
|
string name,
|
||||||
string parentId,
|
string parentId,
|
||||||
string viewType,
|
string viewType,
|
||||||
@ -2175,7 +2172,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
item.DisplayParentId = new Guid(parentId);
|
item.DisplayParentId = new Guid(parentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await CreateItem(item, cancellationToken).ConfigureAwait(false);
|
CreateItem(item, cancellationToken);
|
||||||
|
|
||||||
isNew = true;
|
isNew = true;
|
||||||
}
|
}
|
||||||
@ -2201,7 +2198,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UserView> GetShadowView(BaseItem parent,
|
public UserView GetShadowView(BaseItem parent,
|
||||||
string viewType,
|
string viewType,
|
||||||
string sortName,
|
string sortName,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
@ -2240,7 +2237,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
item.DisplayParentId = parentId;
|
item.DisplayParentId = parentId;
|
||||||
|
|
||||||
await CreateItem(item, cancellationToken).ConfigureAwait(false);
|
CreateItem(item, cancellationToken);
|
||||||
|
|
||||||
isNew = true;
|
isNew = true;
|
||||||
}
|
}
|
||||||
@ -2311,7 +2308,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
item.DisplayParentId = new Guid(parentId);
|
item.DisplayParentId = new Guid(parentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await CreateItem(item, cancellationToken).ConfigureAwait(false);
|
CreateItem(item, cancellationToken);
|
||||||
|
|
||||||
isNew = true;
|
isNew = true;
|
||||||
}
|
}
|
||||||
@ -2825,14 +2822,14 @@ namespace Emby.Server.Implementations.Library
|
|||||||
return ItemRepository.GetPeopleNames(query);
|
return ItemRepository.GetPeopleNames(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task UpdatePeople(BaseItem item, List<PersonInfo> people)
|
public void UpdatePeople(BaseItem item, List<PersonInfo> people)
|
||||||
{
|
{
|
||||||
if (!item.SupportsPeople)
|
if (!item.SupportsPeople)
|
||||||
{
|
{
|
||||||
return Task.FromResult(true);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ItemRepository.UpdatePeople(item.Id, people);
|
ItemRepository.UpdatePeople(item.Id, people);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ItemImageInfo> ConvertImageToLocal(IHasMetadata item, ItemImageInfo image, int imageIndex)
|
public async Task<ItemImageInfo> ConvertImageToLocal(IHasMetadata item, ItemImageInfo image, int imageIndex)
|
||||||
@ -3061,7 +3058,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
var topLibraryFolders = GetUserRootFolder().Children.ToList();
|
var topLibraryFolders = GetUserRootFolder().Children.ToList();
|
||||||
var info = GetVirtualFolderInfo(virtualFolderPath, topLibraryFolders, null);
|
var info = GetVirtualFolderInfo(virtualFolderPath, topLibraryFolders, null);
|
||||||
|
|
||||||
if (info.Locations.Count > 0 && info.Locations.Count != options.PathInfos.Length)
|
if (info.Locations.Length > 0 && info.Locations.Length != options.PathInfos.Length)
|
||||||
{
|
{
|
||||||
var list = options.PathInfos.ToList();
|
var list = options.PathInfos.ToList();
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
|||||||
return new CollectionFolder
|
return new CollectionFolder
|
||||||
{
|
{
|
||||||
CollectionType = GetCollectionType(args),
|
CollectionType = GetCollectionType(args),
|
||||||
PhysicalLocationsList = args.PhysicalLocations.ToList()
|
PhysicalLocationsList = args.PhysicalLocations
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using MediaBrowser.Controller.Configuration;
|
using System.Globalization;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Naming.Common;
|
using MediaBrowser.Naming.Common;
|
||||||
using MediaBrowser.Naming.TV;
|
using MediaBrowser.Naming.TV;
|
||||||
|
|
||||||
@ -17,15 +19,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
|||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||||
|
private readonly ILocalizationManager _localization;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SeasonResolver"/> class.
|
/// Initializes a new instance of the <see cref="SeasonResolver"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="config">The config.</param>
|
/// <param name="config">The config.</param>
|
||||||
public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager)
|
public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
_localization = localization;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -47,9 +52,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
|||||||
SeriesName = series.Name
|
SeriesName = series.Name
|
||||||
};
|
};
|
||||||
|
|
||||||
if (season.IndexNumber.HasValue && season.IndexNumber.Value == 0)
|
if (season.IndexNumber.HasValue)
|
||||||
{
|
{
|
||||||
season.Name = _config.Configuration.SeasonZeroDisplayName;
|
var seasonNumber = season.IndexNumber.Value;
|
||||||
|
|
||||||
|
season.Name = seasonNumber == 0 ?
|
||||||
|
_config.Configuration.SeasonZeroDisplayName :
|
||||||
|
string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
return season;
|
return season;
|
||||||
|
@ -181,7 +181,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
DtoOptions = new DtoOptions
|
DtoOptions = new DtoOptions
|
||||||
{
|
{
|
||||||
Fields = new List<ItemFields>
|
Fields = new ItemFields[]
|
||||||
{
|
{
|
||||||
ItemFields.AirTime,
|
ItemFields.AirTime,
|
||||||
ItemFields.DateCreated,
|
ItemFields.DateCreated,
|
||||||
|
@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
/// <value>The repository.</value>
|
/// <value>The repository.</value>
|
||||||
public IUserDataRepository Repository { get; set; }
|
public IUserDataRepository Repository { get; set; }
|
||||||
|
|
||||||
public async Task SaveUserData(Guid userId, IHasUserData item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken)
|
public void SaveUserData(Guid userId, IHasUserData item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (userData == null)
|
if (userData == null)
|
||||||
{
|
{
|
||||||
@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
foreach (var key in keys)
|
foreach (var key in keys)
|
||||||
{
|
{
|
||||||
await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false);
|
Repository.SaveUserData(userId, key, userData, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
var cacheKey = GetCacheKey(userId, item.Id);
|
var cacheKey = GetCacheKey(userId, item.Id);
|
||||||
@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
/// <param name="userData"></param>
|
/// <param name="userData"></param>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task SaveAllUserData(Guid userId, IEnumerable<UserItemData> userData, CancellationToken cancellationToken)
|
public void SaveAllUserData(Guid userId, UserItemData[] userData, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (userData == null)
|
if (userData == null)
|
||||||
{
|
{
|
||||||
@ -99,7 +99,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
await Repository.SaveAllUserData(userId, userData, cancellationToken).ConfigureAwait(false);
|
Repository.SaveAllUserData(userId, userData, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -107,7 +107,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId"></param>
|
/// <param name="userId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public IEnumerable<UserItemData> GetAllUserData(Guid userId)
|
public List<UserItemData> GetAllUserData(Guid userId)
|
||||||
{
|
{
|
||||||
if (userId == Guid.Empty)
|
if (userId == Guid.Empty)
|
||||||
{
|
{
|
||||||
@ -187,11 +187,11 @@ namespace Emby.Server.Implementations.Library
|
|||||||
var userData = GetUserData(user.Id, item);
|
var userData = GetUserData(user.Id, item);
|
||||||
var dto = GetUserItemDataDto(userData);
|
var dto = GetUserItemDataDto(userData);
|
||||||
|
|
||||||
item.FillUserDataDtoValues(dto, userData, null, user, new List<ItemFields>());
|
item.FillUserDataDtoValues(dto, userData, null, user, new ItemFields[] { });
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserItemDataDto GetUserDataDto(IHasUserData item, BaseItemDto itemDto, User user, List<ItemFields> fields)
|
public UserItemDataDto GetUserDataDto(IHasUserData item, BaseItemDto itemDto, User user, ItemFields[] fields)
|
||||||
{
|
{
|
||||||
var userData = GetUserData(user.Id, item);
|
var userData = GetUserData(user.Id, item);
|
||||||
var dto = GetUserItemDataDto(userData);
|
var dto = GetUserItemDataDto(userData);
|
||||||
|
@ -160,9 +160,9 @@ namespace Emby.Server.Implementations.Library
|
|||||||
return Users.FirstOrDefault(u => string.Equals(u.Name, name, StringComparison.OrdinalIgnoreCase));
|
return Users.FirstOrDefault(u => string.Equals(u.Name, name, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
Users = await LoadUsers().ConfigureAwait(false);
|
Users = LoadUsers();
|
||||||
|
|
||||||
var users = Users.ToList();
|
var users = Users.ToList();
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value == UserLinkType.LinkedUser)
|
if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value == UserLinkType.LinkedUser)
|
||||||
{
|
{
|
||||||
user.Policy.IsAdministrator = true;
|
user.Policy.IsAdministrator = true;
|
||||||
await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false);
|
UpdateUserPolicy(user, user.Policy, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,12 +294,12 @@ namespace Emby.Server.Implementations.Library
|
|||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow;
|
user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow;
|
||||||
await UpdateUser(user).ConfigureAwait(false);
|
UpdateUser(user);
|
||||||
await UpdateInvalidLoginAttemptCount(user, 0).ConfigureAwait(false);
|
UpdateInvalidLoginAttemptCount(user, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await UpdateInvalidLoginAttemptCount(user, user.Policy.InvalidLoginAttemptCount + 1).ConfigureAwait(false);
|
UpdateInvalidLoginAttemptCount(user, user.Policy.InvalidLoginAttemptCount + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Info("Authentication request for {0} {1}.", user.Name, success ? "has succeeded" : "has been denied");
|
_logger.Info("Authentication request for {0} {1}.", user.Name, success ? "has succeeded" : "has been denied");
|
||||||
@ -307,7 +307,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
return success ? user : null;
|
return success ? user : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateInvalidLoginAttemptCount(User user, int newValue)
|
private void UpdateInvalidLoginAttemptCount(User user, int newValue)
|
||||||
{
|
{
|
||||||
if (user.Policy.InvalidLoginAttemptCount != newValue || newValue > 0)
|
if (user.Policy.InvalidLoginAttemptCount != newValue || newValue > 0)
|
||||||
{
|
{
|
||||||
@ -327,7 +327,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
//fireLockout = true;
|
//fireLockout = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false);
|
UpdateUserPolicy(user, user.Policy, false);
|
||||||
|
|
||||||
if (fireLockout)
|
if (fireLockout)
|
||||||
{
|
{
|
||||||
@ -372,7 +372,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
/// Loads the users from the repository
|
/// Loads the users from the repository
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IEnumerable{User}.</returns>
|
/// <returns>IEnumerable{User}.</returns>
|
||||||
private async Task<IEnumerable<User>> LoadUsers()
|
private List<User> LoadUsers()
|
||||||
{
|
{
|
||||||
var users = UserRepository.RetrieveAllUsers().ToList();
|
var users = UserRepository.RetrieveAllUsers().ToList();
|
||||||
|
|
||||||
@ -385,14 +385,14 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
user.DateLastSaved = DateTime.UtcNow;
|
user.DateLastSaved = DateTime.UtcNow;
|
||||||
|
|
||||||
await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false);
|
UserRepository.SaveUser(user, CancellationToken.None);
|
||||||
|
|
||||||
users.Add(user);
|
users.Add(user);
|
||||||
|
|
||||||
user.Policy.IsAdministrator = true;
|
user.Policy.IsAdministrator = true;
|
||||||
user.Policy.EnableContentDeletion = true;
|
user.Policy.EnableContentDeletion = true;
|
||||||
user.Policy.EnableRemoteControlOfOtherUsers = true;
|
user.Policy.EnableRemoteControlOfOtherUsers = true;
|
||||||
await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false);
|
UpdateUserPolicy(user, user.Policy, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return users;
|
return users;
|
||||||
@ -539,7 +539,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <exception cref="System.ArgumentNullException">user</exception>
|
/// <exception cref="System.ArgumentNullException">user</exception>
|
||||||
/// <exception cref="System.ArgumentException"></exception>
|
/// <exception cref="System.ArgumentException"></exception>
|
||||||
public async Task UpdateUser(User user)
|
public void UpdateUser(User user)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
@ -554,7 +554,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
user.DateModified = DateTime.UtcNow;
|
user.DateModified = DateTime.UtcNow;
|
||||||
user.DateLastSaved = DateTime.UtcNow;
|
user.DateLastSaved = DateTime.UtcNow;
|
||||||
|
|
||||||
await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false);
|
UserRepository.SaveUser(user, CancellationToken.None);
|
||||||
|
|
||||||
OnUserUpdated(user);
|
OnUserUpdated(user);
|
||||||
}
|
}
|
||||||
@ -599,7 +599,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
user.DateLastSaved = DateTime.UtcNow;
|
user.DateLastSaved = DateTime.UtcNow;
|
||||||
|
|
||||||
await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false);
|
UserRepository.SaveUser(user, CancellationToken.None);
|
||||||
|
|
||||||
EventHelper.QueueEventIfNotNull(UserCreated, this, new GenericEventArgs<User> { Argument = user }, _logger);
|
EventHelper.QueueEventIfNotNull(UserCreated, this, new GenericEventArgs<User> { Argument = user }, _logger);
|
||||||
|
|
||||||
@ -653,7 +653,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
{
|
{
|
||||||
var configPath = GetConfigurationFilePath(user);
|
var configPath = GetConfigurationFilePath(user);
|
||||||
|
|
||||||
await UserRepository.DeleteUser(user, CancellationToken.None).ConfigureAwait(false);
|
UserRepository.DeleteUser(user, CancellationToken.None);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -667,7 +667,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
DeleteUserPolicy(user);
|
DeleteUserPolicy(user);
|
||||||
|
|
||||||
// Force this to be lazy loaded again
|
// Force this to be lazy loaded again
|
||||||
Users = await LoadUsers().ConfigureAwait(false);
|
Users = LoadUsers();
|
||||||
|
|
||||||
OnUserDeleted(user);
|
OnUserDeleted(user);
|
||||||
}
|
}
|
||||||
@ -681,17 +681,17 @@ namespace Emby.Server.Implementations.Library
|
|||||||
/// Resets the password by clearing it.
|
/// Resets the password by clearing it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public Task ResetPassword(User user)
|
public void ResetPassword(User user)
|
||||||
{
|
{
|
||||||
return ChangePassword(user, GetSha1String(string.Empty));
|
ChangePassword(user, GetSha1String(string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ResetEasyPassword(User user)
|
public void ResetEasyPassword(User user)
|
||||||
{
|
{
|
||||||
return ChangeEasyPassword(user, GetSha1String(string.Empty));
|
ChangeEasyPassword(user, GetSha1String(string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ChangePassword(User user, string newPasswordSha1)
|
public void ChangePassword(User user, string newPasswordSha1)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
@ -709,12 +709,12 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
user.Password = newPasswordSha1;
|
user.Password = newPasswordSha1;
|
||||||
|
|
||||||
await UpdateUser(user).ConfigureAwait(false);
|
UpdateUser(user);
|
||||||
|
|
||||||
EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger);
|
EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ChangeEasyPassword(User user, string newPasswordSha1)
|
public void ChangeEasyPassword(User user, string newPasswordSha1)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
@ -727,7 +727,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
user.EasyPassword = newPasswordSha1;
|
user.EasyPassword = newPasswordSha1;
|
||||||
|
|
||||||
await UpdateUser(user).ConfigureAwait(false);
|
UpdateUser(user);
|
||||||
|
|
||||||
EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger);
|
EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger);
|
||||||
}
|
}
|
||||||
@ -842,7 +842,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PinRedeemResult> RedeemPasswordResetPin(string pin)
|
public PinRedeemResult RedeemPasswordResetPin(string pin)
|
||||||
{
|
{
|
||||||
DeletePinFile();
|
DeletePinFile();
|
||||||
|
|
||||||
@ -863,12 +863,12 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
foreach (var user in users)
|
foreach (var user in users)
|
||||||
{
|
{
|
||||||
await ResetPassword(user).ConfigureAwait(false);
|
ResetPassword(user);
|
||||||
|
|
||||||
if (user.Policy.IsDisabled)
|
if (user.Policy.IsDisabled)
|
||||||
{
|
{
|
||||||
user.Policy.IsDisabled = false;
|
user.Policy.IsDisabled = false;
|
||||||
await UpdateUserPolicy(user, user.Policy, true).ConfigureAwait(false);
|
UpdateUserPolicy(user, user.Policy, true);
|
||||||
}
|
}
|
||||||
usersReset.Add(user.Name);
|
usersReset.Add(user.Name);
|
||||||
}
|
}
|
||||||
@ -945,13 +945,13 @@ namespace Emby.Server.Implementations.Library
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly object _policySyncLock = new object();
|
private readonly object _policySyncLock = new object();
|
||||||
public Task UpdateUserPolicy(string userId, UserPolicy userPolicy)
|
public void UpdateUserPolicy(string userId, UserPolicy userPolicy)
|
||||||
{
|
{
|
||||||
var user = GetUserById(userId);
|
var user = GetUserById(userId);
|
||||||
return UpdateUserPolicy(user, userPolicy, true);
|
UpdateUserPolicy(user, userPolicy, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateUserPolicy(User user, UserPolicy userPolicy, bool fireEvent)
|
private void UpdateUserPolicy(User user, UserPolicy userPolicy, bool fireEvent)
|
||||||
{
|
{
|
||||||
// The xml serializer will output differently if the type is not exact
|
// The xml serializer will output differently if the type is not exact
|
||||||
if (userPolicy.GetType() != typeof(UserPolicy))
|
if (userPolicy.GetType() != typeof(UserPolicy))
|
||||||
@ -970,7 +970,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
user.Policy = userPolicy;
|
user.Policy = userPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
await UpdateConfiguration(user, user.Configuration, true).ConfigureAwait(false);
|
UpdateConfiguration(user, user.Configuration, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteUserPolicy(User user)
|
private void DeleteUserPolicy(User user)
|
||||||
@ -1032,13 +1032,13 @@ namespace Emby.Server.Implementations.Library
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly object _configSyncLock = new object();
|
private readonly object _configSyncLock = new object();
|
||||||
public Task UpdateConfiguration(string userId, UserConfiguration config)
|
public void UpdateConfiguration(string userId, UserConfiguration config)
|
||||||
{
|
{
|
||||||
var user = GetUserById(userId);
|
var user = GetUserById(userId);
|
||||||
return UpdateConfiguration(user, config, true);
|
UpdateConfiguration(user, config, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateConfiguration(User user, UserConfiguration config, bool fireEvent)
|
private void UpdateConfiguration(User user, UserConfiguration config, bool fireEvent)
|
||||||
{
|
{
|
||||||
var path = GetConfigurationFilePath(user);
|
var path = GetConfigurationFilePath(user);
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken)
|
public async Task<Folder[]> GetUserViews(UserViewQuery query, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(query.UserId);
|
var user = _userManager.GetUserById(query.UserId);
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
if (UserView.IsUserSpecific(folder))
|
if (UserView.IsUserSpecific(folder))
|
||||||
{
|
{
|
||||||
list.Add(await _libraryManager.GetNamedView(user, folder.Name, folder.Id.ToString("N"), folderViewType, null, cancellationToken).ConfigureAwait(false));
|
list.Add(_libraryManager.GetNamedView(user, folder.Name, folder.Id.ToString("N"), folderViewType, null, cancellationToken));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
if (query.PresetViews.Contains(folderViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
if (query.PresetViews.Contains(folderViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
list.Add(await GetUserView(folder, folderViewType, string.Empty, cancellationToken).ConfigureAwait(false));
|
list.Add(GetUserView(folder, folderViewType, string.Empty, cancellationToken));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
if (parents.Count > 0)
|
if (parents.Count > 0)
|
||||||
{
|
{
|
||||||
list.Add(await GetUserView(parents, viewType, string.Empty, user, query.PresetViews, cancellationToken).ConfigureAwait(false));
|
list.Add(GetUserView(parents, viewType, string.Empty, user, query.PresetViews, cancellationToken));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,8 @@ namespace Emby.Server.Implementations.Library
|
|||||||
return index == -1 ? int.MaxValue : index;
|
return index == -1 ? int.MaxValue : index;
|
||||||
})
|
})
|
||||||
.ThenBy(sorted.IndexOf)
|
.ThenBy(sorted.IndexOf)
|
||||||
.ThenBy(i => i.SortName);
|
.ThenBy(i => i.SortName)
|
||||||
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<UserView> GetUserSubView(string name, string parentId, string type, string sortName, CancellationToken cancellationToken)
|
public Task<UserView> GetUserSubView(string name, string parentId, string type, string sortName, CancellationToken cancellationToken)
|
||||||
@ -171,7 +172,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
return GetUserSubView(name, parentId, type, sortName, cancellationToken);
|
return GetUserSubView(name, parentId, type, sortName, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Folder> GetUserView(List<ICollectionFolder> parents, string viewType, string sortName, User user, string[] presetViews, CancellationToken cancellationToken)
|
private Folder GetUserView(List<ICollectionFolder> parents, string viewType, string sortName, User user, string[] presetViews, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase)))
|
if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
@ -180,14 +181,14 @@ namespace Emby.Server.Implementations.Library
|
|||||||
return (Folder)parents[0];
|
return (Folder)parents[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return await GetUserView((Folder)parents[0], viewType, string.Empty, cancellationToken).ConfigureAwait(false);
|
return GetUserView((Folder)parents[0], viewType, string.Empty, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = _localizationManager.GetLocalizedString("ViewType" + viewType);
|
var name = _localizationManager.GetLocalizedString("ViewType" + viewType);
|
||||||
return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false);
|
return _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<UserView> GetUserView(Folder parent, string viewType, string sortName, CancellationToken cancellationToken)
|
public UserView GetUserView(Folder parent, string viewType, string sortName, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _libraryManager.GetShadowView(parent, viewType, sortName, cancellationToken);
|
return _libraryManager.GetShadowView(parent, viewType, sortName, cancellationToken);
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virtualFolder.Locations.Count == 1)
|
if (virtualFolder.Locations.Length == 1)
|
||||||
{
|
{
|
||||||
// remove entire virtual folder
|
// remove entire virtual folder
|
||||||
try
|
try
|
||||||
@ -458,7 +458,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
return GetEpgChannelFromTunerChannel(info, tunerChannel, epgChannels);
|
return GetEpgChannelFromTunerChannel(info, tunerChannel, epgChannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetMappedChannel(string channelId, List<NameValuePair> mappings)
|
private string GetMappedChannel(string channelId, NameValuePair[] mappings)
|
||||||
{
|
{
|
||||||
foreach (NameValuePair mapping in mappings)
|
foreach (NameValuePair mapping in mappings)
|
||||||
{
|
{
|
||||||
@ -472,10 +472,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
private ChannelInfo GetEpgChannelFromTunerChannel(ListingsProviderInfo info, ChannelInfo tunerChannel, List<ChannelInfo> epgChannels)
|
private ChannelInfo GetEpgChannelFromTunerChannel(ListingsProviderInfo info, ChannelInfo tunerChannel, List<ChannelInfo> epgChannels)
|
||||||
{
|
{
|
||||||
return GetEpgChannelFromTunerChannel(info.ChannelMappings.ToList(), tunerChannel, epgChannels);
|
return GetEpgChannelFromTunerChannel(info.ChannelMappings, tunerChannel, epgChannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelInfo GetEpgChannelFromTunerChannel(List<NameValuePair> mappings, ChannelInfo tunerChannel, List<ChannelInfo> epgChannels)
|
public ChannelInfo GetEpgChannelFromTunerChannel(NameValuePair[] mappings, ChannelInfo tunerChannel, List<ChannelInfo> epgChannels)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(tunerChannel.Id))
|
if (!string.IsNullOrWhiteSpace(tunerChannel.Id))
|
||||||
{
|
{
|
||||||
@ -607,13 +607,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
var timer = _timerProvider.GetTimer(timerId);
|
var timer = _timerProvider.GetTimer(timerId);
|
||||||
if (timer != null)
|
if (timer != null)
|
||||||
{
|
{
|
||||||
|
timer.Status = RecordingStatus.Cancelled;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(timer.SeriesTimerId) || isSeriesCancelled)
|
if (string.IsNullOrWhiteSpace(timer.SeriesTimerId) || isSeriesCancelled)
|
||||||
{
|
{
|
||||||
_timerProvider.Delete(timer);
|
_timerProvider.Delete(timer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timer.Status = RecordingStatus.Cancelled;
|
|
||||||
_timerProvider.AddOrUpdate(timer, false);
|
_timerProvider.AddOrUpdate(timer, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -621,6 +622,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
if (_activeRecordings.TryGetValue(timerId, out activeRecordingInfo))
|
if (_activeRecordings.TryGetValue(timerId, out activeRecordingInfo))
|
||||||
{
|
{
|
||||||
|
activeRecordingInfo.Timer = timer;
|
||||||
activeRecordingInfo.CancellationTokenSource.Cancel();
|
activeRecordingInfo.CancellationTokenSource.Cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -830,6 +832,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
existingTimer.IsKids = updatedTimer.IsKids;
|
existingTimer.IsKids = updatedTimer.IsKids;
|
||||||
existingTimer.IsNews = updatedTimer.IsNews;
|
existingTimer.IsNews = updatedTimer.IsNews;
|
||||||
existingTimer.IsMovie = updatedTimer.IsMovie;
|
existingTimer.IsMovie = updatedTimer.IsMovie;
|
||||||
|
existingTimer.IsSeries = updatedTimer.IsSeries;
|
||||||
|
existingTimer.IsLive = updatedTimer.IsLive;
|
||||||
|
existingTimer.IsPremiere = updatedTimer.IsPremiere;
|
||||||
existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries;
|
existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries;
|
||||||
existingTimer.IsRepeat = updatedTimer.IsRepeat;
|
existingTimer.IsRepeat = updatedTimer.IsRepeat;
|
||||||
existingTimer.IsSports = updatedTimer.IsSports;
|
existingTimer.IsSports = updatedTimer.IsSports;
|
||||||
@ -861,7 +866,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
public async Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken)
|
public async Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _activeRecordings.Values.ToList().Select(GetRecordingInfo).ToList();
|
return new List<RecordingInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetActiveRecordingPath(string id)
|
public string GetActiveRecordingPath(string id)
|
||||||
@ -875,49 +880,31 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RecordingInfo GetRecordingInfo(ActiveRecordingInfo info)
|
public IEnumerable<ActiveRecordingInfo> GetAllActiveRecordings()
|
||||||
{
|
{
|
||||||
var timer = info.Timer;
|
return _activeRecordings.Values.Where(i => i.Timer.Status == RecordingStatus.InProgress && !i.CancellationTokenSource.IsCancellationRequested);
|
||||||
var program = info.Program;
|
}
|
||||||
|
|
||||||
var result = new RecordingInfo
|
public ActiveRecordingInfo GetActiveRecordingInfo(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
{
|
{
|
||||||
ChannelId = timer.ChannelId,
|
return null;
|
||||||
CommunityRating = timer.CommunityRating,
|
|
||||||
DateLastUpdated = DateTime.UtcNow,
|
|
||||||
EndDate = timer.EndDate,
|
|
||||||
EpisodeTitle = timer.EpisodeTitle,
|
|
||||||
Genres = timer.Genres,
|
|
||||||
Id = "recording" + timer.Id,
|
|
||||||
IsKids = timer.IsKids,
|
|
||||||
IsMovie = timer.IsMovie,
|
|
||||||
IsNews = timer.IsNews,
|
|
||||||
IsRepeat = timer.IsRepeat,
|
|
||||||
IsSeries = timer.IsProgramSeries,
|
|
||||||
IsSports = timer.IsSports,
|
|
||||||
Name = timer.Name,
|
|
||||||
OfficialRating = timer.OfficialRating,
|
|
||||||
OriginalAirDate = timer.OriginalAirDate,
|
|
||||||
Overview = timer.Overview,
|
|
||||||
ProgramId = timer.ProgramId,
|
|
||||||
SeriesTimerId = timer.SeriesTimerId,
|
|
||||||
StartDate = timer.StartDate,
|
|
||||||
Status = RecordingStatus.InProgress,
|
|
||||||
TimerId = timer.Id
|
|
||||||
};
|
|
||||||
|
|
||||||
if (program != null)
|
|
||||||
{
|
|
||||||
result.Audio = program.Audio;
|
|
||||||
result.ImagePath = program.ImagePath;
|
|
||||||
result.ImageUrl = program.ImageUrl;
|
|
||||||
result.IsHD = program.IsHD;
|
|
||||||
result.IsLive = program.IsLive;
|
|
||||||
result.IsPremiere = program.IsPremiere;
|
|
||||||
result.ShowId = program.ShowId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
foreach (var recording in _activeRecordings.Values)
|
||||||
|
{
|
||||||
|
if (string.Equals(recording.Path, path, StringComparison.Ordinal) && !recording.CancellationTokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
var timer = recording.Timer;
|
||||||
|
if (timer.Status != RecordingStatus.InProgress)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return recording;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken)
|
public Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken)
|
||||||
@ -1245,6 +1232,33 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
throw new FileNotFoundException();
|
throw new FileNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(ActiveRecordingInfo info, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var stream = new MediaSourceInfo
|
||||||
|
{
|
||||||
|
Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveRecordings/" + info.Id + "/stream",
|
||||||
|
Id = info.Id,
|
||||||
|
SupportsDirectPlay = false,
|
||||||
|
SupportsDirectStream = true,
|
||||||
|
SupportsTranscoding = true,
|
||||||
|
IsInfiniteStream = true,
|
||||||
|
RequiresOpening = false,
|
||||||
|
RequiresClosing = false,
|
||||||
|
Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http,
|
||||||
|
BufferMs = 0,
|
||||||
|
IgnoreDts = true,
|
||||||
|
IgnoreIndex = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var isAudio = false;
|
||||||
|
await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return new List<MediaSourceInfo>
|
||||||
|
{
|
||||||
|
stream
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
|
public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// Ignore the consumer id
|
// Ignore the consumer id
|
||||||
@ -1327,7 +1341,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
var activeRecordingInfo = new ActiveRecordingInfo
|
var activeRecordingInfo = new ActiveRecordingInfo
|
||||||
{
|
{
|
||||||
CancellationTokenSource = new CancellationTokenSource(),
|
CancellationTokenSource = new CancellationTokenSource(),
|
||||||
Timer = timer
|
Timer = timer,
|
||||||
|
Id = timer.Id
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo))
|
if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo))
|
||||||
@ -1493,7 +1508,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath);
|
recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath);
|
||||||
recordPath = EnsureFileUnique(recordPath, timer.Id);
|
recordPath = EnsureFileUnique(recordPath, timer.Id);
|
||||||
|
|
||||||
_libraryManager.RegisterIgnoredPath(recordPath);
|
|
||||||
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
|
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
|
||||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath));
|
||||||
activeRecordingInfo.Path = recordPath;
|
activeRecordingInfo.Path = recordPath;
|
||||||
@ -1512,6 +1526,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
_timerProvider.AddOrUpdate(timer, false);
|
_timerProvider.AddOrUpdate(timer, false);
|
||||||
|
|
||||||
SaveRecordingMetadata(timer, recordPath, seriesPath);
|
SaveRecordingMetadata(timer, recordPath, seriesPath);
|
||||||
|
TriggerRefresh(recordPath);
|
||||||
EnforceKeepUpTo(timer, seriesPath);
|
EnforceKeepUpTo(timer, seriesPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1543,7 +1558,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_libraryManager.UnRegisterIgnoredPath(recordPath);
|
TriggerRefresh(recordPath);
|
||||||
_libraryMonitor.ReportFileSystemChangeComplete(recordPath, true);
|
_libraryMonitor.ReportFileSystemChangeComplete(recordPath, true);
|
||||||
|
|
||||||
ActiveRecordingInfo removed;
|
ActiveRecordingInfo removed;
|
||||||
@ -1574,6 +1589,44 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
OnRecordingStatusChanged();
|
OnRecordingStatusChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TriggerRefresh(string path)
|
||||||
|
{
|
||||||
|
var item = GetAffectedBaseItem(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
item.ChangedExternally();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseItem GetAffectedBaseItem(string path)
|
||||||
|
{
|
||||||
|
BaseItem item = null;
|
||||||
|
|
||||||
|
while (item == null && !string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
item = _libraryManager.FindByPath(path, null);
|
||||||
|
|
||||||
|
path = _fileSystem.GetDirectoryName(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
// If the item has been deleted find the first valid parent that still exists
|
||||||
|
while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path))
|
||||||
|
{
|
||||||
|
item = item.GetParent();
|
||||||
|
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnRecordingStatusChanged()
|
private void OnRecordingStatusChanged()
|
||||||
{
|
{
|
||||||
EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs
|
EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs
|
||||||
@ -2591,7 +2644,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
{
|
{
|
||||||
list.Add(new VirtualFolderInfo
|
list.Add(new VirtualFolderInfo
|
||||||
{
|
{
|
||||||
Locations = new List<string> { defaultFolder },
|
Locations = new string[] { defaultFolder },
|
||||||
Name = defaultName
|
Name = defaultName
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2601,7 +2654,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
{
|
{
|
||||||
list.Add(new VirtualFolderInfo
|
list.Add(new VirtualFolderInfo
|
||||||
{
|
{
|
||||||
Locations = new List<string> { customPath },
|
Locations = new string[] { customPath },
|
||||||
Name = "Recorded Movies",
|
Name = "Recorded Movies",
|
||||||
CollectionType = CollectionType.Movies
|
CollectionType = CollectionType.Movies
|
||||||
});
|
});
|
||||||
@ -2612,7 +2665,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
{
|
{
|
||||||
list.Add(new VirtualFolderInfo
|
list.Add(new VirtualFolderInfo
|
||||||
{
|
{
|
||||||
Locations = new List<string> { customPath },
|
Locations = new string[] { customPath },
|
||||||
Name = "Recorded Shows",
|
Name = "Recorded Shows",
|
||||||
CollectionType = CollectionType.TvShows
|
CollectionType = CollectionType.TvShows
|
||||||
});
|
});
|
||||||
@ -2621,14 +2674,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ActiveRecordingInfo
|
|
||||||
{
|
|
||||||
public string Path { get; set; }
|
|
||||||
public TimerInfo Timer { get; set; }
|
|
||||||
public ProgramInfo Program { get; set; }
|
|
||||||
public CancellationTokenSource CancellationTokenSource { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private const int TunerDiscoveryDurationMs = 3000;
|
private const int TunerDiscoveryDurationMs = 3000;
|
||||||
|
|
||||||
public async Task<List<TunerHostInfo>> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken)
|
public async Task<List<TunerHostInfo>> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken)
|
||||||
|
@ -58,6 +58,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
timerInfo.OriginalAirDate = programInfo.OriginalAirDate;
|
timerInfo.OriginalAirDate = programInfo.OriginalAirDate;
|
||||||
timerInfo.IsProgramSeries = programInfo.IsSeries;
|
timerInfo.IsProgramSeries = programInfo.IsSeries;
|
||||||
|
|
||||||
|
timerInfo.IsSeries = programInfo.IsSeries;
|
||||||
|
timerInfo.IsLive = programInfo.IsLive;
|
||||||
|
timerInfo.IsPremiere = programInfo.IsPremiere;
|
||||||
|
|
||||||
timerInfo.HomePageUrl = programInfo.HomePageUrl;
|
timerInfo.HomePageUrl = programInfo.HomePageUrl;
|
||||||
timerInfo.CommunityRating = programInfo.CommunityRating;
|
timerInfo.CommunityRating = programInfo.CommunityRating;
|
||||||
timerInfo.Overview = programInfo.Overview;
|
timerInfo.Overview = programInfo.Overview;
|
||||||
|
@ -247,7 +247,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
ProgramAudio audioType = ProgramAudio.Stereo;
|
ProgramAudio audioType = ProgramAudio.Stereo;
|
||||||
|
|
||||||
bool repeat = programInfo.@new == null;
|
bool repeat = programInfo.@new == null;
|
||||||
string newID = programInfo.programID + "T" + startAt.Ticks + "C" + channelId;
|
|
||||||
|
var programId = programInfo.programID ?? string.Empty;
|
||||||
|
|
||||||
|
string newID = programId + "T" + startAt.Ticks + "C" + channelId;
|
||||||
|
|
||||||
if (programInfo.audioProperties != null)
|
if (programInfo.audioProperties != null)
|
||||||
{
|
{
|
||||||
@ -300,7 +303,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
Etag = programInfo.md5
|
Etag = programInfo.md5
|
||||||
};
|
};
|
||||||
|
|
||||||
var showId = programInfo.programID ?? string.Empty;
|
var showId = programId;
|
||||||
|
|
||||||
if (!info.IsSeries)
|
if (!info.IsSeries)
|
||||||
{
|
{
|
||||||
@ -339,11 +342,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
if (details.descriptions != null)
|
if (details.descriptions != null)
|
||||||
{
|
{
|
||||||
if (details.descriptions.description1000 != null)
|
if (details.descriptions.description1000 != null && details.descriptions.description1000.Count > 0)
|
||||||
{
|
{
|
||||||
info.Overview = details.descriptions.description1000[0].description;
|
info.Overview = details.descriptions.description1000[0].description;
|
||||||
}
|
}
|
||||||
else if (details.descriptions.description100 != null)
|
else if (details.descriptions.description100 != null && details.descriptions.description100.Count > 0)
|
||||||
{
|
{
|
||||||
info.Overview = details.descriptions.description100[0].description;
|
info.Overview = details.descriptions.description100[0].description;
|
||||||
}
|
}
|
||||||
@ -351,16 +354,24 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
if (info.IsSeries)
|
if (info.IsSeries)
|
||||||
{
|
{
|
||||||
info.SeriesId = programInfo.programID.Substring(0, 10);
|
info.SeriesId = programId.Substring(0, 10);
|
||||||
|
|
||||||
if (details.metadata != null)
|
if (details.metadata != null)
|
||||||
{
|
{
|
||||||
var gracenote = details.metadata.Find(x => x.Gracenote != null).Gracenote;
|
foreach (var metadataProgram in details.metadata)
|
||||||
info.SeasonNumber = gracenote.season;
|
|
||||||
|
|
||||||
if (gracenote.episode > 0)
|
|
||||||
{
|
{
|
||||||
info.EpisodeNumber = gracenote.episode;
|
var gracenote = metadataProgram.Gracenote;
|
||||||
|
if (gracenote != null)
|
||||||
|
{
|
||||||
|
info.SeasonNumber = gracenote.season;
|
||||||
|
|
||||||
|
if (gracenote.episode > 0)
|
||||||
|
{
|
||||||
|
info.EpisodeNumber = gracenote.episode;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.Extensions;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.LiveTv
|
namespace Emby.Server.Implementations.LiveTv
|
||||||
{
|
{
|
||||||
@ -110,7 +112,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
PostPaddingSeconds = info.PostPaddingSeconds,
|
PostPaddingSeconds = info.PostPaddingSeconds,
|
||||||
IsPostPaddingRequired = info.IsPostPaddingRequired,
|
IsPostPaddingRequired = info.IsPostPaddingRequired,
|
||||||
IsPrePaddingRequired = info.IsPrePaddingRequired,
|
IsPrePaddingRequired = info.IsPrePaddingRequired,
|
||||||
Days = info.Days,
|
Days = info.Days.ToArray(),
|
||||||
Priority = info.Priority,
|
Priority = info.Priority,
|
||||||
RecordAnyChannel = info.RecordAnyChannel,
|
RecordAnyChannel = info.RecordAnyChannel,
|
||||||
RecordAnyTime = info.RecordAnyTime,
|
RecordAnyTime = info.RecordAnyTime,
|
||||||
@ -135,7 +137,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
dto.ProgramId = GetInternalProgramId(service.Name, info.ProgramId).ToString("N");
|
dto.ProgramId = GetInternalProgramId(service.Name, info.ProgramId).ToString("N");
|
||||||
}
|
}
|
||||||
|
|
||||||
dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days);
|
dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days.ToArray(info.Days.Count));
|
||||||
|
|
||||||
FillImages(dto, info.Name, info.SeriesId);
|
FillImages(dto, info.Name, info.SeriesId);
|
||||||
|
|
||||||
@ -150,10 +152,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
Name = seriesName,
|
Name = seriesName,
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
ImageTypes = new ImageType[] { ImageType.Thumb },
|
ImageTypes = new ImageType[] { ImageType.Thumb },
|
||||||
DtoOptions = new DtoOptions
|
DtoOptions = new DtoOptions(false)
|
||||||
{
|
|
||||||
Fields = new List<MediaBrowser.Model.Querying.ItemFields>()
|
|
||||||
}
|
|
||||||
|
|
||||||
}).FirstOrDefault();
|
}).FirstOrDefault();
|
||||||
|
|
||||||
@ -196,10 +195,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
ExternalSeriesId = programSeriesId,
|
ExternalSeriesId = programSeriesId,
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
ImageTypes = new ImageType[] { ImageType.Primary },
|
ImageTypes = new ImageType[] { ImageType.Primary },
|
||||||
DtoOptions = new DtoOptions
|
DtoOptions = new DtoOptions(false)
|
||||||
{
|
|
||||||
Fields = new List<MediaBrowser.Model.Querying.ItemFields>()
|
|
||||||
}
|
|
||||||
|
|
||||||
}).FirstOrDefault();
|
}).FirstOrDefault();
|
||||||
|
|
||||||
@ -248,10 +244,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
Name = seriesName,
|
Name = seriesName,
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
ImageTypes = new ImageType[] { ImageType.Thumb },
|
ImageTypes = new ImageType[] { ImageType.Thumb },
|
||||||
DtoOptions = new DtoOptions
|
DtoOptions = new DtoOptions(false)
|
||||||
{
|
|
||||||
Fields = new List<MediaBrowser.Model.Querying.ItemFields>()
|
|
||||||
}
|
|
||||||
|
|
||||||
}).FirstOrDefault();
|
}).FirstOrDefault();
|
||||||
|
|
||||||
@ -274,7 +267,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dto.ParentBackdropImageTags = new List<string>
|
dto.ParentBackdropImageTags = new string[]
|
||||||
{
|
{
|
||||||
_imageProcessor.GetImageCacheTag(librarySeries, image)
|
_imageProcessor.GetImageCacheTag(librarySeries, image)
|
||||||
};
|
};
|
||||||
@ -294,10 +287,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
Name = seriesName,
|
Name = seriesName,
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
ImageTypes = new ImageType[] { ImageType.Primary },
|
ImageTypes = new ImageType[] { ImageType.Primary },
|
||||||
DtoOptions = new DtoOptions
|
DtoOptions = new DtoOptions(false)
|
||||||
{
|
|
||||||
Fields = new List<MediaBrowser.Model.Querying.ItemFields>()
|
|
||||||
}
|
|
||||||
|
|
||||||
}).FirstOrDefault() ?? _libraryManager.GetItemList(new InternalItemsQuery
|
}).FirstOrDefault() ?? _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
@ -305,10 +295,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
ExternalSeriesId = programSeriesId,
|
ExternalSeriesId = programSeriesId,
|
||||||
Limit = 1,
|
Limit = 1,
|
||||||
ImageTypes = new ImageType[] { ImageType.Primary },
|
ImageTypes = new ImageType[] { ImageType.Primary },
|
||||||
DtoOptions = new DtoOptions
|
DtoOptions = new DtoOptions(false)
|
||||||
{
|
|
||||||
Fields = new List<MediaBrowser.Model.Querying.ItemFields>()
|
|
||||||
}
|
|
||||||
|
|
||||||
}).FirstOrDefault();
|
}).FirstOrDefault();
|
||||||
|
|
||||||
@ -327,14 +314,14 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dto.ParentBackdropImageTags == null || dto.ParentBackdropImageTags.Count == 0)
|
if (dto.ParentBackdropImageTags == null || dto.ParentBackdropImageTags.Length == 0)
|
||||||
{
|
{
|
||||||
image = program.GetImageInfo(ImageType.Backdrop, 0);
|
image = program.GetImageInfo(ImageType.Backdrop, 0);
|
||||||
if (image != null)
|
if (image != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dto.ParentBackdropImageTags = new List<string>
|
dto.ParentBackdropImageTags = new string[]
|
||||||
{
|
{
|
||||||
_imageProcessor.GetImageCacheTag(program, image)
|
_imageProcessor.GetImageCacheTag(program, image)
|
||||||
};
|
};
|
||||||
@ -349,24 +336,24 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DayPattern? GetDayPattern(List<DayOfWeek> days)
|
public DayPattern? GetDayPattern(DayOfWeek[] days)
|
||||||
{
|
{
|
||||||
DayPattern? pattern = null;
|
DayPattern? pattern = null;
|
||||||
|
|
||||||
if (days.Count > 0)
|
if (days.Length > 0)
|
||||||
{
|
{
|
||||||
if (days.Count == 7)
|
if (days.Length == 7)
|
||||||
{
|
{
|
||||||
pattern = DayPattern.Daily;
|
pattern = DayPattern.Daily;
|
||||||
}
|
}
|
||||||
else if (days.Count == 2)
|
else if (days.Length == 2)
|
||||||
{
|
{
|
||||||
if (days.Contains(DayOfWeek.Saturday) && days.Contains(DayOfWeek.Sunday))
|
if (days.Contains(DayOfWeek.Saturday) && days.Contains(DayOfWeek.Sunday))
|
||||||
{
|
{
|
||||||
pattern = DayPattern.Weekends;
|
pattern = DayPattern.Weekends;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (days.Count == 5)
|
else if (days.Length == 5)
|
||||||
{
|
{
|
||||||
if (days.Contains(DayOfWeek.Monday) && days.Contains(DayOfWeek.Tuesday) && days.Contains(DayOfWeek.Wednesday) && days.Contains(DayOfWeek.Thursday) && days.Contains(DayOfWeek.Friday))
|
if (days.Contains(DayOfWeek.Monday) && days.Contains(DayOfWeek.Tuesday) && days.Contains(DayOfWeek.Wednesday) && days.Contains(DayOfWeek.Thursday) && days.Contains(DayOfWeek.Friday))
|
||||||
{
|
{
|
||||||
@ -384,7 +371,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
{
|
{
|
||||||
Name = info.Name,
|
Name = info.Name,
|
||||||
Id = info.Id,
|
Id = info.Id,
|
||||||
Clients = info.Clients,
|
Clients = info.Clients.ToArray(),
|
||||||
ProgramName = info.ProgramName,
|
ProgramName = info.ProgramName,
|
||||||
SourceType = info.SourceType,
|
SourceType = info.SourceType,
|
||||||
Status = info.Status,
|
Status = info.Status,
|
||||||
@ -543,7 +530,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
PostPaddingSeconds = dto.PostPaddingSeconds,
|
PostPaddingSeconds = dto.PostPaddingSeconds,
|
||||||
IsPostPaddingRequired = dto.IsPostPaddingRequired,
|
IsPostPaddingRequired = dto.IsPostPaddingRequired,
|
||||||
IsPrePaddingRequired = dto.IsPrePaddingRequired,
|
IsPrePaddingRequired = dto.IsPrePaddingRequired,
|
||||||
Days = dto.Days,
|
Days = dto.Days.ToList(),
|
||||||
Priority = dto.Priority,
|
Priority = dto.Priority,
|
||||||
RecordAnyChannel = dto.RecordAnyChannel,
|
RecordAnyChannel = dto.RecordAnyChannel,
|
||||||
RecordAnyTime = dto.RecordAnyTime,
|
RecordAnyTime = dto.RecordAnyTime,
|
||||||
|
@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
private readonly LiveTvDtoService _tvDtoService;
|
private readonly LiveTvDtoService _tvDtoService;
|
||||||
|
|
||||||
private readonly List<ILiveTvService> _services = new List<ILiveTvService>();
|
private ILiveTvService[] _services = new ILiveTvService[] { };
|
||||||
|
|
||||||
private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
/// <param name="listingProviders">The listing providers.</param>
|
/// <param name="listingProviders">The listing providers.</param>
|
||||||
public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders)
|
public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders)
|
||||||
{
|
{
|
||||||
_services.AddRange(services);
|
_services = services.ToArray();
|
||||||
_tunerHosts.AddRange(tunerHosts);
|
_tunerHosts.AddRange(tunerHosts);
|
||||||
_listingProviders.AddRange(listingProviders);
|
_listingProviders.AddRange(listingProviders);
|
||||||
|
|
||||||
@ -558,7 +558,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
{
|
{
|
||||||
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
_libraryManager.CreateItem(item, cancellationToken);
|
||||||
}
|
}
|
||||||
else if (forceUpdate)
|
else if (forceUpdate)
|
||||||
{
|
{
|
||||||
@ -875,7 +875,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
{
|
{
|
||||||
await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
_libraryManager.CreateItem(item, cancellationToken);
|
||||||
}
|
}
|
||||||
else if (dataChanged || info.DateLastUpdated > recording.DateLastSaved || statusChanged)
|
else if (dataChanged || info.DateLastUpdated > recording.DateLastSaved || statusChanged)
|
||||||
{
|
{
|
||||||
@ -985,9 +985,8 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var queryResult = _libraryManager.QueryItems(internalQuery);
|
var queryResult = _libraryManager.QueryItems(internalQuery);
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(queryResult.Items, options, user)
|
var returnArray = (await _dtoService.GetBaseItemDtos(queryResult.Items, options, user)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
var returnArray = returnList.ToArray(returnList.Count);
|
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
@ -998,7 +997,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken)
|
public async Task<QueryResult<BaseItem>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(query.UserId);
|
var user = _userManager.GetUserById(query.UserId);
|
||||||
|
|
||||||
@ -1036,10 +1035,10 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var programList = _libraryManager.QueryItems(internalQuery).Items.Cast<LiveTvProgram>().ToList();
|
var programList = _libraryManager.QueryItems(internalQuery).Items;
|
||||||
var totalCount = programList.Count;
|
var totalCount = programList.Length;
|
||||||
|
|
||||||
IOrderedEnumerable<LiveTvProgram> orderedPrograms = programList.OrderBy(i => i.StartDate.Date);
|
IOrderedEnumerable<LiveTvProgram> orderedPrograms = programList.Cast<LiveTvProgram>().OrderBy(i => i.StartDate.Date);
|
||||||
|
|
||||||
if (query.IsAiring ?? false)
|
if (query.IsAiring ?? false)
|
||||||
{
|
{
|
||||||
@ -1047,14 +1046,14 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
.ThenByDescending(i => GetRecommendationScore(i, user.Id, true));
|
.ThenByDescending(i => GetRecommendationScore(i, user.Id, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<LiveTvProgram> programs = orderedPrograms;
|
IEnumerable<BaseItem> programs = orderedPrograms;
|
||||||
|
|
||||||
if (query.Limit.HasValue)
|
if (query.Limit.HasValue)
|
||||||
{
|
{
|
||||||
programs = programs.Take(query.Limit.Value);
|
programs = programs.Take(query.Limit.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new QueryResult<LiveTvProgram>
|
var result = new QueryResult<BaseItem>
|
||||||
{
|
{
|
||||||
Items = programs.ToArray(),
|
Items = programs.ToArray(),
|
||||||
TotalRecordCount = totalCount
|
TotalRecordCount = totalCount
|
||||||
@ -1071,9 +1070,8 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var user = _userManager.GetUserById(query.UserId);
|
var user = _userManager.GetUserById(query.UserId);
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
|
var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
var returnArray = returnList.ToArray(returnList.Count);
|
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
@ -1223,9 +1221,9 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
await EmbyTV.EmbyTV.Current.ScanForTunerDeviceChanges(cancellationToken).ConfigureAwait(false);
|
await EmbyTV.EmbyTV.Current.ScanForTunerDeviceChanges(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
double progressPerService = _services.Count == 0
|
double progressPerService = _services.Length == 0
|
||||||
? 0
|
? 0
|
||||||
: 1 / _services.Count;
|
: 1 / _services.Length;
|
||||||
|
|
||||||
var newChannelIdList = new List<Guid>();
|
var newChannelIdList = new List<Guid>();
|
||||||
var newProgramIdList = new List<Guid>();
|
var newProgramIdList = new List<Guid>();
|
||||||
@ -1257,13 +1255,13 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
numComplete++;
|
numComplete++;
|
||||||
double percent = numComplete;
|
double percent = numComplete;
|
||||||
percent /= _services.Count;
|
percent /= _services.Length;
|
||||||
|
|
||||||
progress.Report(100 * percent);
|
progress.Report(100 * percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
await CleanDatabaseInternal(newChannelIdList, new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false);
|
await CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false);
|
||||||
await CleanDatabaseInternal(newProgramIdList, new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false);
|
await CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var coreService = _services.OfType<EmbyTV.EmbyTV>().FirstOrDefault();
|
var coreService = _services.OfType<EmbyTV.EmbyTV>().FirstOrDefault();
|
||||||
|
|
||||||
@ -1275,8 +1273,11 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
// Load these now which will prefetch metadata
|
// Load these now which will prefetch metadata
|
||||||
var dtoOptions = new DtoOptions();
|
var dtoOptions = new DtoOptions();
|
||||||
dtoOptions.Fields.Remove(ItemFields.SyncInfo);
|
var fields = dtoOptions.Fields.ToList();
|
||||||
dtoOptions.Fields.Remove(ItemFields.BasicSyncInfo);
|
fields.Remove(ItemFields.SyncInfo);
|
||||||
|
fields.Remove(ItemFields.BasicSyncInfo);
|
||||||
|
dtoOptions.Fields = fields.ToArray(fields.Count);
|
||||||
|
|
||||||
await GetRecordings(new RecordingQuery(), dtoOptions, cancellationToken).ConfigureAwait(false);
|
await GetRecordings(new RecordingQuery(), dtoOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
@ -1409,7 +1410,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
if (newPrograms.Count > 0)
|
if (newPrograms.Count > 0)
|
||||||
{
|
{
|
||||||
await _libraryManager.CreateItems(newPrograms, cancellationToken).ConfigureAwait(false);
|
_libraryManager.CreateItems(newPrograms, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Do this in bulk
|
// TODO: Do this in bulk
|
||||||
@ -1446,14 +1447,14 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
return new Tuple<List<Guid>, List<Guid>>(channels, programs);
|
return new Tuple<List<Guid>, List<Guid>>(channels, programs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CleanDatabaseInternal(List<Guid> currentIdList, string[] validTypes, IProgress<double> progress, CancellationToken cancellationToken)
|
private async Task CleanDatabaseInternal(Guid[] currentIdList, string[] validTypes, IProgress<double> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var list = _itemRepo.GetItemIdsList(new InternalItemsQuery
|
var list = _itemRepo.GetItemIdsList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = validTypes,
|
IncludeItemTypes = validTypes,
|
||||||
DtoOptions = new DtoOptions(false)
|
DtoOptions = new DtoOptions(false)
|
||||||
|
|
||||||
}).ToList();
|
});
|
||||||
|
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
|
|
||||||
@ -1543,7 +1544,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var idList = await Task.WhenAll(recordingTasks).ConfigureAwait(false);
|
var idList = await Task.WhenAll(recordingTasks).ConfigureAwait(false);
|
||||||
|
|
||||||
await CleanDatabaseInternal(idList.ToList(), new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }, new SimpleProgress<double>(), cancellationToken).ConfigureAwait(false);
|
await CleanDatabaseInternal(idList, new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }, new SimpleProgress<double>(), cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
_lastRecordingRefreshTime = DateTime.UtcNow;
|
_lastRecordingRefreshTime = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
@ -1560,11 +1561,6 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
return new QueryResult<BaseItem>();
|
return new QueryResult<BaseItem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((query.IsInProgress ?? false))
|
|
||||||
{
|
|
||||||
return new QueryResult<BaseItem>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var folderIds = EmbyTV.EmbyTV.Current.GetRecordingFolders()
|
var folderIds = EmbyTV.EmbyTV.Current.GetRecordingFolders()
|
||||||
.SelectMany(i => i.Locations)
|
.SelectMany(i => i.Locations)
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
@ -1576,13 +1572,10 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var excludeItemTypes = new List<string>();
|
var excludeItemTypes = new List<string>();
|
||||||
|
|
||||||
if (!query.IsInProgress.HasValue)
|
folderIds.Add(internalLiveTvFolderId);
|
||||||
{
|
|
||||||
folderIds.Add(internalLiveTvFolderId);
|
|
||||||
|
|
||||||
excludeItemTypes.Add(typeof(LiveTvChannel).Name);
|
excludeItemTypes.Add(typeof(LiveTvChannel).Name);
|
||||||
excludeItemTypes.Add(typeof(LiveTvProgram).Name);
|
excludeItemTypes.Add(typeof(LiveTvProgram).Name);
|
||||||
}
|
|
||||||
|
|
||||||
if (folderIds.Count == 0)
|
if (folderIds.Count == 0)
|
||||||
{
|
{
|
||||||
@ -1631,6 +1624,19 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((query.IsInProgress ?? false))
|
||||||
|
{
|
||||||
|
// TODO: filter
|
||||||
|
var allActivePaths = EmbyTV.EmbyTV.Current.GetAllActiveRecordings().Select(i => i.Path).ToArray();
|
||||||
|
var items = allActivePaths.Select(i => _libraryManager.FindByPath(i, false)).Where(i => i != null).ToArray();
|
||||||
|
|
||||||
|
return new QueryResult<BaseItem>
|
||||||
|
{
|
||||||
|
Items = items,
|
||||||
|
TotalRecordCount = items.Length
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(new InternalItemsQuery(user)
|
return _libraryManager.GetItemsResult(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
MediaTypes = new[] { MediaType.Video },
|
MediaTypes = new[] { MediaType.Video },
|
||||||
@ -1658,11 +1664,6 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
return new QueryResult<BaseItemDto>();
|
return new QueryResult<BaseItemDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_services.Count > 1)
|
|
||||||
{
|
|
||||||
return new QueryResult<BaseItemDto>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user == null || (query.IsInProgress ?? false))
|
if (user == null || (query.IsInProgress ?? false))
|
||||||
{
|
{
|
||||||
return new QueryResult<BaseItemDto>();
|
return new QueryResult<BaseItemDto>();
|
||||||
@ -1701,11 +1702,9 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
DtoOptions = options
|
DtoOptions = options
|
||||||
});
|
});
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
|
var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
|
|
||||||
var returnArray = returnList.ToArray(returnList.Count);
|
|
||||||
|
|
||||||
return new QueryResult<BaseItemDto>
|
return new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = returnArray,
|
Items = returnArray,
|
||||||
@ -1723,13 +1722,9 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false);
|
var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (_services.Count == 1 && (!query.IsInProgress.HasValue || !query.IsInProgress.Value) && (!query.IsLibraryItem.HasValue || query.IsLibraryItem.Value))
|
// TODO: Figure out how to merge emby recordings + service recordings
|
||||||
|
if (_services.Length == 1)
|
||||||
{
|
{
|
||||||
if (!query.IsInProgress.HasValue)
|
|
||||||
{
|
|
||||||
await RefreshRecordings(folder.Id, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetEmbyRecordings(query, options, folder.Id, user);
|
return GetEmbyRecordings(query, options, folder.Id, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1841,7 +1836,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> tuples, List<ItemFields> fields, User user = null)
|
public async Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> tuples, ItemFields[] fields, User user = null)
|
||||||
{
|
{
|
||||||
var programTuples = new List<Tuple<BaseItemDto, string, string, string>>();
|
var programTuples = new List<Tuple<BaseItemDto, string, string, string>>();
|
||||||
var hasChannelImage = fields.Contains(ItemFields.ChannelImage);
|
var hasChannelImage = fields.Contains(ItemFields.ChannelImage);
|
||||||
@ -1921,6 +1916,11 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
await AddRecordingInfo(programTuples, CancellationToken.None).ConfigureAwait(false);
|
await AddRecordingInfo(programTuples, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ActiveRecordingInfo GetActiveRecordingInfo(string path)
|
||||||
|
{
|
||||||
|
return EmbyTV.EmbyTV.Current.GetActiveRecordingInfo(path);
|
||||||
|
}
|
||||||
|
|
||||||
public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, User user = null)
|
public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, User user = null)
|
||||||
{
|
{
|
||||||
var recording = (ILiveTvRecording)item;
|
var recording = (ILiveTvRecording)item;
|
||||||
@ -1950,20 +1950,6 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
dto.IsKids = info.IsKids;
|
dto.IsKids = info.IsKids;
|
||||||
dto.IsPremiere = info.IsPremiere;
|
dto.IsPremiere = info.IsPremiere;
|
||||||
|
|
||||||
dto.CanDelete = user == null
|
|
||||||
? recording.CanDelete()
|
|
||||||
: recording.CanDelete(user);
|
|
||||||
|
|
||||||
if (dto.MediaSources == null)
|
|
||||||
{
|
|
||||||
dto.MediaSources = recording.GetMediaSources(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dto.MediaStreams == null)
|
|
||||||
{
|
|
||||||
dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue)
|
if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue)
|
||||||
{
|
{
|
||||||
var now = DateTime.UtcNow.Ticks;
|
var now = DateTime.UtcNow.Ticks;
|
||||||
@ -1987,6 +1973,65 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordingInfo activeRecordingInfo, User user = null)
|
||||||
|
{
|
||||||
|
var service = EmbyTV.EmbyTV.Current;
|
||||||
|
|
||||||
|
var info = activeRecordingInfo.Timer;
|
||||||
|
|
||||||
|
var channel = string.IsNullOrWhiteSpace(info.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, info.ChannelId));
|
||||||
|
|
||||||
|
dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId)
|
||||||
|
? null
|
||||||
|
: _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N");
|
||||||
|
|
||||||
|
dto.TimerId = string.IsNullOrEmpty(info.Id)
|
||||||
|
? null
|
||||||
|
: _tvDtoService.GetInternalTimerId(service.Name, info.Id).ToString("N");
|
||||||
|
|
||||||
|
var startDate = info.StartDate;
|
||||||
|
var endDate = info.EndDate;
|
||||||
|
|
||||||
|
dto.StartDate = startDate;
|
||||||
|
dto.EndDate = endDate;
|
||||||
|
dto.Status = info.Status.ToString();
|
||||||
|
dto.IsRepeat = info.IsRepeat;
|
||||||
|
dto.EpisodeTitle = info.EpisodeTitle;
|
||||||
|
dto.IsMovie = info.IsMovie;
|
||||||
|
dto.IsSeries = info.IsSeries;
|
||||||
|
dto.IsSports = info.IsSports;
|
||||||
|
dto.IsLive = info.IsLive;
|
||||||
|
dto.IsNews = info.IsNews;
|
||||||
|
dto.IsKids = info.IsKids;
|
||||||
|
dto.IsPremiere = info.IsPremiere;
|
||||||
|
|
||||||
|
if (info.Status == RecordingStatus.InProgress)
|
||||||
|
{
|
||||||
|
startDate = info.StartDate.AddSeconds(0 - info.PrePaddingSeconds);
|
||||||
|
endDate = info.EndDate.AddSeconds(info.PostPaddingSeconds);
|
||||||
|
|
||||||
|
var now = DateTime.UtcNow.Ticks;
|
||||||
|
var start = startDate.Ticks;
|
||||||
|
var end = endDate.Ticks;
|
||||||
|
|
||||||
|
var pct = now - start;
|
||||||
|
|
||||||
|
pct /= end;
|
||||||
|
pct *= 100;
|
||||||
|
dto.CompletionPercentage = pct;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel != null)
|
||||||
|
{
|
||||||
|
dto.ChannelName = channel.Name;
|
||||||
|
|
||||||
|
if (channel.HasImage(ImageType.Primary))
|
||||||
|
{
|
||||||
|
dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<QueryResult<BaseItemDto>> GetRecordings(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken)
|
public async Task<QueryResult<BaseItemDto>> GetRecordings(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
|
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
|
||||||
@ -1995,9 +2040,8 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var internalResult = await GetInternalRecordings(query, options, cancellationToken).ConfigureAwait(false);
|
var internalResult = await GetInternalRecordings(query, options, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
|
var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
var returnArray = returnList.ToArray(returnList.Count);
|
|
||||||
|
|
||||||
return new QueryResult<BaseItemDto>
|
return new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
@ -2100,7 +2144,6 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
if (service is EmbyTV.EmbyTV)
|
if (service is EmbyTV.EmbyTV)
|
||||||
{
|
{
|
||||||
// We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says
|
|
||||||
return service.DeleteRecordingAsync(GetItemExternalId(recording), CancellationToken.None);
|
return service.DeleteRecordingAsync(GetItemExternalId(recording), CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2350,7 +2393,6 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
var currentChannelsDict = new Dictionary<string, BaseItemDto>();
|
var currentChannelsDict = new Dictionary<string, BaseItemDto>();
|
||||||
|
|
||||||
var addCurrentProgram = options.AddCurrentProgram;
|
var addCurrentProgram = options.AddCurrentProgram;
|
||||||
var addMediaSources = options.Fields.Contains(ItemFields.MediaSources);
|
|
||||||
var addServiceName = options.Fields.Contains(ItemFields.ServiceName);
|
var addServiceName = options.Fields.Contains(ItemFields.ServiceName);
|
||||||
|
|
||||||
foreach (var tuple in tuples)
|
foreach (var tuple in tuples)
|
||||||
@ -2369,11 +2411,6 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
currentChannelsDict[dto.Id] = dto;
|
currentChannelsDict[dto.Id] = dto;
|
||||||
|
|
||||||
if (addMediaSources)
|
|
||||||
{
|
|
||||||
dto.MediaSources = channel.GetMediaSources(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addCurrentProgram)
|
if (addCurrentProgram)
|
||||||
{
|
{
|
||||||
var channelIdString = channel.Id.ToString("N");
|
var channelIdString = channel.Id.ToString("N");
|
||||||
@ -2479,7 +2516,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
var defaults = await GetNewTimerDefaultsInternal(cancellationToken, program).ConfigureAwait(false);
|
var defaults = await GetNewTimerDefaultsInternal(cancellationToken, program).ConfigureAwait(false);
|
||||||
var info = _tvDtoService.GetSeriesTimerInfoDto(defaults.Item1, defaults.Item2, null);
|
var info = _tvDtoService.GetSeriesTimerInfoDto(defaults.Item1, defaults.Item2, null);
|
||||||
|
|
||||||
info.Days = defaults.Item1.Days;
|
info.Days = defaults.Item1.Days.ToArray();
|
||||||
|
|
||||||
info.DayPattern = _tvDtoService.GetDayPattern(info.Days);
|
info.DayPattern = _tvDtoService.GetDayPattern(info.Days);
|
||||||
|
|
||||||
@ -2656,8 +2693,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var series = recordings
|
var series = recordings
|
||||||
.Where(i => i.IsSeries)
|
.Where(i => i.IsSeries)
|
||||||
.ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase)
|
.ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase);
|
||||||
.ToList();
|
|
||||||
|
|
||||||
groups.AddRange(series.OrderByString(i => i.Key).Select(i => new BaseItemDto
|
groups.AddRange(series.OrderByString(i => i.Key).Select(i => new BaseItemDto
|
||||||
{
|
{
|
||||||
@ -2762,7 +2798,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IEnumerable<LiveTvServiceInfo>> GetServiceInfos(CancellationToken cancellationToken)
|
private async Task<LiveTvServiceInfo[]> GetServiceInfos(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var tasks = Services.Select(i => GetServiceInfo(i, cancellationToken));
|
var tasks = Services.Select(i => GetServiceInfo(i, cancellationToken));
|
||||||
|
|
||||||
@ -2806,7 +2842,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
return dto;
|
return dto;
|
||||||
|
|
||||||
}).ToList();
|
}).ToArray();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -2822,25 +2858,24 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
public async Task<LiveTvInfo> GetLiveTvInfo(CancellationToken cancellationToken)
|
public async Task<LiveTvInfo> GetLiveTvInfo(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var services = await GetServiceInfos(CancellationToken.None).ConfigureAwait(false);
|
var services = await GetServiceInfos(CancellationToken.None).ConfigureAwait(false);
|
||||||
var servicesList = services.ToList();
|
|
||||||
|
|
||||||
var info = new LiveTvInfo
|
var info = new LiveTvInfo
|
||||||
{
|
{
|
||||||
Services = servicesList.ToList(),
|
Services = services,
|
||||||
IsEnabled = servicesList.Count > 0
|
IsEnabled = services.Length > 0
|
||||||
};
|
};
|
||||||
|
|
||||||
info.EnabledUsers = _userManager.Users
|
info.EnabledUsers = _userManager.Users
|
||||||
.Where(IsLiveTvEnabled)
|
.Where(IsLiveTvEnabled)
|
||||||
.Select(i => i.Id.ToString("N"))
|
.Select(i => i.Id.ToString("N"))
|
||||||
.ToList();
|
.ToArray();
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsLiveTvEnabled(User user)
|
private bool IsLiveTvEnabled(User user)
|
||||||
{
|
{
|
||||||
return user.Policy.EnableLiveTvAccess && (Services.Count > 1 || GetConfiguration().TunerHosts.Count > 0);
|
return user.Policy.EnableLiveTvAccess && (Services.Count > 1 || GetConfiguration().TunerHosts.Length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<User> GetEnabledUsers()
|
public IEnumerable<User> GetEnabledUsers()
|
||||||
@ -2880,10 +2915,13 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
private void RemoveFields(DtoOptions options)
|
private void RemoveFields(DtoOptions options)
|
||||||
{
|
{
|
||||||
options.Fields.Remove(ItemFields.CanDelete);
|
var fields = options.Fields.ToList();
|
||||||
options.Fields.Remove(ItemFields.CanDownload);
|
|
||||||
options.Fields.Remove(ItemFields.DisplayPreferencesId);
|
fields.Remove(ItemFields.CanDelete);
|
||||||
options.Fields.Remove(ItemFields.Etag);
|
fields.Remove(ItemFields.CanDownload);
|
||||||
|
fields.Remove(ItemFields.DisplayPreferencesId);
|
||||||
|
fields.Remove(ItemFields.Etag);
|
||||||
|
options.Fields = fields.ToArray(fields.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Folder> GetInternalLiveTvFolder(CancellationToken cancellationToken)
|
public async Task<Folder> GetInternalLiveTvFolder(CancellationToken cancellationToken)
|
||||||
@ -2911,12 +2949,14 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var config = GetConfiguration();
|
var config = GetConfiguration();
|
||||||
|
|
||||||
var index = config.TunerHosts.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
|
var list = config.TunerHosts.ToList();
|
||||||
|
var index = list.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
|
if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
|
||||||
{
|
{
|
||||||
info.Id = Guid.NewGuid().ToString("N");
|
info.Id = Guid.NewGuid().ToString("N");
|
||||||
config.TunerHosts.Add(info);
|
list.Add(info);
|
||||||
|
config.TunerHosts = list.ToArray(list.Count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2948,12 +2988,14 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
var config = GetConfiguration();
|
var config = GetConfiguration();
|
||||||
|
|
||||||
var index = config.ListingProviders.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
|
var list = config.ListingProviders.ToList();
|
||||||
|
var index = list.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
|
if (index == -1 || string.IsNullOrWhiteSpace(info.Id))
|
||||||
{
|
{
|
||||||
info.Id = Guid.NewGuid().ToString("N");
|
info.Id = Guid.NewGuid().ToString("N");
|
||||||
config.ListingProviders.Add(info);
|
list.Add(info);
|
||||||
|
config.ListingProviders = list.ToArray(list.Count);
|
||||||
info.EnableNewProgramIds = true;
|
info.EnableNewProgramIds = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2972,7 +3014,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
{
|
{
|
||||||
var config = GetConfiguration();
|
var config = GetConfiguration();
|
||||||
|
|
||||||
config.ListingProviders = config.ListingProviders.Where(i => !string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase)).ToList();
|
config.ListingProviders = config.ListingProviders.Where(i => !string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||||
|
|
||||||
_config.SaveConfiguration("livetv", config);
|
_config.SaveConfiguration("livetv", config);
|
||||||
_taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
|
_taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
|
||||||
@ -3004,7 +3046,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
var providerChannels = await GetChannelsFromListingsProviderData(providerId, CancellationToken.None)
|
var providerChannels = await GetChannelsFromListingsProviderData(providerId, CancellationToken.None)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var mappings = listingsProviderInfo.ChannelMappings.ToList();
|
var mappings = listingsProviderInfo.ChannelMappings;
|
||||||
|
|
||||||
var tunerChannelMappings =
|
var tunerChannelMappings =
|
||||||
tunerChannels.Select(i => GetTunerChannelMapping(i, mappings, providerChannels)).ToList();
|
tunerChannels.Select(i => GetTunerChannelMapping(i, mappings, providerChannels)).ToList();
|
||||||
@ -3014,7 +3056,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
return tunerChannelMappings.First(i => string.Equals(i.Id, tunerChannelId, StringComparison.OrdinalIgnoreCase));
|
return tunerChannelMappings.First(i => string.Equals(i.Id, tunerChannelId, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TunerChannelMapping GetTunerChannelMapping(ChannelInfo tunerChannel, List<NameValuePair> mappings, List<ChannelInfo> epgChannels)
|
public TunerChannelMapping GetTunerChannelMapping(ChannelInfo tunerChannel, NameValuePair[] mappings, List<ChannelInfo> epgChannels)
|
||||||
{
|
{
|
||||||
var result = new TunerChannelMapping
|
var result = new TunerChannelMapping
|
||||||
{
|
{
|
||||||
@ -3078,7 +3120,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
if (string.Equals(feature, "dvr-l", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(feature, "dvr-l", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var config = GetConfiguration();
|
var config = GetConfiguration();
|
||||||
if (config.TunerHosts.Count > 0 &&
|
if (config.TunerHosts.Length > 0 &&
|
||||||
config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0)
|
config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0)
|
||||||
{
|
{
|
||||||
return Task.FromResult(new MBRegistrationRecord
|
return Task.FromResult(new MBRegistrationRecord
|
||||||
|
@ -43,9 +43,11 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
if (baseItem.SourceType == SourceType.LiveTV)
|
if (baseItem.SourceType == SourceType.LiveTV)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(baseItem.Path))
|
var activeRecordingInfo = _liveTvManager.GetActiveRecordingInfo(item.Path);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(baseItem.Path) || activeRecordingInfo != null)
|
||||||
{
|
{
|
||||||
return GetMediaSourcesInternal(item, cancellationToken);
|
return GetMediaSourcesInternal(item, activeRecordingInfo, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +58,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
private const char StreamIdDelimeter = '_';
|
private const char StreamIdDelimeter = '_';
|
||||||
private const string StreamIdDelimeterString = "_";
|
private const string StreamIdDelimeterString = "_";
|
||||||
|
|
||||||
private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(IHasMediaSources item, CancellationToken cancellationToken)
|
private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(IHasMediaSources item, ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
IEnumerable<MediaSourceInfo> sources;
|
IEnumerable<MediaSourceInfo> sources;
|
||||||
|
|
||||||
@ -67,12 +69,20 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
if (item is ILiveTvRecording)
|
if (item is ILiveTvRecording)
|
||||||
{
|
{
|
||||||
sources = await _liveTvManager.GetRecordingMediaSources(item, cancellationToken)
|
sources = await _liveTvManager.GetRecordingMediaSources(item, cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken)
|
if (activeRecordingInfo != null)
|
||||||
.ConfigureAwait(false);
|
{
|
||||||
|
sources = await EmbyTV.EmbyTV.Current.GetRecordingStreamMediaSources(activeRecordingInfo, cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (NotImplementedException)
|
catch (NotImplementedException)
|
||||||
|
@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
public bool IsHidden
|
public bool IsHidden
|
||||||
{
|
{
|
||||||
get { return _liveTvManager.Services.Count == 1 && GetConfiguration().TunerHosts.Count == 0; }
|
get { return _liveTvManager.Services.Count == 1 && GetConfiguration().TunerHosts.Length == 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEnabled
|
public bool IsEnabled
|
||||||
|
@ -25,12 +25,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly IEnvironmentInfo _environment;
|
private readonly IEnvironmentInfo _environment;
|
||||||
|
private readonly INetworkManager _networkManager;
|
||||||
|
|
||||||
public M3UTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost, IEnvironmentInfo environment) : base(config, logger, jsonSerializer, mediaEncoder, fileSystem)
|
public M3UTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost, IEnvironmentInfo environment, INetworkManager networkManager) : base(config, logger, jsonSerializer, mediaEncoder, fileSystem)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_environment = environment;
|
_environment = environment;
|
||||||
|
_networkManager = networkManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Type
|
public override string Type
|
||||||
@ -38,7 +40,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
get { return "m3u"; }
|
get { return "m3u"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public virtual string Name
|
||||||
{
|
{
|
||||||
get { return "M3U Tuner"; }
|
get { return "M3U Tuner"; }
|
||||||
}
|
}
|
||||||
@ -99,74 +101,86 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
}
|
}
|
||||||
|
|
||||||
var channels = await GetChannels(info, true, cancellationToken).ConfigureAwait(false);
|
var channels = await GetChannels(info, true, cancellationToken).ConfigureAwait(false);
|
||||||
var m3uchannels = channels.Cast<M3UChannel>();
|
var channel = channels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase));
|
||||||
var channel = m3uchannels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase));
|
|
||||||
if (channel != null)
|
if (channel != null)
|
||||||
{
|
{
|
||||||
var path = channel.Path;
|
return new List<MediaSourceInfo> { CreateMediaSourceInfo(info, channel) };
|
||||||
MediaProtocol protocol = MediaProtocol.File;
|
|
||||||
if (path.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
protocol = MediaProtocol.Http;
|
|
||||||
}
|
|
||||||
else if (path.StartsWith("rtmp", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
protocol = MediaProtocol.Rtmp;
|
|
||||||
}
|
|
||||||
else if (path.StartsWith("rtsp", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
protocol = MediaProtocol.Rtsp;
|
|
||||||
}
|
|
||||||
else if (path.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
protocol = MediaProtocol.Udp;
|
|
||||||
}
|
|
||||||
else if (path.StartsWith("rtp", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
protocol = MediaProtocol.Rtmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mediaSource = new MediaSourceInfo
|
|
||||||
{
|
|
||||||
Path = channel.Path,
|
|
||||||
Protocol = protocol,
|
|
||||||
MediaStreams = new List<MediaStream>
|
|
||||||
{
|
|
||||||
new MediaStream
|
|
||||||
{
|
|
||||||
Type = MediaStreamType.Video,
|
|
||||||
// Set the index to -1 because we don't know the exact index of the video stream within the container
|
|
||||||
Index = -1,
|
|
||||||
IsInterlaced = true
|
|
||||||
},
|
|
||||||
new MediaStream
|
|
||||||
{
|
|
||||||
Type = MediaStreamType.Audio,
|
|
||||||
// Set the index to -1 because we don't know the exact index of the audio stream within the container
|
|
||||||
Index = -1
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
RequiresOpening = true,
|
|
||||||
RequiresClosing = true,
|
|
||||||
RequiresLooping = info.EnableStreamLooping,
|
|
||||||
|
|
||||||
ReadAtNativeFramerate = false,
|
|
||||||
|
|
||||||
Id = channel.Path.GetMD5().ToString("N"),
|
|
||||||
IsInfiniteStream = true,
|
|
||||||
IsRemote = true,
|
|
||||||
|
|
||||||
IgnoreDts = true
|
|
||||||
};
|
|
||||||
|
|
||||||
mediaSource.InferTotalBitrate();
|
|
||||||
|
|
||||||
return new List<MediaSourceInfo> { mediaSource };
|
|
||||||
}
|
}
|
||||||
return new List<MediaSourceInfo>();
|
return new List<MediaSourceInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual MediaSourceInfo CreateMediaSourceInfo(TunerHostInfo info, ChannelInfo channel)
|
||||||
|
{
|
||||||
|
var path = channel.Path;
|
||||||
|
MediaProtocol protocol = MediaProtocol.File;
|
||||||
|
if (path.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
protocol = MediaProtocol.Http;
|
||||||
|
}
|
||||||
|
else if (path.StartsWith("rtmp", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
protocol = MediaProtocol.Rtmp;
|
||||||
|
}
|
||||||
|
else if (path.StartsWith("rtsp", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
protocol = MediaProtocol.Rtsp;
|
||||||
|
}
|
||||||
|
else if (path.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
protocol = MediaProtocol.Udp;
|
||||||
|
}
|
||||||
|
else if (path.StartsWith("rtp", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
protocol = MediaProtocol.Rtmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri uri;
|
||||||
|
var isRemote = true;
|
||||||
|
if (Uri.TryCreate(path, UriKind.Absolute, out uri))
|
||||||
|
{
|
||||||
|
isRemote = !_networkManager.IsInLocalNetwork(uri.Host);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaSource = new MediaSourceInfo
|
||||||
|
{
|
||||||
|
Path = path,
|
||||||
|
Protocol = protocol,
|
||||||
|
MediaStreams = new List<MediaStream>
|
||||||
|
{
|
||||||
|
new MediaStream
|
||||||
|
{
|
||||||
|
Type = MediaStreamType.Video,
|
||||||
|
// Set the index to -1 because we don't know the exact index of the video stream within the container
|
||||||
|
Index = -1,
|
||||||
|
IsInterlaced = true
|
||||||
|
},
|
||||||
|
new MediaStream
|
||||||
|
{
|
||||||
|
Type = MediaStreamType.Audio,
|
||||||
|
// Set the index to -1 because we don't know the exact index of the audio stream within the container
|
||||||
|
Index = -1
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
RequiresOpening = true,
|
||||||
|
RequiresClosing = true,
|
||||||
|
RequiresLooping = info.EnableStreamLooping,
|
||||||
|
EnableMpDecimate = info.EnableMpDecimate,
|
||||||
|
|
||||||
|
ReadAtNativeFramerate = false,
|
||||||
|
|
||||||
|
Id = channel.Path.GetMD5().ToString("N"),
|
||||||
|
IsInfiniteStream = true,
|
||||||
|
IsRemote = isRemote,
|
||||||
|
|
||||||
|
IgnoreDts = true
|
||||||
|
};
|
||||||
|
|
||||||
|
mediaSource.InferTotalBitrate();
|
||||||
|
|
||||||
|
return mediaSource;
|
||||||
|
}
|
||||||
|
|
||||||
protected override Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
|
protected override Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
|
@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<M3UChannel>> Parse(string url, string channelIdPrefix, string tunerHostId, CancellationToken cancellationToken)
|
public async Task<List<ChannelInfo>> Parse(string url, string channelIdPrefix, string tunerHostId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// Read the file and display it line by line.
|
// Read the file and display it line by line.
|
||||||
using (var reader = new StreamReader(await GetListingsStream(url, cancellationToken).ConfigureAwait(false)))
|
using (var reader = new StreamReader(await GetListingsStream(url, cancellationToken).ConfigureAwait(false)))
|
||||||
@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<M3UChannel> ParseString(string text, string channelIdPrefix, string tunerHostId)
|
public List<ChannelInfo> ParseString(string text, string channelIdPrefix, string tunerHostId)
|
||||||
{
|
{
|
||||||
// Read the file and display it line by line.
|
// Read the file and display it line by line.
|
||||||
using (var reader = new StringReader(text))
|
using (var reader = new StringReader(text))
|
||||||
@ -66,9 +66,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
}
|
}
|
||||||
|
|
||||||
const string ExtInfPrefix = "#EXTINF:";
|
const string ExtInfPrefix = "#EXTINF:";
|
||||||
private List<M3UChannel> GetChannels(TextReader reader, string channelIdPrefix, string tunerHostId)
|
private List<ChannelInfo> GetChannels(TextReader reader, string channelIdPrefix, string tunerHostId)
|
||||||
{
|
{
|
||||||
var channels = new List<M3UChannel>();
|
var channels = new List<ChannelInfo>();
|
||||||
string line;
|
string line;
|
||||||
string extInf = "";
|
string extInf = "";
|
||||||
|
|
||||||
@ -111,9 +111,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
return channels;
|
return channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private M3UChannel GetChannelnfo(string extInf, string tunerHostId, string mediaUrl)
|
private ChannelInfo GetChannelnfo(string extInf, string tunerHostId, string mediaUrl)
|
||||||
{
|
{
|
||||||
var channel = new M3UChannel();
|
var channel = new ChannelInfo();
|
||||||
channel.TunerHostId = tunerHostId;
|
channel.TunerHostId = tunerHostId;
|
||||||
|
|
||||||
extInf = extInf.Trim();
|
extInf = extInf.Trim();
|
||||||
@ -335,10 +335,4 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class M3UChannel : ChannelInfo
|
|
||||||
{
|
|
||||||
public string Path { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -24,8 +24,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
|
|
||||||
public async Task CopyUntilCancelled(Stream source, Action onStarted, CancellationToken cancellationToken)
|
public async Task CopyUntilCancelled(Stream source, Action onStarted, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
byte[] buffer = new byte[BufferSize];
|
|
||||||
|
|
||||||
if (source == null)
|
if (source == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("source");
|
throw new ArgumentNullException("source");
|
||||||
@ -35,25 +33,15 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
byte[] buffer = new byte[BufferSize];
|
||||||
|
|
||||||
var bytesRead = source.Read(buffer, 0, buffer.Length);
|
var bytesRead = source.Read(buffer, 0, buffer.Length);
|
||||||
|
|
||||||
if (bytesRead > 0)
|
if (bytesRead > 0)
|
||||||
{
|
{
|
||||||
var allStreams = _outputStreams.ToList();
|
foreach (var stream in _outputStreams)
|
||||||
|
|
||||||
//if (allStreams.Count == 1)
|
|
||||||
//{
|
|
||||||
// allStreams[0].Value.Write(buffer, 0, bytesRead);
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
{
|
{
|
||||||
byte[] copy = new byte[bytesRead];
|
stream.Value.Queue(buffer, 0, bytesRead);
|
||||||
Buffer.BlockCopy(buffer, 0, copy, 0, bytesRead);
|
|
||||||
|
|
||||||
foreach (var stream in allStreams)
|
|
||||||
{
|
|
||||||
stream.Value.Queue(copy, 0, copy.Length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onStarted != null)
|
if (onStarted != null)
|
||||||
@ -73,27 +61,21 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
|
|
||||||
public Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
|
public Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var result = new QueueStream(stream, _logger)
|
var queueStream = new QueueStream(stream, _logger);
|
||||||
|
|
||||||
|
_outputStreams.TryAdd(queueStream.Id, queueStream);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
OnFinished = OnFinished
|
queueStream.Start(cancellationToken);
|
||||||
};
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_outputStreams.TryRemove(queueStream.Id, out queueStream);
|
||||||
|
GC.Collect();
|
||||||
|
}
|
||||||
|
|
||||||
_outputStreams.TryAdd(result.Id, result);
|
return Task.FromResult(true);
|
||||||
|
|
||||||
result.Start(cancellationToken);
|
|
||||||
|
|
||||||
return result.TaskCompletion.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveOutputStream(QueueStream stream)
|
|
||||||
{
|
|
||||||
QueueStream removed;
|
|
||||||
_outputStreams.TryRemove(stream.Id, out removed);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFinished(QueueStream queueStream)
|
|
||||||
{
|
|
||||||
RemoveOutputStream(queueStream);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
public class QueueStream
|
public class QueueStream
|
||||||
{
|
{
|
||||||
private readonly Stream _outputStream;
|
private readonly Stream _outputStream;
|
||||||
private readonly ConcurrentQueue<Tuple<byte[], int, int>> _queue = new ConcurrentQueue<Tuple<byte[], int, int>>();
|
private readonly BlockingCollection<Tuple<byte[], int, int>> _queue = new BlockingCollection<Tuple<byte[], int, int>>();
|
||||||
public TaskCompletionSource<bool> TaskCompletion { get; private set; }
|
|
||||||
|
|
||||||
public Action<QueueStream> OnFinished { get; set; }
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
public Guid Id = Guid.NewGuid();
|
public Guid Id = Guid.NewGuid();
|
||||||
|
|
||||||
@ -24,94 +22,24 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
{
|
{
|
||||||
_outputStream = outputStream;
|
_outputStream = outputStream;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
TaskCompletion = new TaskCompletionSource<bool>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Queue(byte[] bytes, int offset, int count)
|
public void Queue(byte[] bytes, int offset, int count)
|
||||||
{
|
{
|
||||||
_queue.Enqueue(new Tuple<byte[], int, int>(bytes, offset, count));
|
_queue.Add(new Tuple<byte[], int, int>(bytes, offset, count));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start(CancellationToken cancellationToken)
|
public void Start(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Task.Run(() => StartInternal(cancellationToken));
|
while (true)
|
||||||
}
|
|
||||||
|
|
||||||
private Tuple<byte[], int, int> Dequeue()
|
|
||||||
{
|
|
||||||
Tuple<byte[], int, int> result;
|
|
||||||
if (_queue.TryDequeue(out result))
|
|
||||||
{
|
{
|
||||||
return result;
|
foreach (var result in _queue.GetConsumingEnumerable())
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnClosed()
|
|
||||||
{
|
|
||||||
GC.Collect();
|
|
||||||
if (OnFinished != null)
|
|
||||||
{
|
|
||||||
OnFinished(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(byte[] bytes, int offset, int count)
|
|
||||||
{
|
|
||||||
//return _outputStream.WriteAsync(bytes, offset, count, cancellationToken);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_outputStream.Write(bytes, offset, count);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
_logger.Debug("QueueStream cancelled");
|
|
||||||
TaskCompletion.TrySetCanceled();
|
|
||||||
OnClosed();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Error in QueueStream", ex);
|
|
||||||
TaskCompletion.TrySetException(ex);
|
|
||||||
OnClosed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task StartInternal(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var result = Dequeue();
|
_outputStream.Write(result.Item1, result.Item2, result.Item3);
|
||||||
if (result != null)
|
|
||||||
{
|
|
||||||
_outputStream.Write(result.Item1, result.Item2, result.Item3);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await Task.Delay(50, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
_logger.Debug("QueueStream cancelled");
|
|
||||||
TaskCompletion.TrySetCanceled();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Error in QueueStream", ex);
|
|
||||||
TaskCompletion.TrySetException(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
OnClosed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,179 +0,0 @@
|
|||||||
{
|
|
||||||
"AppDeviceValues": "App: {0}, Device: {1}",
|
|
||||||
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
|
||||||
"FolderTypeMixed": "Mixed content",
|
|
||||||
"FolderTypeMovies": "Movies",
|
|
||||||
"FolderTypeMusic": "Music",
|
|
||||||
"FolderTypeAdultVideos": "Adult videos",
|
|
||||||
"FolderTypePhotos": "Photos",
|
|
||||||
"FolderTypeMusicVideos": "Music videos",
|
|
||||||
"FolderTypeHomeVideos": "Home videos",
|
|
||||||
"FolderTypeGames": "Games",
|
|
||||||
"FolderTypeBooks": "Books",
|
|
||||||
"FolderTypeTvShows": "TV",
|
|
||||||
"FolderTypeInherit": "Inherit",
|
|
||||||
"HeaderCastCrew": "Cast & Crew",
|
|
||||||
"HeaderPeople": "People",
|
|
||||||
"ValueSpecialEpisodeName": "Special - {0}",
|
|
||||||
"LabelChapterName": "Chapter {0}",
|
|
||||||
"NameSeasonNumber": "Season {0}",
|
|
||||||
"LabelExit": "Exit",
|
|
||||||
"LabelVisitCommunity": "Visit Community",
|
|
||||||
"LabelGithub": "Github",
|
|
||||||
"LabelApiDocumentation": "Api Documentation",
|
|
||||||
"LabelDeveloperResources": "Developer Resources",
|
|
||||||
"LabelBrowseLibrary": "Browse Library",
|
|
||||||
"LabelConfigureServer": "Configure Emby",
|
|
||||||
"LabelRestartServer": "Restart Server",
|
|
||||||
"CategorySync": "Sync",
|
|
||||||
"CategoryUser": "User",
|
|
||||||
"CategorySystem": "System",
|
|
||||||
"CategoryApplication": "Application",
|
|
||||||
"CategoryPlugin": "Plugin",
|
|
||||||
"NotificationOptionPluginError": "Plugin failure",
|
|
||||||
"NotificationOptionApplicationUpdateAvailable": "Application update available",
|
|
||||||
"NotificationOptionApplicationUpdateInstalled": "Application update installed",
|
|
||||||
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
|
|
||||||
"NotificationOptionPluginInstalled": "Plugin installed",
|
|
||||||
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
|
|
||||||
"NotificationOptionVideoPlayback": "Video playback started",
|
|
||||||
"NotificationOptionAudioPlayback": "Audio playback started",
|
|
||||||
"NotificationOptionGamePlayback": "Game playback started",
|
|
||||||
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
|
|
||||||
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
|
|
||||||
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
|
|
||||||
"NotificationOptionTaskFailed": "Scheduled task failure",
|
|
||||||
"NotificationOptionInstallationFailed": "Installation failure",
|
|
||||||
"NotificationOptionNewLibraryContent": "New content added",
|
|
||||||
"NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
|
|
||||||
"NotificationOptionCameraImageUploaded": "Camera image uploaded",
|
|
||||||
"NotificationOptionUserLockedOut": "User locked out",
|
|
||||||
"NotificationOptionServerRestartRequired": "Server restart required",
|
|
||||||
"ViewTypePlaylists": "Playlists",
|
|
||||||
"ViewTypeMovies": "Movies",
|
|
||||||
"ViewTypeTvShows": "TV",
|
|
||||||
"ViewTypeGames": "Games",
|
|
||||||
"ViewTypeMusic": "Music",
|
|
||||||
"ViewTypeMusicGenres": "Genres",
|
|
||||||
"ViewTypeMusicArtists": "Artists",
|
|
||||||
"ViewTypeBoxSets": "Collections",
|
|
||||||
"ViewTypeChannels": "Channels",
|
|
||||||
"ViewTypeLiveTV": "Live TV",
|
|
||||||
"ViewTypeLiveTvNowPlaying": "Now Airing",
|
|
||||||
"ViewTypeLatestGames": "Latest Games",
|
|
||||||
"ViewTypeRecentlyPlayedGames": "Recently Played",
|
|
||||||
"ViewTypeGameFavorites": "Favorites",
|
|
||||||
"ViewTypeGameSystems": "Game Systems",
|
|
||||||
"ViewTypeGameGenres": "Genres",
|
|
||||||
"ViewTypeTvResume": "Resume",
|
|
||||||
"ViewTypeTvNextUp": "Next Up",
|
|
||||||
"ViewTypeTvLatest": "Latest",
|
|
||||||
"ViewTypeTvShowSeries": "Series",
|
|
||||||
"ViewTypeTvGenres": "Genres",
|
|
||||||
"ViewTypeTvFavoriteSeries": "Favorite Series",
|
|
||||||
"ViewTypeTvFavoriteEpisodes": "Favorite Episodes",
|
|
||||||
"ViewTypeMovieResume": "Resume",
|
|
||||||
"ViewTypeMovieLatest": "Latest",
|
|
||||||
"ViewTypeMovieMovies": "Movies",
|
|
||||||
"ViewTypeMovieCollections": "Collections",
|
|
||||||
"ViewTypeMovieFavorites": "Favorites",
|
|
||||||
"ViewTypeMovieGenres": "Genres",
|
|
||||||
"ViewTypeMusicLatest": "Latest",
|
|
||||||
"ViewTypeMusicPlaylists": "Playlists",
|
|
||||||
"ViewTypeMusicAlbums": "Albums",
|
|
||||||
"ViewTypeMusicAlbumArtists": "Album Artists",
|
|
||||||
"HeaderOtherDisplaySettings": "Display Settings",
|
|
||||||
"ViewTypeMusicSongs": "Songs",
|
|
||||||
"ViewTypeMusicFavorites": "Favorites",
|
|
||||||
"ViewTypeMusicFavoriteAlbums": "Favorite Albums",
|
|
||||||
"ViewTypeMusicFavoriteArtists": "Favorite Artists",
|
|
||||||
"ViewTypeMusicFavoriteSongs": "Favorite Songs",
|
|
||||||
"ViewTypeFolders": "Folders",
|
|
||||||
"ViewTypeLiveTvRecordingGroups": "Recordings",
|
|
||||||
"ViewTypeLiveTvChannels": "Channels",
|
|
||||||
"ScheduledTaskFailedWithName": "{0} failed",
|
|
||||||
"LabelRunningTimeValue": "Running time: {0}",
|
|
||||||
"ScheduledTaskStartedWithName": "{0} started",
|
|
||||||
"VersionNumber": "Version {0}",
|
|
||||||
"PluginInstalledWithName": "{0} was installed",
|
|
||||||
"PluginUpdatedWithName": "{0} was updated",
|
|
||||||
"PluginUninstalledWithName": "{0} was uninstalled",
|
|
||||||
"ItemAddedWithName": "{0} was added to the library",
|
|
||||||
"ItemRemovedWithName": "{0} was removed from the library",
|
|
||||||
"LabelIpAddressValue": "Ip address: {0}",
|
|
||||||
"DeviceOnlineWithName": "{0} is connected",
|
|
||||||
"UserOnlineFromDevice": "{0} is online from {1}",
|
|
||||||
"ProviderValue": "Provider: {0}",
|
|
||||||
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
|
|
||||||
"UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
|
|
||||||
"UserCreatedWithName": "User {0} has been created",
|
|
||||||
"UserPasswordChangedWithName": "Password has been changed for user {0}",
|
|
||||||
"UserDeletedWithName": "User {0} has been deleted",
|
|
||||||
"MessageServerConfigurationUpdated": "Server configuration has been updated",
|
|
||||||
"MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
|
|
||||||
"MessageApplicationUpdated": "Emby Server has been updated",
|
|
||||||
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
|
|
||||||
"AuthenticationSucceededWithUserName": "{0} successfully authenticated",
|
|
||||||
"DeviceOfflineWithName": "{0} has disconnected",
|
|
||||||
"UserLockedOutWithName": "User {0} has been locked out",
|
|
||||||
"UserOfflineFromDevice": "{0} has disconnected from {1}",
|
|
||||||
"UserStartedPlayingItemWithValues": "{0} has started playing {1}",
|
|
||||||
"UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
|
|
||||||
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
|
|
||||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
|
||||||
"HeaderUnidentified": "Unidentified",
|
|
||||||
"HeaderImagePrimary": "Primary",
|
|
||||||
"HeaderImageBackdrop": "Backdrop",
|
|
||||||
"HeaderImageLogo": "Logo",
|
|
||||||
"HeaderUserPrimaryImage": "User Image",
|
|
||||||
"HeaderOverview": "Overview",
|
|
||||||
"HeaderShortOverview": "Short Overview",
|
|
||||||
"HeaderType": "Type",
|
|
||||||
"HeaderSeverity": "Severity",
|
|
||||||
"HeaderUser": "User",
|
|
||||||
"HeaderName": "Name",
|
|
||||||
"HeaderDate": "Date",
|
|
||||||
"HeaderPremiereDate": "Premiere Date",
|
|
||||||
"HeaderDateAdded": "Date Added",
|
|
||||||
"HeaderReleaseDate": "Release date",
|
|
||||||
"HeaderRuntime": "Runtime",
|
|
||||||
"HeaderPlayCount": "Play Count",
|
|
||||||
"HeaderSeason": "Season",
|
|
||||||
"HeaderSeasonNumber": "Season number",
|
|
||||||
"HeaderSeries": "Series:",
|
|
||||||
"HeaderNetwork": "Network",
|
|
||||||
"HeaderYear": "Year:",
|
|
||||||
"HeaderYears": "Years:",
|
|
||||||
"HeaderParentalRating": "Parental Rating",
|
|
||||||
"HeaderCommunityRating": "Community rating",
|
|
||||||
"HeaderTrailers": "Trailers",
|
|
||||||
"HeaderSpecials": "Specials",
|
|
||||||
"HeaderGameSystems": "Game Systems",
|
|
||||||
"HeaderPlayers": "Players:",
|
|
||||||
"HeaderAlbumArtists": "Album Artists",
|
|
||||||
"HeaderAlbums": "Albums",
|
|
||||||
"HeaderDisc": "Disc",
|
|
||||||
"HeaderTrack": "Track",
|
|
||||||
"HeaderAudio": "Audio",
|
|
||||||
"HeaderVideo": "Video",
|
|
||||||
"HeaderEmbeddedImage": "Embedded image",
|
|
||||||
"HeaderResolution": "Resolution",
|
|
||||||
"HeaderSubtitles": "Subtitles",
|
|
||||||
"HeaderGenres": "Genres",
|
|
||||||
"HeaderCountries": "Countries",
|
|
||||||
"HeaderStatus": "Status",
|
|
||||||
"HeaderTracks": "Tracks",
|
|
||||||
"HeaderMusicArtist": "Music artist",
|
|
||||||
"HeaderLocked": "Locked",
|
|
||||||
"HeaderStudios": "Studios",
|
|
||||||
"HeaderActor": "Actors",
|
|
||||||
"HeaderComposer": "Composers",
|
|
||||||
"HeaderDirector": "Directors",
|
|
||||||
"HeaderGuestStar": "Guest star",
|
|
||||||
"HeaderProducer": "Producers",
|
|
||||||
"HeaderWriter": "Writers",
|
|
||||||
"HeaderParentalRatings": "Parental Ratings",
|
|
||||||
"HeaderCommunityRatings": "Community ratings",
|
|
||||||
"StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.",
|
|
||||||
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete."
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.",
|
|
||||||
"AppDeviceValues": "App: {0}, Device: {1}",
|
"AppDeviceValues": "App: {0}, Device: {1}",
|
||||||
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
||||||
"FolderTypeMixed": "Mixed content",
|
"FolderTypeMixed": "Mixed content",
|
||||||
@ -13,15 +12,12 @@
|
|||||||
"FolderTypeBooks": "Books",
|
"FolderTypeBooks": "Books",
|
||||||
"FolderTypeTvShows": "TV",
|
"FolderTypeTvShows": "TV",
|
||||||
"FolderTypeInherit": "Inherit",
|
"FolderTypeInherit": "Inherit",
|
||||||
"HeaderCastCrew": "Cast & Crew",
|
|
||||||
"HeaderPeople": "People",
|
|
||||||
"ValueSpecialEpisodeName": "Special - {0}",
|
"ValueSpecialEpisodeName": "Special - {0}",
|
||||||
"LabelChapterName": "Chapter {0}",
|
"LabelChapterName": "Chapter {0}",
|
||||||
"NameSeasonUnknown": "Season Unknown",
|
"NameSeasonUnknown": "Season Unknown",
|
||||||
"NameSeasonNumber": "Season {0}",
|
"NameSeasonNumber": "Season {0}",
|
||||||
"LabelExit": "Exit",
|
"LabelExit": "Exit",
|
||||||
"LabelVisitCommunity": "Visit Community",
|
"LabelVisitCommunity": "Visit Community",
|
||||||
"LabelGithub": "Github",
|
|
||||||
"LabelApiDocumentation": "Api Documentation",
|
"LabelApiDocumentation": "Api Documentation",
|
||||||
"LabelDeveloperResources": "Developer Resources",
|
"LabelDeveloperResources": "Developer Resources",
|
||||||
"LabelBrowseLibrary": "Browse Library",
|
"LabelBrowseLibrary": "Browse Library",
|
||||||
@ -164,15 +160,5 @@
|
|||||||
"HeaderStatus": "Status",
|
"HeaderStatus": "Status",
|
||||||
"HeaderTracks": "Tracks",
|
"HeaderTracks": "Tracks",
|
||||||
"HeaderMusicArtist": "Music artist",
|
"HeaderMusicArtist": "Music artist",
|
||||||
"HeaderLocked": "Locked",
|
|
||||||
"HeaderStudios": "Studios",
|
|
||||||
"HeaderActor": "Actors",
|
|
||||||
"HeaderComposer": "Composers",
|
|
||||||
"HeaderDirector": "Directors",
|
|
||||||
"HeaderGuestStar": "Guest star",
|
|
||||||
"HeaderProducer": "Producers",
|
|
||||||
"HeaderWriter": "Writers",
|
|
||||||
"HeaderParentalRatings": "Parental Ratings",
|
|
||||||
"HeaderCommunityRatings": "Community ratings",
|
|
||||||
"StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
|
"StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
|
||||||
}
|
}
|
@ -132,7 +132,7 @@ namespace Emby.Server.Implementations.Localization
|
|||||||
/// Gets the cultures.
|
/// Gets the cultures.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IEnumerable{CultureDto}.</returns>
|
/// <returns>IEnumerable{CultureDto}.</returns>
|
||||||
public List<CultureDto> GetCultures()
|
public CultureDto[] GetCultures()
|
||||||
{
|
{
|
||||||
var type = GetType();
|
var type = GetType();
|
||||||
var path = type.Namespace + ".iso6392.txt";
|
var path = type.Namespace + ".iso6392.txt";
|
||||||
@ -169,21 +169,21 @@ namespace Emby.Server.Implementations.Localization
|
|||||||
return list.Where(i => !string.IsNullOrWhiteSpace(i.Name) &&
|
return list.Where(i => !string.IsNullOrWhiteSpace(i.Name) &&
|
||||||
!string.IsNullOrWhiteSpace(i.DisplayName) &&
|
!string.IsNullOrWhiteSpace(i.DisplayName) &&
|
||||||
!string.IsNullOrWhiteSpace(i.ThreeLetterISOLanguageName) &&
|
!string.IsNullOrWhiteSpace(i.ThreeLetterISOLanguageName) &&
|
||||||
!string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)).ToList();
|
!string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the countries.
|
/// Gets the countries.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IEnumerable{CountryInfo}.</returns>
|
/// <returns>IEnumerable{CountryInfo}.</returns>
|
||||||
public List<CountryInfo> GetCountries()
|
public CountryInfo[] GetCountries()
|
||||||
{
|
{
|
||||||
var type = GetType();
|
var type = GetType();
|
||||||
var path = type.Namespace + ".countries.json";
|
var path = type.Namespace + ".countries.json";
|
||||||
|
|
||||||
using (var stream = _assemblyInfo.GetManifestResourceStream(type, path))
|
using (var stream = _assemblyInfo.GetManifestResourceStream(type, path))
|
||||||
{
|
{
|
||||||
return _jsonSerializer.DeserializeFromStream<List<CountryInfo>>(stream);
|
return _jsonSerializer.DeserializeFromStream<CountryInfo[]>(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,9 +191,9 @@ namespace Emby.Server.Implementations.Localization
|
|||||||
/// Gets the parental ratings.
|
/// Gets the parental ratings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IEnumerable{ParentalRating}.</returns>
|
/// <returns>IEnumerable{ParentalRating}.</returns>
|
||||||
public IEnumerable<ParentalRating> GetParentalRatings()
|
public ParentalRating[] GetParentalRatings()
|
||||||
{
|
{
|
||||||
return GetParentalRatingsDictionary().Values.ToList();
|
return GetParentalRatingsDictionary().Values.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -335,7 +335,7 @@ namespace Emby.Server.Implementations.Localization
|
|||||||
const string prefix = "Core";
|
const string prefix = "Core";
|
||||||
var key = prefix + culture;
|
var key = prefix + culture;
|
||||||
|
|
||||||
return _dictionaries.GetOrAdd(key, k => GetDictionary(prefix, culture, "core.json"));
|
return _dictionaries.GetOrAdd(key, k => GetDictionary(prefix, culture, "en-US.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<string, string> GetDictionary(string prefix, string culture, string baseFilename)
|
private Dictionary<string, string> GetDictionary(string prefix, string culture, string baseFilename)
|
||||||
@ -382,9 +382,9 @@ namespace Emby.Server.Implementations.Localization
|
|||||||
return culture + ".json";
|
return culture + ".json";
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<LocalizatonOption> GetLocalizationOptions()
|
public LocalizatonOption[] GetLocalizationOptions()
|
||||||
{
|
{
|
||||||
return new List<LocalizatonOption>
|
return new LocalizatonOption[]
|
||||||
{
|
{
|
||||||
new LocalizatonOption{ Name="Arabic", Value="ar"},
|
new LocalizatonOption{ Name="Arabic", Value="ar"},
|
||||||
new LocalizatonOption{ Name="Bulgarian (Bulgaria)", Value="bg-BG"},
|
new LocalizatonOption{ Name="Bulgarian (Bulgaria)", Value="bg-BG"},
|
||||||
@ -421,7 +421,7 @@ namespace Emby.Server.Implementations.Localization
|
|||||||
new LocalizatonOption{ Name="Ukrainian", Value="uk"},
|
new LocalizatonOption{ Name="Ukrainian", Value="uk"},
|
||||||
new LocalizatonOption{ Name="Vietnamese", Value="vi"}
|
new LocalizatonOption{ Name="Vietnamese", Value="vi"}
|
||||||
|
|
||||||
}.OrderBy(i => i.Name);
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ namespace Emby.Server.Implementations.Logging
|
|||||||
|
|
||||||
public class FileLogger : IDisposable
|
public class FileLogger : IDisposable
|
||||||
{
|
{
|
||||||
private readonly Stream _fileStream;
|
private readonly FileStream _fileStream;
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private readonly CancellationTokenSource _cancellationTokenSource;
|
private readonly CancellationTokenSource _cancellationTokenSource;
|
||||||
@ -122,7 +122,7 @@ namespace Emby.Server.Implementations.Logging
|
|||||||
{
|
{
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||||
|
|
||||||
_fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read);
|
_fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, 32768);
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
_cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
Task.Factory.StartNew(LogInternal, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
Task.Factory.StartNew(LogInternal, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
||||||
@ -134,19 +134,12 @@ namespace Emby.Server.Implementations.Logging
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var any = false;
|
|
||||||
|
|
||||||
foreach (var message in _queue.GetConsumingEnumerable())
|
foreach (var message in _queue.GetConsumingEnumerable())
|
||||||
{
|
{
|
||||||
var bytes = Encoding.UTF8.GetBytes(message + Environment.NewLine);
|
var bytes = Encoding.UTF8.GetBytes(message + Environment.NewLine);
|
||||||
_fileStream.Write(bytes, 0, bytes.Length);
|
_fileStream.Write(bytes, 0, bytes.Length);
|
||||||
|
|
||||||
any = true;
|
_fileStream.Flush(true);
|
||||||
}
|
|
||||||
|
|
||||||
if (any)
|
|
||||||
{
|
|
||||||
_fileStream.Flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@ -75,6 +75,11 @@ namespace Emby.Server.Implementations.MediaEncoder
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!video.IsCompleteMedia)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Can't extract images if there are no video streams
|
// Can't extract images if there are no video streams
|
||||||
return video.DefaultVideoStreamIndex.HasValue;
|
return video.DefaultVideoStreamIndex.HasValue;
|
||||||
}
|
}
|
||||||
@ -129,7 +134,7 @@ namespace Emby.Server.Implementations.MediaEncoder
|
|||||||
|
|
||||||
var protocol = MediaProtocol.File;
|
var protocol = MediaProtocol.File;
|
||||||
|
|
||||||
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, new List<string>());
|
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, new string[] { });
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
@ -174,7 +179,7 @@ namespace Emby.Server.Implementations.MediaEncoder
|
|||||||
|
|
||||||
if (saveChapters && changesMade)
|
if (saveChapters && changesMade)
|
||||||
{
|
{
|
||||||
await _chapterManager.SaveChapters(video.Id.ToString(), chapters).ConfigureAwait(false);
|
_chapterManager.SaveChapters(video.Id.ToString(), chapters);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteDeadImages(currentImages, chapters);
|
DeleteDeadImages(currentImages, chapters);
|
||||||
|
@ -28,21 +28,21 @@ namespace Emby.Server.Implementations.Notifications
|
|||||||
Type = NotificationType.ApplicationUpdateInstalled.ToString(),
|
Type = NotificationType.ApplicationUpdateInstalled.ToString(),
|
||||||
DefaultDescription = "{ReleaseNotes}",
|
DefaultDescription = "{ReleaseNotes}",
|
||||||
DefaultTitle = "A new version of Emby Server has been installed.",
|
DefaultTitle = "A new version of Emby Server has been installed.",
|
||||||
Variables = new List<string>{"Version"}
|
Variables = new string[]{"Version"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.InstallationFailed.ToString(),
|
Type = NotificationType.InstallationFailed.ToString(),
|
||||||
DefaultTitle = "{Name} installation failed.",
|
DefaultTitle = "{Name} installation failed.",
|
||||||
Variables = new List<string>{"Name", "Version"}
|
Variables = new string[]{"Name", "Version"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.PluginInstalled.ToString(),
|
Type = NotificationType.PluginInstalled.ToString(),
|
||||||
DefaultTitle = "{Name} was installed.",
|
DefaultTitle = "{Name} was installed.",
|
||||||
Variables = new List<string>{"Name", "Version"}
|
Variables = new string[]{"Name", "Version"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
@ -50,14 +50,14 @@ namespace Emby.Server.Implementations.Notifications
|
|||||||
Type = NotificationType.PluginError.ToString(),
|
Type = NotificationType.PluginError.ToString(),
|
||||||
DefaultTitle = "{Name} has encountered an error.",
|
DefaultTitle = "{Name} has encountered an error.",
|
||||||
DefaultDescription = "{ErrorMessage}",
|
DefaultDescription = "{ErrorMessage}",
|
||||||
Variables = new List<string>{"Name", "ErrorMessage"}
|
Variables = new string[]{"Name", "ErrorMessage"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.PluginUninstalled.ToString(),
|
Type = NotificationType.PluginUninstalled.ToString(),
|
||||||
DefaultTitle = "{Name} was uninstalled.",
|
DefaultTitle = "{Name} was uninstalled.",
|
||||||
Variables = new List<string>{"Name", "Version"}
|
Variables = new string[]{"Name", "Version"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
@ -65,7 +65,7 @@ namespace Emby.Server.Implementations.Notifications
|
|||||||
Type = NotificationType.PluginUpdateInstalled.ToString(),
|
Type = NotificationType.PluginUpdateInstalled.ToString(),
|
||||||
DefaultTitle = "{Name} was updated.",
|
DefaultTitle = "{Name} was updated.",
|
||||||
DefaultDescription = "{ReleaseNotes}",
|
DefaultDescription = "{ReleaseNotes}",
|
||||||
Variables = new List<string>{"Name", "ReleaseNotes", "Version"}
|
Variables = new string[]{"Name", "ReleaseNotes", "Version"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
@ -79,70 +79,70 @@ namespace Emby.Server.Implementations.Notifications
|
|||||||
Type = NotificationType.TaskFailed.ToString(),
|
Type = NotificationType.TaskFailed.ToString(),
|
||||||
DefaultTitle = "{Name} failed.",
|
DefaultTitle = "{Name} failed.",
|
||||||
DefaultDescription = "{ErrorMessage}",
|
DefaultDescription = "{ErrorMessage}",
|
||||||
Variables = new List<string>{"Name", "ErrorMessage"}
|
Variables = new string[]{"Name", "ErrorMessage"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.NewLibraryContent.ToString(),
|
Type = NotificationType.NewLibraryContent.ToString(),
|
||||||
DefaultTitle = "{Name} has been added to your media library.",
|
DefaultTitle = "{Name} has been added to your media library.",
|
||||||
Variables = new List<string>{"Name"}
|
Variables = new string[]{"Name"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.AudioPlayback.ToString(),
|
Type = NotificationType.AudioPlayback.ToString(),
|
||||||
DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.",
|
DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.",
|
||||||
Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
|
Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.GamePlayback.ToString(),
|
Type = NotificationType.GamePlayback.ToString(),
|
||||||
DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.",
|
DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.",
|
||||||
Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
|
Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.VideoPlayback.ToString(),
|
Type = NotificationType.VideoPlayback.ToString(),
|
||||||
DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.",
|
DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.",
|
||||||
Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
|
Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.AudioPlaybackStopped.ToString(),
|
Type = NotificationType.AudioPlaybackStopped.ToString(),
|
||||||
DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.",
|
DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.",
|
||||||
Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
|
Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.GamePlaybackStopped.ToString(),
|
Type = NotificationType.GamePlaybackStopped.ToString(),
|
||||||
DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.",
|
DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.",
|
||||||
Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
|
Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.VideoPlaybackStopped.ToString(),
|
Type = NotificationType.VideoPlaybackStopped.ToString(),
|
||||||
DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.",
|
DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.",
|
||||||
Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
|
Variables = new string[]{"UserName", "ItemName", "DeviceName", "AppName"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.CameraImageUploaded.ToString(),
|
Type = NotificationType.CameraImageUploaded.ToString(),
|
||||||
DefaultTitle = "A new camera image has been uploaded from {DeviceName}.",
|
DefaultTitle = "A new camera image has been uploaded from {DeviceName}.",
|
||||||
Variables = new List<string>{"DeviceName"}
|
Variables = new string[]{"DeviceName"}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NotificationTypeInfo
|
new NotificationTypeInfo
|
||||||
{
|
{
|
||||||
Type = NotificationType.UserLockedOut.ToString(),
|
Type = NotificationType.UserLockedOut.ToString(),
|
||||||
DefaultTitle = "{UserName} has been locked out.",
|
DefaultTitle = "{UserName} has been locked out.",
|
||||||
Variables = new List<string>{"UserName"}
|
Variables = new string[]{"UserName"}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ namespace Emby.Server.Implementations.Notifications
|
|||||||
_typeFactories = notificationTypeFactories.ToArray();
|
_typeFactories = notificationTypeFactories.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<NotificationTypeInfo> GetNotificationTypes()
|
public List<NotificationTypeInfo> GetNotificationTypes()
|
||||||
{
|
{
|
||||||
var list = _typeFactories.Select(i =>
|
var list = _typeFactories.Select(i =>
|
||||||
{
|
{
|
||||||
|
@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.Notifications
|
|||||||
{
|
{
|
||||||
var artists = hasArtist.AllArtists;
|
var artists = hasArtist.AllArtists;
|
||||||
|
|
||||||
if (artists.Count > 0)
|
if (artists.Length > 0)
|
||||||
{
|
{
|
||||||
name = hasArtist.AllArtists[0] + " - " + name;
|
name = hasArtist.AllArtists[0] + " - " + name;
|
||||||
}
|
}
|
||||||
@ -440,7 +440,7 @@ namespace Emby.Server.Implementations.Notifications
|
|||||||
name = item.SeriesName + " - " + name;
|
name = item.SeriesName + " - " + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.Artists != null && item.Artists.Count > 0)
|
if (item.Artists != null && item.Artists.Length > 0)
|
||||||
{
|
{
|
||||||
name = item.Artists[0] + " - " + name;
|
name = item.Artists[0] + " - " + name;
|
||||||
}
|
}
|
||||||
|
@ -128,12 +128,12 @@ namespace Emby.Server.Implementations.Playlists
|
|||||||
|
|
||||||
playlist.SetMediaType(options.MediaType);
|
playlist.SetMediaType(options.MediaType);
|
||||||
|
|
||||||
await parentFolder.AddChild(playlist, CancellationToken.None).ConfigureAwait(false);
|
parentFolder.AddChild(playlist, CancellationToken.None);
|
||||||
|
|
||||||
await playlist.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) { ForceSave = true }, CancellationToken.None)
|
await playlist.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) { ForceSave = true }, CancellationToken.None)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (options.ItemIdList.Count > 0)
|
if (options.ItemIdList.Length > 0)
|
||||||
{
|
{
|
||||||
await AddToPlaylistInternal(playlist.Id.ToString("N"), options.ItemIdList, user, new DtoOptions(false)
|
await AddToPlaylistInternal(playlist.Id.ToString("N"), options.ItemIdList, user, new DtoOptions(false)
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,6 @@ using System.Globalization;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Emby.Server.Implementations.Data;
|
using Emby.Server.Implementations.Data;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Security;
|
using MediaBrowser.Controller.Security;
|
||||||
@ -51,14 +50,14 @@ namespace Emby.Server.Implementations.Security
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Create(AuthenticationInfo info, CancellationToken cancellationToken)
|
public void Create(AuthenticationInfo info, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
info.Id = Guid.NewGuid().ToString("N");
|
info.Id = Guid.NewGuid().ToString("N");
|
||||||
|
|
||||||
return Update(info, cancellationToken);
|
Update(info, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Update(AuthenticationInfo info, CancellationToken cancellationToken)
|
public void Update(AuthenticationInfo info, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (info == null)
|
if (info == null)
|
||||||
{
|
{
|
||||||
|
@ -29,13 +29,6 @@ namespace Emby.Server.Implementations.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type[] GetGenericArguments(Type type)
|
|
||||||
{
|
|
||||||
return type.GetTypeInfo().IsGenericTypeDefinition
|
|
||||||
? type.GetTypeInfo().GenericTypeParameters
|
|
||||||
: type.GetTypeInfo().GenericTypeArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RegisterService(HttpListenerHost appHost, Type serviceType)
|
public void RegisterService(HttpListenerHost appHost, Type serviceType)
|
||||||
{
|
{
|
||||||
var processedReqs = new HashSet<Type>();
|
var processedReqs = new HashSet<Type>();
|
||||||
@ -50,38 +43,19 @@ namespace Emby.Server.Implementations.Services
|
|||||||
|
|
||||||
ServiceExecGeneral.CreateServiceRunnersFor(requestType, actions);
|
ServiceExecGeneral.CreateServiceRunnersFor(requestType, actions);
|
||||||
|
|
||||||
var returnMarker = GetTypeWithGenericTypeDefinitionOf(requestType, typeof(IReturn<>));
|
//var returnMarker = GetTypeWithGenericTypeDefinitionOf(requestType, typeof(IReturn<>));
|
||||||
var responseType = returnMarker != null ?
|
//var responseType = returnMarker != null ?
|
||||||
GetGenericArguments(returnMarker)[0]
|
// GetGenericArguments(returnMarker)[0]
|
||||||
: mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void) ?
|
// : mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void) ?
|
||||||
mi.ReturnType
|
// mi.ReturnType
|
||||||
: Type.GetType(requestType.FullName + "Response");
|
// : Type.GetType(requestType.FullName + "Response");
|
||||||
|
|
||||||
RegisterRestPaths(appHost, requestType);
|
RegisterRestPaths(appHost, requestType);
|
||||||
|
|
||||||
appHost.AddServiceInfo(serviceType, requestType, responseType);
|
appHost.AddServiceInfo(serviceType, requestType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type GetTypeWithGenericTypeDefinitionOf(Type type, Type genericTypeDefinition)
|
|
||||||
{
|
|
||||||
foreach (var t in type.GetTypeInfo().ImplementedInterfaces)
|
|
||||||
{
|
|
||||||
if (t.GetTypeInfo().IsGenericType && t.GetGenericTypeDefinition() == genericTypeDefinition)
|
|
||||||
{
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var genericType = FirstGenericType(type);
|
|
||||||
if (genericType != null && genericType.GetGenericTypeDefinition() == genericTypeDefinition)
|
|
||||||
{
|
|
||||||
return genericType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Type FirstGenericType(Type type)
|
public static Type FirstGenericType(Type type)
|
||||||
{
|
{
|
||||||
while (type != null)
|
while (type != null)
|
||||||
|
@ -215,13 +215,13 @@ namespace Emby.Server.Implementations.Services
|
|||||||
if (name == null) continue; //thank you ASP.NET
|
if (name == null) continue; //thank you ASP.NET
|
||||||
|
|
||||||
var values = request.QueryString.GetValues(name);
|
var values = request.QueryString.GetValues(name);
|
||||||
if (values.Length == 1)
|
if (values.Count == 1)
|
||||||
{
|
{
|
||||||
map[name] = values[0];
|
map[name] = values[0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (var i = 0; i < values.Length; i++)
|
for (var i = 0; i < values.Count; i++)
|
||||||
{
|
{
|
||||||
map[name + (i == 0 ? "" : "#" + i)] = values[i];
|
map[name + (i == 0 ? "" : "#" + i)] = values[i];
|
||||||
}
|
}
|
||||||
@ -235,13 +235,13 @@ namespace Emby.Server.Implementations.Services
|
|||||||
if (name == null) continue; //thank you ASP.NET
|
if (name == null) continue; //thank you ASP.NET
|
||||||
|
|
||||||
var values = request.FormData.GetValues(name);
|
var values = request.FormData.GetValues(name);
|
||||||
if (values.Length == 1)
|
if (values.Count == 1)
|
||||||
{
|
{
|
||||||
map[name] = values[0];
|
map[name] = values[0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (var i = 0; i < values.Length; i++)
|
for (var i = 0; i < values.Count; i++)
|
||||||
{
|
{
|
||||||
map[name + (i == 0 ? "" : "#" + i)] = values[i];
|
map[name + (i == 0 ? "" : "#" + i)] = values[i];
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,8 @@ using MediaBrowser.Controller.Devices;
|
|||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
|
||||||
using MediaBrowser.Controller.Persistence;
|
|
||||||
using MediaBrowser.Controller.Security;
|
using MediaBrowser.Controller.Security;
|
||||||
using MediaBrowser.Controller.Session;
|
using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Devices;
|
using MediaBrowser.Model.Devices;
|
||||||
@ -253,7 +250,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _userManager.UpdateUser(user).ConfigureAwait(false);
|
_userManager.UpdateUser(user);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -468,7 +465,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
|
|
||||||
if (!userId.HasValue)
|
if (!userId.HasValue)
|
||||||
{
|
{
|
||||||
sessionInfo.AdditionalUsers.Clear();
|
sessionInfo.AdditionalUsers = new SessionUserInfo[] { };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sessionInfo.SessionController == null)
|
if (sessionInfo.SessionController == null)
|
||||||
@ -622,7 +619,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
{
|
{
|
||||||
foreach (var user in users)
|
foreach (var user in users)
|
||||||
{
|
{
|
||||||
await OnPlaybackStart(user.Id, libraryItem).ConfigureAwait(false);
|
OnPlaybackStart(user.Id, libraryItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,8 +647,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId">The user identifier.</param>
|
/// <param name="userId">The user identifier.</param>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <returns>Task.</returns>
|
private void OnPlaybackStart(Guid userId, IHasUserData item)
|
||||||
private async Task OnPlaybackStart(Guid userId, IHasUserData item)
|
|
||||||
{
|
{
|
||||||
var data = _userDataManager.GetUserData(userId, item);
|
var data = _userDataManager.GetUserData(userId, item);
|
||||||
|
|
||||||
@ -670,7 +666,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
data.Played = false;
|
data.Played = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None).ConfigureAwait(false);
|
_userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task OnPlaybackProgress(PlaybackProgressInfo info)
|
public Task OnPlaybackProgress(PlaybackProgressInfo info)
|
||||||
@ -702,7 +698,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
{
|
{
|
||||||
foreach (var user in users)
|
foreach (var user in users)
|
||||||
{
|
{
|
||||||
await OnPlaybackProgress(user, libraryItem, info).ConfigureAwait(false);
|
OnPlaybackProgress(user, libraryItem, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,7 +726,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
StartIdleCheckTimer();
|
StartIdleCheckTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnPlaybackProgress(User user, BaseItem item, PlaybackProgressInfo info)
|
private void OnPlaybackProgress(User user, BaseItem item, PlaybackProgressInfo info)
|
||||||
{
|
{
|
||||||
var data = _userDataManager.GetUserData(user.Id, item);
|
var data = _userDataManager.GetUserData(user.Id, item);
|
||||||
|
|
||||||
@ -742,7 +738,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
|
|
||||||
UpdatePlaybackSettings(user, info, data);
|
UpdatePlaybackSettings(user, info, data);
|
||||||
|
|
||||||
await _userDataManager.SaveUserData(user.Id, item, data, UserDataSaveReason.PlaybackProgress, CancellationToken.None).ConfigureAwait(false);
|
_userDataManager.SaveUserData(user.Id, item, data, UserDataSaveReason.PlaybackProgress, CancellationToken.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -842,7 +838,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
{
|
{
|
||||||
foreach (var user in users)
|
foreach (var user in users)
|
||||||
{
|
{
|
||||||
playedToCompletion = await OnPlaybackStopped(user.Id, libraryItem, info.PositionTicks, info.Failed).ConfigureAwait(false);
|
playedToCompletion = OnPlaybackStopped(user.Id, libraryItem, info.PositionTicks, info.Failed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -875,7 +871,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
await SendPlaybackStoppedNotification(session, CancellationToken.None).ConfigureAwait(false);
|
await SendPlaybackStoppedNotification(session, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> OnPlaybackStopped(Guid userId, BaseItem item, long? positionTicks, bool playbackFailed)
|
private bool OnPlaybackStopped(Guid userId, BaseItem item, long? positionTicks, bool playbackFailed)
|
||||||
{
|
{
|
||||||
bool playedToCompletion = false;
|
bool playedToCompletion = false;
|
||||||
|
|
||||||
@ -896,7 +892,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
playedToCompletion = true;
|
playedToCompletion = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackFinished, CancellationToken.None).ConfigureAwait(false);
|
_userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackFinished, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
return playedToCompletion;
|
return playedToCompletion;
|
||||||
@ -1074,7 +1070,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
DtoOptions = new DtoOptions(false)
|
DtoOptions = new DtoOptions(false)
|
||||||
{
|
{
|
||||||
EnableImages = false,
|
EnableImages = false,
|
||||||
Fields = new List<ItemFields>
|
Fields = new ItemFields[]
|
||||||
{
|
{
|
||||||
ItemFields.SortName
|
ItemFields.SortName
|
||||||
}
|
}
|
||||||
@ -1097,7 +1093,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
DtoOptions = new DtoOptions(false)
|
DtoOptions = new DtoOptions(false)
|
||||||
{
|
{
|
||||||
EnableImages = false,
|
EnableImages = false,
|
||||||
Fields = new List<ItemFields>
|
Fields = new ItemFields[]
|
||||||
{
|
{
|
||||||
ItemFields.SortName
|
ItemFields.SortName
|
||||||
}
|
}
|
||||||
@ -1340,11 +1336,15 @@ namespace Emby.Server.Implementations.Session
|
|||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(userId);
|
var user = _userManager.GetUserById(userId);
|
||||||
|
|
||||||
session.AdditionalUsers.Add(new SessionUserInfo
|
var list = session.AdditionalUsers.ToList();
|
||||||
|
|
||||||
|
list.Add(new SessionUserInfo
|
||||||
{
|
{
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
UserName = user.Name
|
UserName = user.Name
|
||||||
});
|
});
|
||||||
|
|
||||||
|
session.AdditionalUsers = list.ToArray(list.Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1368,7 +1368,10 @@ namespace Emby.Server.Implementations.Session
|
|||||||
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
session.AdditionalUsers.Remove(user);
|
var list = session.AdditionalUsers.ToList();
|
||||||
|
list.Remove(user);
|
||||||
|
|
||||||
|
session.AdditionalUsers = list.ToArray(list.Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1425,7 +1428,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
user = result;
|
user = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
var token = await GetAuthorizationToken(user.Id.ToString("N"), request.DeviceId, request.App, request.AppVersion, request.DeviceName).ConfigureAwait(false);
|
var token = GetAuthorizationToken(user.Id.ToString("N"), request.DeviceId, request.App, request.AppVersion, request.DeviceName);
|
||||||
|
|
||||||
EventHelper.FireEventIfNotNull(AuthenticationSucceeded, this, new GenericEventArgs<AuthenticationRequest>(request), _logger);
|
EventHelper.FireEventIfNotNull(AuthenticationSucceeded, this, new GenericEventArgs<AuthenticationRequest>(request), _logger);
|
||||||
|
|
||||||
@ -1447,7 +1450,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task<string> GetAuthorizationToken(string userId, string deviceId, string app, string appVersion, string deviceName)
|
private string GetAuthorizationToken(string userId, string deviceId, string app, string appVersion, string deviceName)
|
||||||
{
|
{
|
||||||
var existing = _authRepo.Get(new AuthenticationInfoQuery
|
var existing = _authRepo.Get(new AuthenticationInfoQuery
|
||||||
{
|
{
|
||||||
@ -1477,12 +1480,12 @@ namespace Emby.Server.Implementations.Session
|
|||||||
};
|
};
|
||||||
|
|
||||||
_logger.Info("Creating new access token for user {0}", userId);
|
_logger.Info("Creating new access token for user {0}", userId);
|
||||||
await _authRepo.Create(newToken, CancellationToken.None).ConfigureAwait(false);
|
_authRepo.Create(newToken, CancellationToken.None);
|
||||||
|
|
||||||
return newToken.AccessToken;
|
return newToken.AccessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Logout(string accessToken)
|
public void Logout(string accessToken)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(accessToken))
|
if (string.IsNullOrWhiteSpace(accessToken))
|
||||||
{
|
{
|
||||||
@ -1502,7 +1505,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
{
|
{
|
||||||
existing.IsActive = false;
|
existing.IsActive = false;
|
||||||
|
|
||||||
await _authRepo.Update(existing, CancellationToken.None).ConfigureAwait(false);
|
_authRepo.Update(existing, CancellationToken.None);
|
||||||
|
|
||||||
var sessions = Sessions
|
var sessions = Sessions
|
||||||
.Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase))
|
.Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase))
|
||||||
@ -1522,7 +1525,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RevokeUserTokens(string userId, string currentAccessToken)
|
public void RevokeUserTokens(string userId, string currentAccessToken)
|
||||||
{
|
{
|
||||||
var existing = _authRepo.Get(new AuthenticationInfoQuery
|
var existing = _authRepo.Get(new AuthenticationInfoQuery
|
||||||
{
|
{
|
||||||
@ -1534,14 +1537,14 @@ namespace Emby.Server.Implementations.Session
|
|||||||
{
|
{
|
||||||
if (!string.Equals(currentAccessToken, info.AccessToken, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(currentAccessToken, info.AccessToken, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
await Logout(info.AccessToken).ConfigureAwait(false);
|
Logout(info.AccessToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task RevokeToken(string token)
|
public void RevokeToken(string token)
|
||||||
{
|
{
|
||||||
return Logout(token);
|
Logout(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1661,35 +1664,39 @@ namespace Emby.Server.Implementations.Session
|
|||||||
AddProgramRecordingInfo = false
|
AddProgramRecordingInfo = false
|
||||||
};
|
};
|
||||||
|
|
||||||
dtoOptions.Fields.Remove(ItemFields.BasicSyncInfo);
|
var fields = dtoOptions.Fields.ToList();
|
||||||
dtoOptions.Fields.Remove(ItemFields.SyncInfo);
|
|
||||||
dtoOptions.Fields.Remove(ItemFields.CanDelete);
|
fields.Remove(ItemFields.BasicSyncInfo);
|
||||||
dtoOptions.Fields.Remove(ItemFields.CanDownload);
|
fields.Remove(ItemFields.SyncInfo);
|
||||||
dtoOptions.Fields.Remove(ItemFields.ChildCount);
|
fields.Remove(ItemFields.CanDelete);
|
||||||
dtoOptions.Fields.Remove(ItemFields.CustomRating);
|
fields.Remove(ItemFields.CanDownload);
|
||||||
dtoOptions.Fields.Remove(ItemFields.DateLastMediaAdded);
|
fields.Remove(ItemFields.ChildCount);
|
||||||
dtoOptions.Fields.Remove(ItemFields.DateLastRefreshed);
|
fields.Remove(ItemFields.CustomRating);
|
||||||
dtoOptions.Fields.Remove(ItemFields.DateLastSaved);
|
fields.Remove(ItemFields.DateLastMediaAdded);
|
||||||
dtoOptions.Fields.Remove(ItemFields.DisplayPreferencesId);
|
fields.Remove(ItemFields.DateLastRefreshed);
|
||||||
dtoOptions.Fields.Remove(ItemFields.Etag);
|
fields.Remove(ItemFields.DateLastSaved);
|
||||||
dtoOptions.Fields.Remove(ItemFields.ExternalEtag);
|
fields.Remove(ItemFields.DisplayPreferencesId);
|
||||||
dtoOptions.Fields.Remove(ItemFields.InheritedParentalRatingValue);
|
fields.Remove(ItemFields.Etag);
|
||||||
dtoOptions.Fields.Remove(ItemFields.ItemCounts);
|
fields.Remove(ItemFields.ExternalEtag);
|
||||||
dtoOptions.Fields.Remove(ItemFields.MediaSourceCount);
|
fields.Remove(ItemFields.InheritedParentalRatingValue);
|
||||||
dtoOptions.Fields.Remove(ItemFields.MediaStreams);
|
fields.Remove(ItemFields.ItemCounts);
|
||||||
dtoOptions.Fields.Remove(ItemFields.MediaSources);
|
fields.Remove(ItemFields.MediaSourceCount);
|
||||||
dtoOptions.Fields.Remove(ItemFields.People);
|
fields.Remove(ItemFields.MediaStreams);
|
||||||
dtoOptions.Fields.Remove(ItemFields.PlayAccess);
|
fields.Remove(ItemFields.MediaSources);
|
||||||
dtoOptions.Fields.Remove(ItemFields.People);
|
fields.Remove(ItemFields.People);
|
||||||
dtoOptions.Fields.Remove(ItemFields.ProductionLocations);
|
fields.Remove(ItemFields.PlayAccess);
|
||||||
dtoOptions.Fields.Remove(ItemFields.RecursiveItemCount);
|
fields.Remove(ItemFields.People);
|
||||||
dtoOptions.Fields.Remove(ItemFields.RemoteTrailers);
|
fields.Remove(ItemFields.ProductionLocations);
|
||||||
dtoOptions.Fields.Remove(ItemFields.SeasonUserData);
|
fields.Remove(ItemFields.RecursiveItemCount);
|
||||||
dtoOptions.Fields.Remove(ItemFields.Settings);
|
fields.Remove(ItemFields.RemoteTrailers);
|
||||||
dtoOptions.Fields.Remove(ItemFields.SortName);
|
fields.Remove(ItemFields.SeasonUserData);
|
||||||
dtoOptions.Fields.Remove(ItemFields.Tags);
|
fields.Remove(ItemFields.Settings);
|
||||||
dtoOptions.Fields.Remove(ItemFields.ThemeSongIds);
|
fields.Remove(ItemFields.SortName);
|
||||||
dtoOptions.Fields.Remove(ItemFields.ThemeVideoIds);
|
fields.Remove(ItemFields.Tags);
|
||||||
|
fields.Remove(ItemFields.ThemeSongIds);
|
||||||
|
fields.Remove(ItemFields.ThemeVideoIds);
|
||||||
|
|
||||||
|
dtoOptions.Fields = fields.ToArray(fields.Count);
|
||||||
|
|
||||||
_itemInfoDtoOptions = dtoOptions;
|
_itemInfoDtoOptions = dtoOptions;
|
||||||
}
|
}
|
||||||
@ -1698,7 +1705,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
|
|
||||||
if (mediaSource != null)
|
if (mediaSource != null)
|
||||||
{
|
{
|
||||||
info.MediaStreams = mediaSource.MediaStreams;
|
info.MediaStreams = mediaSource.MediaStreams.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
|
@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.Social
|
|||||||
|
|
||||||
AddShareInfo(info, externalUrl);
|
AddShareInfo(info, externalUrl);
|
||||||
|
|
||||||
await _repository.CreateShare(info).ConfigureAwait(false);
|
_repository.CreateShare(info);
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@ -92,9 +92,9 @@ namespace Emby.Server.Implementations.Social
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteShare(string id)
|
public void DeleteShare(string id)
|
||||||
{
|
{
|
||||||
return _repository.DeleteShare(id);
|
_repository.DeleteShare(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Emby.Server.Implementations.Data;
|
using Emby.Server.Implementations.Data;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
@ -42,7 +40,7 @@ namespace Emby.Server.Implementations.Social
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CreateShare(SocialShareInfo info)
|
public void CreateShare(SocialShareInfo info)
|
||||||
{
|
{
|
||||||
if (info == null)
|
if (info == null)
|
||||||
{
|
{
|
||||||
@ -109,7 +107,7 @@ namespace Emby.Server.Implementations.Social
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteShare(string id)
|
public void DeleteShare(string id)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
return audio.Artists.Count == 0 ? null : audio.Artists[0];
|
return audio.Artists.Length == 0 ? null : audio.Artists[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.TV
|
|||||||
Recursive = true,
|
Recursive = true,
|
||||||
DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
|
DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
|
||||||
{
|
{
|
||||||
Fields = new List<ItemFields>
|
Fields = new ItemFields[]
|
||||||
{
|
{
|
||||||
ItemFields.SeriesPresentationUniqueKey
|
ItemFields.SeriesPresentationUniqueKey
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ namespace Emby.Server.Implementations.TV
|
|||||||
Limit = limit,
|
Limit = limit,
|
||||||
DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
|
DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
|
||||||
{
|
{
|
||||||
Fields = new List<ItemFields>
|
Fields = new ItemFields[]
|
||||||
{
|
{
|
||||||
ItemFields.SeriesPresentationUniqueKey
|
ItemFields.SeriesPresentationUniqueKey
|
||||||
},
|
},
|
||||||
@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.TV
|
|||||||
ParentIndexNumberNotEquals = 0,
|
ParentIndexNumberNotEquals = 0,
|
||||||
DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
|
DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
|
||||||
{
|
{
|
||||||
Fields = new List<ItemFields>
|
Fields = new ItemFields[]
|
||||||
{
|
{
|
||||||
ItemFields.SortName
|
ItemFields.SortName
|
||||||
},
|
},
|
||||||
|
@ -122,7 +122,10 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
|
|
||||||
private readonly ICryptoProvider _cryptographyProvider;
|
private readonly ICryptoProvider _cryptographyProvider;
|
||||||
|
|
||||||
public InstallationManager(ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, IJsonSerializer jsonSerializer, ISecurityManager securityManager, IConfigurationManager config, IFileSystem fileSystem, ICryptoProvider cryptographyProvider)
|
// netframework or netcore
|
||||||
|
private readonly string _packageRuntime;
|
||||||
|
|
||||||
|
public InstallationManager(ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, IJsonSerializer jsonSerializer, ISecurityManager securityManager, IConfigurationManager config, IFileSystem fileSystem, ICryptoProvider cryptographyProvider, string packageRuntime)
|
||||||
{
|
{
|
||||||
if (logger == null)
|
if (logger == null)
|
||||||
{
|
{
|
||||||
@ -140,6 +143,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
_config = config;
|
_config = config;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_cryptographyProvider = cryptographyProvider;
|
_cryptographyProvider = cryptographyProvider;
|
||||||
|
_packageRuntime = packageRuntime;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +161,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
/// Gets all available packages.
|
/// Gets all available packages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task{List{PackageInfo}}.</returns>
|
/// <returns>Task{List{PackageInfo}}.</returns>
|
||||||
public async Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
public async Task<List<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
||||||
bool withRegistration = true,
|
bool withRegistration = true,
|
||||||
string packageType = null,
|
string packageType = null,
|
||||||
Version applicationVersion = null)
|
Version applicationVersion = null)
|
||||||
@ -171,11 +175,11 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
{ "systemid", _applicationHost.SystemId }
|
{ "systemid", _applicationHost.SystemId }
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var json = await _httpClient.Post("https://www.mb3admin.com/admin/service/package/retrieveall", data, cancellationToken).ConfigureAwait(false))
|
using (var json = await _httpClient.Post("https://www.mb3admin.com/admin/service/package/retrieveall?includeAllRuntimes=true", data, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(json).ToList();
|
var packages = _jsonSerializer.DeserializeFromStream<PackageInfo[]>(json);
|
||||||
|
|
||||||
return FilterPackages(packages, packageType, applicationVersion);
|
return FilterPackages(packages, packageType, applicationVersion);
|
||||||
}
|
}
|
||||||
@ -184,7 +188,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
{
|
{
|
||||||
var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
|
var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
return FilterPackages(packages.ToList(), packageType, applicationVersion);
|
return FilterPackages(packages, packageType, applicationVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,21 +199,21 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{List{PackageInfo}}.</returns>
|
/// <returns>Task{List{PackageInfo}}.</returns>
|
||||||
public async Task<IEnumerable<PackageInfo>> GetAvailablePackagesWithoutRegistrationInfo(CancellationToken cancellationToken)
|
public async Task<List<PackageInfo>> GetAvailablePackagesWithoutRegistrationInfo(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_logger.Info("Opening {0}", PackageCachePath);
|
_logger.Info("Opening {0}", PackageCachePath);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var stream = _fileSystem.OpenRead(PackageCachePath))
|
using (var stream = _fileSystem.OpenRead(PackageCachePath))
|
||||||
{
|
{
|
||||||
var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(stream).ToList();
|
var packages = _jsonSerializer.DeserializeFromStream<PackageInfo[]>(stream);
|
||||||
|
|
||||||
if (DateTime.UtcNow - _lastPackageUpdateTime > GetCacheLength())
|
if (DateTime.UtcNow - _lastPackageUpdateTime > GetCacheLength())
|
||||||
{
|
{
|
||||||
UpdateCachedPackages(CancellationToken.None, false);
|
UpdateCachedPackages(CancellationToken.None, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return packages;
|
return FilterPackages(packages);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@ -221,7 +225,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
await UpdateCachedPackages(cancellationToken, true).ConfigureAwait(false);
|
await UpdateCachedPackages(cancellationToken, true).ConfigureAwait(false);
|
||||||
using (var stream = _fileSystem.OpenRead(PackageCachePath))
|
using (var stream = _fileSystem.OpenRead(PackageCachePath))
|
||||||
{
|
{
|
||||||
return _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(stream).ToList();
|
return FilterPackages(_jsonSerializer.DeserializeFromStream<PackageInfo[]>(stream));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +248,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
|
|
||||||
var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
|
var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = "https://www.mb3admin.com/admin/service/MB3Packages.json",
|
Url = "https://www.mb3admin.com/admin/service/EmbyPackages.json",
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Progress = new SimpleProgress<Double>()
|
Progress = new SimpleProgress<Double>()
|
||||||
|
|
||||||
@ -277,57 +281,77 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
|
|
||||||
private TimeSpan GetCacheLength()
|
private TimeSpan GetCacheLength()
|
||||||
{
|
{
|
||||||
switch (GetSystemUpdateLevel())
|
return TimeSpan.FromMinutes(3);
|
||||||
{
|
|
||||||
case PackageVersionClass.Beta:
|
|
||||||
return TimeSpan.FromMinutes(30);
|
|
||||||
case PackageVersionClass.Dev:
|
|
||||||
return TimeSpan.FromMinutes(3);
|
|
||||||
default:
|
|
||||||
return TimeSpan.FromHours(24);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IEnumerable<PackageInfo> FilterPackages(List<PackageInfo> packages)
|
protected List<PackageInfo> FilterPackages(IEnumerable<PackageInfo> packages)
|
||||||
{
|
{
|
||||||
|
var list = new List<PackageInfo>();
|
||||||
|
|
||||||
foreach (var package in packages)
|
foreach (var package in packages)
|
||||||
{
|
{
|
||||||
package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl))
|
var versions = new List<PackageVersionInfo>();
|
||||||
.OrderByDescending(GetPackageVersion).ToList();
|
foreach (var version in package.versions)
|
||||||
}
|
|
||||||
|
|
||||||
// Remove packages with no versions
|
|
||||||
packages = packages.Where(p => p.versions.Any()).ToList();
|
|
||||||
|
|
||||||
return packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected IEnumerable<PackageInfo> FilterPackages(List<PackageInfo> packages, string packageType, Version applicationVersion)
|
|
||||||
{
|
|
||||||
foreach (var package in packages)
|
|
||||||
{
|
|
||||||
package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl))
|
|
||||||
.OrderByDescending(GetPackageVersion).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(packageType))
|
|
||||||
{
|
|
||||||
packages = packages.Where(p => string.Equals(p.type, packageType, StringComparison.OrdinalIgnoreCase)).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If an app version was supplied, filter the versions for each package to only include supported versions
|
|
||||||
if (applicationVersion != null)
|
|
||||||
{
|
|
||||||
foreach (var package in packages)
|
|
||||||
{
|
{
|
||||||
package.versions = package.versions.Where(v => IsPackageVersionUpToDate(v, applicationVersion)).ToList();
|
if (string.IsNullOrWhiteSpace(version.sourceUrl))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(version.runtimes) || version.runtimes.IndexOf(_packageRuntime, StringComparison.OrdinalIgnoreCase) == -1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
versions.Add(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
package.versions = versions
|
||||||
|
.OrderByDescending(GetPackageVersion)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
if (package.versions.Length == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Add(package);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove packages with no versions
|
// Remove packages with no versions
|
||||||
packages = packages.Where(p => p.versions.Any()).ToList();
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
return packages;
|
protected List<PackageInfo> FilterPackages(IEnumerable<PackageInfo> packages, string packageType, Version applicationVersion)
|
||||||
|
{
|
||||||
|
var packagesList = FilterPackages(packages);
|
||||||
|
|
||||||
|
var returnList = new List<PackageInfo>();
|
||||||
|
|
||||||
|
var filterOnPackageType = !string.IsNullOrWhiteSpace(packageType);
|
||||||
|
|
||||||
|
foreach (var p in packagesList)
|
||||||
|
{
|
||||||
|
if (filterOnPackageType && !string.Equals(p.type, packageType, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If an app version was supplied, filter the versions for each package to only include supported versions
|
||||||
|
if (applicationVersion != null)
|
||||||
|
{
|
||||||
|
p.versions = p.versions.Where(v => IsPackageVersionUpToDate(v, applicationVersion)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.versions.Length == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnList.Add(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -418,30 +442,24 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
/// <returns>Task{IEnumerable{PackageVersionInfo}}.</returns>
|
/// <returns>Task{IEnumerable{PackageVersionInfo}}.</returns>
|
||||||
public async Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(Version applicationVersion, bool withAutoUpdateEnabled, CancellationToken cancellationToken)
|
public async Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(Version applicationVersion, bool withAutoUpdateEnabled, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var catalog = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
|
if (!_config.CommonConfiguration.EnableAutoUpdate)
|
||||||
|
|
||||||
var plugins = _applicationHost.Plugins.ToList();
|
|
||||||
|
|
||||||
if (withAutoUpdateEnabled)
|
|
||||||
{
|
{
|
||||||
plugins = plugins
|
return new PackageVersionInfo[] { };
|
||||||
.Where(p => _config.CommonConfiguration.EnableAutoUpdate)
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var catalog = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var systemUpdateLevel = GetSystemUpdateLevel();
|
var systemUpdateLevel = GetSystemUpdateLevel();
|
||||||
|
|
||||||
// Figure out what needs to be installed
|
// Figure out what needs to be installed
|
||||||
var packages = plugins.Select(p =>
|
return _applicationHost.Plugins.Select(p =>
|
||||||
{
|
{
|
||||||
var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, systemUpdateLevel);
|
var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, systemUpdateLevel);
|
||||||
|
|
||||||
return latestPluginInfo != null && GetPackageVersion(latestPluginInfo) > p.Version ? latestPluginInfo : null;
|
return latestPluginInfo != null && GetPackageVersion(latestPluginInfo) > p.Version ? latestPluginInfo : null;
|
||||||
|
|
||||||
}).Where(i => i != null).ToList();
|
}).Where(i => i != null)
|
||||||
|
.Where(p => !string.IsNullOrWhiteSpace(p.sourceUrl) && !CompletedInstallations.Any(i => string.Equals(i.AssemblyGuid, p.guid, StringComparison.OrdinalIgnoreCase)));
|
||||||
return packages
|
|
||||||
.Where(p => !string.IsNullOrWhiteSpace(p.sourceUrl) && !CompletedInstallations.Any(i => string.Equals(i.AssemblyGuid, p.guid, StringComparison.OrdinalIgnoreCase)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Emby.XmlTv" version="1.0.10" targetFramework="net46" />
|
<package id="Emby.XmlTv" version="1.0.10" targetFramework="net46" />
|
||||||
<package id="MediaBrowser.Naming" version="1.0.6" targetFramework="net46" />
|
<package id="MediaBrowser.Naming" version="1.0.7" targetFramework="net46" />
|
||||||
<package id="ServiceStack.Text" version="4.5.8" targetFramework="net46" />
|
<package id="ServiceStack.Text" version="4.5.8" targetFramework="net46" />
|
||||||
<package id="SharpCompress" version="0.14.0" targetFramework="net46" />
|
<package id="SharpCompress" version="0.14.0" targetFramework="net46" />
|
||||||
<package id="SimpleInjector" version="4.0.8" targetFramework="net46" />
|
<package id="SimpleInjector" version="4.0.8" targetFramework="net46" />
|
||||||
|
@ -11,6 +11,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
using MediaBrowser.Model.Extensions;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
@ -54,6 +55,17 @@ namespace MediaBrowser.Api
|
|||||||
return Request.Headers[name];
|
return Request.Headers[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly string[] EmptyStringArray = new string[] { };
|
||||||
|
public static string[] SplitValue(string value, char delim)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
{
|
||||||
|
return EmptyStringArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.Split(new[] { delim }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// To the optimized result.
|
/// To the optimized result.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -128,7 +140,7 @@ namespace MediaBrowser.Api
|
|||||||
var hasFields = request as IHasItemFields;
|
var hasFields = request as IHasItemFields;
|
||||||
if (hasFields != null)
|
if (hasFields != null)
|
||||||
{
|
{
|
||||||
options.Fields = hasFields.GetItemFields().ToList();
|
options.Fields = hasFields.GetItemFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
var client = authInfo.Client ?? string.Empty;
|
var client = authInfo.Client ?? string.Empty;
|
||||||
@ -137,7 +149,9 @@ namespace MediaBrowser.Api
|
|||||||
client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 ||
|
client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||||
client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1)
|
client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
{
|
{
|
||||||
options.Fields.Add(Model.Querying.ItemFields.RecursiveItemCount);
|
var list = options.Fields.ToList();
|
||||||
|
list.Add(Model.Querying.ItemFields.RecursiveItemCount);
|
||||||
|
options.Fields = list.ToArray(list.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 ||
|
if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||||
@ -148,7 +162,9 @@ namespace MediaBrowser.Api
|
|||||||
client.IndexOf("samsung", StringComparison.OrdinalIgnoreCase) != -1 ||
|
client.IndexOf("samsung", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||||
client.IndexOf("androidtv", StringComparison.OrdinalIgnoreCase) != -1)
|
client.IndexOf("androidtv", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
{
|
{
|
||||||
options.Fields.Add(Model.Querying.ItemFields.ChildCount);
|
var list = options.Fields.ToList();
|
||||||
|
list.Add(Model.Querying.ItemFields.ChildCount);
|
||||||
|
options.Fields = list.ToArray(list.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasDtoOptions = request as IHasDtoOptions;
|
var hasDtoOptions = request as IHasDtoOptions;
|
||||||
@ -167,7 +183,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(hasDtoOptions.EnableImageTypes))
|
if (!string.IsNullOrWhiteSpace(hasDtoOptions.EnableImageTypes))
|
||||||
{
|
{
|
||||||
options.ImageTypes = (hasDtoOptions.EnableImageTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true)).ToList();
|
options.ImageTypes = (hasDtoOptions.EnableImageTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true)).ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ namespace MediaBrowser.Api
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Channels/Features", "GET", Summary = "Gets features for a channel")]
|
[Route("/Channels/Features", "GET", Summary = "Gets features for a channel")]
|
||||||
public class GetAllChannelFeatures : IReturn<List<ChannelFeatures>>
|
public class GetAllChannelFeatures : IReturn<ChannelFeatures[]>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
public object Get(GetAllChannelFeatures request)
|
public object Get(GetAllChannelFeatures request)
|
||||||
{
|
{
|
||||||
var result = _channelManager.GetAllChannelFeatures().ToList();
|
var result = _channelManager.GetAllChannelFeatures();
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
@ -231,7 +231,7 @@ namespace MediaBrowser.Api
|
|||||||
SortOrder = request.SortOrder,
|
SortOrder = request.SortOrder,
|
||||||
SortBy = (request.SortBy ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(),
|
SortBy = (request.SortBy ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(),
|
||||||
Filters = request.GetFilters().ToArray(),
|
Filters = request.GetFilters().ToArray(),
|
||||||
Fields = request.GetItemFields().ToArray()
|
Fields = request.GetItemFields()
|
||||||
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
}, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -247,7 +247,7 @@ namespace MediaBrowser.Api
|
|||||||
ChannelIds = (request.ChannelIds ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(),
|
ChannelIds = (request.ChannelIds ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(),
|
||||||
UserId = request.UserId,
|
UserId = request.UserId,
|
||||||
Filters = request.GetFilters().ToArray(),
|
Filters = request.GetFilters().ToArray(),
|
||||||
Fields = request.GetItemFields().ToList()
|
Fields = request.GetItemFields()
|
||||||
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
}, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ using MediaBrowser.Model.Configuration;
|
|||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Controller.IO;
|
||||||
@ -62,7 +61,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
[Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")]
|
[Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")]
|
||||||
[Authenticated(Roles = "Admin")]
|
[Authenticated(Roles = "Admin")]
|
||||||
public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>>
|
public class GetMetadataPlugins : IReturn<MetadataPluginSummary[]>
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -170,7 +169,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
public object Get(GetMetadataPlugins request)
|
public object Get(GetMetadataPlugins request)
|
||||||
{
|
{
|
||||||
return ToOptimizedSerializedResultUsingCache(_providerManager.GetAllMetadataPlugins().ToList());
|
return ToOptimizedSerializedResultUsingCache(_providerManager.GetAllMetadataPlugins());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using MediaBrowser.Controller.Devices;
|
using MediaBrowser.Controller.Devices;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Devices;
|
using MediaBrowser.Model.Devices;
|
||||||
@ -143,7 +142,7 @@ namespace MediaBrowser.Api.Devices
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var file = Request.Files.First();
|
var file = Request.Files.Length == 0 ? null : Request.Files[0];
|
||||||
|
|
||||||
var task = _deviceManager.AcceptCameraUpload(deviceId, file.InputStream, new LocalFileInfo
|
var task = _deviceManager.AcceptCameraUpload(deviceId, file.InputStream, new LocalFileInfo
|
||||||
{
|
{
|
||||||
|
@ -88,9 +88,7 @@ namespace MediaBrowser.Api
|
|||||||
// Serialize to json and then back so that the core doesn't see the request dto type
|
// Serialize to json and then back so that the core doesn't see the request dto type
|
||||||
var displayPreferences = _jsonSerializer.DeserializeFromString<DisplayPreferences>(_jsonSerializer.SerializeToString(request));
|
var displayPreferences = _jsonSerializer.DeserializeFromString<DisplayPreferences>(_jsonSerializer.SerializeToString(request));
|
||||||
|
|
||||||
var task = _displayPreferencesManager.SaveDisplayPreferences(displayPreferences, request.UserId, request.Client, CancellationToken.None);
|
_displayPreferencesManager.SaveDisplayPreferences(displayPreferences, request.UserId, request.Client, CancellationToken.None);
|
||||||
|
|
||||||
Task.WaitAll(task);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Controller.IO;
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
using MediaBrowser.Controller.Dlna;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Dlna
|
namespace MediaBrowser.Api.Dlna
|
||||||
{
|
{
|
||||||
[Route("/Dlna/ProfileInfos", "GET", Summary = "Gets a list of profiles")]
|
[Route("/Dlna/ProfileInfos", "GET", Summary = "Gets a list of profiles")]
|
||||||
public class GetProfileInfos : IReturn<List<DeviceProfileInfo>>
|
public class GetProfileInfos : IReturn<DeviceProfileInfo[]>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +52,7 @@ namespace MediaBrowser.Api.Dlna
|
|||||||
|
|
||||||
public object Get(GetProfileInfos request)
|
public object Get(GetProfileInfos request)
|
||||||
{
|
{
|
||||||
var result = _dlnaManager.GetProfileInfos().ToList();
|
var result = _dlnaManager.GetProfileInfos().ToArray();
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ namespace MediaBrowser.Api
|
|||||||
return ToOptimizedSerializedResultUsingCache(GetNetworkShares(path).OrderBy(i => i.Path).ToList());
|
return ToOptimizedSerializedResultUsingCache(GetNetworkShares(path).OrderBy(i => i.Path).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(GetFileSystemEntries(request).OrderBy(i => i.Path).ToList());
|
return ToOptimizedSerializedResultUsingCache(GetFileSystemEntries(request).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetNetworkShares request)
|
public object Get(GetNetworkShares request)
|
||||||
@ -271,9 +271,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetNetworkDevices request)
|
public object Get(GetNetworkDevices request)
|
||||||
{
|
{
|
||||||
var result = _networkManager.GetNetworkDevices()
|
var result = _networkManager.GetNetworkDevices().ToList();
|
||||||
.OrderBy(i => i.Path)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
@ -300,7 +298,6 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
|
/// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
|
||||||
private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
|
private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
|
||||||
{
|
{
|
||||||
// using EnumerateFileSystemInfos doesn't handle reparse points (symlinks)
|
|
||||||
var entries = _fileSystem.GetFileSystemEntries(request.Path).Where(i =>
|
var entries = _fileSystem.GetFileSystemEntries(request.Path).Where(i =>
|
||||||
{
|
{
|
||||||
if (!request.IncludeHidden && i.IsHidden)
|
if (!request.IncludeHidden && i.IsHidden)
|
||||||
@ -329,7 +326,7 @@ namespace MediaBrowser.Api
|
|||||||
Path = f.FullName,
|
Path = f.FullName,
|
||||||
Type = f.IsDirectory ? FileSystemEntryType.Directory : FileSystemEntryType.File
|
Type = f.IsDirectory ? FileSystemEntryType.Directory : FileSystemEntryType.File
|
||||||
|
|
||||||
}).ToList();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetParentPath request)
|
public object Get(GetParentPath request)
|
||||||
|
@ -108,7 +108,7 @@ namespace MediaBrowser.Api
|
|||||||
EnableTotalRecordCount = false,
|
EnableTotalRecordCount = false,
|
||||||
DtoOptions = new Controller.Dto.DtoOptions
|
DtoOptions = new Controller.Dto.DtoOptions
|
||||||
{
|
{
|
||||||
Fields = new List<ItemFields> { ItemFields.Genres, ItemFields.Tags },
|
Fields = new ItemFields[] { ItemFields.Genres, ItemFields.Tags },
|
||||||
EnableImages = false,
|
EnableImages = false,
|
||||||
EnableUserData = false
|
EnableUserData = false
|
||||||
}
|
}
|
||||||
|
@ -28,21 +28,7 @@ namespace MediaBrowser.Api
|
|||||||
/// Class GetGameSystemSummaries
|
/// Class GetGameSystemSummaries
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Games/SystemSummaries", "GET", Summary = "Finds games similar to a given game.")]
|
[Route("/Games/SystemSummaries", "GET", Summary = "Finds games similar to a given game.")]
|
||||||
public class GetGameSystemSummaries : IReturn<List<GameSystemSummary>>
|
public class GetGameSystemSummaries : IReturn<GameSystemSummary[]>
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user id.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user id.</value>
|
|
||||||
[ApiMember(Name = "UserId", Description = "Optional. Filter by user id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
|
||||||
public string UserId { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Class GetGameSystemSummaries
|
|
||||||
/// </summary>
|
|
||||||
[Route("/Games/PlayerIndex", "GET", Summary = "Gets an index of players (1-x) and the number of games listed under each")]
|
|
||||||
public class GetPlayerIndex : IReturn<List<ItemIndex>>
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the user id.
|
/// Gets or sets the user id.
|
||||||
@ -117,47 +103,17 @@ namespace MediaBrowser.Api
|
|||||||
EnableImages = false
|
EnableImages = false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var gameSystems = _libraryManager.GetItemList(query)
|
|
||||||
.Cast<GameSystem>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var result = gameSystems
|
var result = _libraryManager.GetItemList(query)
|
||||||
|
.Cast<GameSystem>()
|
||||||
.Select(i => GetSummary(i, user))
|
.Select(i => GetSummary(i, user))
|
||||||
.ToList();
|
.ToArray();
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
public object Get(GetPlayerIndex request)
|
|
||||||
{
|
|
||||||
var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
|
|
||||||
var query = new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Game).Name },
|
|
||||||
DtoOptions = new DtoOptions(false)
|
|
||||||
{
|
|
||||||
EnableImages = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var games = _libraryManager.GetItemList(query)
|
|
||||||
.Cast<Game>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var lookup = games
|
|
||||||
.ToLookup(i => i.PlayersSupported ?? -1)
|
|
||||||
.OrderBy(i => i.Key)
|
|
||||||
.Select(i => new ItemIndex
|
|
||||||
{
|
|
||||||
ItemCount = i.Count(),
|
|
||||||
Name = i.Key == -1 ? string.Empty : i.Key.ToString(UsCulture)
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(lookup);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the summary.
|
/// Gets the summary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -183,15 +139,15 @@ namespace MediaBrowser.Api
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var games = items.Cast<Game>().ToList();
|
var games = items.Cast<Game>().ToArray();
|
||||||
|
|
||||||
summary.ClientInstalledGameCount = games.Count(i => i.IsPlaceHolder);
|
summary.ClientInstalledGameCount = games.Count(i => i.IsPlaceHolder);
|
||||||
|
|
||||||
summary.GameCount = games.Count;
|
summary.GameCount = games.Length;
|
||||||
|
|
||||||
summary.GameFileExtensions = games.Where(i => !i.IsPlaceHolder).Select(i => Path.GetExtension(i.Path))
|
summary.GameFileExtensions = games.Where(i => !i.IsPlaceHolder).Select(i => Path.GetExtension(i.Path))
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
.ToList();
|
.ToArray();
|
||||||
|
|
||||||
return summary;
|
return summary;
|
||||||
}
|
}
|
||||||
@ -234,7 +190,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = returnList.ToArray(returnList.Count),
|
Items = returnList,
|
||||||
|
|
||||||
TotalRecordCount = itemsResult.Count
|
TotalRecordCount = itemsResult.Count
|
||||||
};
|
};
|
||||||
|
@ -27,7 +27,7 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>IEnumerable{ItemFields}.</returns>
|
/// <returns>IEnumerable{ItemFields}.</returns>
|
||||||
public static IEnumerable<ItemFields> GetItemFields(this IHasItemFields request)
|
public static ItemFields[] GetItemFields(this IHasItemFields request)
|
||||||
{
|
{
|
||||||
var val = request.Fields;
|
var val = request.Fields;
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ namespace MediaBrowser.Api
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}).Where(i => i.HasValue).Select(i => i.Value);
|
}).Where(i => i.HasValue).Select(i => i.Value).ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -556,20 +556,7 @@ namespace MediaBrowser.Api.Images
|
|||||||
throw new ResourceNotFoundException(string.Format("{0} does not have an image of type {1}", item.Name, request.Type));
|
throw new ResourceNotFoundException(string.Format("{0} does not have an image of type {1}", item.Name, request.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
var supportedImageEnhancers = request.EnableImageEnhancers ? _imageProcessor.ImageEnhancers.Where(i =>
|
var supportedImageEnhancers = request.EnableImageEnhancers ? _imageProcessor.GetSupportedEnhancers(item, request.Type) : new List<IImageEnhancer>();
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return i.Supports(item, request.Type);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error in image enhancer: {0}", ex, i.GetType().Name);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}).ToList() : new List<IImageEnhancer>();
|
|
||||||
|
|
||||||
var cropwhitespace = request.Type == ImageType.Logo ||
|
var cropwhitespace = request.Type == ImageType.Logo ||
|
||||||
request.Type == ImageType.Art
|
request.Type == ImageType.Art
|
||||||
|
@ -150,7 +150,7 @@ namespace MediaBrowser.Api.Images
|
|||||||
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
}, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
var imagesList = images.ToList();
|
var imagesList = images.ToArray();
|
||||||
|
|
||||||
var allProviders = _providerManager.GetRemoteImageProviderInfo(item);
|
var allProviders = _providerManager.GetRemoteImageProviderInfo(item);
|
||||||
|
|
||||||
@ -161,22 +161,22 @@ namespace MediaBrowser.Api.Images
|
|||||||
|
|
||||||
var result = new RemoteImageResult
|
var result = new RemoteImageResult
|
||||||
{
|
{
|
||||||
TotalRecordCount = imagesList.Count,
|
TotalRecordCount = imagesList.Length,
|
||||||
Providers = allProviders.Select(i => i.Name)
|
Providers = allProviders.Select(i => i.Name)
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
.ToList()
|
.ToArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (request.StartIndex.HasValue)
|
if (request.StartIndex.HasValue)
|
||||||
{
|
{
|
||||||
imagesList = imagesList.Skip(request.StartIndex.Value)
|
imagesList = imagesList.Skip(request.StartIndex.Value)
|
||||||
.ToList();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.Limit.HasValue)
|
if (request.Limit.HasValue)
|
||||||
{
|
{
|
||||||
imagesList = imagesList.Take(request.Limit.Value)
|
imagesList = imagesList.Take(request.Limit.Value)
|
||||||
.ToList();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Images = imagesList;
|
result.Images = imagesList;
|
||||||
|
@ -64,8 +64,8 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
var info = new MetadataEditorInfo
|
var info = new MetadataEditorInfo
|
||||||
{
|
{
|
||||||
ParentalRatingOptions = _localizationManager.GetParentalRatings().ToList(),
|
ParentalRatingOptions = _localizationManager.GetParentalRatings(),
|
||||||
ExternalIdInfos = _providerManager.GetExternalIdInfos(item).ToList(),
|
ExternalIdInfos = _providerManager.GetExternalIdInfos(item).ToArray(),
|
||||||
Countries = _localizationManager.GetCountries(),
|
Countries = _localizationManager.GetCountries(),
|
||||||
Cultures = _localizationManager.GetCultures()
|
Cultures = _localizationManager.GetCultures()
|
||||||
};
|
};
|
||||||
@ -78,14 +78,14 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(inheritedContentType) || !string.IsNullOrWhiteSpace(configuredContentType))
|
if (string.IsNullOrWhiteSpace(inheritedContentType) || !string.IsNullOrWhiteSpace(configuredContentType))
|
||||||
{
|
{
|
||||||
info.ContentTypeOptions = GetContentTypeOptions(true);
|
info.ContentTypeOptions = GetContentTypeOptions(true).ToArray();
|
||||||
info.ContentType = configuredContentType;
|
info.ContentType = configuredContentType;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(inheritedContentType) || string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
if (string.IsNullOrWhiteSpace(inheritedContentType) || string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
info.ContentTypeOptions = info.ContentTypeOptions
|
info.ContentTypeOptions = info.ContentTypeOptions
|
||||||
.Where(i => string.IsNullOrWhiteSpace(i.Value) || string.Equals(i.Value, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
.Where(i => string.IsNullOrWhiteSpace(i.Value) || string.Equals(i.Value, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
||||||
.ToList();
|
.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ namespace MediaBrowser.Api
|
|||||||
// Do this first so that metadata savers can pull the updates from the database.
|
// Do this first so that metadata savers can pull the updates from the database.
|
||||||
if (request.People != null)
|
if (request.People != null)
|
||||||
{
|
{
|
||||||
await _libraryManager.UpdatePeople(item, request.People.Select(x => new PersonInfo { Name = x.Name, Role = x.Role, Type = x.Type }).ToList());
|
_libraryManager.UpdatePeople(item, request.People.Select(x => new PersonInfo { Name = x.Name, Role = x.Role, Type = x.Type }).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateItem(request, item);
|
UpdateItem(request, item);
|
||||||
@ -352,7 +352,7 @@ namespace MediaBrowser.Api
|
|||||||
hasArtists.Artists = request
|
hasArtists.Artists = request
|
||||||
.ArtistItems
|
.ArtistItems
|
||||||
.Select(i => i.Name)
|
.Select(i => i.Name)
|
||||||
.ToList();
|
.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
|
|
||||||
[Route("/Library/MediaFolders", "GET", Summary = "Gets all user media folders.")]
|
[Route("/Library/MediaFolders", "GET", Summary = "Gets all user media folders.")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetMediaFolders : IReturn<ItemsResult>
|
public class GetMediaFolders : IReturn<QueryResult<BaseItemDto>>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "IsHidden", Description = "Optional. Filter by folders that are marked hidden, or not.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "IsHidden", Description = "Optional. Filter by folders that are marked hidden, or not.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? IsHidden { get; set; }
|
public bool? IsHidden { get; set; }
|
||||||
@ -400,7 +400,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ItemsResult();
|
return new QueryResult<BaseItemDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetMediaFolders request)
|
public object Get(GetMediaFolders request)
|
||||||
@ -416,7 +416,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
|
|
||||||
var dtoOptions = GetDtoOptions(_authContext, request);
|
var dtoOptions = GetDtoOptions(_authContext, request);
|
||||||
|
|
||||||
var result = new ItemsResult
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
TotalRecordCount = items.Count,
|
TotalRecordCount = items.Count,
|
||||||
|
|
||||||
@ -525,18 +525,18 @@ namespace MediaBrowser.Api.Library
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void LogDownload(BaseItem item, User user, AuthorizationInfo auth)
|
private void LogDownload(BaseItem item, User user, AuthorizationInfo auth)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _activityManager.Create(new ActivityLogEntry
|
_activityManager.Create(new ActivityLogEntry
|
||||||
{
|
{
|
||||||
Name = string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Name, item.Name),
|
Name = string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Name, item.Name),
|
||||||
Type = "UserDownloadingContent",
|
Type = "UserDownloadingContent",
|
||||||
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device),
|
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device),
|
||||||
UserId = auth.UserId
|
UserId = auth.UserId
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
});
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -615,7 +615,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
parent = parent.GetParent();
|
parent = parent.GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return baseItemDtos.ToList();
|
return baseItemDtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BaseItem TranslateParentItem(BaseItem item, User user)
|
private BaseItem TranslateParentItem(BaseItem item, User user)
|
||||||
|
@ -648,7 +648,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
{
|
{
|
||||||
public List<TunerChannelMapping> TunerChannels { get; set; }
|
public List<TunerChannelMapping> TunerChannels { get; set; }
|
||||||
public List<NameIdPair> ProviderChannels { get; set; }
|
public List<NameIdPair> ProviderChannels { get; set; }
|
||||||
public List<NameValuePair> Mappings { get; set; }
|
public NameValuePair[] Mappings { get; set; }
|
||||||
public string ProviderName { get; set; }
|
public string ProviderName { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,7 +789,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(request.ProviderId, CancellationToken.None)
|
var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(request.ProviderId, CancellationToken.None)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var mappings = listingsProviderInfo.ChannelMappings.ToList();
|
var mappings = listingsProviderInfo.ChannelMappings;
|
||||||
|
|
||||||
var result = new ChannelMappingOptions
|
var result = new ChannelMappingOptions
|
||||||
{
|
{
|
||||||
@ -862,7 +862,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
{
|
{
|
||||||
var config = GetConfiguration();
|
var config = GetConfiguration();
|
||||||
|
|
||||||
config.TunerHosts = config.TunerHosts.Where(i => !string.Equals(request.Id, i.Id, StringComparison.OrdinalIgnoreCase)).ToList();
|
config.TunerHosts = config.TunerHosts.Where(i => !string.Equals(request.Id, i.Id, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||||
|
|
||||||
_config.SaveConfiguration("livetv", config);
|
_config.SaveConfiguration("livetv", config);
|
||||||
}
|
}
|
||||||
@ -922,9 +922,8 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
options.AddCurrentProgram = request.AddCurrentProgram;
|
options.AddCurrentProgram = request.AddCurrentProgram;
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(channelResult.Items, options, user)
|
var returnArray = (await _dtoService.GetBaseItemDtos(channelResult.Items, options, user)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
var returnArray = returnList.ToArray(returnList.Count);
|
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
@ -937,10 +936,13 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
private void RemoveFields(DtoOptions options)
|
private void RemoveFields(DtoOptions options)
|
||||||
{
|
{
|
||||||
options.Fields.Remove(ItemFields.CanDelete);
|
var fields = options.Fields.ToList();
|
||||||
options.Fields.Remove(ItemFields.CanDownload);
|
|
||||||
options.Fields.Remove(ItemFields.DisplayPreferencesId);
|
fields.Remove(ItemFields.CanDelete);
|
||||||
options.Fields.Remove(ItemFields.Etag);
|
fields.Remove(ItemFields.CanDownload);
|
||||||
|
fields.Remove(ItemFields.DisplayPreferencesId);
|
||||||
|
fields.Remove(ItemFields.Etag);
|
||||||
|
options.Fields = fields.ToArray(fields.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetChannel request)
|
public object Get(GetChannel request)
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
@ -11,7 +10,7 @@ namespace MediaBrowser.Api
|
|||||||
/// Class GetCultures
|
/// Class GetCultures
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Localization/Cultures", "GET", Summary = "Gets known cultures")]
|
[Route("/Localization/Cultures", "GET", Summary = "Gets known cultures")]
|
||||||
public class GetCultures : IReturn<List<CultureDto>>
|
public class GetCultures : IReturn<CultureDto[]>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +18,7 @@ namespace MediaBrowser.Api
|
|||||||
/// Class GetCountries
|
/// Class GetCountries
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Localization/Countries", "GET", Summary = "Gets known countries")]
|
[Route("/Localization/Countries", "GET", Summary = "Gets known countries")]
|
||||||
public class GetCountries : IReturn<List<CountryInfo>>
|
public class GetCountries : IReturn<CountryInfo[]>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ namespace MediaBrowser.Api
|
|||||||
/// Class ParentalRatings
|
/// Class ParentalRatings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Localization/ParentalRatings", "GET", Summary = "Gets known parental ratings")]
|
[Route("/Localization/ParentalRatings", "GET", Summary = "Gets known parental ratings")]
|
||||||
public class GetParentalRatings : IReturn<List<ParentalRating>>
|
public class GetParentalRatings : IReturn<ParentalRating[]>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ namespace MediaBrowser.Api
|
|||||||
/// Class ParentalRatings
|
/// Class ParentalRatings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Localization/Options", "GET", Summary = "Gets localization options")]
|
[Route("/Localization/Options", "GET", Summary = "Gets localization options")]
|
||||||
public class GetLocalizationOptions : IReturn<List<LocalizatonOption>>
|
public class GetLocalizationOptions : IReturn<LocalizatonOption[]>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,14 +65,14 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetParentalRatings request)
|
public object Get(GetParentalRatings request)
|
||||||
{
|
{
|
||||||
var result = _localization.GetParentalRatings().ToList();
|
var result = _localization.GetParentalRatings();
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetLocalizationOptions request)
|
public object Get(GetLocalizationOptions request)
|
||||||
{
|
{
|
||||||
var result = _localization.GetLocalizationOptions().ToList();
|
var result = _localization.GetLocalizationOptions();
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,6 @@
|
|||||||
<Compile Include="Movies\MoviesService.cs" />
|
<Compile Include="Movies\MoviesService.cs" />
|
||||||
<Compile Include="NewsService.cs" />
|
<Compile Include="NewsService.cs" />
|
||||||
<Compile Include="NotificationsService.cs" />
|
<Compile Include="NotificationsService.cs" />
|
||||||
<Compile Include="PackageReviewService.cs" />
|
|
||||||
<Compile Include="PackageService.cs" />
|
<Compile Include="PackageService.cs" />
|
||||||
<Compile Include="PluginService.cs" />
|
<Compile Include="PluginService.cs" />
|
||||||
<Compile Include="Images\RemoteImageService.cs" />
|
<Compile Include="Images\RemoteImageService.cs" />
|
||||||
|
@ -4,7 +4,6 @@ using MediaBrowser.Controller.Net;
|
|||||||
using MediaBrowser.Model.Collections;
|
using MediaBrowser.Model.Collections;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
|
||||||
@ -71,8 +70,8 @@ namespace MediaBrowser.Api.Movies
|
|||||||
IsLocked = request.IsLocked,
|
IsLocked = request.IsLocked,
|
||||||
Name = request.Name,
|
Name = request.Name,
|
||||||
ParentId = parentId,
|
ParentId = parentId,
|
||||||
ItemIdList = (request.Ids ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToList(),
|
ItemIdList = SplitValue(request.Ids, ','),
|
||||||
UserIds = new List<Guid> { new Guid(userId) }
|
UserIds = new string[] { userId }
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -88,14 +87,14 @@ namespace MediaBrowser.Api.Movies
|
|||||||
|
|
||||||
public void Post(AddToCollection request)
|
public void Post(AddToCollection request)
|
||||||
{
|
{
|
||||||
var task = _collectionManager.AddToCollection(new Guid(request.Id), request.Ids.Split(',').Select(i => new Guid(i)));
|
var task = _collectionManager.AddToCollection(new Guid(request.Id), SplitValue(request.Ids, ','));
|
||||||
|
|
||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Delete(RemoveFromCollection request)
|
public void Delete(RemoveFromCollection request)
|
||||||
{
|
{
|
||||||
var task = _collectionManager.RemoveFromCollection(new Guid(request.Id), request.Ids.Split(',').Select(i => new Guid(i)));
|
var task = _collectionManager.RemoveFromCollection(new Guid(request.Id), SplitValue(request.Ids, ','));
|
||||||
|
|
||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = returnList.ToArray(returnList.Count),
|
Items = returnList,
|
||||||
|
|
||||||
TotalRecordCount = itemsResult.Count
|
TotalRecordCount = itemsResult.Count
|
||||||
};
|
};
|
||||||
@ -320,7 +320,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
BaselineItemName = name,
|
BaselineItemName = name,
|
||||||
CategoryId = name.GetMD5().ToString("N"),
|
CategoryId = name.GetMD5().ToString("N"),
|
||||||
RecommendationType = type,
|
RecommendationType = type,
|
||||||
Items = returnItems.ToArray(returnItems.Count)
|
Items = returnItems
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,7 +360,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
BaselineItemName = name,
|
BaselineItemName = name,
|
||||||
CategoryId = name.GetMD5().ToString("N"),
|
CategoryId = name.GetMD5().ToString("N"),
|
||||||
RecommendationType = type,
|
RecommendationType = type,
|
||||||
Items = returnItems.ToArray(returnItems.Count)
|
Items = returnItems
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -397,7 +397,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
BaselineItemName = item.Name,
|
BaselineItemName = item.Name,
|
||||||
CategoryId = item.Id.ToString("N"),
|
CategoryId = item.Id.ToString("N"),
|
||||||
RecommendationType = type,
|
RecommendationType = type,
|
||||||
Items = returnItems.ToArray(returnItems.Count)
|
Items = returnItems
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,7 +426,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
{
|
{
|
||||||
var people = _libraryManager.GetPeople(new InternalPeopleQuery
|
var people = _libraryManager.GetPeople(new InternalPeopleQuery
|
||||||
{
|
{
|
||||||
PersonTypes = new List<string>
|
PersonTypes = new string[]
|
||||||
{
|
{
|
||||||
PersonType.Director
|
PersonType.Director
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using MediaBrowser.Controller.Library;
|
|||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using MediaBrowser.Controller.Collections;
|
using MediaBrowser.Controller.Collections;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
@ -11,7 +12,7 @@ using MediaBrowser.Model.Services;
|
|||||||
namespace MediaBrowser.Api.Movies
|
namespace MediaBrowser.Api.Movies
|
||||||
{
|
{
|
||||||
[Route("/Trailers", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
|
[Route("/Trailers", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
|
||||||
public class Getrailers : BaseItemsRequest, IReturn<ItemsResult>
|
public class Getrailers : BaseItemsRequest, IReturn<QueryResult<BaseItemDto>>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ using MediaBrowser.Model.Querying;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
using MediaBrowser.Model.Extensions;
|
using MediaBrowser.Model.Extensions;
|
||||||
|
|
||||||
@ -185,15 +186,20 @@ namespace MediaBrowser.Api.Music
|
|||||||
{
|
{
|
||||||
var list = items;
|
var list = items;
|
||||||
|
|
||||||
var result = new ItemsResult
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
TotalRecordCount = list.Count
|
TotalRecordCount = list.Count
|
||||||
};
|
};
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(list.Take(request.Limit ?? list.Count), dtoOptions, user)
|
if (request.Limit.HasValue)
|
||||||
|
{
|
||||||
|
list = list.Take(request.Limit.Value).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
var returnList = (await _dtoService.GetBaseItemDtos(list, dtoOptions, user)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
|
|
||||||
result.Items = returnList.ToArray(returnList.Count);
|
result.Items = returnList;
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
public object Get(GetNotificationTypes request)
|
public object Get(GetNotificationTypes request)
|
||||||
{
|
{
|
||||||
var result = _notificationManager.GetNotificationTypes().ToList();
|
var result = _notificationManager.GetNotificationTypes();
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
@ -1,162 +0,0 @@
|
|||||||
using MediaBrowser.Common.Net;
|
|
||||||
using MediaBrowser.Controller;
|
|
||||||
using MediaBrowser.Controller.Net;
|
|
||||||
using MediaBrowser.Model.Entities;
|
|
||||||
using MediaBrowser.Model.Serialization;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Net;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediaBrowser.Model.Services;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class InstallPackage
|
|
||||||
/// </summary>
|
|
||||||
[Route("/Packages/Reviews/{Id}", "POST", Summary = "Creates or updates a package review")]
|
|
||||||
public class CreateReviewRequest : IReturnVoid
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the Id.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The Id.</value>
|
|
||||||
[ApiMember(Name = "Id", Description = "Package Id", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "POST")]
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the rating.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The review.</value>
|
|
||||||
[ApiMember(Name = "Rating", Description = "The rating value (1-5)", IsRequired = true, DataType = "int", ParameterType = "query", Verb = "POST")]
|
|
||||||
public int Rating { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the recommend value.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>Whether or not this review recommends this item.</value>
|
|
||||||
[ApiMember(Name = "Recommend", Description = "Whether or not this review recommends this item", IsRequired = true, DataType = "bool", ParameterType = "query", Verb = "POST")]
|
|
||||||
public bool Recommend { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the title.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The title.</value>
|
|
||||||
[ApiMember(Name = "Title", Description = "Optional short description of review.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
|
||||||
public string Title { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the full review.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The full review.</value>
|
|
||||||
[ApiMember(Name = "Review", Description = "Optional full review.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
|
|
||||||
public string Review { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Class InstallPackage
|
|
||||||
/// </summary>
|
|
||||||
[Route("/Packages/{Id}/Reviews", "GET", Summary = "Gets reviews for a package")]
|
|
||||||
public class ReviewRequest : IReturn<List<PackageReviewInfo>>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the Id.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The Id.</value>
|
|
||||||
[ApiMember(Name = "Id", Description = "Package Id", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the max rating.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The max rating.</value>
|
|
||||||
[ApiMember(Name = "MaxRating", Description = "Retrieve only reviews less than or equal to this", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int MaxRating { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the min rating.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The max rating.</value>
|
|
||||||
[ApiMember(Name = "MinRating", Description = "Retrieve only reviews greator than or equal to this", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int MinRating { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Only retrieve reviews with at least a short review.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>True if should only get reviews with a title.</value>
|
|
||||||
[ApiMember(Name = "ForceTitle", Description = "Whether or not to restrict results to those with a title", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool ForceTitle { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the limit for the query.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The max rating.</value>
|
|
||||||
[ApiMember(Name = "Limit", Description = "Limit the result to this many reviews (ordered by latest)", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
|
||||||
public int Limit { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authenticated]
|
|
||||||
public class PackageReviewService : BaseApiService
|
|
||||||
{
|
|
||||||
private readonly IHttpClient _httpClient;
|
|
||||||
private readonly IJsonSerializer _serializer;
|
|
||||||
private const string MbAdminUrl = "https://www.mb3admin.com/admin/";
|
|
||||||
private readonly IServerApplicationHost _appHost;
|
|
||||||
|
|
||||||
public PackageReviewService(IHttpClient httpClient, IJsonSerializer serializer, IServerApplicationHost appHost)
|
|
||||||
{
|
|
||||||
_httpClient = httpClient;
|
|
||||||
_serializer = serializer;
|
|
||||||
_appHost = appHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<object> Get(ReviewRequest request)
|
|
||||||
{
|
|
||||||
var parms = "?id=" + request.Id;
|
|
||||||
|
|
||||||
if (request.MaxRating > 0)
|
|
||||||
{
|
|
||||||
parms += "&max=" + request.MaxRating;
|
|
||||||
}
|
|
||||||
if (request.MinRating > 0)
|
|
||||||
{
|
|
||||||
parms += "&min=" + request.MinRating;
|
|
||||||
}
|
|
||||||
if (request.MinRating > 0)
|
|
||||||
{
|
|
||||||
parms += "&limit=" + request.Limit;
|
|
||||||
}
|
|
||||||
if (request.ForceTitle)
|
|
||||||
{
|
|
||||||
parms += "&title=true";
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var result = await _httpClient.Get(MbAdminUrl + "/service/packageReview/retrieve" + parms, CancellationToken.None)
|
|
||||||
.ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
var reviews = _serializer.DeserializeFromStream<List<PackageReviewInfo>>(result);
|
|
||||||
|
|
||||||
return ToOptimizedResult(reviews);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Post(CreateReviewRequest request)
|
|
||||||
{
|
|
||||||
var reviewText = WebUtility.HtmlEncode(request.Review ?? string.Empty);
|
|
||||||
var title = WebUtility.HtmlEncode(request.Title ?? string.Empty);
|
|
||||||
|
|
||||||
var review = new Dictionary<string, string>
|
|
||||||
{ { "id", request.Id.ToString(CultureInfo.InvariantCulture) },
|
|
||||||
{ "mac", _appHost.SystemId },
|
|
||||||
{ "rating", request.Rating.ToString(CultureInfo.InvariantCulture) },
|
|
||||||
{ "recommend", request.Recommend.ToString() },
|
|
||||||
{ "title", title },
|
|
||||||
{ "review", reviewText },
|
|
||||||
};
|
|
||||||
|
|
||||||
Task.WaitAll(_httpClient.Post(MbAdminUrl + "/service/packageReview/update", review, CancellationToken.None));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -40,7 +40,7 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Packages", "GET", Summary = "Gets available packages")]
|
[Route("/Packages", "GET", Summary = "Gets available packages")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetPackages : IReturn<List<PackageInfo>>
|
public class GetPackages : IReturn<PackageInfo[]>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the name.
|
/// Gets or sets the name.
|
||||||
@ -66,7 +66,7 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Packages/Updates", "GET", Summary = "Gets available package updates for currently installed packages")]
|
[Route("/Packages/Updates", "GET", Summary = "Gets available package updates for currently installed packages")]
|
||||||
[Authenticated(Roles = "Admin")]
|
[Authenticated(Roles = "Admin")]
|
||||||
public class GetPackageVersionUpdates : IReturn<List<PackageVersionInfo>>
|
public class GetPackageVersionUpdates : IReturn<PackageVersionInfo[]>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the name.
|
/// Gets or sets the name.
|
||||||
@ -148,24 +148,26 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetPackageVersionUpdates request)
|
public object Get(GetPackageVersionUpdates request)
|
||||||
{
|
{
|
||||||
var result = new List<PackageVersionInfo>();
|
PackageVersionInfo[] result = null;
|
||||||
|
|
||||||
if (string.Equals(request.PackageType, "UserInstalled", StringComparison.OrdinalIgnoreCase) || string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(request.PackageType, "UserInstalled", StringComparison.OrdinalIgnoreCase) || string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
result.AddRange(_installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, false, CancellationToken.None).Result.ToList());
|
result = _installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, false, CancellationToken.None).Result.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (string.Equals(request.PackageType, "System", StringComparison.OrdinalIgnoreCase) || string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(request.PackageType, "System", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var updateCheckResult = _appHost.CheckForApplicationUpdate(CancellationToken.None, new SimpleProgress<double>()).Result;
|
var updateCheckResult = _appHost
|
||||||
|
.CheckForApplicationUpdate(CancellationToken.None, new SimpleProgress<double>()).Result;
|
||||||
|
|
||||||
if (updateCheckResult.IsUpdateAvailable)
|
if (updateCheckResult.IsUpdateAvailable)
|
||||||
{
|
{
|
||||||
result.Add(updateCheckResult.Package);
|
result = new PackageVersionInfo[] {updateCheckResult.Package};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result ?? new PackageVersionInfo[] { });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -176,10 +178,9 @@ namespace MediaBrowser.Api
|
|||||||
public object Get(GetPackage request)
|
public object Get(GetPackage request)
|
||||||
{
|
{
|
||||||
var packages = _installationManager.GetAvailablePackages(CancellationToken.None, applicationVersion: _appHost.ApplicationVersion).Result;
|
var packages = _installationManager.GetAvailablePackages(CancellationToken.None, applicationVersion: _appHost.ApplicationVersion).Result;
|
||||||
var list = packages.ToList();
|
|
||||||
|
|
||||||
var result = list.FirstOrDefault(p => string.Equals(p.guid, request.AssemblyGuid ?? "none", StringComparison.OrdinalIgnoreCase))
|
var result = packages.FirstOrDefault(p => string.Equals(p.guid, request.AssemblyGuid ?? "none", StringComparison.OrdinalIgnoreCase))
|
||||||
?? list.FirstOrDefault(p => p.name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
|
?? packages.FirstOrDefault(p => p.name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
@ -191,7 +192,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public async Task<object> Get(GetPackages request)
|
public async Task<object> Get(GetPackages request)
|
||||||
{
|
{
|
||||||
var packages = await _installationManager.GetAvailablePackages(CancellationToken.None, false, request.PackageType, _appHost.ApplicationVersion).ConfigureAwait(false);
|
IEnumerable<PackageInfo> packages = await _installationManager.GetAvailablePackages(CancellationToken.None, false, request.PackageType, _appHost.ApplicationVersion).ConfigureAwait(false);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.TargetSystems))
|
if (!string.IsNullOrEmpty(request.TargetSystems))
|
||||||
{
|
{
|
||||||
@ -215,7 +216,7 @@ namespace MediaBrowser.Api
|
|||||||
packages = packages.Where(p => p.enableInAppStore == request.IsAppStoreEnabled.Value);
|
packages = packages.Where(p => p.enableInAppStore == request.IsAppStoreEnabled.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToOptimizedResult(packages.ToList());
|
return ToOptimizedResult(packages.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
using MediaBrowser.Controller.Dto;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Controller.Playlists;
|
using MediaBrowser.Controller.Playlists;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Playlists;
|
using MediaBrowser.Model.Playlists;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
using MediaBrowser.Model.Extensions;
|
using MediaBrowser.Model.Extensions;
|
||||||
@ -149,7 +149,7 @@ namespace MediaBrowser.Api
|
|||||||
var result = await _playlistManager.CreatePlaylist(new PlaylistCreationRequest
|
var result = await _playlistManager.CreatePlaylist(new PlaylistCreationRequest
|
||||||
{
|
{
|
||||||
Name = request.Name,
|
Name = request.Name,
|
||||||
ItemIdList = (request.Ids ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(),
|
ItemIdList = SplitValue(request.Ids, ','),
|
||||||
UserId = request.UserId,
|
UserId = request.UserId,
|
||||||
MediaType = request.MediaType
|
MediaType = request.MediaType
|
||||||
|
|
||||||
@ -193,10 +193,8 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
var dtoOptions = GetDtoOptions(_authContext, request);
|
var dtoOptions = GetDtoOptions(_authContext, request);
|
||||||
|
|
||||||
var returnList = (await _dtoService.GetBaseItemDtos(items.Select(i => i.Item2), dtoOptions, user)
|
var dtos = (await _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user)
|
||||||
.ConfigureAwait(false));
|
.ConfigureAwait(false));
|
||||||
var dtos = returnList
|
|
||||||
.ToArray(returnList.Count);
|
|
||||||
|
|
||||||
var index = 0;
|
var index = 0;
|
||||||
foreach (var item in dtos)
|
foreach (var item in dtos)
|
||||||
@ -205,7 +203,7 @@ namespace MediaBrowser.Api
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new ItemsResult
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = dtos,
|
Items = dtos,
|
||||||
TotalRecordCount = count
|
TotalRecordCount = count
|
||||||
|
@ -23,7 +23,7 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")]
|
[Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetPlugins : IReturn<List<PluginInfo>>
|
public class GetPlugins : IReturn<PluginInfo[]>
|
||||||
{
|
{
|
||||||
public bool? IsAppStoreEnabled { get; set; }
|
public bool? IsAppStoreEnabled { get; set; }
|
||||||
}
|
}
|
||||||
@ -195,14 +195,13 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public async Task<object> Get(GetPlugins request)
|
public async Task<object> Get(GetPlugins request)
|
||||||
{
|
{
|
||||||
var result = _appHost.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToList();
|
var result = _appHost.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToArray();
|
||||||
var requireAppStoreEnabled = request.IsAppStoreEnabled.HasValue && request.IsAppStoreEnabled.Value;
|
var requireAppStoreEnabled = request.IsAppStoreEnabled.HasValue && request.IsAppStoreEnabled.Value;
|
||||||
|
|
||||||
// Don't fail just on account of image url's
|
// Don't fail just on account of image url's
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var packages = (await _installationManager.GetAvailablePackagesWithoutRegistrationInfo(CancellationToken.None))
|
var packages = (await _installationManager.GetAvailablePackagesWithoutRegistrationInfo(CancellationToken.None));
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (var plugin in result)
|
foreach (var plugin in result)
|
||||||
{
|
{
|
||||||
@ -223,7 +222,7 @@ namespace MediaBrowser.Api
|
|||||||
return pkg != null && pkg.enableInAppStore;
|
return pkg != null && pkg.enableInAppStore;
|
||||||
|
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -232,7 +231,7 @@ namespace MediaBrowser.Api
|
|||||||
// Play it safe here
|
// Play it safe here
|
||||||
if (requireAppStoreEnabled)
|
if (requireAppStoreEnabled)
|
||||||
{
|
{
|
||||||
result = new List<PluginInfo>();
|
result = new PluginInfo[] { };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,7 +533,7 @@ namespace MediaBrowser.Api.Reports
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Tracks:
|
case HeaderMetadata.Tracks:
|
||||||
option.Column = (i, r) => this.GetObject<MusicAlbum, List<Audio>>(i, (x) => x.Tracks.ToList(), new List<Audio>()).Count();
|
option.Column = (i, r) => this.GetObject<MusicAlbum, List<Audio>>(i, (x) => x.Tracks.Cast<Audio>().ToList(), new List<Audio>()).Count();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Audio:
|
case HeaderMetadata.Audio:
|
||||||
|
@ -27,7 +27,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
|||||||
/// Class GetScheduledTasks
|
/// Class GetScheduledTasks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")]
|
[Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")]
|
||||||
public class GetScheduledTasks : IReturn<List<TaskInfo>>
|
public class GetScheduledTasks : IReturn<TaskInfo[]>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? IsHidden { get; set; }
|
public bool? IsHidden { get; set; }
|
||||||
@ -158,7 +158,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
|||||||
|
|
||||||
var infos = result
|
var infos = result
|
||||||
.Select(ScheduledTaskHelpers.GetTaskInfo)
|
.Select(ScheduledTaskHelpers.GetTaskInfo)
|
||||||
.ToList();
|
.ToArray();
|
||||||
|
|
||||||
return ToOptimizedResult(infos);
|
return ToOptimizedResult(infos);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Drawing;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
@ -7,7 +8,6 @@ using MediaBrowser.Controller.Library;
|
|||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Search;
|
using MediaBrowser.Model.Search;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
@ -240,7 +240,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
if (album != null)
|
if (album != null)
|
||||||
{
|
{
|
||||||
result.Artists = album.Artists.ToArray();
|
result.Artists = album.Artists;
|
||||||
result.AlbumArtist = album.AlbumArtist;
|
result.AlbumArtist = album.AlbumArtist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +250,7 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
result.Album = song.Album;
|
result.Album = song.Album;
|
||||||
result.AlbumArtist = song.AlbumArtists.FirstOrDefault();
|
result.AlbumArtist = song.AlbumArtists.FirstOrDefault();
|
||||||
result.Artists = song.Artists.ToArray();
|
result.Artists = song.Artists;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(item.ChannelId))
|
if (!string.IsNullOrWhiteSpace(item.ChannelId))
|
||||||
|
@ -18,7 +18,7 @@ namespace MediaBrowser.Api.Session
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Sessions", "GET", Summary = "Gets a list of sessions")]
|
[Route("/Sessions", "GET", Summary = "Gets a list of sessions")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetSessions : IReturn<List<SessionInfoDto>>
|
public class GetSessions : IReturn<SessionInfoDto[]>
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "ControllableByUserId", Description = "Optional. Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "ControllableByUserId", Description = "Optional. Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string ControllableByUserId { get; set; }
|
public string ControllableByUserId { get; set; }
|
||||||
@ -313,14 +313,13 @@ namespace MediaBrowser.Api.Session
|
|||||||
|
|
||||||
public void Delete(RevokeKey request)
|
public void Delete(RevokeKey request)
|
||||||
{
|
{
|
||||||
var task = _sessionManager.RevokeToken(request.Key);
|
_sessionManager.RevokeToken(request.Key);
|
||||||
|
|
||||||
Task.WaitAll(task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(CreateKey request)
|
public void Post(CreateKey request)
|
||||||
{
|
{
|
||||||
var task = _authRepo.Create(new AuthenticationInfo
|
_authRepo.Create(new AuthenticationInfo
|
||||||
{
|
{
|
||||||
AppName = request.App,
|
AppName = request.App,
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
@ -328,8 +327,6 @@ namespace MediaBrowser.Api.Session
|
|||||||
DateCreated = DateTime.UtcNow
|
DateCreated = DateTime.UtcNow
|
||||||
|
|
||||||
}, CancellationToken.None);
|
}, CancellationToken.None);
|
||||||
|
|
||||||
Task.WaitAll(task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(ReportSessionEnded request)
|
public void Post(ReportSessionEnded request)
|
||||||
@ -396,7 +393,7 @@ namespace MediaBrowser.Api.Session
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToOptimizedResult(result.Select(_sessionManager.GetSessionInfoDto).ToList());
|
return ToOptimizedResult(result.Select(_sessionManager.GetSessionInfoDto).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(SendPlaystateCommand request)
|
public void Post(SendPlaystateCommand request)
|
||||||
@ -532,9 +529,9 @@ namespace MediaBrowser.Api.Session
|
|||||||
}
|
}
|
||||||
_sessionManager.ReportCapabilities(request.Id, new ClientCapabilities
|
_sessionManager.ReportCapabilities(request.Id, new ClientCapabilities
|
||||||
{
|
{
|
||||||
PlayableMediaTypes = (request.PlayableMediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
|
PlayableMediaTypes = SplitValue(request.PlayableMediaTypes, ','),
|
||||||
|
|
||||||
SupportedCommands = (request.SupportedCommands ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
|
SupportedCommands = SplitValue(request.SupportedCommands, ','),
|
||||||
|
|
||||||
SupportsMediaControl = request.SupportsMediaControl,
|
SupportsMediaControl = request.SupportsMediaControl,
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ namespace MediaBrowser.Api
|
|||||||
public string ExcludeArtistIds { get; set; }
|
public string ExcludeArtistIds { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BaseGetSimilarItems : IReturn<ItemsResult>, IHasDtoOptions
|
public class BaseGetSimilarItems : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? EnableImages { get; set; }
|
public bool? EnableImages { get; set; }
|
||||||
@ -97,18 +97,18 @@ namespace MediaBrowser.Api
|
|||||||
var items = GetSimilaritems(item, libraryManager, inputItems, getSimilarityScore)
|
var items = GetSimilaritems(item, libraryManager, inputItems, getSimilarityScore)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
IEnumerable<BaseItem> returnItems = items;
|
List<BaseItem> returnItems = items;
|
||||||
|
|
||||||
if (request.Limit.HasValue)
|
if (request.Limit.HasValue)
|
||||||
{
|
{
|
||||||
returnItems = returnItems.Take(request.Limit.Value);
|
returnItems = returnItems.Take(request.Limit.Value).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtos = await dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ConfigureAwait(false);
|
var dtos = await dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ConfigureAwait(false);
|
||||||
|
|
||||||
return new QueryResult<BaseItemDto>
|
return new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = dtos.ToArray(dtos.Count),
|
Items = dtos,
|
||||||
|
|
||||||
TotalRecordCount = items.Count
|
TotalRecordCount = items.Count
|
||||||
};
|
};
|
||||||
|
@ -121,8 +121,7 @@ namespace MediaBrowser.Api.Social
|
|||||||
|
|
||||||
public void Delete(DeleteShare request)
|
public void Delete(DeleteShare request)
|
||||||
{
|
{
|
||||||
var task = _sharingManager.DeleteShare(request.Id);
|
_sharingManager.DeleteShare(request.Id);
|
||||||
Task.WaitAll(task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetShareImage request)
|
public async Task<object> Get(GetShareImage request)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user