add playback of in-progress recordings

This commit is contained in:
Luke Pulverenti
2016-10-09 03:18:43 -04:00
parent b3595eab6a
commit daaae69df5
49 changed files with 570 additions and 397 deletions

View File

@@ -1577,97 +1577,5 @@ namespace MediaBrowser.Server.Implementations.Channels
return await _libraryManager.GetNamedView(name, "channels", "zz_" + name, cancellationToken).ConfigureAwait(false);
}
public async Task DownloadChannelItem(BaseItem item, string destination,
IProgress<double> progress, CancellationToken cancellationToken)
{
var sources = await GetDynamicMediaSources(item, cancellationToken)
.ConfigureAwait(false);
var list = sources.Where(i => i.Protocol == MediaProtocol.Http).ToList();
foreach (var source in list)
{
await TryDownloadChannelItem(source, item, destination, progress, cancellationToken).ConfigureAwait(false);
return;
}
}
private async Task TryDownloadChannelItem(MediaSourceInfo source,
BaseItem item,
string destination,
IProgress<double> progress,
CancellationToken cancellationToken)
{
var options = new HttpRequestOptions
{
CancellationToken = cancellationToken,
Url = source.Path,
Progress = new Progress<double>()
};
var channel = GetChannel(item.ChannelId);
var channelProvider = GetChannelProvider(channel);
var features = channelProvider.GetChannelFeatures();
if (!features.SupportsContentDownloading)
{
throw new ArgumentException("The channel does not support downloading.");
}
var limit = features.DailyDownloadLimit;
foreach (var header in source.RequiredHttpHeaders)
{
options.RequestHeaders[header.Key] = header.Value;
}
_fileSystem.CreateDirectory(Path.GetDirectoryName(destination));
// Determine output extension
var response = await _httpClient.GetTempFileResponse(options).ConfigureAwait(false);
if (response.ContentType.StartsWith("text/html"))
{
throw new HttpException("File not found")
{
StatusCode = HttpStatusCode.NotFound
};
}
if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase) && response.ContentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
{
var extension = response.ContentType.Split('/')
.Last()
.Replace("quicktime", "mov", StringComparison.OrdinalIgnoreCase);
destination += "." + extension;
}
else if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) && response.ContentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase))
{
var extension = response.ContentType.Replace("audio/mpeg", "audio/mp3", StringComparison.OrdinalIgnoreCase)
.Split('/')
.Last();
destination += "." + extension;
}
else
{
_fileSystem.DeleteFile(response.TempFilePath);
throw new ApplicationException("Unexpected response type encountered: " + response.ContentType);
}
_fileSystem.CopyFile(response.TempFilePath, destination, true);
try
{
_fileSystem.DeleteFile(response.TempFilePath);
}
catch
{
}
}
}
}

View File

@@ -907,15 +907,6 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.Keywords = item.Keywords;
}
if (fields.Contains(ItemFields.PlaceOfBirth))
{
var person = item as Person;
if (person != null)
{
dto.PlaceOfBirth = person.PlaceOfBirth;
}
}
var hasAspectRatio = item as IHasAspectRatio;
if (hasAspectRatio != null)
{
@@ -1432,10 +1423,9 @@ namespace MediaBrowser.Server.Implementations.Dto
SetBookProperties(dto, book);
}
var movie = item as Movie;
if (movie != null)
if (item.ProductionLocations.Count > 0 || item is Movie)
{
dto.ProductionLocations = new string[] { };
dto.ProductionLocations = item.ProductionLocations.ToArray();
}
var photo = item as Photo;

View File

