Merge pull request #23 from jellyfin/master

updating
pull/3342/head
BaronGreenback 4 years ago committed by GitHub
commit 862bcdba67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,6 +7,7 @@
- [anthonylavado](https://github.com/anthonylavado) - [anthonylavado](https://github.com/anthonylavado)
- [Artiume](https://github.com/Artiume) - [Artiume](https://github.com/Artiume)
- [AThomsen](https://github.com/AThomsen) - [AThomsen](https://github.com/AThomsen)
- [barronpm](https://github.com/barronpm)
- [bilde2910](https://github.com/bilde2910) - [bilde2910](https://github.com/bilde2910)
- [bfayers](https://github.com/bfayers) - [bfayers](https://github.com/bfayers)
- [BnMcG](https://github.com/BnMcG) - [BnMcG](https://github.com/BnMcG)
@ -130,6 +131,7 @@
- [XVicarious](https://github.com/XVicarious) - [XVicarious](https://github.com/XVicarious)
- [YouKnowBlom](https://github.com/YouKnowBlom) - [YouKnowBlom](https://github.com/YouKnowBlom)
- [KristupasSavickas](https://github.com/KristupasSavickas) - [KristupasSavickas](https://github.com/KristupasSavickas)
- [Pusta](https://github.com/pusta)
# Emby Contributors # Emby Contributors

@ -4,11 +4,12 @@ using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Dlna.Service; using Emby.Dlna.Service;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.TV; using MediaBrowser.Controller.TV;
@ -32,7 +33,8 @@ namespace Emby.Dlna.ContentDirectory
private readonly IMediaEncoder _mediaEncoder; private readonly IMediaEncoder _mediaEncoder;
private readonly ITVSeriesManager _tvSeriesManager; private readonly ITVSeriesManager _tvSeriesManager;
public ContentDirectory(IDlnaManager dlna, public ContentDirectory(
IDlnaManager dlna,
IUserDataManager userDataManager, IUserDataManager userDataManager,
IImageProcessor imageProcessor, IImageProcessor imageProcessor,
ILibraryManager libraryManager, ILibraryManager libraryManager,
@ -131,7 +133,7 @@ namespace Emby.Dlna.ContentDirectory
foreach (var user in _userManager.Users) foreach (var user in _userManager.Users)
{ {
if (user.Policy.IsAdministrator) if (user.HasPermission(PermissionKind.IsAdministrator))
{ {
return user; return user;
} }

@ -10,6 +10,7 @@ using System.Threading;
using System.Xml; using System.Xml;
using Emby.Dlna.Didl; using Emby.Dlna.Didl;
using Emby.Dlna.Service; using Emby.Dlna.Service;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
@ -17,7 +18,6 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
@ -28,6 +28,12 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Book = MediaBrowser.Controller.Entities.Book;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace Emby.Dlna.ContentDirectory namespace Emby.Dlna.ContentDirectory
{ {
@ -460,12 +466,12 @@ namespace Emby.Dlna.ContentDirectory
} }
else if (search.SearchType == SearchType.Playlist) else if (search.SearchType == SearchType.Playlist)
{ {
//items = items.OfType<Playlist>(); // items = items.OfType<Playlist>();
isFolder = true; isFolder = true;
} }
else if (search.SearchType == SearchType.MusicAlbum) else if (search.SearchType == SearchType.MusicAlbum)
{ {
//items = items.OfType<MusicAlbum>(); // items = items.OfType<MusicAlbum>();
isFolder = true; isFolder = true;
} }
@ -731,7 +737,7 @@ namespace Emby.Dlna.ContentDirectory
return GetGenres(item, user, query); return GetGenres(item, user, query);
} }
var array = new ServerItem[] var array = new[]
{ {
new ServerItem(item) new ServerItem(item)
{ {
@ -920,7 +926,7 @@ namespace Emby.Dlna.ContentDirectory
private QueryResult<ServerItem> GetMovieCollections(User user, InternalItemsQuery query) private QueryResult<ServerItem> GetMovieCollections(User user, InternalItemsQuery query)
{ {
query.Recursive = true; query.Recursive = true;
//query.Parent = parent; // query.Parent = parent;
query.SetUser(user); query.SetUser(user);
query.IncludeItemTypes = new[] { typeof(BoxSet).Name }; query.IncludeItemTypes = new[] { typeof(BoxSet).Name };
@ -1115,7 +1121,7 @@ namespace Emby.Dlna.ContentDirectory
private QueryResult<ServerItem> GetMusicPlaylists(User user, InternalItemsQuery query) private QueryResult<ServerItem> GetMusicPlaylists(User user, InternalItemsQuery query)
{ {
query.Parent = null; query.Parent = null;
query.IncludeItemTypes = new[] { typeof(Playlist).Name }; query.IncludeItemTypes = new[] { nameof(Playlist) };
query.SetUser(user); query.SetUser(user);
query.Recursive = true; query.Recursive = true;
@ -1132,10 +1138,9 @@ namespace Emby.Dlna.ContentDirectory
{ {
UserId = user.Id, UserId = user.Id,
Limit = 50, Limit = 50,
IncludeItemTypes = new[] { typeof(Audio).Name }, IncludeItemTypes = new[] { nameof(Audio) },
ParentId = parent == null ? Guid.Empty : parent.Id, ParentId = parent?.Id ?? Guid.Empty,
GroupItems = true GroupItems = true
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
return ToResult(items); return ToResult(items);
@ -1150,7 +1155,6 @@ namespace Emby.Dlna.ContentDirectory
Limit = query.Limit, Limit = query.Limit,
StartIndex = query.StartIndex, StartIndex = query.StartIndex,
UserId = query.User.Id UserId = query.User.Id
}, new[] { parent }, query.DtoOptions); }, new[] { parent }, query.DtoOptions);
return ToResult(result); return ToResult(result);
@ -1167,7 +1171,6 @@ namespace Emby.Dlna.ContentDirectory
IncludeItemTypes = new[] { typeof(Episode).Name }, IncludeItemTypes = new[] { typeof(Episode).Name },
ParentId = parent == null ? Guid.Empty : parent.Id, ParentId = parent == null ? Guid.Empty : parent.Id,
GroupItems = false GroupItems = false
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
return ToResult(items); return ToResult(items);
@ -1177,14 +1180,14 @@ namespace Emby.Dlna.ContentDirectory
{ {
query.OrderBy = Array.Empty<(string, SortOrder)>(); query.OrderBy = Array.Empty<(string, SortOrder)>();
var items = _userViewManager.GetLatestItems(new LatestItemsQuery var items = _userViewManager.GetLatestItems(
new LatestItemsQuery
{ {
UserId = user.Id, UserId = user.Id,
Limit = 50, Limit = 50,
IncludeItemTypes = new[] { typeof(Movie).Name }, IncludeItemTypes = new[] { nameof(Movie) },
ParentId = parent == null ? Guid.Empty : parent.Id, ParentId = parent?.Id ?? Guid.Empty,
GroupItems = true GroupItems = true
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
return ToResult(items); return ToResult(items);
@ -1217,7 +1220,11 @@ namespace Emby.Dlna.ContentDirectory
Recursive = true, Recursive = true,
ParentId = parentId, ParentId = parentId,
GenreIds = new[] { item.Id }, GenreIds = new[] { item.Id },
IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name }, IncludeItemTypes = new[]
{
nameof(Movie),
nameof(Series)
},
Limit = limit, Limit = limit,
StartIndex = startIndex, StartIndex = startIndex,
DtoOptions = GetDtoOptions() DtoOptions = GetDtoOptions()

@ -6,14 +6,13 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Xml; using System.Xml;
using Emby.Dlna.Configuration;
using Emby.Dlna.ContentDirectory; using Emby.Dlna.ContentDirectory;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Playlists;
@ -23,6 +22,13 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
using Season = MediaBrowser.Controller.Entities.TV.Season;
using Series = MediaBrowser.Controller.Entities.TV.Series;
using XmlAttribute = MediaBrowser.Model.Dlna.XmlAttribute;
namespace Emby.Dlna.Didl namespace Emby.Dlna.Didl
{ {
@ -92,21 +98,21 @@ namespace Emby.Dlna.Didl
{ {
using (var writer = XmlWriter.Create(builder, settings)) using (var writer = XmlWriter.Create(builder, settings))
{ {
//writer.WriteStartDocument(); // writer.WriteStartDocument();
writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL); writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL);
writer.WriteAttributeString("xmlns", "dc", null, NS_DC); writer.WriteAttributeString("xmlns", "dc", null, NS_DC);
writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA); writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA);
writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP); writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP);
//didl.SetAttribute("xmlns:sec", NS_SEC); // didl.SetAttribute("xmlns:sec", NS_SEC);
WriteXmlRootAttributes(_profile, writer); WriteXmlRootAttributes(_profile, writer);
WriteItemElement(writer, item, user, context, null, deviceId, filter, streamInfo); WriteItemElement(writer, item, user, context, null, deviceId, filter, streamInfo);
writer.WriteFullEndElement(); writer.WriteFullEndElement();
//writer.WriteEndDocument(); // writer.WriteEndDocument();
} }
return builder.ToString(); return builder.ToString();
@ -421,7 +427,6 @@ namespace Emby.Dlna.Didl
case StubType.FavoriteSeries: return _localization.GetLocalizedString("HeaderFavoriteShows"); case StubType.FavoriteSeries: return _localization.GetLocalizedString("HeaderFavoriteShows");
case StubType.FavoriteEpisodes: return _localization.GetLocalizedString("HeaderFavoriteEpisodes"); case StubType.FavoriteEpisodes: return _localization.GetLocalizedString("HeaderFavoriteEpisodes");
case StubType.Series: return _localization.GetLocalizedString("Shows"); case StubType.Series: return _localization.GetLocalizedString("Shows");
default: break;
} }
} }
@ -670,7 +675,7 @@ namespace Emby.Dlna.Didl
return; return;
} }
MediaBrowser.Model.Dlna.XmlAttribute secAttribute = null; XmlAttribute secAttribute = null;
foreach (var attribute in _profile.XmlRootAttributes) foreach (var attribute in _profile.XmlRootAttributes)
{ {
if (string.Equals(attribute.Name, "xmlns:sec", StringComparison.OrdinalIgnoreCase)) if (string.Equals(attribute.Name, "xmlns:sec", StringComparison.OrdinalIgnoreCase))
@ -706,7 +711,7 @@ namespace Emby.Dlna.Didl
{ {
// Don't filter on dc:title because not all devices will include it in the filter // Don't filter on dc:title because not all devices will include it in the filter
// MediaMonkey for example won't display content without a title // MediaMonkey for example won't display content without a title
//if (filter.Contains("dc:title")) // if (filter.Contains("dc:title"))
{ {
AddValue(writer, "dc", "title", GetDisplayName(item, itemStubType, context), NS_DC); AddValue(writer, "dc", "title", GetDisplayName(item, itemStubType, context), NS_DC);
} }
@ -745,7 +750,7 @@ namespace Emby.Dlna.Didl
AddValue(writer, "dc", "description", desc, NS_DC); AddValue(writer, "dc", "description", desc, NS_DC);
} }
} }
//if (filter.Contains("upnp:longDescription")) // if (filter.Contains("upnp:longDescription"))
//{ //{
// if (!string.IsNullOrWhiteSpace(item.Overview)) // if (!string.IsNullOrWhiteSpace(item.Overview))
// { // {
@ -995,7 +1000,6 @@ namespace Emby.Dlna.Didl
} }
AddImageResElement(item, writer, 160, 160, "jpg", "JPEG_TN"); AddImageResElement(item, writer, 160, 160, "jpg", "JPEG_TN");
} }
private void AddImageResElement( private void AddImageResElement(
@ -1131,25 +1135,24 @@ namespace Emby.Dlna.Didl
if (width == 0 || height == 0) if (width == 0 || height == 0)
{ {
//_imageProcessor.GetImageSize(item, imageInfo); // _imageProcessor.GetImageSize(item, imageInfo);
width = null; width = null;
height = null; height = null;
} }
else if (width == -1 || height == -1) else if (width == -1 || height == -1)
{ {
width = null; width = null;
height = null; height = null;
} }
//try // try
//{ //{
// var size = _imageProcessor.GetImageSize(imageInfo); // var size = _imageProcessor.GetImageSize(imageInfo);
// width = size.Width; // width = size.Width;
// height = size.Height; // height = size.Height;
//} //}
//catch // catch
//{ //{
//} //}

@ -12,7 +12,6 @@ namespace Emby.Dlna.Didl
public Filter() public Filter()
: this("*") : this("*")
{ {
} }
public Filter(string filter) public Filter(string filter)
@ -26,7 +25,7 @@ namespace Emby.Dlna.Didl
{ {
// Don't bother with this. Some clients (media monkey) use the filter and then don't display very well when very little data comes back. // Don't bother with this. Some clients (media monkey) use the filter and then don't display very well when very little data comes back.
return true; return true;
//return _all || ListHelper.ContainsIgnoreCase(_fields, field); // return _all || ListHelper.ContainsIgnoreCase(_fields, field);
} }
} }
} }

@ -88,7 +88,6 @@ namespace Emby.Dlna
.Select(i => i.Item2) .Select(i => i.Item2)
.ToList(); .ToList();
} }
} }
public DeviceProfile GetDefaultProfile() public DeviceProfile GetDefaultProfile()
@ -251,7 +250,7 @@ namespace Emby.Dlna
return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase); return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase);
case HeaderMatchType.Substring: case HeaderMatchType.Substring:
var isMatch = value.ToString().IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1; var isMatch = value.ToString().IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1;
//_logger.LogDebug("IsMatch-Substring value: {0} testValue: {1} isMatch: {2}", value, header.Value, isMatch); // _logger.LogDebug("IsMatch-Substring value: {0} testValue: {1} isMatch: {2}", value, header.Value, isMatch);
return isMatch; return isMatch;
case HeaderMatchType.Regex: case HeaderMatchType.Regex:
return Regex.IsMatch(value, header.Value, RegexOptions.IgnoreCase); return Regex.IsMatch(value, header.Value, RegexOptions.IgnoreCase);
@ -566,9 +565,9 @@ namespace Emby.Dlna
new Foobar2000Profile(), new Foobar2000Profile(),
new SharpSmartTvProfile(), new SharpSmartTvProfile(),
new MediaMonkeyProfile(), new MediaMonkeyProfile(),
//new Windows81Profile(), // new Windows81Profile(),
//new WindowsMediaCenterProfile(), // new WindowsMediaCenterProfile(),
//new WindowsPhoneProfile(), // new WindowsPhoneProfile(),
new DirectTvProfile(), new DirectTvProfile(),
new DishHopperJoeyProfile(), new DishHopperJoeyProfile(),
new DefaultProfile(), new DefaultProfile(),

@ -169,7 +169,6 @@ namespace Emby.Dlna.Eventing
{ {
using (await _httpClient.SendAsync(options, new HttpMethod("NOTIFY")).ConfigureAwait(false)) using (await _httpClient.SendAsync(options, new HttpMethod("NOTIFY")).ConfigureAwait(false))
{ {
} }
} }
catch (OperationCanceledException) catch (OperationCanceledException)

@ -276,7 +276,7 @@ namespace Emby.Dlna.Main
var device = new SsdpRootDevice var device = new SsdpRootDevice
{ {
CacheLifetime = TimeSpan.FromSeconds(1800), //How long SSDP clients can cache this info. CacheLifetime = TimeSpan.FromSeconds(1800), // How long SSDP clients can cache this info.
Location = uri, // Must point to the URL that serves your devices UPnP description document. Location = uri, // Must point to the URL that serves your devices UPnP description document.
Address = address, Address = address,
SubnetMask = _networkManager.GetLocalIpSubnetMask(address), SubnetMask = _networkManager.GetLocalIpSubnetMask(address),

@ -750,7 +750,7 @@ namespace Emby.Dlna.PlayTo
if (track == null) if (track == null)
{ {
//If track is null, some vendors do this, use GetMediaInfo instead // If track is null, some vendors do this, use GetMediaInfo instead
return (true, null); return (true, null);
} }
@ -794,7 +794,6 @@ namespace Emby.Dlna.PlayTo
} }
catch (XmlException) catch (XmlException)
{ {
} }
// first try to add a root node with a dlna namesapce // first try to add a root node with a dlna namesapce
@ -806,7 +805,6 @@ namespace Emby.Dlna.PlayTo
} }
catch (XmlException) catch (XmlException)
{ {
} }
// some devices send back invalid xml // some devices send back invalid xml
@ -816,7 +814,6 @@ namespace Emby.Dlna.PlayTo
} }
catch (XmlException) catch (XmlException)
{ {
} }
return null; return null;