@@ -17,7 +17,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
public Container Container { get; set; }
private readonly HttpListenerRequest request;
private readonly IHttpResponse response;
private IMemoryStreamProvider _memoryStreamProvider;
private readonly IMemoryStreamProvider _memoryStreamProvider;
public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, RequestAttributes requestAttributes, ILogger logger, IMemoryStreamProvider memoryStreamProvider)
{

View File

@@ -335,15 +335,6 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
/// <summary>
/// Updates the item in library cache.
/// </summary>
/// <param name="item">The item.</param>
private void UpdateItemInLibraryCache(BaseItem item)
{
RegisterItem(item);
}
public void RegisterItem(BaseItem item)
{
if (item == null)
@@ -1777,7 +1768,7 @@ namespace MediaBrowser.Server.Implementations.Library
foreach (var item in list)
{
UpdateItemInLibraryCache(item);
RegisterItem(item);
}
if (ItemAdded != null)
@@ -1818,7 +1809,7 @@ namespace MediaBrowser.Server.Implementations.Library
await ItemRepository.SaveItem(item, cancellationToken).ConfigureAwait(false);
UpdateItemInLibraryCache(item);
RegisterItem(item);
if (ItemUpdated != null)
{

View File

@@ -54,8 +54,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
if (!args.IsDirectory) return null;
// Avoid mis-identifying top folders
if (args.Parent.IsRoot) return null;
if (args.HasParent<MusicAlbum>()) return null;
if (args.Parent.IsRoot) return null;
var collectionType = args.GetCollectionType();

View File

@@ -51,9 +51,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
{
if (!args.IsDirectory) return null;
// Avoid mis-identifying top folders
if (args.Parent.IsRoot) return null;
// Don't allow nested artists
if (args.HasParent<MusicArtist>() || args.HasParent<MusicAlbum>())
{
@@ -70,12 +67,9 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
return null;
}
if (args.IsDirectory)
if (args.ContainsFileSystemEntryByName("artist.nfo"))
{
if (args.ContainsFileSystemEntryByName("artist.nfo"))
{
return new MusicArtist();
}
return new MusicArtist();
}
if (_config.Configuration.EnableSimpleArtistDetection)
@@ -83,6 +77,9 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
return null;
}
// Avoid mis-identifying top folders
if (args.Parent.IsRoot) return null;
var directoryService = args.DirectoryService;
var albumResolver = new MusicAlbumResolver(_logger, _fileSystem, _libraryManager);

View File

@@ -51,7 +51,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
base.SetInitialItemValues(item, args);
item.IsRoot = args.Parent == null;
item.IsPhysicalRoot = args.IsPhysicalRoot;
}
}
}

View File

@@ -59,6 +59,15 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
return null;
}
if (args.ContainsFileSystemEntryByName("tvshow.nfo"))
{
return new Series
{
Path = args.Path,
Name = Path.GetFileName(args.Path)
};
}
var collectionType = args.GetCollectionType();
if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
{
@@ -72,23 +81,20 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
};
}
}
else
else if (string.IsNullOrWhiteSpace(collectionType))
{
if (string.IsNullOrWhiteSpace(collectionType))
if (args.Parent.IsRoot)
{
if (args.Parent.IsRoot)
return null;
}
if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, args.GetLibraryOptions(), false))
{
return new Series
{
return null;
}
if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, args.GetLibraryOptions(), false) ||
args.ContainsFileSystemEntryByName("tvshow.nfo"))
{
return new Series
{
Path = args.Path,
Name = Path.GetFileName(args.Path)
};
}
Path = args.Path,
Name = Path.GetFileName(args.Path)
};
}
}
}

View File