@ -7,6 +7,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Dlna.Didl; using Emby.Dlna.Didl;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
@ -22,6 +23,7 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;
using Microsoft.AspNetCore.WebUtilities; using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Photo = MediaBrowser.Controller.Entities.Photo;
namespace Emby.Dlna.PlayTo namespace Emby.Dlna.PlayTo
{ {
@ -446,7 +448,13 @@ namespace Emby.Dlna.PlayTo
} }
} }
private PlaylistItem CreatePlaylistItem(BaseItem item, User user, long startPostionTicks, string mediaSourceId, int? audioStreamIndex, int? subtitleStreamIndex) private PlaylistItem CreatePlaylistItem(
BaseItem item,
User user,
long startPostionTicks,
string mediaSourceId,
int? audioStreamIndex,
int? subtitleStreamIndex)
{ {
var deviceInfo = _device.Properties; var deviceInfo = _device.Properties;

@ -88,7 +88,7 @@ namespace Emby.Dlna.PlayTo
if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1 && if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1 &&
nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1) nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1)
{ {
//_logger.LogDebug("Upnp device {0} does not contain a MediaRenderer device (0).", location); // _logger.LogDebug("Upnp device {0} does not contain a MediaRenderer device (0).", location);
return; return;
} }
@ -112,7 +112,6 @@ namespace Emby.Dlna.PlayTo
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -243,7 +242,6 @@ namespace Emby.Dlna.PlayTo
} }
catch catch
{ {
} }
_sessionLock.Dispose(); _sessionLock.Dispose();

@ -91,7 +91,6 @@ namespace Emby.Dlna.PlayTo
using (await _httpClient.SendAsync(options, new HttpMethod("SUBSCRIBE")).ConfigureAwait(false)) using (await _httpClient.SendAsync(options, new HttpMethod("SUBSCRIBE")).ConfigureAwait(false))
{ {
} }
} }

@ -77,7 +77,7 @@ namespace Emby.Dlna.Ssdp
// (Optional) Set the filter so we only see notifications for devices we care about // (Optional) Set the filter so we only see notifications for devices we care about
// (can be any search target value i.e device type, uuid value etc - any value that appears in the // (can be any search target value i.e device type, uuid value etc - any value that appears in the
// DiscoverdSsdpDevice.NotificationType property or that is used with the searchTarget parameter of the Search method). // DiscoverdSsdpDevice.NotificationType property or that is used with the searchTarget parameter of the Search method).
//_DeviceLocator.NotificationFilter = "upnp:rootdevice"; // _DeviceLocator.NotificationFilter = "upnp:rootdevice";
// Connect our event handler so we process devices as they are found // Connect our event handler so we process devices as they are found
_deviceLocator.DeviceAvailable += OnDeviceLocatorDeviceAvailable; _deviceLocator.DeviceAvailable += OnDeviceLocatorDeviceAvailable;

@ -4,6 +4,7 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
@ -14,6 +15,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Photo = MediaBrowser.Controller.Entities.Photo;
namespace Emby.Drawing namespace Emby.Drawing
{ {
@ -349,6 +351,13 @@ namespace Emby.Drawing
}); });
} }
/// <inheritdoc />
public string GetImageCacheTag(User user)
{
return (user.ProfileImage.Path + user.ProfileImage.LastModified.Ticks).GetMD5()
.ToString("N", CultureInfo.InvariantCulture);
}
private async Task<(string path, DateTime dateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified) private async Task<(string path, DateTime dateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
{ {
var inputFormat = Path.GetExtension(originalImagePath) var inputFormat = Path.GetExtension(originalImagePath)

@ -8,6 +8,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Notifications; using MediaBrowser.Controller.Notifications;
@ -149,9 +150,7 @@ namespace Emby.Notifications.Api
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetNotificationsSummary request) public object Get(GetNotificationsSummary request)
{ {
return new NotificationsSummary return new NotificationsSummary();
{
};
} }
public Task Post(AddAdminNotification request) public Task Post(AddAdminNotification request)
@ -164,7 +163,10 @@ namespace Emby.Notifications.Api
Level = request.Level, Level = request.Level,
Name = request.Name, Name = request.Name,
Url = request.Url, Url = request.Url,
UserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id).ToArray() UserIds = _userManager.Users
.Where(user => user.HasPermission(PermissionKind.IsAdministrator))
.Select(user => user.Id)
.ToArray()
}; };
return _notificationManager.SendNotification(notification, CancellationToken.None); return _notificationManager.SendNotification(notification, CancellationToken.None);

@ -4,6 +4,8 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
@ -101,7 +103,7 @@ namespace Emby.Notifications
switch (request.SendToUserMode.Value) switch (request.SendToUserMode.Value)
{ {
case SendToUserType.Admins: case SendToUserType.Admins:
return _userManager.Users.Where(i => i.Policy.IsAdministrator) return _userManager.Users.Where(i => i.HasPermission(PermissionKind.IsAdministrator))
.Select(i => i.Id); .Select(i => i.Id);
case SendToUserType.All: case SendToUserType.All:
return _userManager.UsersIds; return _userManager.UsersIds;
@ -117,7 +119,7 @@ namespace Emby.Notifications
var config = GetConfiguration(); var config = GetConfiguration();
return _userManager.Users return _userManager.Users
.Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N", CultureInfo.InvariantCulture), i.Policy)) .Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N", CultureInfo.InvariantCulture), i))
.Select(i => i.Id); .Select(i => i.Id);
} }
@ -142,7 +144,7 @@ namespace Emby.Notifications
User = user User = user
}; };
_logger.LogDebug("Sending notification via {0} to user {1}", service.Name, user.Name); _logger.LogDebug("Sending notification via {0} to user {1}", service.Name, user.Username);
try try
{ {

@ -88,25 +88,26 @@ namespace Emby.Server.Implementations.Activity
_subManager.SubtitleDownloadFailure += OnSubtitleDownloadFailure; _subManager.SubtitleDownloadFailure += OnSubtitleDownloadFailure;
_userManager.UserCreated += OnUserCreated; _userManager.OnUserCreated += OnUserCreated;
_userManager.UserPasswordChanged += OnUserPasswordChanged; _userManager.OnUserPasswordChanged += OnUserPasswordChanged;
_userManager.UserDeleted += OnUserDeleted; _userManager.OnUserDeleted += OnUserDeleted;
_userManager.UserPolicyUpdated += OnUserPolicyUpdated; _userManager.OnUserLockedOut += OnUserLockedOut;
_userManager.UserLockedOut += OnUserLockedOut;
return Task.CompletedTask; return Task.CompletedTask;
} }
private async void OnUserLockedOut(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e) private async void OnUserLockedOut(object sender, GenericEventArgs<User> e)
{ {
await CreateLogEntry(new ActivityLog( await CreateLogEntry(new ActivityLog(
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserLockedOutWithName"), _localization.GetLocalizedString("UserLockedOutWithName"),
e.Argument.Name), e.Argument.Username),
NotificationType.UserLockedOut.ToString(), NotificationType.UserLockedOut.ToString(),
e.Argument.Id)) e.Argument.Id)
.ConfigureAwait(false); {
LogSeverity = LogLevel.Error
}).ConfigureAwait(false);
} }
private async void OnSubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e) private async void OnSubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e)
@ -152,7 +153,7 @@ namespace Emby.Server.Implementations.Activity
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), _localization.GetLocalizedString("UserStoppedPlayingItemWithValues"),
user.Name, user.Username,
GetItemName(item), GetItemName(item),
e.DeviceName), e.DeviceName),
GetPlaybackStoppedNotificationType(item.MediaType), GetPlaybackStoppedNotificationType(item.MediaType),
@ -187,7 +188,7 @@ namespace Emby.Server.Implementations.Activity
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), _localization.GetLocalizedString("UserStartedPlayingItemWithValues"),
user.Name, user.Username,
GetItemName(item), GetItemName(item),
e.DeviceName), e.DeviceName),
GetPlaybackNotificationType(item.MediaType), GetPlaybackNotificationType(item.MediaType),
@ -304,49 +305,37 @@ namespace Emby.Server.Implementations.Activity
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
private async void OnUserPolicyUpdated(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e) private async void OnUserDeleted(object sender, GenericEventArgs<User> e)
{
await CreateLogEntry(new ActivityLog(
string.Format(
CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserPolicyUpdatedWithName"),
e.Argument.Name),
"UserPolicyUpdated",
e.Argument.Id))
.ConfigureAwait(false);
}
private async void OnUserDeleted(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e)
{ {
await CreateLogEntry(new ActivityLog( await CreateLogEntry(new ActivityLog(
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserDeletedWithName"), _localization.GetLocalizedString("UserDeletedWithName"),
e.Argument.Name), e.Argument.Username),
"UserDeleted", "UserDeleted",
Guid.Empty)) Guid.Empty))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
private async void OnUserPasswordChanged(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e) private async void OnUserPasswordChanged(object sender, GenericEventArgs<User> e)
{ {
await CreateLogEntry(new ActivityLog( await CreateLogEntry(new ActivityLog(
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserPasswordChangedWithName"), _localization.GetLocalizedString("UserPasswordChangedWithName"),
e.Argument.Name), e.Argument.Username),
"UserPasswordChanged", "UserPasswordChanged",
e.Argument.Id)) e.Argument.Id))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
private async void OnUserCreated(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e) private async void OnUserCreated(object sender, GenericEventArgs<User> e)
{ {
await CreateLogEntry(new ActivityLog( await CreateLogEntry(new ActivityLog(
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserCreatedWithName"), _localization.GetLocalizedString("UserCreatedWithName"),
e.Argument.Name), e.Argument.Username),
"UserCreated", "UserCreated",
e.Argument.Id)) e.Argument.Id))
.ConfigureAwait(false); .ConfigureAwait(false);
@ -510,11 +499,10 @@ namespace Emby.Server.Implementations.Activity
_subManager.SubtitleDownloadFailure -= OnSubtitleDownloadFailure; _subManager.SubtitleDownloadFailure -= OnSubtitleDownloadFailure;
_userManager.UserCreated -= OnUserCreated; _userManager.OnUserCreated -= OnUserCreated;
_userManager.UserPasswordChanged -= OnUserPasswordChanged; _userManager.OnUserPasswordChanged -= OnUserPasswordChanged;
_userManager.UserDeleted -= OnUserDeleted; _userManager.OnUserDeleted -= OnUserDeleted;
_userManager.UserPolicyUpdated -= OnUserPolicyUpdated; _userManager.OnUserLockedOut -= OnUserLockedOut;
_userManager.UserLockedOut -= OnUserLockedOut;
} }
/// <summary> /// <summary>

@ -562,11 +562,8 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>(); serviceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>();
serviceCollection.AddSingleton<IUserRepository, SqliteUserRepository>();
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
serviceCollection.AddTransient(provider => new Lazy<IDtoService>(provider.GetRequiredService<IDtoService>)); serviceCollection.AddTransient(provider => new Lazy<IDtoService>(provider.GetRequiredService<IDtoService>));
serviceCollection.AddSingleton<IUserManager, UserManager>();
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
// TODO: Add StartupOptions.FFmpegPath to IConfiguration and remove this custom activation // TODO: Add StartupOptions.FFmpegPath to IConfiguration and remove this custom activation
@ -659,15 +656,11 @@ namespace Emby.Server.Implementations
((SqliteDisplayPreferencesRepository)Resolve<IDisplayPreferencesRepository>()).Initialize(); ((SqliteDisplayPreferencesRepository)Resolve<IDisplayPreferencesRepository>()).Initialize();
((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize(); ((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize();
((SqliteUserRepository)Resolve<IUserRepository>()).Initialize();
SetStaticProperties(); SetStaticProperties();
var userManager = (UserManager)Resolve<IUserManager>();
userManager.Initialize();
var userDataRepo = (SqliteUserDataRepository)Resolve<IUserDataRepository>(); var userDataRepo = (SqliteUserDataRepository)Resolve<IUserDataRepository>();
((SqliteItemRepository)Resolve<IItemRepository>()).Initialize(userDataRepo, userManager); ((SqliteItemRepository)Resolve<IItemRepository>()).Initialize(userDataRepo, Resolve<IUserManager>());
FindParts(); FindParts();
} }
@ -750,7 +743,6 @@ namespace Emby.Server.Implementations
BaseItem.ProviderManager = Resolve<IProviderManager>(); BaseItem.ProviderManager = Resolve<IProviderManager>();
BaseItem.LocalizationManager = Resolve<ILocalizationManager>(); BaseItem.LocalizationManager = Resolve<ILocalizationManager>();
BaseItem.ItemRepository = Resolve<IItemRepository>(); BaseItem.ItemRepository = Resolve<IItemRepository>();
User.UserManager = Resolve<IUserManager>();
BaseItem.FileSystem = _fileSystemManager; BaseItem.FileSystem = _fileSystemManager;
BaseItem.UserDataManager = Resolve<IUserDataManager>(); BaseItem.UserDataManager = Resolve<IUserDataManager>();
BaseItem.ChannelManager = Resolve<IChannelManager>(); BaseItem.ChannelManager = Resolve<IChannelManager>();

@ -6,6 +6,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress; using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
@ -13,8 +14,6 @@ using MediaBrowser.Controller.Configuration;
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;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Channels; using MediaBrowser.Model.Channels;
@ -24,6 +23,11 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
using Season = MediaBrowser.Controller.Entities.TV.Season;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace Emby.Server.Implementations.Channels namespace Emby.Server.Implementations.Channels
{ {
@ -791,7 +795,8 @@ namespace Emby.Server.Implementations.Channels
return result; return result;
} }
private async Task<ChannelItemResult> GetChannelItems(IChannel channel, private async Task<ChannelItemResult> GetChannelItems(
IChannel channel,
User user, User user,
string externalFolderId, string externalFolderId,
ChannelItemSortField? sortField, ChannelItemSortField? sortField,
@ -1067,7 +1072,7 @@ namespace Emby.Server.Implementations.Channels
} }
// was used for status // was used for status
//if (!string.Equals(item.ExternalEtag ?? string.Empty, info.Etag ?? string.Empty, StringComparison.Ordinal)) // if (!string.Equals(item.ExternalEtag ?? string.Empty, info.Etag ?? string.Empty, StringComparison.Ordinal))
//{ //{
// item.ExternalEtag = info.Etag; // item.ExternalEtag = info.Etag;
// forceUpdate = true; // forceUpdate = true;

@ -5,6 +5,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;

@ -162,7 +162,6 @@ namespace Emby.Server.Implementations.Data
} }
return false; return false;
}, ReadTransactionMode); }, ReadTransactionMode);
} }

@ -51,7 +51,6 @@ namespace Emby.Server.Implementations.Data
_libraryManager.DeleteItem(item, new DeleteOptions _libraryManager.DeleteItem(item, new DeleteOptions
{ {
DeleteFileLocation = false DeleteFileLocation = false
}); });
} }

@ -1,4 +1,4 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

@ -321,7 +321,6 @@ namespace Emby.Server.Implementations.Data
AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames); AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames);
AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames); AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames);
AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames); AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames);
}, TransactionMode); }, TransactionMode);
connection.RunQueries(postQueries); connection.RunQueries(postQueries);
@ -2044,7 +2043,6 @@ namespace Emby.Server.Implementations.Data
db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob); db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob);
InsertChapters(idBlob, chapters, db); InsertChapters(idBlob, chapters, db);
}, TransactionMode); }, TransactionMode);
} }
} }
@ -4360,7 +4358,7 @@ namespace Emby.Server.Implementations.Data
// TODO this seems to be an idea for a better schema where ProviderIds are their own table // TODO this seems to be an idea for a better schema where ProviderIds are their own table
// buut this is not implemented // buut this is not implemented
//hasProviderIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")"); // hasProviderIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")");
// TODO this is a really BAD way to do it since the pair: // TODO this is a really BAD way to do it since the pair:
// Tmdb, 1234 matches Tmdb=1234 but also Tmdb=1234567 // Tmdb, 1234 matches Tmdb=1234 but also Tmdb=1234567
@ -4789,7 +4787,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
connection.RunInTransaction(db => connection.RunInTransaction(db =>
{ {
connection.ExecuteAll(sql); connection.ExecuteAll(sql);
}, TransactionMode); }, TransactionMode);
} }
} }
@ -5180,7 +5177,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
} }
} }
} }
} }
LogQueryTime("GetItemValueNames", commandText, now); LogQueryTime("GetItemValueNames", commandText, now);
@ -5631,7 +5627,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
db.Execute("delete from People where ItemId=@ItemId", itemIdBlob); db.Execute("delete from People where ItemId=@ItemId", itemIdBlob);
InsertPeople(itemIdBlob, people, db); InsertPeople(itemIdBlob, people, db);
}, TransactionMode); }, TransactionMode);
} }
} }
@ -5788,7 +5783,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob); db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob);
InsertMediaStreams(itemIdBlob, streams, db); InsertMediaStreams(itemIdBlob, streams, db);
}, TransactionMode); }, TransactionMode);
} }
} }
@ -6134,7 +6128,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob); db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob);
InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken); InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken);
}, TransactionMode); }, TransactionMode);
} }
} }