@@ -28,6 +28,7 @@ using System.Threading.Tasks;
using System.Xml;
using CommonIO;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Configuration;
@@ -38,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
public class EmbyTV : ILiveTvService, ISupportsDirectStreamProvider, ISupportsNewTimerIds, IDisposable
{
private readonly IApplicationHost _appHpst;
private readonly IServerApplicationHost _appHost;
private readonly ILogger _logger;
private readonly IHttpClient _httpClient;
private readonly IServerConfigurationManager _config;
@@ -64,11 +65,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
private readonly ConcurrentDictionary<string, ActiveRecordingInfo> _activeRecordings =
new ConcurrentDictionary<string, ActiveRecordingInfo>(StringComparer.OrdinalIgnoreCase);
public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder)
public EmbyTV(IServerApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder)
{
Current = this;
_appHpst = appHost;
_appHost = appHost;
_logger = logger;
_httpClient = httpClient;
_config = config;
@@ -293,7 +294,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
status.Tuners = list;
status.Status = LiveTvServiceStatus.Ok;
status.Version = _appHpst.ApplicationVersion.ToString();
status.Version = _appHost.ApplicationVersion.ToString();
status.IsVisible = false;
return status;
}
@@ -659,7 +660,63 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public async Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken)
{
return new List<RecordingInfo>();
return _activeRecordings.Values.ToList().Select(GetRecordingInfo).ToList();
}
public string GetActiveRecordingPath(string id)
{
ActiveRecordingInfo info;
if (_activeRecordings.TryGetValue(id, out info))
{
return info.Path;
}
return null;
}
private RecordingInfo GetRecordingInfo(ActiveRecordingInfo info)
{
var timer = info.Timer;
var program = info.Program;
var result = new RecordingInfo
{
ChannelId = timer.ChannelId,
CommunityRating = timer.CommunityRating,
DateLastUpdated = DateTime.UtcNow,
EndDate = timer.EndDate,
EpisodeTitle = timer.EpisodeTitle,
Genres = timer.Genres,
Id = "recording" + timer.Id,
IsKids = timer.IsKids,
IsMovie = timer.IsMovie,
IsNews = timer.IsNews,
IsRepeat = timer.IsRepeat,
IsSeries = timer.IsProgramSeries,
IsSports = timer.IsSports,
Name = timer.Name,
OfficialRating = timer.OfficialRating,
OriginalAirDate = timer.OriginalAirDate,
Overview = timer.Overview,
ProgramId = timer.ProgramId,
SeriesTimerId = timer.SeriesTimerId,
StartDate = timer.StartDate,
Status = RecordingStatus.InProgress,
TimerId = timer.Id
};
if (program != null)
{
result.Audio = program.Audio;
result.ImagePath = program.ImagePath;
result.ImageUrl = program.ImageUrl;
result.IsHD = program.IsHD;
result.IsLive = program.IsLive;
result.IsPremiere = program.IsPremiere;
result.ShowId = program.ShowId;
}
return result;
}
public Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken)
@@ -954,7 +1011,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken)
{
throw new NotImplementedException();
ActiveRecordingInfo info;
recordingId = recordingId.Replace("recording", string.Empty);
if (_activeRecordings.TryGetValue(recordingId, out info))
{
return Task.FromResult(new List<MediaSourceInfo>
{
new MediaSourceInfo
{
Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveRecordings/" + recordingId + "/stream",
Id = recordingId,
SupportsDirectPlay = false,
SupportsDirectStream = true,
SupportsTranscoding = true,
IsInfiniteStream = true,
RequiresOpening = false,
RequiresClosing = false,
Protocol = Model.MediaInfo.MediaProtocol.Http,
BufferMs = 0
}
});
}
throw new FileNotFoundException();
}
public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
@@ -1031,7 +1112,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
var activeRecordingInfo = new ActiveRecordingInfo
{
CancellationTokenSource = new CancellationTokenSource(),
TimerId = timer.Id
Timer = timer
};
if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo))
@@ -1168,6 +1249,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
if (programInfo != null)
{
RecordingHelper.CopyProgramInfoToTimerInfo(programInfo, timer);
activeRecordingInfo.Program = programInfo;
}
string seriesPath = null;
@@ -1394,7 +1476,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return true;
}
var hasRecordingAtPath = _activeRecordings.Values.ToList().Any(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) && !string.Equals(i.TimerId, timerId, StringComparison.OrdinalIgnoreCase));
var hasRecordingAtPath = _activeRecordings
.Values
.ToList()
.Any(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Timer.Id, timerId, StringComparison.OrdinalIgnoreCase));
if (hasRecordingAtPath)
{
@@ -1878,7 +1963,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
class ActiveRecordingInfo
{
public string Path { get; set; }
public string TimerId { get; set; }
public TimerInfo Timer { get; set; }
public ProgramInfo Program { get; set; }
public CancellationTokenSource CancellationTokenSource { get; set; }
}
}

View File

@@ -10,6 +10,7 @@ using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -125,6 +126,34 @@ namespace MediaBrowser.Server.Implementations.LiveTv
dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days);
if (!string.IsNullOrWhiteSpace(info.SeriesId))
{
var program = _libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
ExternalSeriesId = info.SeriesId,
Limit = 1,
ImageTypes = new ImageType[] { ImageType.Primary }
}).FirstOrDefault();
if (program != null)
{
var image = program.GetImageInfo(ImageType.Primary, 0);
if (image != null)
{
try
{
dto.ParentPrimaryImageTag = _imageProcessor.GetImageCacheTag(program, image);
dto.ParentPrimaryImageItemId = program.Id.ToString("N");
}
catch (Exception ex)
{
}
}
}
}
return dto;
}

View File

@@ -235,20 +235,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return await GetLiveStream(id, mediaSourceId, true, cancellationToken).ConfigureAwait(false);
}
public async Task<IEnumerable<MediaSourceInfo>> GetRecordingMediaSources(string id, CancellationToken cancellationToken)
public async Task<IEnumerable<MediaSourceInfo>> GetRecordingMediaSources(IHasMediaSources item, CancellationToken cancellationToken)
{
var item = await GetInternalRecording(id, cancellationToken).ConfigureAwait(false);
var service = GetService(item);
var baseItem = (BaseItem)item;
var service = GetService(baseItem);
return await service.GetRecordingStreamMediaSources(id, cancellationToken).ConfigureAwait(false);
return await service.GetRecordingStreamMediaSources(baseItem.ExternalId, cancellationToken).ConfigureAwait(false);
}
public async Task<IEnumerable<MediaSourceInfo>> GetChannelMediaSources(string id, CancellationToken cancellationToken)
public async Task<IEnumerable<MediaSourceInfo>> GetChannelMediaSources(IHasMediaSources item, CancellationToken cancellationToken)
{
var item = GetInternalChannel(id);
var service = GetService(item);
var baseItem = (LiveTvChannel)item;
var service = GetService(baseItem);
var sources = await service.GetChannelStreamMediaSources(item.ExternalId, cancellationToken).ConfigureAwait(false);
var sources = await service.GetChannelStreamMediaSources(baseItem.ExternalId, cancellationToken).ConfigureAwait(false);
if (sources.Count == 0)
{
@@ -259,7 +259,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var source in list)
{
Normalize(source, service, item.ChannelType == ChannelType.TV);
Normalize(source, service, baseItem.ChannelType == ChannelType.TV);
}
return list;
@@ -738,6 +738,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
recording.IsRepeat = info.IsRepeat;
recording.IsSports = info.IsSports;
recording.SeriesTimerId = info.SeriesTimerId;
recording.TimerId = info.TimerId;
recording.StartDate = info.StartDate;
if (!dataChanged)
@@ -1083,10 +1084,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (timer != null)
{
program.TimerId = _tvDtoService.GetInternalTimerId(serviceName, timer.Id)
.ToString("N");
if (timer.Status != RecordingStatus.Cancelled && timer.Status != RecordingStatus.Error)
{
program.TimerId = _tvDtoService.GetInternalTimerId(serviceName, timer.Id)
.ToString("N");
program.TimerStatus = timer.Status;
program.Status = timer.Status.ToString();
}
if (!string.IsNullOrEmpty(timer.SeriesTimerId))
{
@@ -1432,7 +1436,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private DateTime _lastRecordingRefreshTime;
private async Task RefreshRecordings(CancellationToken cancellationToken)
{
const int cacheMinutes = 5;
const int cacheMinutes = 3;
if ((DateTime.UtcNow - _lastRecordingRefreshTime).TotalMinutes < cacheMinutes)
{
@@ -1482,7 +1486,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private QueryResult<BaseItem> GetEmbyRecordings(RecordingQuery query, DtoOptions dtoOptions, User user)
{
if (user == null || (query.IsInProgress ?? false))
if (user == null)
{
return new QueryResult<BaseItem>();
}
if ((query.IsInProgress ?? false))
{
return new QueryResult<BaseItem>();
}
@@ -1628,7 +1637,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return new QueryResult<BaseItem>();
}
if (_services.Count == 1)
if (_services.Count == 1 && !(query.IsInProgress ?? false))
{
return GetEmbyRecordings(query, new DtoOptions(), user);
}
@@ -1824,6 +1833,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
? null
: _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N");
dto.TimerId = string.IsNullOrEmpty(info.TimerId)
? null
: _tvDtoService.GetInternalTimerId(service.Name, info.TimerId).ToString("N");
dto.StartDate = info.StartDate;
dto.RecordingStatus = info.Status;
dto.IsRepeat = info.IsRepeat;

View File

@@ -65,12 +65,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
if (item is ILiveTvRecording)
{
sources = await _liveTvManager.GetRecordingMediaSources(item.Id.ToString("N"), cancellationToken)
sources = await _liveTvManager.GetRecordingMediaSources(item, cancellationToken)
.ConfigureAwait(false);
}
else
{
sources = await _liveTvManager.GetChannelMediaSources(item.Id.ToString("N"), cancellationToken)
sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken)
.ConfigureAwait(false);
}
}

View File

@@ -21,10 +21,13 @@ using System.Threading.Tasks;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Server.Implementations.Devices;
using MediaBrowser.Server.Implementations.Playlists;
namespace MediaBrowser.Server.Implementations.Persistence
{
@@ -279,6 +282,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.AddColumn(Logger, "TypedBaseItems", "Keywords", "Text");
_connection.AddColumn(Logger, "TypedBaseItems", "ProviderIds", "Text");
_connection.AddColumn(Logger, "TypedBaseItems", "Images", "Text");
_connection.AddColumn(Logger, "TypedBaseItems", "ProductionLocations", "Text");
_connection.AddColumn(Logger, "TypedBaseItems", "ThemeSongIds", "Text");
_connection.AddColumn(Logger, "TypedBaseItems", "ThemeVideoIds", "Text");
_connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT");
_connection.AddColumn(Logger, "ItemValues", "CleanValue", "Text");
@@ -428,7 +434,10 @@ namespace MediaBrowser.Server.Implementations.Persistence
"Tagline",
"Keywords",
"ProviderIds",
"Images"
"Images",
"ProductionLocations",
"ThemeSongIds",
"ThemeVideoIds"
};
private readonly string[] _mediaStreamSaveColumns =
@@ -556,7 +565,10 @@ namespace MediaBrowser.Server.Implementations.Persistence
"Tagline",
"Keywords",
"ProviderIds",
"Images"
"Images",
"ProductionLocations",
"ThemeSongIds",
"ThemeVideoIds"
};
_saveItemCommand = _connection.CreateCommand();
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
@@ -1007,10 +1019,46 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveItemCommand.GetParameter(index++).Value = item.ExternalSeriesId;
_saveItemCommand.GetParameter(index++).Value = item.ShortOverview;
_saveItemCommand.GetParameter(index++).Value = item.Tagline;
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Keywords.ToArray());
if (item.Keywords.Count > 0)
{
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Keywords.ToArray());
}
else
{
_saveItemCommand.GetParameter(index++).Value = null;
}
_saveItemCommand.GetParameter(index++).Value = SerializeProviderIds(item);
_saveItemCommand.GetParameter(index++).Value = SerializeImages(item);
if (item.ProductionLocations.Count > 0)
{
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.ProductionLocations.ToArray());
}
else
{
_saveItemCommand.GetParameter(index++).Value = null;
}
if (item.ThemeSongIds.Count > 0)
{
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.ThemeSongIds.Select(i => i.ToString("N")).ToArray());
}
else
{
_saveItemCommand.GetParameter(index++).Value = null;
}
if (item.ThemeVideoIds.Count > 0)
{
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.ThemeVideoIds.Select(i => i.ToString("N")).ToArray());
}
else
{
_saveItemCommand.GetParameter(index++).Value = null;
}
_saveItemCommand.Transaction = transaction;
_saveItemCommand.ExecuteNonQuery();
@@ -1217,6 +1265,46 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
return false;
}
if (type == typeof(Person))
{
return false;
}
if (type == typeof(RecordingGroup))
{
return false;
}
if (type == typeof(Channel))
{
return false;
}
if (type == typeof(ManualCollectionsFolder))
{
return false;
}
if (type == typeof(CameraUploadsFolder))
{
return false;
}
if (type == typeof(PlaylistsFolder))
{
return false;
}
if (type == typeof(UserRootFolder))
{
return false;
}
if (type == typeof(PhotoAlbum))
{
return false;
}
if (type == typeof(Season))
{
return false;
}
if (type == typeof(MusicArtist))
{
return false;
}
}
if (_config.Configuration.SkipDeserializationForPrograms)
{
@@ -1775,6 +1863,27 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
index++;
if (query.HasField(ItemFields.ProductionLocations))
{
if (!reader.IsDBNull(index))
{
item.ProductionLocations = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
}
index++;
}
if (!reader.IsDBNull(index))
{
item.ThemeSongIds = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToList();
}
index++;
if (!reader.IsDBNull(index))
{
item.ThemeVideoIds = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToList();
}
index++;
if (string.IsNullOrWhiteSpace(item.Tagline))
{
var movie = item as Movie;
@@ -1784,6 +1893,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
if (type == typeof(Person) && item.ProductionLocations.Count == 0)
{
var person = (Person)item;
if (!string.IsNullOrWhiteSpace(person.PlaceOfBirth))
{
item.ProductionLocations = new List<string> { person.PlaceOfBirth };
}
}
return item;
}