@ -4,6 +4,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
@ -346,7 +347,7 @@ namespace Emby.Server.Implementations.Data
var userData = new UserItemData(); var userData = new UserItemData();
userData.Key = reader[0].ToString(); userData.Key = reader[0].ToString();
//userData.UserId = reader[1].ReadGuidFromBlob(); // userData.UserId = reader[1].ReadGuidFromBlob();
if (reader[2].SQLiteType != SQLiteType.Null) if (reader[2].SQLiteType != SQLiteType.Null)
{ {

@ -1,240 +0,0 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using MediaBrowser.Common.Json;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Persistence;
using Microsoft.Extensions.Logging;
using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Data
{
/// <summary>
/// Class SQLiteUserRepository
/// </summary>
public class SqliteUserRepository : BaseSqliteRepository, IUserRepository
{
private readonly JsonSerializerOptions _jsonOptions;
public SqliteUserRepository(
ILogger<SqliteUserRepository> logger,
IServerApplicationPaths appPaths)
: base(logger)
{
_jsonOptions = JsonDefaults.GetOptions();
DbFilePath = Path.Combine(appPaths.DataPath, "users.db");
}
/// <summary>
/// Gets the name of the repository
/// </summary>
/// <value>The name.</value>
public string Name => "SQLite";
/// <summary>
/// Opens the connection to the database.
/// </summary>
public void Initialize()
{
using (var connection = GetConnection())
{
var localUsersTableExists = TableExists(connection, "LocalUsersv2");
connection.RunQueries(new[] {
"create table if not exists LocalUsersv2 (Id INTEGER PRIMARY KEY, guid GUID NOT NULL, data BLOB NOT NULL)",
"drop index if exists idx_users"
});
if (!localUsersTableExists && TableExists(connection, "Users"))
{
TryMigrateToLocalUsersTable(connection);
}
RemoveEmptyPasswordHashes(connection);
}
}
private void TryMigrateToLocalUsersTable(ManagedConnection connection)
{
try
{
connection.RunQueries(new[]
{
"INSERT INTO LocalUsersv2 (guid, data) SELECT guid,data from users"
});
}
catch (Exception ex)
{
Logger.LogError(ex, "Error migrating users database");
}
}
private void RemoveEmptyPasswordHashes(ManagedConnection connection)
{
foreach (var user in RetrieveAllUsers(connection))
{
// If the user password is the sha1 hash of the empty string, remove it
if (!string.Equals(user.Password, "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", StringComparison.Ordinal)
&& !string.Equals(user.Password, "$SHA1$DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", StringComparison.Ordinal))
{
continue;
}
user.Password = null;
var serialized = JsonSerializer.SerializeToUtf8Bytes(user, _jsonOptions);
connection.RunInTransaction(db =>
{
using (var statement = db.PrepareStatement("update LocalUsersv2 set data=@data where Id=@InternalId"))
{
statement.TryBind("@InternalId", user.InternalId);
statement.TryBind("@data", serialized);
statement.MoveNext();
}
}, TransactionMode);
}
}
/// <summary>
/// Save a user in the repo
/// </summary>
public void CreateUser(User user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
var serialized = JsonSerializer.SerializeToUtf8Bytes(user, _jsonOptions);
using (var connection = GetConnection())
{
connection.RunInTransaction(db =>
{
using (var statement = db.PrepareStatement("insert into LocalUsersv2 (guid, data) values (@guid, @data)"))
{
statement.TryBind("@guid", user.Id.ToByteArray());
statement.TryBind("@data", serialized);
statement.MoveNext();
}
var createdUser = GetUser(user.Id, connection);
if (createdUser == null)
{
throw new ApplicationException("created user should never be null");
}
user.InternalId = createdUser.InternalId;
}, TransactionMode);
}
}
public void UpdateUser(User user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
var serialized = JsonSerializer.SerializeToUtf8Bytes(user, _jsonOptions);
using (var connection = GetConnection())
{
connection.RunInTransaction(db =>
{
using (var statement = db.PrepareStatement("update LocalUsersv2 set data=@data where Id=@InternalId"))
{
statement.TryBind("@InternalId", user.InternalId);
statement.TryBind("@data", serialized);
statement.MoveNext();
}
}, TransactionMode);
}
}
private User GetUser(Guid guid, ManagedConnection connection)
{
using (var statement = connection.PrepareStatement("select id,guid,data from LocalUsersv2 where guid=@guid"))
{
statement.TryBind("@guid", guid);
foreach (var row in statement.ExecuteQuery())
{
return GetUser(row);
}
}
return null;
}
private User GetUser(IReadOnlyList<IResultSetValue> row)
{
var id = row[0].ToInt64();
var guid = row[1].ReadGuidFromBlob();
var user = JsonSerializer.Deserialize<User>(row[2].ToBlob(), _jsonOptions);
user.InternalId = id;
user.Id = guid;
return user;
}
/// <summary>
/// Retrieve all users from the database
/// </summary>
/// <returns>IEnumerable{User}.</returns>
public List<User> RetrieveAllUsers()
{
using (var connection = GetConnection(true))
{
return new List<User>(RetrieveAllUsers(connection));
}
}
/// <summary>
/// Retrieve all users from the database
/// </summary>
/// <returns>IEnumerable{User}.</returns>
private IEnumerable<User> RetrieveAllUsers(ManagedConnection connection)
{
foreach (var row in connection.Query("select id,guid,data from LocalUsersv2"))
{
yield return GetUser(row);
}
}
/// <summary>
/// Deletes the user.
/// </summary>
/// <param name="user">The user.</param>
/// <returns>Task.</returns>
/// <exception cref="ArgumentNullException">user</exception>
public void DeleteUser(User user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
using (var connection = GetConnection())
{
connection.RunInTransaction(db =>
{
using (var statement = db.PrepareStatement("delete from LocalUsersv2 where Id=@id"))
{
statement.TryBind("@id", user.InternalId);
statement.MoveNext();
}
}, TransactionMode);
}
}
}
}

@ -5,10 +5,11 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;
using MediaBrowser.Model.Devices; using MediaBrowser.Model.Devices;
@ -16,7 +17,6 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;
using MediaBrowser.Model.Users;
namespace Emby.Server.Implementations.Devices namespace Emby.Server.Implementations.Devices
{ {
@ -27,11 +27,10 @@ namespace Emby.Server.Implementations.Devices
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly IAuthenticationRepository _authRepo; private readonly IAuthenticationRepository _authRepo;
private readonly Dictionary<string, ClientCapabilities> _capabilitiesCache; private readonly Dictionary<string, ClientCapabilities> _capabilitiesCache;
private readonly object _capabilitiesSyncLock = new object();
public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated; public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
private readonly object _capabilitiesSyncLock = new object();
public DeviceManager( public DeviceManager(
IAuthenticationRepository authRepo, IAuthenticationRepository authRepo,
IJsonSerializer json, IJsonSerializer json,
@ -113,7 +112,7 @@ namespace Emby.Server.Implementations.Devices
{ {
IEnumerable<AuthenticationInfo> sessions = _authRepo.Get(new AuthenticationInfoQuery IEnumerable<AuthenticationInfo> sessions = _authRepo.Get(new AuthenticationInfoQuery
{ {
//UserId = query.UserId // UserId = query.UserId
HasUser = true HasUser = true
}).Items; }).Items;
@ -175,7 +174,12 @@ namespace Emby.Server.Implementations.Devices
throw new ArgumentNullException(nameof(deviceId)); throw new ArgumentNullException(nameof(deviceId));
} }
if (!CanAccessDevice(user.Policy, deviceId)) if (user.HasPermission(PermissionKind.EnableAllDevices) || user.HasPermission(PermissionKind.IsAdministrator))
{
return true;
}
if (!user.GetPreference(PreferenceKind.EnabledDevices).Contains(deviceId, StringComparer.OrdinalIgnoreCase))
{ {
var capabilities = GetCapabilities(deviceId); var capabilities = GetCapabilities(deviceId);
@ -187,20 +191,5 @@ namespace Emby.Server.Implementations.Devices
return true; return true;
} }
private static bool CanAccessDevice(UserPolicy policy, string id)
{
if (policy.EnableAllDevices)
{
return true;
}
if (policy.IsAdministrator)
{
return true;
}
return policy.EnabledDevices.Contains(id, StringComparer.OrdinalIgnoreCase);
}
} }
} }

@ -6,14 +6,14 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common; using MediaBrowser.Common;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
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.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
@ -24,6 +24,14 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Book = MediaBrowser.Controller.Entities.Book;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
using Person = MediaBrowser.Controller.Entities.Person;
using Photo = MediaBrowser.Controller.Entities.Photo;
using Season = MediaBrowser.Controller.Entities.TV.Season;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace Emby.Server.Implementations.Dto namespace Emby.Server.Implementations.Dto
{ {
@ -384,7 +392,7 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.ChildCount)) if (options.ContainsField(ItemFields.ChildCount))
{ {
dto.ChildCount = dto.ChildCount ?? GetChildCount(folder, user); dto.ChildCount ??= GetChildCount(folder, user);
} }
} }
@ -398,7 +406,6 @@ namespace Emby.Server.Implementations.Dto
dto.DateLastMediaAdded = folder.DateLastMediaAdded; dto.DateLastMediaAdded = folder.DateLastMediaAdded;
} }
} }
else else
{ {
if (options.EnableUserData) if (options.EnableUserData)
@ -414,7 +421,7 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.BasicSyncInfo)) if (options.ContainsField(ItemFields.BasicSyncInfo))
{ {
var userCanSync = user != null && user.Policy.EnableContentDownloading; var userCanSync = user != null && user.HasPermission(PermissionKind.EnableContentDownloading);
if (userCanSync && item.SupportsExternalTransfer) if (userCanSync && item.SupportsExternalTransfer)
{ {
dto.SupportsSync = true; dto.SupportsSync = true;
@ -586,7 +593,6 @@ namespace Emby.Server.Implementations.Dto
_logger.LogError(ex, "Error getting person {Name}", c); _logger.LogError(ex, "Error getting person {Name}", c);
return null; return null;
} }
}).Where(i => i != null) }).Where(i => i != null)
.GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase) .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
.Select(x => x.First()) .Select(x => x.First())
@ -939,7 +945,7 @@ namespace Emby.Server.Implementations.Dto
dto.AlbumPrimaryImageTag = GetTagAndFillBlurhash(dto, albumParent, ImageType.Primary); dto.AlbumPrimaryImageTag = GetTagAndFillBlurhash(dto, albumParent, ImageType.Primary);
} }
//if (options.ContainsField(ItemFields.MediaSourceCount)) // if (options.ContainsField(ItemFields.MediaSourceCount))
//{ //{
// Songs always have one // Songs always have one
//} //}
@ -949,13 +955,13 @@ namespace Emby.Server.Implementations.Dto
{ {
dto.Artists = hasArtist.Artists; dto.Artists = hasArtist.Artists;
//var artistItems = _libraryManager.GetArtists(new InternalItemsQuery // var artistItems = _libraryManager.GetArtists(new InternalItemsQuery
//{ //{
// EnableTotalRecordCount = false, // EnableTotalRecordCount = false,
// ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) } // ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) }
//}); //});
//dto.ArtistItems = artistItems.Items // dto.ArtistItems = artistItems.Items
// .Select(i => // .Select(i =>
// { // {
// var artist = i.Item1; // var artist = i.Item1;
@ -968,7 +974,7 @@ namespace Emby.Server.Implementations.Dto
// .ToList(); // .ToList();
// Include artists that are not in the database yet, e.g., just added via metadata editor // Include artists that are not in the database yet, e.g., just added via metadata editor
//var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList(); // var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList();
dto.ArtistItems = hasArtist.Artists dto.ArtistItems = hasArtist.Artists
//.Except(foundArtists, new DistinctNameComparer()) //.Except(foundArtists, new DistinctNameComparer())
.Select(i => .Select(i =>
@ -993,7 +999,6 @@ namespace Emby.Server.Implementations.Dto
} }
return null; return null;
}).Where(i => i != null).ToArray(); }).Where(i => i != null).ToArray();
} }
@ -1002,13 +1007,13 @@ namespace Emby.Server.Implementations.Dto
{ {
dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault(); dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault();
//var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery // var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery
//{ //{
// EnableTotalRecordCount = false, // EnableTotalRecordCount = false,
// ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) } // ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) }
//}); //});
//dto.AlbumArtists = artistItems.Items // dto.AlbumArtists = artistItems.Items
// .Select(i => // .Select(i =>
// { // {
// var artist = i.Item1; // var artist = i.Item1;
@ -1044,7 +1049,6 @@ namespace Emby.Server.Implementations.Dto
} }
return null; return null;
}).Where(i => i != null).ToArray(); }).Where(i => i != null).ToArray();
} }
@ -1158,7 +1162,7 @@ namespace Emby.Server.Implementations.Dto
// this block will add the series poster for episodes without a poster // this block will add the series poster for episodes without a poster
// TODO maybe remove the if statement entirely // TODO maybe remove the if statement entirely
//if (options.ContainsField(ItemFields.SeriesPrimaryImage)) // if (options.ContainsField(ItemFields.SeriesPrimaryImage))
{ {
episodeSeries = episodeSeries ?? episode.Series; episodeSeries = episodeSeries ?? episode.Series;
if (episodeSeries != null) if (episodeSeries != null)
@ -1204,7 +1208,7 @@ namespace Emby.Server.Implementations.Dto
// this block will add the series poster for seasons without a poster // this block will add the series poster for seasons without a poster
// TODO maybe remove the if statement entirely // TODO maybe remove the if statement entirely
//if (options.ContainsField(ItemFields.SeriesPrimaryImage)) // if (options.ContainsField(ItemFields.SeriesPrimaryImage))
{ {
series = series ?? season.Series; series = series ?? season.Series;
if (series != null) if (series != null)

@ -6,6 +6,7 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
@ -131,7 +132,6 @@ namespace Emby.Server.Implementations.EntryPoints
} }
catch catch
{ {
} }
} }
} }

@ -4,6 +4,7 @@ using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Plugins;
@ -64,7 +65,7 @@ namespace Emby.Server.Implementations.EntryPoints
private async Task SendMessage(string name, TimerEventInfo info) private async Task SendMessage(string name, TimerEventInfo info)
{ {
var users = _userManager.Users.Where(i => i.Policy.EnableLiveTvAccess).Select(i => i.Id).ToList(); var users = _userManager.Users.Where(i => i.HasPermission(PermissionKind.EnableLiveTvAccess)).Select(i => i.Id).ToList();
try try
{ {

@ -1,77 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Tasks;
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
/// Class RefreshUsersMetadata.
/// </summary>
public class RefreshUsersMetadata : IScheduledTask, IConfigurableScheduledTask
{
/// <summary>
/// The user manager.
/// </summary>
private readonly IUserManager _userManager;
private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class.
/// </summary>
public RefreshUsersMetadata(IUserManager userManager, IFileSystem fileSystem)
{
_userManager = userManager;
_fileSystem = fileSystem;
}
/// <inheritdoc />
public string Name => "Refresh Users";
/// <inheritdoc />
public string Key => "RefreshUsers";
/// <inheritdoc />
public string Description => "Refresh user infos";
/// <inheritdoc />
public string Category => "Library";
/// <inheritdoc />
public bool IsHidden => true;
/// <inheritdoc />
public bool IsEnabled => true;
/// <inheritdoc />
public bool IsLogged => true;
/// <inheritdoc />
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
foreach (var user in _userManager.Users)
{
cancellationToken.ThrowIfCancellationRequested();
await user.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_fileSystem)), cancellationToken).ConfigureAwait(false);
}
}
/// <inheritdoc />
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
return new[]
{
new TaskTriggerInfo
{
IntervalTicks = TimeSpan.FromDays(1).Ticks,
Type = TaskTriggerInfo.TriggerInterval
}
};
}
}
}

@ -3,10 +3,10 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Updates; using MediaBrowser.Common.Updates;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
@ -68,10 +68,8 @@ namespace Emby.Server.Implementations.EntryPoints
/// <inheritdoc /> /// <inheritdoc />
public Task RunAsync() public Task RunAsync()
{ {
_userManager.UserDeleted += OnUserDeleted; _userManager.OnUserDeleted += OnUserDeleted;
_userManager.UserUpdated += OnUserUpdated; _userManager.OnUserUpdated += OnUserUpdated;
_userManager.UserPolicyUpdated += OnUserPolicyUpdated;
_userManager.UserConfigurationUpdated += OnUserConfigurationUpdated;
_appHost.HasPendingRestartChanged += OnHasPendingRestartChanged; _appHost.HasPendingRestartChanged += OnHasPendingRestartChanged;
@ -153,20 +151,6 @@ namespace Emby.Server.Implementations.EntryPoints
await SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture)).ConfigureAwait(false); await SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture)).ConfigureAwait(false);
} }
private async void OnUserPolicyUpdated(object sender, GenericEventArgs<User> e)
{
var dto = _userManager.GetUserDto(e.Argument);
await SendMessageToUserSession(e.Argument, "UserPolicyUpdated", dto).ConfigureAwait(false);
}
private async void OnUserConfigurationUpdated(object sender, GenericEventArgs<User> e)
{
var dto = _userManager.GetUserDto(e.Argument);
await SendMessageToUserSession(e.Argument, "UserConfigurationUpdated", dto).ConfigureAwait(false);
}
private async Task SendMessageToAdminSessions<T>(string name, T data) private async Task SendMessageToAdminSessions<T>(string name, T data)
{ {
try try
@ -175,7 +159,6 @@ namespace Emby.Server.Implementations.EntryPoints
} }
catch (Exception) catch (Exception)
{ {
} }
} }
@ -191,7 +174,6 @@ namespace Emby.Server.Implementations.EntryPoints
} }
catch (Exception) catch (Exception)
{ {
} }
} }
@ -210,10 +192,8 @@ namespace Emby.Server.Implementations.EntryPoints
{ {
if (dispose) if (dispose)
{ {
_userManager.UserDeleted -= OnUserDeleted; _userManager.OnUserDeleted -= OnUserDeleted;
_userManager.UserUpdated -= OnUserUpdated; _userManager.OnUserUpdated -= OnUserUpdated;
_userManager.UserPolicyUpdated -= OnUserPolicyUpdated;
_userManager.UserConfigurationUpdated -= OnUserConfigurationUpdated;
_installationManager.PluginUninstalled -= OnPluginUninstalled; _installationManager.PluginUninstalled -= OnPluginUninstalled;
_installationManager.PackageInstalling -= OnPackageInstalling; _installationManager.PackageInstalling -= OnPackageInstalling;

@ -43,7 +43,6 @@ namespace Emby.Server.Implementations.EntryPoints
_logger = logger; _logger = logger;
_appHost = appHost; _appHost = appHost;
_config = configuration; _config = configuration;
} }
/// <inheritdoc /> /// <inheritdoc />

@ -580,7 +580,6 @@ namespace Emby.Server.Implementations.HttpServer
} }
catch (NotSupportedException) catch (NotSupportedException)
{ {
} }
} }

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Text; using System.Text;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;

@ -3,10 +3,11 @@
using System; using System;
using System.Linq; using System.Linq;
using Emby.Server.Implementations.SocketSharp; using Emby.Server.Implementations.SocketSharp;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
@ -90,7 +91,8 @@ namespace Emby.Server.Implementations.HttpServer.Security
!string.IsNullOrEmpty(auth.Client) && !string.IsNullOrEmpty(auth.Client) &&
!string.IsNullOrEmpty(auth.Device)) !string.IsNullOrEmpty(auth.Device))
{ {
_sessionManager.LogSessionActivity(auth.Client, _sessionManager.LogSessionActivity(
auth.Client,
auth.Version, auth.Version,
auth.DeviceId, auth.DeviceId,
auth.Device, auth.Device,
@ -104,21 +106,21 @@ namespace Emby.Server.Implementations.HttpServer.Security
private void ValidateUserAccess( private void ValidateUserAccess(
User user, User user,
IRequest request, IRequest request,
IAuthenticationAttributes authAttribtues, IAuthenticationAttributes authAttributes,
AuthorizationInfo auth) AuthorizationInfo auth)
{ {
if (user.Policy.IsDisabled) if (user.HasPermission(PermissionKind.IsDisabled))
{ {
throw new SecurityException("User account has been disabled."); throw new SecurityException("User account has been disabled.");
} }
if (!user.Policy.EnableRemoteAccess && !_networkManager.IsInLocalNetwork(request.RemoteIp)) if (!user.HasPermission(PermissionKind.EnableRemoteAccess) && !_networkManager.IsInLocalNetwork(request.RemoteIp))
{ {
throw new SecurityException("User account has been disabled."); throw new SecurityException("User account has been disabled.");
} }
if (!user.Policy.IsAdministrator if (!user.HasPermission(PermissionKind.IsAdministrator)
&& !authAttribtues.EscapeParentalControl && !authAttributes.EscapeParentalControl
&& !user.IsParentalScheduleAllowed()) && !user.IsParentalScheduleAllowed())
{ {
request.Response.Headers.Add("X-Application-Error-Code", "ParentalControl"); request.Response.Headers.Add("X-Application-Error-Code", "ParentalControl");
@ -180,7 +182,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
{ {
if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase)) if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase))
{ {
if (user == null || !user.Policy.IsAdministrator) if (user == null || !user.HasPermission(PermissionKind.IsAdministrator))
{ {
throw new SecurityException("User does not have admin access."); throw new SecurityException("User does not have admin access.");
} }
@ -188,7 +190,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
if (roles.Contains("delete", StringComparer.OrdinalIgnoreCase)) if (roles.Contains("delete", StringComparer.OrdinalIgnoreCase))
{ {
if (user == null || !user.Policy.EnableContentDeletion) if (user == null || !user.HasPermission(PermissionKind.EnableContentDeletion))
{ {
throw new SecurityException("User does not have delete access."); throw new SecurityException("User does not have delete access.");
} }
@ -196,7 +198,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
if (roles.Contains("download", StringComparer.OrdinalIgnoreCase)) if (roles.Contains("download", StringComparer.OrdinalIgnoreCase))
{ {
if (user == null || !user.Policy.EnableContentDownloading) if (user == null || !user.HasPermission(PermissionKind.EnableContentDownloading))
{ {
throw new SecurityException("User does not have download access."); throw new SecurityException("User does not have download access.");
} }
@ -223,7 +225,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
throw new AuthenticationException("Access token is invalid or expired."); throw new AuthenticationException("Access token is invalid or expired.");
} }
//if (!string.IsNullOrEmpty(info.UserId)) // if (!string.IsNullOrEmpty(info.UserId))
//{ //{
// var user = _userManager.GetUserById(info.UserId); // var user = _userManager.GetUserById(info.UserId);

@ -116,7 +116,6 @@ namespace Emby.Server.Implementations.HttpServer.Security
{ {
info.Device = tokenInfo.DeviceName; info.Device = tokenInfo.DeviceName;
} }
else if (!string.Equals(info.Device, tokenInfo.DeviceName, StringComparison.OrdinalIgnoreCase)) else if (!string.Equals(info.Device, tokenInfo.DeviceName, StringComparison.OrdinalIgnoreCase))
{ {
if (allowTokenInfoUpdate) if (allowTokenInfoUpdate)
@ -149,9 +148,9 @@ namespace Emby.Server.Implementations.HttpServer.Security
{ {
info.User = _userManager.GetUserById(tokenInfo.UserId); info.User = _userManager.GetUserById(tokenInfo.UserId);
if (info.User != null && !string.Equals(info.User.Name, tokenInfo.UserName, StringComparison.OrdinalIgnoreCase)) if (info.User != null && !string.Equals(info.User.Username, tokenInfo.UserName, StringComparison.OrdinalIgnoreCase))
{ {
tokenInfo.UserName = info.User.Name; tokenInfo.UserName = info.User.Username;
updateToken = true; updateToken = true;
} }
} }

@ -1,7 +1,7 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using MediaBrowser.Controller.Entities; using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;

@ -234,10 +234,12 @@ namespace Emby.Server.Implementations.HttpServer
private Task SendKeepAliveResponse() private Task SendKeepAliveResponse()
{ {
LastKeepAliveDate = DateTime.UtcNow; LastKeepAliveDate = DateTime.UtcNow;
return SendAsync(new WebSocketMessage<string> return SendAsync(
{ new WebSocketMessage<string>
MessageType = "KeepAlive" {
}, CancellationToken.None); MessageId = Guid.NewGuid(),
MessageType = "KeepAlive"
}, CancellationToken.None);
} }
/// <inheritdoc /> /// <inheritdoc />

@ -266,7 +266,6 @@ namespace Emby.Server.Implementations.IO
{ {
DisposeWatcher(newWatcher, false); DisposeWatcher(newWatcher, false);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -393,7 +392,6 @@ namespace Emby.Server.Implementations.IO
} }
return false; return false;
})) }))
{ {
monitorPath = false; monitorPath = false;

@ -237,7 +237,7 @@ namespace Emby.Server.Implementations.IO
{ {
result.IsDirectory = info is DirectoryInfo || (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory; result.IsDirectory = info is DirectoryInfo || (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory;
//if (!result.IsDirectory) // if (!result.IsDirectory)
//{ //{
// result.IsHidden = (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden; // result.IsHidden = (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
//} //}

@ -71,7 +71,6 @@ namespace Emby.Server.Implementations.Images
new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending) new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)
}, },
IncludeItemTypes = includeItemTypes IncludeItemTypes = includeItemTypes
}); });
} }

@ -78,7 +78,6 @@ namespace Emby.Server.Implementations.Images
} }
return i; return i;
}).GroupBy(x => x.Id) }).GroupBy(x => x.Id)
.Select(x => x.First()); .Select(x => x.First());

@ -17,6 +17,8 @@ using Emby.Server.Implementations.Library.Resolvers;
using Emby.Server.Implementations.Library.Validators; using Emby.Server.Implementations.Library.Validators;
using Emby.Server.Implementations.Playlists; using Emby.Server.Implementations.Playlists;
using Emby.Server.Implementations.ScheduledTasks; using Emby.Server.Implementations.ScheduledTasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress; using MediaBrowser.Common.Progress;
using MediaBrowser.Controller; using MediaBrowser.Controller;
@ -25,7 +27,6 @@ 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;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO; using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
@ -46,6 +47,9 @@ using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Tasks;
using MediaBrowser.Providers.MediaInfo; using MediaBrowser.Providers.MediaInfo;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Person = MediaBrowser.Controller.Entities.Person;
using SortOrder = MediaBrowser.Model.Entities.SortOrder; using SortOrder = MediaBrowser.Model.Entities.SortOrder;
using VideoResolver = Emby.Naming.Video.VideoResolver; using VideoResolver = Emby.Naming.Video.VideoResolver;
@ -1539,7 +1543,8 @@ namespace Emby.Server.Implementations.Library
} }
// Handle grouping // Handle grouping
if (user != null && !string.IsNullOrEmpty(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType) && user.Configuration.GroupedFolders.Length > 0) if (user != null && !string.IsNullOrEmpty(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType)
&& user.GetPreference(PreferenceKind.GroupedFolders).Length > 0)
{ {
return GetUserRootFolder() return GetUserRootFolder()
.GetChildren(user, true) .GetChildren(user, true)
@ -2590,7 +2595,7 @@ namespace Emby.Server.Implementations.Library
Anime series don't generally have a season in their file name, however, Anime series don't generally have a season in their file name, however,
tvdb needs a season to correctly get the metadata. tvdb needs a season to correctly get the metadata.
Hence, a null season needs to be filled with something. */ Hence, a null season needs to be filled with something. */
//FIXME perhaps this would be better for tvdb parser to ask for season 1 if no season is specified // FIXME perhaps this would be better for tvdb parser to ask for season 1 if no season is specified
episode.ParentIndexNumber = 1; episode.ParentIndexNumber = 1;
} }
@ -2856,7 +2861,6 @@ namespace Emby.Server.Implementations.Library
_logger.LogError(ex, "Error getting person"); _logger.LogError(ex, "Error getting person");
return null; return null;
} }
}).Where(i => i != null).ToList(); }).Where(i => i != null).ToList();
} }
@ -2986,7 +2990,7 @@ namespace Emby.Server.Implementations.Library
private static bool ValidateNetworkPath(string path) private static bool ValidateNetworkPath(string path)
{ {
//if (Environment.OSVersion.Platform == PlatformID.Win32NT) // if (Environment.OSVersion.Platform == PlatformID.Win32NT)
//{ //{
// // We can't validate protocol-based paths, so just allow them // // We can't validate protocol-based paths, so just allow them
// if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1) // if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1)

@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.Library
{ {
mediaInfo = _json.DeserializeFromFile<MediaInfo>(cacheFilePath); mediaInfo = _json.DeserializeFromFile<MediaInfo>(cacheFilePath);
//_logger.LogDebug("Found cached media info"); // _logger.LogDebug("Found cached media info");
} }
catch catch
{ {
@ -85,7 +85,7 @@ namespace Emby.Server.Implementations.Library
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
_json.SerializeToFile(mediaInfo, cacheFilePath); _json.SerializeToFile(mediaInfo, cacheFilePath);
//_logger.LogDebug("Saved media info to {0}", cacheFilePath); // _logger.LogDebug("Saved media info to {0}", cacheFilePath);
} }
} }
@ -148,17 +148,14 @@ namespace Emby.Server.Implementations.Library
{ {
videoStream.BitRate = 30000000; videoStream.BitRate = 30000000;
} }
else if (width >= 1900) else if (width >= 1900)
{ {
videoStream.BitRate = 20000000; videoStream.BitRate = 20000000;
} }
else if (width >= 1200) else if (width >= 1200)
{ {
videoStream.BitRate = 8000000; videoStream.BitRate = 8000000;
} }
else if (width >= 700) else if (width >= 700)
{ {
videoStream.BitRate = 2000000; videoStream.BitRate = 2000000;

@ -7,6 +7,8 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
@ -14,7 +16,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -190,10 +191,7 @@ namespace Emby.Server.Implementations.Library
{ {
if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
{ {
if (!user.Policy.EnableAudioPlaybackTranscoding) source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding);
{
source.SupportsTranscoding = false;
}
} }
} }
} }
@ -352,7 +350,9 @@ namespace Emby.Server.Implementations.Library
private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection)
{ {
if (userData.SubtitleStreamIndex.HasValue && user.Configuration.RememberSubtitleSelections && user.Configuration.SubtitleMode != SubtitlePlaybackMode.None && allowRememberingSelection) if (userData.SubtitleStreamIndex.HasValue
&& user.RememberSubtitleSelections
&& user.SubtitleMode != SubtitlePlaybackMode.None && allowRememberingSelection)
{ {
var index = userData.SubtitleStreamIndex.Value; var index = userData.SubtitleStreamIndex.Value;
// Make sure the saved index is still valid // Make sure the saved index is still valid
@ -363,26 +363,27 @@ namespace Emby.Server.Implementations.Library
} }
} }
var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference)
? Array.Empty<string>() : NormalizeLanguage(user.Configuration.SubtitleLanguagePreference); var preferredSubs = string.IsNullOrEmpty(user.SubtitleLanguagePreference)
? Array.Empty<string>() : NormalizeLanguage(user.SubtitleLanguagePreference);
var defaultAudioIndex = source.DefaultAudioStreamIndex; var defaultAudioIndex = source.DefaultAudioStreamIndex;
var audioLangage = defaultAudioIndex == null var audioLangage = defaultAudioIndex == null
? null ? null
: source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault(); : source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault();
source.DefaultSubtitleStreamIndex = MediaStreamSelector.GetDefaultSubtitleStreamIndex(source.MediaStreams, source.DefaultSubtitleStreamIndex = MediaStreamSelector.GetDefaultSubtitleStreamIndex(
source.MediaStreams,
preferredSubs, preferredSubs,
user.Configuration.SubtitleMode, user.SubtitleMode,
audioLangage); audioLangage);
MediaStreamSelector.SetSubtitleStreamScores(source.MediaStreams, preferredSubs, MediaStreamSelector.SetSubtitleStreamScores(source.MediaStreams, preferredSubs, user.SubtitleMode, audioLangage);
user.Configuration.SubtitleMode, audioLangage);
} }
private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection)
{ {
if (userData.AudioStreamIndex.HasValue && user.Configuration.RememberAudioSelections && allowRememberingSelection) if (userData.AudioStreamIndex.HasValue && user.RememberAudioSelections && allowRememberingSelection)
{ {
var index = userData.AudioStreamIndex.Value; var index = userData.AudioStreamIndex.Value;
// Make sure the saved index is still valid // Make sure the saved index is still valid
@ -393,11 +394,11 @@ namespace Emby.Server.Implementations.Library
} }
} }
var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference) var preferredAudio = string.IsNullOrEmpty(user.AudioLanguagePreference)
? Array.Empty<string>() ? Array.Empty<string>()
: NormalizeLanguage(user.Configuration.AudioLanguagePreference); : NormalizeLanguage(user.AudioLanguagePreference);
source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.Configuration.PlayDefaultAudioTrack); source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.PlayDefaultAudioTrack);
} }
public void SetDefaultAudioAndSubtitleStreamIndexes(BaseItem item, MediaSourceInfo source, User user) public void SetDefaultAudioAndSubtitleStreamIndexes(BaseItem item, MediaSourceInfo source, User user)
@ -435,7 +436,6 @@ namespace Emby.Server.Implementations.Library
} }
return 1; return 1;
}).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
.ThenByDescending(i => .ThenByDescending(i =>
{ {
@ -534,7 +534,7 @@ namespace Emby.Server.Implementations.Library
mediaSource.RunTimeTicks = null; mediaSource.RunTimeTicks = null;
} }
var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaBrowser.Model.Entities.MediaStreamType.Audio); var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
if (audioStream == null || audioStream.Index == -1) if (audioStream == null || audioStream.Index == -1)
{ {
@ -545,7 +545,7 @@ namespace Emby.Server.Implementations.Library
mediaSource.DefaultAudioStreamIndex = audioStream.Index; mediaSource.DefaultAudioStreamIndex = audioStream.Index;
} }
var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaBrowser.Model.Entities.MediaStreamType.Video); var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
if (videoStream != null) if (videoStream != null)
{ {
if (!videoStream.BitRate.HasValue) if (!videoStream.BitRate.HasValue)
@ -556,17 +556,14 @@ namespace Emby.Server.Implementations.Library
{ {
videoStream.BitRate = 30000000; videoStream.BitRate = 30000000;
} }
else if (width >= 1900) else if (width >= 1900)
{ {
videoStream.BitRate = 20000000; videoStream.BitRate = 20000000;
} }
else if (width >= 1200) else if (width >= 1200)
{ {
videoStream.BitRate = 8000000; videoStream.BitRate = 8000000;
} }
else if (width >= 700) else if (width >= 700)
{ {
videoStream.BitRate = 2000000; videoStream.BitRate = 2000000;
@ -622,7 +619,6 @@ namespace Emby.Server.Implementations.Library
MediaSource = mediaSource, MediaSource = mediaSource,
ExtractChapters = false, ExtractChapters = false,
MediaType = DlnaProfileType.Video MediaType = DlnaProfileType.Video
}, cancellationToken).ConfigureAwait(false); }, cancellationToken).ConfigureAwait(false);
mediaSource.MediaStreams = info.MediaStreams; mediaSource.MediaStreams = info.MediaStreams;
@ -648,7 +644,7 @@ namespace Emby.Server.Implementations.Library
{ {
mediaInfo = _jsonSerializer.DeserializeFromFile<MediaInfo>(cacheFilePath); mediaInfo = _jsonSerializer.DeserializeFromFile<MediaInfo>(cacheFilePath);
//_logger.LogDebug("Found cached media info"); // _logger.LogDebug("Found cached media info");
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -670,20 +666,21 @@ namespace Emby.Server.Implementations.Library
mediaSource.AnalyzeDurationMs = 3000; mediaSource.AnalyzeDurationMs = 3000;
} }
mediaInfo = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest mediaInfo = await _mediaEncoder.GetMediaInfo(
new MediaInfoRequest
{ {
MediaSource = mediaSource, MediaSource = mediaSource,
MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
ExtractChapters = false ExtractChapters = false
},
}, cancellationToken).ConfigureAwait(false); cancellationToken).ConfigureAwait(false);
if (cacheFilePath != null) if (cacheFilePath != null)
{ {
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
_jsonSerializer.SerializeToFile(mediaInfo, cacheFilePath); _jsonSerializer.SerializeToFile(mediaInfo, cacheFilePath);
//_logger.LogDebug("Saved media info to {0}", cacheFilePath); // _logger.LogDebug("Saved media info to {0}", cacheFilePath);
} }
} }
@ -749,17 +746,14 @@ namespace Emby.Server.Implementations.Library
{ {
videoStream.BitRate = 30000000; videoStream.BitRate = 30000000;
} }
else if (width >= 1900) else if (width >= 1900)
{ {
videoStream.BitRate = 20000000; videoStream.BitRate = 20000000;
} }
else if (width >= 1200) else if (width >= 1200)
{ {
videoStream.BitRate = 8000000; videoStream.BitRate = 8000000;
} }
else if (width >= 700) else if (width >= 700)
{ {
videoStream.BitRate = 2000000; videoStream.BitRate = 2000000;

@ -3,7 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using MediaBrowser.Model.Configuration; using Jellyfin.Data.Enums;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Jellyfin.Data.Entities;
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;
@ -10,6 +11,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
@ -75,7 +77,6 @@ namespace Emby.Server.Implementations.Library
{ {
return Guid.Empty; return Guid.Empty;
} }
}).Where(i => !i.Equals(Guid.Empty)).ToArray(); }).Where(i => !i.Equals(Guid.Empty)).ToArray();
return GetInstantMixFromGenreIds(genreIds, user, dtoOptions); return GetInstantMixFromGenreIds(genreIds, user, dtoOptions);
@ -105,32 +106,27 @@ namespace Emby.Server.Implementations.Library
return GetInstantMixFromGenreIds(new[] { item.Id }, user, dtoOptions); return GetInstantMixFromGenreIds(new[] { item.Id }, user, dtoOptions);
} }
var playlist = item as Playlist; if (item is Playlist playlist)
if (playlist != null)
{ {
return GetInstantMixFromPlaylist(playlist, user, dtoOptions); return GetInstantMixFromPlaylist(playlist, user, dtoOptions);
} }
var album = item as MusicAlbum; if (item is MusicAlbum album)
if (album != null)
{ {
return GetInstantMixFromAlbum(album, user, dtoOptions); return GetInstantMixFromAlbum(album, user, dtoOptions);
} }
var artist = item as MusicArtist; if (item is MusicArtist artist)
if (artist != null)
{ {
return GetInstantMixFromArtist(artist, user, dtoOptions); return GetInstantMixFromArtist(artist, user, dtoOptions);
} }
var song = item as Audio; if (item is Audio song)
if (song != null)
{ {
return GetInstantMixFromSong(song, user, dtoOptions); return GetInstantMixFromSong(song, user, dtoOptions);
} }
var folder = item as Folder; if (item is Folder folder)
if (folder != null)
{ {
return GetInstantMixFromFolder(folder, user, dtoOptions); return GetInstantMixFromFolder(folder, user, dtoOptions);
} }

@ -209,8 +209,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
Name = parseName ? Name = parseName ?
resolvedItem.Name : resolvedItem.Name :
Path.GetFileNameWithoutExtension(firstMedia.Path), Path.GetFileNameWithoutExtension(firstMedia.Path),
//AdditionalParts = resolvedItem.Files.Skip(1).Select(i => i.Path).ToArray(), // AdditionalParts = resolvedItem.Files.Skip(1).Select(i => i.Path).ToArray(),
//LocalAlternateVersions = resolvedItem.AlternateVersions.Select(i => i.Path).ToArray() // LocalAlternateVersions = resolvedItem.AlternateVersions.Select(i => i.Path).ToArray()
}; };
result.Items.Add(libraryItem); result.Items.Add(libraryItem);

@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
// Args points to an album if parent is an Artist folder or it directly contains music // Args points to an album if parent is an Artist folder or it directly contains music
if (args.IsDirectory) if (args.IsDirectory)
{ {
// if (args.Parent is MusicArtist) return true; //saves us from testing children twice // if (args.Parent is MusicArtist) return true; // saves us from testing children twice
if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, _libraryManager)) if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, _libraryManager))
{ {
return true; return true;

@ -292,7 +292,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
} }
return true; return true;
//var blurayExtensions = new[] // var blurayExtensions = new[]
//{ //{
// ".mts", // ".mts",
// ".m2ts", // ".m2ts",
@ -300,7 +300,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
// ".mpls" // ".mpls"
//}; //};
//return directoryService.GetFiles(fullPath).Any(i => blurayExtensions.Contains(i.Extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)); // return directoryService.GetFiles(fullPath).Any(i => blurayExtensions.Contains(i.Extension ?? string.Empty, StringComparer.OrdinalIgnoreCase));
} }
} }
} }

@ -43,7 +43,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
} }
if (string.Equals(args.Path, _appPaths.DefaultUserViewsPath, StringComparison.OrdinalIgnoreCase)) if (string.Equals(args.Path, _appPaths.DefaultUserViewsPath, StringComparison.OrdinalIgnoreCase))
{ {
return new UserRootFolder(); //if we got here and still a root - must be user root return new UserRootFolder(); // if we got here and still a root - must be user root
} }
if (args.IsVf) if (args.IsVf)
{ {
@ -73,7 +73,6 @@ namespace Emby.Server.Implementations.Library.Resolvers
{ {
return false; return false;
} }
}) })
.Select(i => _fileSystem.GetFileNameWithoutExtension(i)) .Select(i => _fileSystem.GetFileNameWithoutExtension(i))
.FirstOrDefault(); .FirstOrDefault();

@ -94,7 +94,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
_localization.GetLocalizedString("NameSeasonNumber"), _localization.GetLocalizedString("NameSeasonNumber"),
seasonNumber, seasonNumber,
args.GetLibraryOptions().PreferredMetadataLanguage); args.GetLibraryOptions().PreferredMetadataLanguage);
} }
return season; return season;

@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
var collectionType = args.GetCollectionType(); var collectionType = args.GetCollectionType();
if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
{ {
//if (args.ContainsFileSystemEntryByName("tvshow.nfo")) // if (args.ContainsFileSystemEntryByName("tvshow.nfo"))
//{ //{
// return new Series // return new Series
// { // {

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Jellyfin.Data.Entities;
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;
@ -12,6 +13,8 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Search; using MediaBrowser.Model.Search;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Person = MediaBrowser.Controller.Entities.Person;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
@ -204,7 +207,6 @@ namespace Emby.Server.Implementations.Library
return mediaItems.Select(i => new SearchHintInfo return mediaItems.Select(i => new SearchHintInfo
{ {
Item = i Item = i
}).ToList(); }).ToList();
} }
} }

@ -5,6 +5,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Threading; using System.Threading;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
@ -13,6 +14,7 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Book = MediaBrowser.Controller.Entities.Book;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {

File diff suppressed because it is too large Load Diff

@ -5,6 +5,8 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
@ -17,6 +19,8 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Library; using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Person = MediaBrowser.Controller.Entities.Person;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
@ -125,12 +129,12 @@ namespace Emby.Server.Implementations.Library
if (!query.IncludeHidden) if (!query.IncludeHidden)
{ {
list = list.Where(i => !user.Configuration.MyMediaExcludes.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture))).ToList(); list = list.Where(i => !user.GetPreference(PreferenceKind.MyMediaExcludes).Contains(i.Id.ToString("N", CultureInfo.InvariantCulture))).ToList();
} }
var sorted = _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList(); var sorted = _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList();
var orders = user.Configuration.OrderedViews.ToList(); var orders = user.GetPreference(PreferenceKind.OrderedViews).ToList();
return list return list
.OrderBy(i => .OrderBy(i =>
@ -165,7 +169,13 @@ namespace Emby.Server.Implementations.Library
return GetUserSubViewWithName(name, parentId, type, sortName); return GetUserSubViewWithName(name, parentId, type, sortName);
} }
private Folder GetUserView(List<ICollectionFolder> parents, string viewType, string localizationKey, string sortName, User user, string[] presetViews) private Folder GetUserView(
List<ICollectionFolder> parents,
string viewType,
string localizationKey,
string sortName,
Jellyfin.Data.Entities.User user,
string[] presetViews)
{ {
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)))
{ {
@ -270,7 +280,8 @@ namespace Emby.Server.Implementations.Library
{ {
parents = _libraryManager.GetUserRootFolder().GetChildren(user, true) parents = _libraryManager.GetUserRootFolder().GetChildren(user, true)
.Where(i => i is Folder) .Where(i => i is Folder)
.Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture))) .Where(i => !user.GetPreference(PreferenceKind.LatestItemExcludes)
.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture)))
.ToList(); .ToList();
} }
@ -331,12 +342,11 @@ namespace Emby.Server.Implementations.Library
var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Count == 0 ? new[] var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Count == 0 ? new[]
{ {
typeof(Person).Name, nameof(Person),
typeof(Studio).Name, nameof(Studio),
typeof(Year).Name, nameof(Year),
typeof(MusicGenre).Name, nameof(MusicGenre),
typeof(Genre).Name nameof(Genre)
} : Array.Empty<string>(); } : Array.Empty<string>();
var query = new InternalItemsQuery(user) var query = new InternalItemsQuery(user)

@ -98,7 +98,6 @@ namespace Emby.Server.Implementations.Library.Validators
_libraryManager.DeleteItem(item, new DeleteOptions _libraryManager.DeleteItem(item, new DeleteOptions
{ {
DeleteFileLocation = false DeleteFileLocation = false
}, false); }, false);
} }

@ -92,7 +92,6 @@ namespace Emby.Server.Implementations.Library.Validators
_libraryManager.DeleteItem(item, new DeleteOptions _libraryManager.DeleteItem(item, new DeleteOptions
{ {
DeleteFileLocation = false DeleteFileLocation = false
}, false); }, false);
} }

@ -1547,7 +1547,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
IsFolder = false, IsFolder = false,
Recursive = true, Recursive = true,
DtoOptions = new DtoOptions(true) DtoOptions = new DtoOptions(true)
}) })
.Where(i => i.IsFileProtocol && File.Exists(i.Path)) .Where(i => i.IsFileProtocol && File.Exists(i.Path))
.Skip(seriesTimer.KeepUpTo - 1) .Skip(seriesTimer.KeepUpTo - 1)

@ -183,7 +183,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var subtitleArgs = CopySubtitles ? " -codec:s copy" : " -sn"; var subtitleArgs = CopySubtitles ? " -codec:s copy" : " -sn";
//var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ? // var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ?
// " -f mp4 -movflags frag_keyframe+empty_moov" : // " -f mp4 -movflags frag_keyframe+empty_moov" :
// string.Empty; // string.Empty;
@ -206,13 +206,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{ {
return "-codec:a:0 copy"; return "-codec:a:0 copy";
//var audioChannels = 2; // var audioChannels = 2;
//var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); // var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
//if (audioStream != null) // if (audioStream != null)
//{ //{
// audioChannels = audioStream.Channels ?? audioChannels; // audioChannels = audioStream.Channels ?? audioChannels;
//} //}
//return "-codec:a:0 aac -strict experimental -ab 320000"; // return "-codec:a:0 aac -strict experimental -ab 320000";
} }
private static bool EncodeVideo(MediaSourceInfo mediaSource) private static bool EncodeVideo(MediaSourceInfo mediaSource)

@ -56,7 +56,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
name += " " + info.EpisodeTitle; name += " " + info.EpisodeTitle;
} }
} }
else if (info.IsMovie && info.ProductionYear != null) else if (info.IsMovie && info.ProductionYear != null)
{ {
name += " (" + info.ProductionYear + ")"; name += " (" + info.ProductionYear + ")";

@ -145,7 +145,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
var programsInfo = new List<ProgramInfo>(); var programsInfo = new List<ProgramInfo>();
foreach (ScheduleDirect.Program schedule in dailySchedules.SelectMany(d => d.programs)) foreach (ScheduleDirect.Program schedule in dailySchedules.SelectMany(d => d.programs))
{ {
//_logger.LogDebug("Proccesing Schedule for statio ID " + stationID + // _logger.LogDebug("Proccesing Schedule for statio ID " + stationID +
// " which corresponds to channel " + channelNumber + " and program id " + // " which corresponds to channel " + channelNumber + " and program id " +
// schedule.programID + " which says it has images? " + // schedule.programID + " which says it has images? " +
// programDict[schedule.programID].hasImageArtwork); // programDict[schedule.programID].hasImageArtwork);
@ -178,7 +178,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect); programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect);
//programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ?? // programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ??
// GetProgramImage(ApiUrl, data, "Banner-L1", false) ?? // GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
// GetProgramImage(ApiUrl, data, "Banner-LO", false) ?? // GetProgramImage(ApiUrl, data, "Banner-LO", false) ??
// GetProgramImage(ApiUrl, data, "Banner-LOT", false); // GetProgramImage(ApiUrl, data, "Banner-LOT", false);
@ -276,7 +276,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
CommunityRating = null, CommunityRating = null,
EpisodeTitle = episodeTitle, EpisodeTitle = episodeTitle,
Audio = audioType, Audio = audioType,
//IsNew = programInfo.@new ?? false, // IsNew = programInfo.@new ?? false,
IsRepeat = programInfo.@new == null, IsRepeat = programInfo.@new == null,
IsSeries = string.Equals(details.entityType, "episode", StringComparison.OrdinalIgnoreCase), IsSeries = string.Equals(details.entityType, "episode", StringComparison.OrdinalIgnoreCase),
ImageUrl = details.primaryImage, ImageUrl = details.primaryImage,
@ -701,7 +701,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
LogErrorResponseBody = true LogErrorResponseBody = true
}; };
//_logger.LogInformation("Obtaining token from Schedules Direct from addres: " + httpOptions.Url + " with body " + // _logger.LogInformation("Obtaining token from Schedules Direct from addres: " + httpOptions.Url + " with body " +
// httpOptions.RequestContent); // httpOptions.RequestContent);
using (var response = await Post(httpOptions, false, null).ConfigureAwait(false)) using (var response = await Post(httpOptions, false, null).ConfigureAwait(false))
@ -1218,7 +1218,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
public string programID { get; set; } public string programID { get; set; }
public List<ImageData> data { get; set; } public List<ImageData> data { get; set; }
} }
} }
} }
} }

@ -7,6 +7,8 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Server.Implementations.Library; using Emby.Server.Implementations.Library;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress; using MediaBrowser.Common.Progress;
@ -14,8 +16,6 @@ using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
@ -31,6 +31,8 @@ using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
namespace Emby.Server.Implementations.LiveTv namespace Emby.Server.Implementations.LiveTv
{ {
@ -404,8 +406,8 @@ 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 // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says
//mediaSource.SupportsDirectPlay = false; // mediaSource.SupportsDirectPlay = false;
//mediaSource.SupportsDirectStream = false; // mediaSource.SupportsDirectStream = false;
mediaSource.SupportsTranscoding = true; mediaSource.SupportsTranscoding = true;
foreach (var stream in mediaSource.MediaStreams) foreach (var stream in mediaSource.MediaStreams)
{ {
@ -556,7 +558,7 @@ namespace Emby.Server.Implementations.LiveTv
} }
item.ParentId = channel.Id; item.ParentId = channel.Id;
//item.ChannelType = channelType; // item.ChannelType = channelType;
item.Audio = info.Audio; item.Audio = info.Audio;
item.ChannelId = channel.Id; item.ChannelId = channel.Id;
@ -696,7 +698,6 @@ namespace Emby.Server.Implementations.LiveTv
{ {
Path = info.ThumbImageUrl, Path = info.ThumbImageUrl,
Type = ImageType.Thumb Type = ImageType.Thumb
}, 0); }, 0);
} }
} }
@ -709,7 +710,6 @@ namespace Emby.Server.Implementations.LiveTv
{ {
Path = info.LogoImageUrl, Path = info.LogoImageUrl,
Type = ImageType.Logo Type = ImageType.Logo
}, 0); }, 0);
} }
} }
@ -722,7 +722,6 @@ namespace Emby.Server.Implementations.LiveTv
{ {
Path = info.BackdropImageUrl, Path = info.BackdropImageUrl,
Type = ImageType.Backdrop Type = ImageType.Backdrop
}, 0); }, 0);
} }
} }
@ -760,7 +759,8 @@ namespace Emby.Server.Implementations.LiveTv
var dto = _dtoService.GetBaseItemDto(program, new DtoOptions(), user); var dto = _dtoService.GetBaseItemDto(program, new DtoOptions(), user);
var list = new List<Tuple<BaseItemDto, string, string>>() { var list = new List<Tuple<BaseItemDto, string, string>>
{
new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, program.ExternalSeriesId) new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, program.ExternalSeriesId)
}; };
@ -1168,7 +1168,6 @@ namespace Emby.Server.Implementations.LiveTv
IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name }, IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
ChannelIds = new Guid[] { currentChannel.Id }, ChannelIds = new Guid[] { currentChannel.Id },
DtoOptions = new DtoOptions(true) DtoOptions = new DtoOptions(true)
}).Cast<LiveTvProgram>().ToDictionary(i => i.Id); }).Cast<LiveTvProgram>().ToDictionary(i => i.Id);
var newPrograms = new List<LiveTvProgram>(); var newPrograms = new List<LiveTvProgram>();
@ -1368,10 +1367,10 @@ namespace Emby.Server.Implementations.LiveTv
// limit = (query.Limit ?? 10) * 2; // limit = (query.Limit ?? 10) * 2;
limit = null; limit = null;
//var allActivePaths = EmbyTV.EmbyTV.Current.GetAllActiveRecordings().Select(i => i.Path).ToArray(); // 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(); // var items = allActivePaths.Select(i => _libraryManager.FindByPath(i, false)).Where(i => i != null).ToArray();
//return new QueryResult<BaseItem> // return new QueryResult<BaseItem>
//{ //{
// Items = items, // Items = items,
// TotalRecordCount = items.Length // TotalRecordCount = items.Length
@ -1738,7 +1737,6 @@ namespace Emby.Server.Implementations.LiveTv
var results = await GetTimers(new TimerQuery var results = await GetTimers(new TimerQuery
{ {
Id = id Id = id
}, cancellationToken).ConfigureAwait(false); }, cancellationToken).ConfigureAwait(false);
return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase));
@ -1790,7 +1788,6 @@ namespace Emby.Server.Implementations.LiveTv
.Select(i => .Select(i =>
{ {
return i.Item1; return i.Item1;
}) })
.ToArray(); .ToArray();
@ -1845,7 +1842,6 @@ namespace Emby.Server.Implementations.LiveTv
} }
return _tvDtoService.GetSeriesTimerInfoDto(i.Item1, i.Item2, channelName); return _tvDtoService.GetSeriesTimerInfoDto(i.Item1, i.Item2, channelName);
}) })
.ToArray(); .ToArray();
@ -1878,7 +1874,6 @@ namespace Emby.Server.Implementations.LiveTv
OrderBy = new[] { (ItemSortBy.StartDate, SortOrder.Ascending) }, OrderBy = new[] { (ItemSortBy.StartDate, SortOrder.Ascending) },
TopParentIds = new[] { GetInternalLiveTvFolder(CancellationToken.None).Id }, TopParentIds = new[] { GetInternalLiveTvFolder(CancellationToken.None).Id },
DtoOptions = options DtoOptions = options
}) : new List<BaseItem>(); }) : new List<BaseItem>();
RemoveFields(options); RemoveFields(options);
@ -1956,7 +1951,7 @@ namespace Emby.Server.Implementations.LiveTv
OriginalAirDate = program.PremiereDate, OriginalAirDate = program.PremiereDate,
Overview = program.Overview, Overview = program.Overview,
StartDate = program.StartDate, StartDate = program.StartDate,
//ImagePath = program.ExternalImagePath, // ImagePath = program.ExternalImagePath,
Name = program.Name, Name = program.Name,
OfficialRating = program.OfficialRating OfficialRating = program.OfficialRating
}; };
@ -2167,20 +2162,19 @@ namespace Emby.Server.Implementations.LiveTv
var info = new LiveTvInfo var info = new LiveTvInfo
{ {
Services = services, Services = services,
IsEnabled = services.Length > 0 IsEnabled = services.Length > 0,
EnabledUsers = _userManager.Users
.Where(IsLiveTvEnabled)
.Select(i => i.Id.ToString("N", CultureInfo.InvariantCulture))
.ToArray()
}; };
info.EnabledUsers = _userManager.Users
.Where(IsLiveTvEnabled)
.Select(i => i.Id.ToString("N", CultureInfo.InvariantCulture))
.ToArray();
return info; return info;
} }
private bool IsLiveTvEnabled(User user) private bool IsLiveTvEnabled(User user)
{ {
return user.Policy.EnableLiveTvAccess && (Services.Count > 1 || GetConfiguration().TunerHosts.Length > 0); return user.HasPermission(PermissionKind.EnableLiveTvAccess) && (Services.Count > 1 || GetConfiguration().TunerHosts.Length > 0);
} }
public IEnumerable<User> GetEnabledUsers() public IEnumerable<User> GetEnabledUsers()
@ -2457,7 +2451,6 @@ namespace Emby.Server.Implementations.LiveTv
UserId = user.Id, UserId = user.Id,
IsRecordingsFolder = true, IsRecordingsFolder = true,
RefreshLatestChannelItems = refreshChannels RefreshLatestChannelItems = refreshChannels
}).Items); }).Items);
return folders.Cast<BaseItem>().ToList(); return folders.Cast<BaseItem>().ToList();

@ -54,7 +54,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
var result = await GetChannelsInternal(tuner, cancellationToken).ConfigureAwait(false); var result = await GetChannelsInternal(tuner, cancellationToken).ConfigureAwait(false);
var list = result.ToList(); var list = result.ToList();
//logger.LogInformation("Channels from {0}: {1}", tuner.Url, JsonSerializer.SerializeToString(list)); // logger.LogInformation("Channels from {0}: {1}", tuner.Url, JsonSerializer.SerializeToString(list));
if (!string.IsNullOrEmpty(key) && list.Count > 0) if (!string.IsNullOrEmpty(key) && list.Count > 0)
{ {
@ -99,7 +99,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
catch (IOException) catch (IOException)
{ {
} }
} }
} }
@ -116,7 +115,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
catch (IOException) catch (IOException)
{ {
} }
} }
} }

@ -111,7 +111,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
ChannelType = ChannelType.TV, ChannelType = ChannelType.TV,
IsLegacyTuner = (i.URL ?? string.Empty).StartsWith("hdhomerun", StringComparison.OrdinalIgnoreCase), IsLegacyTuner = (i.URL ?? string.Empty).StartsWith("hdhomerun", StringComparison.OrdinalIgnoreCase),
Path = i.URL Path = i.URL
}).Cast<ChannelInfo>().ToList(); }).Cast<ChannelInfo>().ToList();
} }
@ -481,7 +480,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
Height = height, Height = height,
BitRate = videoBitrate, BitRate = videoBitrate,
NalLengthSize = nal NalLengthSize = nal
}, },
new MediaStream new MediaStream
{ {
@ -502,8 +500,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
SupportsTranscoding = true, SupportsTranscoding = true,
IsInfiniteStream = true, IsInfiniteStream = true,
IgnoreDts = true, IgnoreDts = true,
//IgnoreIndex = true, // IgnoreIndex = true,
//ReadAtNativeFramerate = true // ReadAtNativeFramerate = true
}; };
mediaSource.InferTotalBitrate(); mediaSource.InferTotalBitrate();
@ -722,7 +720,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
} }
} }
} }
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {

@ -117,17 +117,17 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
taskCompletionSource, taskCompletionSource,
LiveStreamCancellationTokenSource.Token).ConfigureAwait(false); LiveStreamCancellationTokenSource.Token).ConfigureAwait(false);
//OpenedMediaSource.Protocol = MediaProtocol.File; // OpenedMediaSource.Protocol = MediaProtocol.File;
//OpenedMediaSource.Path = tempFile; // OpenedMediaSource.Path = tempFile;
//OpenedMediaSource.ReadAtNativeFramerate = true; // OpenedMediaSource.ReadAtNativeFramerate = true;
MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
MediaSource.Protocol = MediaProtocol.Http; MediaSource.Protocol = MediaProtocol.Http;
//OpenedMediaSource.SupportsDirectPlay = false; // OpenedMediaSource.SupportsDirectPlay = false;
//OpenedMediaSource.SupportsDirectStream = true; // OpenedMediaSource.SupportsDirectStream = true;
//OpenedMediaSource.SupportsTranscoding = true; // OpenedMediaSource.SupportsTranscoding = true;
//await Task.Delay(5000).ConfigureAwait(false); // await Task.Delay(5000).ConfigureAwait(false);
await taskCompletionSource.Task.ConfigureAwait(false); await taskCompletionSource.Task.ConfigureAwait(false);
} }

@ -220,11 +220,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
catch (IOException) catch (IOException)
{ {
} }
catch (ArgumentException) catch (ArgumentException)
{ {
} }
catch (Exception ex) catch (Exception ex)
{ {

@ -127,7 +127,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
{ {
using (var stream = await new M3uParser(Logger, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false)) using (var stream = await new M3uParser(Logger, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false))
{ {
} }
} }

@ -210,7 +210,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
} }
} }
} }
if (!IsValidChannelNumber(numberString)) if (!IsValidChannelNumber(numberString))
@ -284,7 +283,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out var number)) if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out var number))
{ {
//channel.Number = number.ToString(); // channel.Number = number.ToString();
nameInExtInf = nameInExtInf.Substring(numberIndex + 1).Trim(new[] { ' ', '-' }); nameInExtInf = nameInExtInf.Substring(numberIndex + 1).Trim(new[] { ' ', '-' });
} }
} }

@ -103,21 +103,21 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
_ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); _ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);
//OpenedMediaSource.Protocol = MediaProtocol.File; // OpenedMediaSource.Protocol = MediaProtocol.File;
//OpenedMediaSource.Path = tempFile; // OpenedMediaSource.Path = tempFile;
//OpenedMediaSource.ReadAtNativeFramerate = true; // OpenedMediaSource.ReadAtNativeFramerate = true;
MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
MediaSource.Protocol = MediaProtocol.Http; MediaSource.Protocol = MediaProtocol.Http;
//OpenedMediaSource.Path = TempFilePath; // OpenedMediaSource.Path = TempFilePath;
//OpenedMediaSource.Protocol = MediaProtocol.File; // OpenedMediaSource.Protocol = MediaProtocol.File;
//OpenedMediaSource.Path = _tempFilePath; // OpenedMediaSource.Path = _tempFilePath;
//OpenedMediaSource.Protocol = MediaProtocol.File; // OpenedMediaSource.Protocol = MediaProtocol.File;
//OpenedMediaSource.SupportsDirectPlay = false; // OpenedMediaSource.SupportsDirectPlay = false;
//OpenedMediaSource.SupportsDirectStream = true; // OpenedMediaSource.SupportsDirectStream = true;
//OpenedMediaSource.SupportsTranscoding = true; // OpenedMediaSource.SupportsTranscoding = true;
await taskCompletionSource.Task.ConfigureAwait(false); await taskCompletionSource.Task.ConfigureAwait(false);
if (taskCompletionSource.Task.Exception != null) if (taskCompletionSource.Task.Exception != null)
{ {

@ -98,7 +98,6 @@ namespace Emby.Server.Implementations.Net
} }
catch (SocketException) catch (SocketException)
{ {
} }
try try
@ -109,12 +108,11 @@ namespace Emby.Server.Implementations.Net
} }
catch (SocketException) catch (SocketException)
{ {
} }
try try
{ {
//retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); // retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive); retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive);
var localIp = IPAddress.Any; var localIp = IPAddress.Any;

@ -167,7 +167,7 @@ namespace Emby.Server.Implementations.Networking
foreach (var subnet_Match in subnets) foreach (var subnet_Match in subnets)
{ {
//logger.LogDebug("subnet_Match:" + subnet_Match); // logger.LogDebug("subnet_Match:" + subnet_Match);
if (endpoint.StartsWith(subnet_Match + ".", StringComparison.OrdinalIgnoreCase)) if (endpoint.StartsWith(subnet_Match + ".", StringComparison.OrdinalIgnoreCase))
{ {

@ -3,6 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
@ -44,7 +45,7 @@ namespace Emby.Server.Implementations.Playlists
} }
query.Recursive = true; query.Recursive = true;
query.IncludeItemTypes = new string[] { "Playlist" }; query.IncludeItemTypes = new[] { "Playlist" };
query.Parent = null; query.Parent = null;
return LibraryManager.GetItemsResult(query); return LibraryManager.GetItemsResult(query);
} }

@ -7,6 +7,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
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;
@ -21,6 +22,8 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PlaylistsNET.Content; using PlaylistsNET.Content;
using PlaylistsNET.Models; using PlaylistsNET.Models;
using Genre = MediaBrowser.Controller.Entities.Genre;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
namespace Emby.Server.Implementations.Playlists namespace Emby.Server.Implementations.Playlists
{ {

@ -163,7 +163,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
{ {
//TODO Investigate and properly fix. // TODO Investigate and properly fix.
break; break;
} }
} }

@ -61,7 +61,6 @@ namespace Emby.Server.Implementations.Security
AddColumn(db, "AccessTokens", "UserName", "TEXT", existingColumnNames); AddColumn(db, "AccessTokens", "UserName", "TEXT", existingColumnNames);
AddColumn(db, "AccessTokens", "DateLastActivity", "DATETIME", existingColumnNames); AddColumn(db, "AccessTokens", "DateLastActivity", "DATETIME", existingColumnNames);
AddColumn(db, "AccessTokens", "AppVersion", "TEXT", existingColumnNames); AddColumn(db, "AccessTokens", "AppVersion", "TEXT", existingColumnNames);
}, TransactionMode); }, TransactionMode);
connection.RunQueries(new[] connection.RunQueries(new[]
@ -107,7 +106,6 @@ namespace Emby.Server.Implementations.Security
statement.MoveNext(); statement.MoveNext();
} }
}, TransactionMode); }, TransactionMode);
} }
} }
@ -367,7 +365,6 @@ namespace Emby.Server.Implementations.Security
return result; return result;
} }
}, ReadTransactionMode); }, ReadTransactionMode);
} }
} }
@ -398,7 +395,6 @@ namespace Emby.Server.Implementations.Security
statement.MoveNext(); statement.MoveNext();
} }
}, TransactionMode); }, TransactionMode);
} }
} }

@ -59,8 +59,8 @@ namespace Emby.Server.Implementations.Services
} }
} }
//ContentType='text/html' is the default for a HttpResponse // ContentType='text/html' is the default for a HttpResponse
//Do not override if another has been set // Do not override if another has been set
if (response.ContentType == null || response.ContentType == "text/html") if (response.ContentType == null || response.ContentType == "text/html")
{ {
response.ContentType = defaultContentType; response.ContentType = defaultContentType;

@ -59,8 +59,8 @@ 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
@ -182,7 +182,7 @@ namespace Emby.Server.Implementations.Services
serviceRequiresContext.Request = req; serviceRequiresContext.Request = req;
} }
//Executes the service and returns the result // Executes the service and returns the result
return ServiceExecGeneral.Execute(serviceType, req, service, requestDto, requestType.GetMethodName()); return ServiceExecGeneral.Execute(serviceType, req, service, requestDto, requestType.GetMethodName());
} }
} }

@ -118,7 +118,7 @@ namespace Emby.Server.Implementations.Services
var componentsList = new List<string>(); var componentsList = new List<string>();
//We only split on '.' if the restPath has them. Allows for /{action}.{type} // We only split on '.' if the restPath has them. Allows for /{action}.{type}
var hasSeparators = new List<bool>(); var hasSeparators = new List<bool>();
foreach (var component in this.restPath.Split(PathSeperatorChar)) foreach (var component in this.restPath.Split(PathSeperatorChar))
{ {
@ -298,12 +298,12 @@ namespace Emby.Server.Implementations.Services
return -1; return -1;
} }
//Routes with least wildcard matches get the highest score // Routes with least wildcard matches get the highest score
var score = Math.Max((100 - wildcardMatchCount), 1) * 1000 var score = Math.Max((100 - wildcardMatchCount), 1) * 1000
//Routes with less variable (and more literal) matches // Routes with less variable (and more literal) matches
+ Math.Max((10 - VariableArgsCount), 1) * 100; + Math.Max((10 - VariableArgsCount), 1) * 100;
//Exact verb match is better than ANY // Exact verb match is better than ANY
if (Verbs.Length == 1 && string.Equals(httpMethod, Verbs[0], StringComparison.OrdinalIgnoreCase)) if (Verbs.Length == 1 && string.Equals(httpMethod, Verbs[0], StringComparison.OrdinalIgnoreCase))
{ {
score += 10; score += 10;
@ -470,7 +470,7 @@ namespace Emby.Server.Implementations.Services
+ variableName + " on " + RequestType.GetMethodName()); + variableName + " on " + RequestType.GetMethodName());
} }
var value = requestComponents.Length > pathIx ? requestComponents[pathIx] : null; //wildcard has arg mismatch var value = requestComponents.Length > pathIx ? requestComponents[pathIx] : null; // wildcard has arg mismatch
if (value != null && this.isWildcard[i]) if (value != null && this.isWildcard[i])
{ {
if (i == this.TotalComponentsCount - 1) if (i == this.TotalComponentsCount - 1)
@ -519,8 +519,8 @@ namespace Emby.Server.Implementations.Services
if (queryStringAndFormData != null) if (queryStringAndFormData != null)
{ {
//Query String and form data can override variable path matches // Query String and form data can override variable path matches
//path variables < query string < form data // path variables < query string < form data
foreach (var name in queryStringAndFormData) foreach (var name in queryStringAndFormData)
{ {
requestKeyValuesMap[name.Key] = name.Value; requestKeyValuesMap[name.Key] = name.Value;

@ -83,7 +83,7 @@ namespace Emby.Server.Implementations.Services
if (propertySerializerEntry.PropertyType == typeof(bool)) if (propertySerializerEntry.PropertyType == typeof(bool))
{ {
//InputExtensions.cs#530 MVC Checkbox helper emits extra hidden input field, generating 2 values, first is the real value // InputExtensions.cs#530 MVC Checkbox helper emits extra hidden input field, generating 2 values, first is the real value
propertyTextValue = StringExtensions.LeftPart(propertyTextValue, ',').ToString(); propertyTextValue = StringExtensions.LeftPart(propertyTextValue, ',').ToString();
} }

@ -7,6 +7,8 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Events; using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller; using MediaBrowser.Controller;
@ -15,7 +17,6 @@ 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.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;
@ -28,7 +29,9 @@ using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;
using MediaBrowser.Model.SyncPlay; using MediaBrowser.Model.SyncPlay;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
namespace Emby.Server.Implementations.Session namespace Emby.Server.Implementations.Session
{ {
@ -283,11 +286,18 @@ namespace Emby.Server.Implementations.Session
if (user != null) if (user != null)
{ {
var userLastActivityDate = user.LastActivityDate ?? DateTime.MinValue; var userLastActivityDate = user.LastActivityDate ?? DateTime.MinValue;
user.LastActivityDate = activityDate;
if ((activityDate - userLastActivityDate).TotalSeconds > 60) if ((activityDate - userLastActivityDate).TotalSeconds > 60)
{ {
_userManager.UpdateUser(user); try
{
user.LastActivityDate = activityDate;
_userManager.UpdateUser(user);
}
catch (DbUpdateConcurrencyException e)
{
_logger.LogWarning(e, "Error updating user's last activity date.");
}
} }
} }
@ -434,7 +444,13 @@ namespace Emby.Server.Implementations.Session
/// <param name="remoteEndPoint">The remote end point.</param> /// <param name="remoteEndPoint">The remote end point.</param>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <returns>SessionInfo.</returns> /// <returns>SessionInfo.</returns>
private SessionInfo GetSessionInfo(string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user) private SessionInfo GetSessionInfo(
string appName,
string appVersion,
string deviceId,
string deviceName,
string remoteEndPoint,
User user)
{ {
CheckDisposed(); CheckDisposed();
@ -447,14 +463,13 @@ namespace Emby.Server.Implementations.Session
CheckDisposed(); CheckDisposed();
var sessionInfo = _activeConnections.GetOrAdd(key, k => var sessionInfo = _activeConnections.GetOrAdd(
{ key,
return CreateSession(k, appName, appVersion, deviceId, deviceName, remoteEndPoint, user); k => CreateSession(k, appName, appVersion, deviceId, deviceName, remoteEndPoint, user));
});
sessionInfo.UserId = user == null ? Guid.Empty : user.Id; sessionInfo.UserId = user?.Id ?? Guid.Empty;
sessionInfo.UserName = user?.Name; sessionInfo.UserName = user?.Username;
sessionInfo.UserPrimaryImageTag = user == null ? null : GetImageCacheTag(user, ImageType.Primary); sessionInfo.UserPrimaryImageTag = user?.ProfileImage == null ? null : GetImageCacheTag(user);
sessionInfo.RemoteEndPoint = remoteEndPoint; sessionInfo.RemoteEndPoint = remoteEndPoint;
sessionInfo.Client = appName; sessionInfo.Client = appName;
@ -473,7 +488,14 @@ namespace Emby.Server.Implementations.Session
return sessionInfo; return sessionInfo;
} }
private SessionInfo CreateSession(string key, string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user) private SessionInfo CreateSession(
string key,
string appName,
string appVersion,
string deviceId,
string deviceName,
string remoteEndPoint,
User user)
{ {
var sessionInfo = new SessionInfo(this, _logger) var sessionInfo = new SessionInfo(this, _logger)
{ {
@ -483,11 +505,11 @@ namespace Emby.Server.Implementations.Session
Id = key.GetMD5().ToString("N", CultureInfo.InvariantCulture) Id = key.GetMD5().ToString("N", CultureInfo.InvariantCulture)
}; };
var username = user?.Name; var username = user?.Username;
sessionInfo.UserId = user?.Id ?? Guid.Empty; sessionInfo.UserId = user?.Id ?? Guid.Empty;
sessionInfo.UserName = username; sessionInfo.UserName = username;
sessionInfo.UserPrimaryImageTag = user == null ? null : GetImageCacheTag(user, ImageType.Primary); sessionInfo.UserPrimaryImageTag = user?.ProfileImage == null ? null : GetImageCacheTag(user);
sessionInfo.RemoteEndPoint = remoteEndPoint; sessionInfo.RemoteEndPoint = remoteEndPoint;
if (string.IsNullOrEmpty(deviceName)) if (string.IsNullOrEmpty(deviceName))
@ -535,10 +557,7 @@ namespace Emby.Server.Implementations.Session
private void StartIdleCheckTimer() private void StartIdleCheckTimer()
{ {
if (_idleTimer == null) _idleTimer ??= new Timer(CheckForIdlePlayback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
{
_idleTimer = new Timer(CheckForIdlePlayback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
}
} }
private void StopIdleCheckTimer() private void StopIdleCheckTimer()
@ -786,7 +805,7 @@ namespace Emby.Server.Implementations.Session
{ {
var changed = false; var changed = false;
if (user.Configuration.RememberAudioSelections) if (user.RememberAudioSelections)
{ {
if (data.AudioStreamIndex != info.AudioStreamIndex) if (data.AudioStreamIndex != info.AudioStreamIndex)
{ {
@ -803,7 +822,7 @@ namespace Emby.Server.Implementations.Session
} }
} }
if (user.Configuration.RememberSubtitleSelections) if (user.RememberSubtitleSelections)
{ {
if (data.SubtitleStreamIndex != info.SubtitleStreamIndex) if (data.SubtitleStreamIndex != info.SubtitleStreamIndex)
{ {
@ -1114,13 +1133,13 @@ namespace Emby.Server.Implementations.Session
if (items.Any(i => i.GetPlayAccess(user) != PlayAccess.Full)) if (items.Any(i => i.GetPlayAccess(user) != PlayAccess.Full))
{ {
throw new ArgumentException( throw new ArgumentException(
string.Format(CultureInfo.InvariantCulture, "{0} is not allowed to play media.", user.Name)); string.Format(CultureInfo.InvariantCulture, "{0} is not allowed to play media.", user.Username));
} }
} }
if (user != null if (user != null
&& command.ItemIds.Length == 1 && command.ItemIds.Length == 1
&& user.Configuration.EnableNextEpisodeAutoPlay && user.EnableNextEpisodeAutoPlay
&& _libraryManager.GetItemById(command.ItemIds[0]) is Episode episode) && _libraryManager.GetItemById(command.ItemIds[0]) is Episode episode)
{ {
var series = episode.Series; var series = episode.Series;
@ -1191,7 +1210,7 @@ namespace Emby.Server.Implementations.Session
DtoOptions = new DtoOptions(false) DtoOptions = new DtoOptions(false)
{ {
EnableImages = false, EnableImages = false,
Fields = new ItemFields[] Fields = new[]
{ {
ItemFields.SortName ItemFields.SortName
} }
@ -1353,7 +1372,7 @@ namespace Emby.Server.Implementations.Session
list.Add(new SessionUserInfo list.Add(new SessionUserInfo
{ {
UserId = userId, UserId = userId,
UserName = user.Name UserName = user.Username
}); });
session.AdditionalUsers = list.ToArray(); session.AdditionalUsers = list.ToArray();
@ -1513,7 +1532,7 @@ namespace Emby.Server.Implementations.Session
DeviceName = deviceName, DeviceName = deviceName,
UserId = user.Id, UserId = user.Id,
AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture), AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture),
UserName = user.Name UserName = user.Username
}; };
_logger.LogInformation("Creating new access token for user {0}", user.Id); _logger.LogInformation("Creating new access token for user {0}", user.Id);
@ -1710,15 +1729,15 @@ namespace Emby.Server.Implementations.Session
return info; return info;
} }
private string GetImageCacheTag(BaseItem item, ImageType type) private string GetImageCacheTag(User user)
{ {
try try
{ {
return _imageProcessor.GetImageCacheTag(item, type); return _imageProcessor.GetImageCacheTag(user);
} }
catch (Exception ex) catch (Exception e)
{ {
_logger.LogError(ex, "Error getting image information for {Type}", type); _logger.LogError(e, "Error getting image information for profile image");
return null; return null;
} }
} }
@ -1827,7 +1846,10 @@ namespace Emby.Server.Implementations.Session
{ {
CheckDisposed(); CheckDisposed();
var adminUserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id).ToList(); var adminUserIds = _userManager.Users
.Where(i => i.HasPermission(PermissionKind.IsAdministrator))
.Select(i => i.Id)
.ToList();
return SendMessageToUserSessions(adminUserIds, name, data, cancellationToken); return SendMessageToUserSessions(adminUserIds, name, data, cancellationToken);
} }

@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.Sorting
if (val != 0) if (val != 0)
{ {
//return val; // return val;
} }
} }

@ -1,6 +1,7 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

@ -1,4 +1,5 @@
using System; using System;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

@ -1,5 +1,6 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

@ -1,5 +1,6 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

@ -1,5 +1,6 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

@ -1,3 +1,4 @@
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

@ -102,20 +102,15 @@ namespace Emby.Server.Implementations.SyncPlay
return new SessionInfo[] { from }; return new SessionInfo[] { from };
case BroadcastType.AllGroup: case BroadcastType.AllGroup:
return _group.Participants.Values.Select( return _group.Participants.Values.Select(
session => session.Session session => session.Session).ToArray();
).ToArray();
case BroadcastType.AllExceptCurrentSession: case BroadcastType.AllExceptCurrentSession:
return _group.Participants.Values.Select( return _group.Participants.Values.Select(
session => session.Session session => session.Session).Where(
).Where( session => !session.Id.Equals(from.Id)).ToArray();
session => !session.Id.Equals(from.Id)
).ToArray();
case BroadcastType.AllReady: case BroadcastType.AllReady:
return _group.Participants.Values.Where( return _group.Participants.Values.Where(
session => !session.IsBuffering session => !session.IsBuffering).Select(
).Select( session => session.Session).ToArray();
session => session.Session
).ToArray();
default: default:
return Array.Empty<SessionInfo>(); return Array.Empty<SessionInfo>();
} }
@ -314,8 +309,7 @@ namespace Emby.Server.Implementations.SyncPlay
// Playback synchronization will mainly happen client side // Playback synchronization will mainly happen client side
_group.IsPaused = false; _group.IsPaused = false;
_group.LastActivity = DateTime.UtcNow.AddMilliseconds( _group.LastActivity = DateTime.UtcNow.AddMilliseconds(
delay delay);
);
var command = NewSyncPlayCommand(SendCommandType.Play); var command = NewSyncPlayCommand(SendCommandType.Play);
SendCommand(session, BroadcastType.AllGroup, command, cancellationToken); SendCommand(session, BroadcastType.AllGroup, command, cancellationToken);
@ -449,8 +443,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
// Client that was buffering is recovering, notifying others to resume // Client that was buffering is recovering, notifying others to resume
_group.LastActivity = currentTime.AddMilliseconds( _group.LastActivity = currentTime.AddMilliseconds(
delay delay);
);
var command = NewSyncPlayCommand(SendCommandType.Play); var command = NewSyncPlayCommand(SendCommandType.Play);
SendCommand(session, BroadcastType.AllExceptCurrentSession, command, cancellationToken); SendCommand(session, BroadcastType.AllExceptCurrentSession, command, cancellationToken);
} }
@ -461,8 +454,7 @@ namespace Emby.Server.Implementations.SyncPlay
delay = delay < _group.DefaulPing ? _group.DefaulPing : delay; delay = delay < _group.DefaulPing ? _group.DefaulPing : delay;
_group.LastActivity = currentTime.AddMilliseconds( _group.LastActivity = currentTime.AddMilliseconds(
delay delay);
);
var command = NewSyncPlayCommand(SendCommandType.Play); var command = NewSyncPlayCommand(SendCommandType.Play);
SendCommand(session, BroadcastType.AllGroup, command, cancellationToken); SendCommand(session, BroadcastType.AllGroup, command, cancellationToken);

@ -3,13 +3,13 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Microsoft.Extensions.Logging; using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.SyncPlay; using MediaBrowser.Controller.SyncPlay;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.SyncPlay; using MediaBrowser.Model.SyncPlay;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.SyncPlay namespace Emby.Server.Implementations.SyncPlay
{ {
@ -109,14 +109,6 @@ namespace Emby.Server.Implementations.SyncPlay
_disposed = true; _disposed = true;
} }
private void CheckDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
private void OnSessionManagerSessionEnded(object sender, SessionEventArgs e) private void OnSessionManagerSessionEnded(object sender, SessionEventArgs e)
{ {
var session = e.SessionInfo; var session = e.SessionInfo;
@ -149,38 +141,24 @@ namespace Emby.Server.Implementations.SyncPlay
var item = _libraryManager.GetItemById(itemId); var item = _libraryManager.GetItemById(itemId);
// Check ParentalRating access // Check ParentalRating access
var hasParentalRatingAccess = true; var hasParentalRatingAccess = !user.MaxParentalAgeRating.HasValue
if (user.Policy.MaxParentalRating.HasValue) || item.InheritedParentalRatingValue <= user.MaxParentalAgeRating;
{
hasParentalRatingAccess = item.InheritedParentalRatingValue <= user.Policy.MaxParentalRating;
}
if (!user.Policy.EnableAllFolders && hasParentalRatingAccess) if (!user.HasPermission(PermissionKind.EnableAllFolders) && hasParentalRatingAccess)
{ {
var collections = _libraryManager.GetCollectionFolders(item).Select( var collections = _libraryManager.GetCollectionFolders(item).Select(
folder => folder.Id.ToString("N", CultureInfo.InvariantCulture) folder => folder.Id.ToString("N", CultureInfo.InvariantCulture));
);
var intersect = collections.Intersect(user.Policy.EnabledFolders); return collections.Intersect(user.GetPreference(PreferenceKind.EnabledFolders)).Any();
return intersect.Any();
}
else
{
return hasParentalRatingAccess;
} }
return hasParentalRatingAccess;
} }
private Guid? GetSessionGroup(SessionInfo session) private Guid? GetSessionGroup(SessionInfo session)
{ {
ISyncPlayController group; _sessionToGroupMap.TryGetValue(session.Id, out var group);
_sessionToGroupMap.TryGetValue(session.Id, out group); return group?.GetGroupId();
if (group != null)
{
return group.GetGroupId();
}
else
{
return null;
}
} }
/// <inheritdoc /> /// <inheritdoc />
@ -188,7 +166,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
var user = _userManager.GetUserById(session.UserId); var user = _userManager.GetUserById(session.UserId);
if (user.Policy.SyncPlayAccess != SyncPlayAccess.CreateAndJoinGroups) if (user.SyncPlayAccess != SyncPlayAccess.CreateAndJoinGroups)
{ {
_logger.LogWarning("NewGroup: {0} does not have permission to create groups.", session.Id); _logger.LogWarning("NewGroup: {0} does not have permission to create groups.", session.Id);
@ -196,7 +174,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.CreateGroupDenied Type = GroupUpdateType.CreateGroupDenied
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -219,7 +197,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
var user = _userManager.GetUserById(session.UserId); var user = _userManager.GetUserById(session.UserId);
if (user.Policy.SyncPlayAccess == SyncPlayAccess.None) if (user.SyncPlayAccess == SyncPlayAccess.None)
{ {
_logger.LogWarning("JoinGroup: {0} does not have access to SyncPlay.", session.Id); _logger.LogWarning("JoinGroup: {0} does not have access to SyncPlay.", session.Id);
@ -227,7 +205,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.JoinGroupDenied Type = GroupUpdateType.JoinGroupDenied
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -244,7 +222,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.GroupDoesNotExist Type = GroupUpdateType.GroupDoesNotExist
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -257,7 +235,7 @@ namespace Emby.Server.Implementations.SyncPlay
GroupId = group.GetGroupId().ToString(), GroupId = group.GetGroupId().ToString(),
Type = GroupUpdateType.LibraryAccessDenied Type = GroupUpdateType.LibraryAccessDenied
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -281,8 +259,7 @@ namespace Emby.Server.Implementations.SyncPlay
// TODO: determine what happens to users that are in a group and get their permissions revoked // TODO: determine what happens to users that are in a group and get their permissions revoked
lock (_groupsLock) lock (_groupsLock)
{ {
ISyncPlayController group; _sessionToGroupMap.TryGetValue(session.Id, out var group);
_sessionToGroupMap.TryGetValue(session.Id, out group);
if (group == null) if (group == null)
{ {
@ -292,7 +269,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.NotInGroup Type = GroupUpdateType.NotInGroup
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -311,7 +288,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
var user = _userManager.GetUserById(session.UserId); var user = _userManager.GetUserById(session.UserId);
if (user.Policy.SyncPlayAccess == SyncPlayAccess.None) if (user.SyncPlayAccess == SyncPlayAccess.None)
{ {
return new List<GroupInfoView>(); return new List<GroupInfoView>();
} }
@ -320,19 +297,15 @@ namespace Emby.Server.Implementations.SyncPlay
if (!filterItemId.Equals(Guid.Empty)) if (!filterItemId.Equals(Guid.Empty))
{ {
return _groups.Values.Where( return _groups.Values.Where(
group => group.GetPlayingItemId().Equals(filterItemId) && HasAccessToItem(user, group.GetPlayingItemId()) group => group.GetPlayingItemId().Equals(filterItemId) && HasAccessToItem(user, group.GetPlayingItemId())).Select(
).Select( group => group.GetInfo()).ToList();
group => group.GetInfo()
).ToList();
} }
// Otherwise show all available groups // Otherwise show all available groups
else else
{ {
return _groups.Values.Where( return _groups.Values.Where(
group => HasAccessToItem(user, group.GetPlayingItemId()) group => HasAccessToItem(user, group.GetPlayingItemId())).Select(
).Select( group => group.GetInfo()).ToList();
group => group.GetInfo()
).ToList();
} }
} }
@ -341,7 +314,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
var user = _userManager.GetUserById(session.UserId); var user = _userManager.GetUserById(session.UserId);
if (user.Policy.SyncPlayAccess == SyncPlayAccess.None) if (user.SyncPlayAccess == SyncPlayAccess.None)
{ {
_logger.LogWarning("HandleRequest: {0} does not have access to SyncPlay.", session.Id); _logger.LogWarning("HandleRequest: {0} does not have access to SyncPlay.", session.Id);
@ -349,14 +322,13 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.JoinGroupDenied Type = GroupUpdateType.JoinGroupDenied
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
lock (_groupsLock) lock (_groupsLock)
{ {
ISyncPlayController group; _sessionToGroupMap.TryGetValue(session.Id, out var group);
_sessionToGroupMap.TryGetValue(session.Id, out group);
if (group == null) if (group == null)
{ {
@ -366,7 +338,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.NotInGroup Type = GroupUpdateType.NotInGroup
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -393,8 +365,7 @@ namespace Emby.Server.Implementations.SyncPlay
throw new InvalidOperationException("Session not in any group!"); throw new InvalidOperationException("Session not in any group!");
} }
ISyncPlayController tempGroup; _sessionToGroupMap.Remove(session.Id, out var tempGroup);
_sessionToGroupMap.Remove(session.Id, out tempGroup);
if (!tempGroup.GetGroupId().Equals(group.GetGroupId())) if (!tempGroup.GetGroupId().Equals(group.GetGroupId()))
{ {

@ -4,13 +4,17 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.TV; using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace Emby.Server.Implementations.TV namespace Emby.Server.Implementations.TV
{ {
@ -73,7 +77,8 @@ namespace Emby.Server.Implementations.TV
{ {
parents = _libraryManager.GetUserRootFolder().GetChildren(user, true) parents = _libraryManager.GetUserRootFolder().GetChildren(user, true)
.Where(i => i is Folder) .Where(i => i is Folder)
.Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture))) .Where(i => !user.GetPreference(PreferenceKind.LatestItemExcludes)
.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture)))
.ToArray(); .ToArray();
} }
@ -144,7 +149,7 @@ namespace Emby.Server.Implementations.TV
var allNextUp = seriesKeys var allNextUp = seriesKeys
.Select(i => GetNextUp(i, currentUser, dtoOptions)); .Select(i => GetNextUp(i, currentUser, dtoOptions));
//allNextUp = allNextUp.OrderByDescending(i => i.Item1); // allNextUp = allNextUp.OrderByDescending(i => i.Item1);
// If viewing all next up for all series, remove first episodes // If viewing all next up for all series, remove first episodes
// But if that returns empty, keep those first episodes (avoid completely empty view) // But if that returns empty, keep those first episodes (avoid completely empty view)
@ -191,7 +196,7 @@ namespace Emby.Server.Implementations.TV
{ {
AncestorWithPresentationUniqueKey = null, AncestorWithPresentationUniqueKey = null,
SeriesPresentationUniqueKey = seriesKey, SeriesPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { typeof(Episode).Name }, IncludeItemTypes = new[] { nameof(Episode) },
OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Descending) }, OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Descending) },
IsPlayed = true, IsPlayed = true,
Limit = 1, Limit = 1,
@ -204,7 +209,6 @@ namespace Emby.Server.Implementations.TV
}, },
EnableImages = false EnableImages = false
} }
}).FirstOrDefault(); }).FirstOrDefault();
Func<Episode> getEpisode = () => Func<Episode> getEpisode = () =>
@ -219,9 +223,8 @@ namespace Emby.Server.Implementations.TV
IsPlayed = false, IsPlayed = false,
IsVirtualItem = false, IsVirtualItem = false,
ParentIndexNumberNotEquals = 0, ParentIndexNumberNotEquals = 0,
MinSortName = lastWatchedEpisode == null ? null : lastWatchedEpisode.SortName, MinSortName = lastWatchedEpisode?.SortName,
DtoOptions = dtoOptions DtoOptions = dtoOptions
}).Cast<Episode>().FirstOrDefault(); }).Cast<Episode>().FirstOrDefault();
}; };

@ -3,6 +3,7 @@ using System.Security.Claims;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -49,10 +50,10 @@ namespace Jellyfin.Api.Auth
var claims = new[] var claims = new[]
{ {
new Claim(ClaimTypes.Name, user.Name), new Claim(ClaimTypes.Name, user.Username),
new Claim( new Claim(
ClaimTypes.Role, ClaimTypes.Role,
value: user.Policy.IsAdministrator ? UserRoles.Administrator : UserRoles.User) value: user.HasPermission(PermissionKind.IsAdministrator) ? UserRoles.Administrator : UserRoles.User)
}; };
var identity = new ClaimsIdentity(claims, Scheme.Name); var identity = new ClaimsIdentity(claims, Scheme.Name);
var principal = new ClaimsPrincipal(identity); var principal = new ClaimsPrincipal(identity);

@ -95,10 +95,12 @@ namespace Jellyfin.Api.Controllers
[HttpGet("User")] [HttpGet("User")]
public StartupUserDto GetFirstUser() public StartupUserDto GetFirstUser()
{ {
// TODO: Remove this method when startup wizard no longer requires an existing user.
_userManager.Initialize();
var user = _userManager.Users.First(); var user = _userManager.Users.First();
return new StartupUserDto return new StartupUserDto
{ {
Name = user.Name, Name = user.Username,
Password = user.Password Password = user.Password
}; };
} }
@ -113,9 +115,9 @@ namespace Jellyfin.Api.Controllers
{ {
var user = _userManager.Users.First(); var user = _userManager.Users.First();
user.Name = startupUserDto.Name; user.Username = startupUserDto.Name;
_userManager.UpdateUser(user); await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
if (!string.IsNullOrEmpty(startupUserDto.Password)) if (!string.IsNullOrEmpty(startupUserDto.Password))
{ {

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data
{
public static class DayOfWeekHelper
{
public static List<DayOfWeek> GetDaysOfWeek(DynamicDayOfWeek day)
{
var days = new List<DayOfWeek>(7);
if (day == DynamicDayOfWeek.Sunday
|| day == DynamicDayOfWeek.Weekend
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Sunday);
}
if (day == DynamicDayOfWeek.Monday
|| day == DynamicDayOfWeek.Weekday
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Monday);
}
if (day == DynamicDayOfWeek.Tuesday
|| day == DynamicDayOfWeek.Weekday
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Tuesday);
}
if (day == DynamicDayOfWeek.Wednesday
|| day == DynamicDayOfWeek.Weekday
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Wednesday);
}
if (day == DynamicDayOfWeek.Thursday
|| day == DynamicDayOfWeek.Weekday
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Thursday);
}
if (day == DynamicDayOfWeek.Friday
|| day == DynamicDayOfWeek.Weekday
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Friday);
}
if (day == DynamicDayOfWeek.Saturday
|| day == DynamicDayOfWeek.Weekend
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Saturday);
}
return days;
}
}
}

@ -0,0 +1,91 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using System.Xml.Serialization;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity representing a user's access schedule.
/// </summary>
public class AccessSchedule
{
/// <summary>
/// Initializes a new instance of the <see cref="AccessSchedule"/> class.
/// </summary>
/// <param name="dayOfWeek">The day of the week.</param>
/// <param name="startHour">The start hour.</param>
/// <param name="endHour">The end hour.</param>
/// <param name="userId">The associated user's id.</param>
public AccessSchedule(DynamicDayOfWeek dayOfWeek, double startHour, double endHour, Guid userId)
{
UserId = userId;
DayOfWeek = dayOfWeek;
StartHour = startHour;
EndHour = endHour;
}
/// <summary>
/// Initializes a new instance of the <see cref="AccessSchedule"/> class.
/// Default constructor. Protected due to required properties, but present because EF needs it.
/// </summary>
protected AccessSchedule()
{
}
/// <summary>
/// Gets or sets the id of this instance.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[XmlIgnore]
[Key]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; protected set; }
/// <summary>
/// Gets or sets the id of the associated user.
/// </summary>
[XmlIgnore]
[Required]
public Guid UserId { get; protected set; }
/// <summary>
/// Gets or sets the day of week.
/// </summary>
/// <value>The day of week.</value>
[Required]
public DynamicDayOfWeek DayOfWeek { get; set; }
/// <summary>
/// Gets or sets the start hour.
/// </summary>
/// <value>The start hour.</value>
[Required]
public double StartHour { get; set; }
/// <summary>
/// Gets or sets the end hour.
/// </summary>
/// <value>The end hour.</value>
[Required]
public double EndHour { get; set; }
/// <summary>
/// Static create function (for use in LINQ queries, etc.)
/// </summary>
/// <param name="dayOfWeek">The day of the week.</param>
/// <param name="startHour">The start hour.</param>
/// <param name="endHour">The end hour.</param>
/// <param name="userId">The associated user's id.</param>
/// <returns>The newly created instance.</returns>
public static AccessSchedule Create(DynamicDayOfWeek dayOfWeek, double startHour, double endHour, Guid userId)
{
return new AccessSchedule(dayOfWeek, startHour, endHour, userId);
}
}
}

@ -189,7 +189,6 @@ namespace Jellyfin.Data.Entities
/************************************************************************* /*************************************************************************
* Navigation properties * Navigation properties
*************************************************************************/ *************************************************************************/
} }
} }

@ -63,7 +63,6 @@ namespace Jellyfin.Data.Entities
[ForeignKey("Release_Releases_Id")] [ForeignKey("Release_Releases_Id")]
public virtual ICollection<Release> Releases { get; protected set; } public virtual ICollection<Release> Releases { get; protected set; }
} }
} }

@ -101,7 +101,6 @@ namespace Jellyfin.Data.Entities
[ForeignKey("Company_Publishers_Id")] [ForeignKey("Company_Publishers_Id")]
public virtual ICollection<Company> Publishers { get; protected set; } public virtual ICollection<Company> Publishers { get; protected set; }
} }
} }

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save