sync updates

This commit is contained in:
Luke Pulverenti 2015-01-23 01:15:15 -05:00
parent 6a4a29b803
commit db03846481
15 changed files with 129 additions and 44 deletions

View File

@ -96,6 +96,11 @@ namespace MediaBrowser.Model.Sync
/// </summary> /// </summary>
/// <value><c>true</c> if this instance is marked for removal; otherwise, <c>false</c>.</value> /// <value><c>true</c> if this instance is marked for removal; otherwise, <c>false</c>.</value>
public bool IsMarkedForRemoval { get; set; } public bool IsMarkedForRemoval { get; set; }
/// <summary>
/// Gets or sets the index of the job item.
/// </summary>
/// <value>The index of the job item.</value>
public int JobItemIndex { get; set; }
public SyncJobItem() public SyncJobItem()
{ {

View File

@ -2,14 +2,12 @@
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
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.Localization; using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager; using MediaBrowser.Providers.Manager;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@ -15,7 +15,7 @@ using TagLib.IFD.Tags;
namespace MediaBrowser.Providers.Photos namespace MediaBrowser.Providers.Photos
{ {
public class PhotoProvider : ICustomMetadataProvider<Photo>, IHasItemChangeMonitor public class PhotoProvider : ICustomMetadataProvider<Photo>, IHasItemChangeMonitor, IForcedProvider
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IImageProcessor _imageProcessor; private readonly IImageProcessor _imageProcessor;

View File

@ -0,0 +1,67 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Server.Implementations.Photos;
using MoreLinq;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Collections
{
public class CollectionImageProvider : BaseDynamicImageProvider<BoxSet>, ICustomMetadataProvider<BoxSet>
{
public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager)
: base(fileSystem, providerManager)
{
}
protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item)
{
var playlist = (BoxSet)item;
var items = playlist.Children.Concat(playlist.GetLinkedChildren())
.Select(i =>
{
var subItem = i;
var episode = subItem as Episode;
if (episode != null)
{
var series = episode.Series;
if (series != null && series.HasImage(ImageType.Primary))
{
return series;
}
}
if (subItem.HasImage(ImageType.Primary))
{
return subItem;
}
var parent = subItem.Parent;
if (parent != null && parent.HasImage(ImageType.Primary))
{
if (parent is MusicAlbum)
{
return parent;
}
}
return null;
})
.Where(i => i != null)
.DistinctBy(i => i.Id)
.ToList();
return Task.FromResult(GetFinalItems(items));
}
}
}

View File

@ -13,8 +13,8 @@ namespace MediaBrowser.Server.Implementations.Collections
public override bool IsVisible(User user) public override bool IsVisible(User user)
{ {
return GetChildren(user, true).Any() && return base.IsVisible(user) && GetChildren(user, false)
base.IsVisible(user); .Any();
} }
public override bool IsHidden public override bool IsHidden

View File

@ -34,6 +34,7 @@
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.", "MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"HeaderSearch": "Search", "HeaderSearch": "Search",
"ValueDateCreated": "Date created: {0}",
"LabelArtist": "Artist", "LabelArtist": "Artist",
"LabelMovie": "Movie", "LabelMovie": "Movie",
"LabelMusicVideo": "Music Video", "LabelMusicVideo": "Music Video",
@ -46,6 +47,7 @@
"ButtonSave": "Save", "ButtonSave": "Save",
"HeaderDevices": "Devices", "HeaderDevices": "Devices",
"ButtonScheduledTasks": "Scheduled tasks", "ButtonScheduledTasks": "Scheduled tasks",
"HeaderSelectCertificatePath": "Select Certificate Path",
"ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:", "ConfirmMessageScheduledTaskButton": "This operation normally runs automatically as a scheduled task. It can also be run manually here. To configure the scheduled task, see:",
"HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.", "HeaderSupporterBenefit": "A supporter membership provides additional benefits such as access to premium plugins, internet channel content, and more. {0}Learn more{1}.",
"HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard", "HeaderWelcomeToMediaBrowserServerDashboard": "Welcome to the Media Browser Dashboard",

View File

@ -55,6 +55,8 @@
"HeaderAudio": "Audio", "HeaderAudio": "Audio",
"HeaderVideo": "Video", "HeaderVideo": "Video",
"HeaderPaths": "Paths", "HeaderPaths": "Paths",
"LabelCustomCertificatePath": "Custom certificate path:",
"LabelCustomCertificatePathHelp": "Supply your own ssl certificate. If omitted, the server will create a self-signed certificate.",
"TitleNotifications": "Notifications", "TitleNotifications": "Notifications",
"ButtonDonateWithPayPal": "Donate with PayPal", "ButtonDonateWithPayPal": "Donate with PayPal",
"OptionDetectArchiveFilesAsMedia": "Detect archive files as media", "OptionDetectArchiveFilesAsMedia": "Detect archive files as media",

View File

@ -117,6 +117,7 @@
<Compile Include="Collections\CollectionManager.cs" /> <Compile Include="Collections\CollectionManager.cs" />
<Compile Include="Collections\CollectionsDynamicFolder.cs" /> <Compile Include="Collections\CollectionsDynamicFolder.cs" />
<Compile Include="Collections\ManualCollectionsFolder.cs" /> <Compile Include="Collections\ManualCollectionsFolder.cs" />
<Compile Include="Collections\CollectionImageProvider.cs" />
<Compile Include="Configuration\ServerConfigurationManager.cs" /> <Compile Include="Configuration\ServerConfigurationManager.cs" />
<Compile Include="Connect\ConnectData.cs" /> <Compile Include="Connect\ConnectData.cs" />
<Compile Include="Connect\ConnectManager.cs" /> <Compile Include="Connect\ConnectManager.cs" />

View File

@ -1,7 +1,6 @@
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;

View File

@ -14,7 +14,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Photos namespace MediaBrowser.Server.Implementations.Photos
{ {
public abstract class BaseDynamicImageProvider<T> : IHasChangeMonitor public abstract class BaseDynamicImageProvider<T> : IHasChangeMonitor, IForcedProvider
where T : IHasImages where T : IHasImages
{ {
protected IFileSystem FileSystem { get; private set; } protected IFileSystem FileSystem { get; private set; }

View File

@ -16,7 +16,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
public override bool IsVisible(User user) public override bool IsVisible(User user)
{ {
return base.IsVisible(user) && GetRecursiveChildren(user, false) return base.IsVisible(user) && GetChildren(user, false)
.OfType<Playlist>() .OfType<Playlist>()
.Any(i => i.IsVisible(user)); .Any(i => i.IsVisible(user));
} }

View File

@ -90,6 +90,10 @@ namespace MediaBrowser.Server.Implementations.Sync
continue; continue;
} }
var index = jobItems.Count == 0 ?
0 :
(jobItems.Select(i => i.JobItemIndex).Max() + 1);
jobItem = new SyncJobItem jobItem = new SyncJobItem
{ {
Id = Guid.NewGuid().ToString("N"), Id = Guid.NewGuid().ToString("N"),
@ -97,7 +101,8 @@ namespace MediaBrowser.Server.Implementations.Sync
ItemName = GetSyncJobItemName(item), ItemName = GetSyncJobItemName(item),
JobId = job.Id, JobId = job.Id,
TargetId = job.TargetId, TargetId = job.TargetId,
DateCreated = DateTime.UtcNow DateCreated = DateTime.UtcNow,
JobItemIndex = index
}; };
await _syncRepo.Create(jobItem).ConfigureAwait(false); await _syncRepo.Create(jobItem).ConfigureAwait(false);

View File

@ -41,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public async Task Initialize() public async Task Initialize()
{ {
var dbFile = Path.Combine(_appPaths.DataPath, "sync13.db"); var dbFile = Path.Combine(_appPaths.DataPath, "sync14.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
@ -50,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.Sync
"create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT NOT NULL, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)", "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT NOT NULL, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)",
"create index if not exists idx_SyncJobs on SyncJobs(Id)", "create index if not exists idx_SyncJobs on SyncJobs(Id)",
"create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, TemporaryPath TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT, AdditionalFiles TEXT, MediaSource TEXT, IsMarkedForRemoval BIT)", "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, TemporaryPath TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT, AdditionalFiles TEXT, MediaSource TEXT, IsMarkedForRemoval BIT, JobItemIndex INT)",
"create index if not exists idx_SyncJobItems on SyncJobs(Id)", "create index if not exists idx_SyncJobItems on SyncJobs(Id)",
//pragmas //pragmas
@ -95,7 +95,7 @@ namespace MediaBrowser.Server.Implementations.Sync
_saveJobCommand.Parameters.Add(_saveJobCommand, "@ItemCount"); _saveJobCommand.Parameters.Add(_saveJobCommand, "@ItemCount");
_saveJobItemCommand = _connection.CreateCommand(); _saveJobItemCommand = _connection.CreateCommand();
_saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource, @IsMarkedForRemoval)"; _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource, @IsMarkedForRemoval, @JobItemIndex)";
_saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Id"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Id");
_saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@ItemId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@ItemId");
@ -111,10 +111,11 @@ namespace MediaBrowser.Server.Implementations.Sync
_saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@AdditionalFiles"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@AdditionalFiles");
_saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@MediaSource"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@MediaSource");
_saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@IsMarkedForRemoval"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@IsMarkedForRemoval");
_saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@JobItemIndex");
} }
private const string BaseJobSelectText = "select Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs"; private const string BaseJobSelectText = "select Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs";
private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval from SyncJobItems"; private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex from SyncJobItems";
public SyncJob GetJob(string id) public SyncJob GetJob(string id)
{ {
@ -496,7 +497,7 @@ namespace MediaBrowser.Server.Implementations.Sync
var startIndex = query.StartIndex ?? 0; var startIndex = query.StartIndex ?? 0;
if (startIndex > 0) if (startIndex > 0)
{ {
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobItems ORDER BY DateCreated LIMIT {0})", whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobItems ORDER BY JobItemIndex, DateCreated LIMIT {0})",
startIndex.ToString(_usCulture))); startIndex.ToString(_usCulture)));
} }
@ -505,7 +506,7 @@ namespace MediaBrowser.Server.Implementations.Sync
cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray());
} }
cmd.CommandText += " ORDER BY DateCreated"; cmd.CommandText += " ORDER BY JobItemIndex, DateCreated";
if (query.Limit.HasValue) if (query.Limit.HasValue)
{ {
@ -574,6 +575,7 @@ namespace MediaBrowser.Server.Implementations.Sync
_saveJobItemCommand.GetParameter(index++).Value = _json.SerializeToString(jobItem.AdditionalFiles); _saveJobItemCommand.GetParameter(index++).Value = _json.SerializeToString(jobItem.AdditionalFiles);
_saveJobItemCommand.GetParameter(index++).Value = jobItem.MediaSource == null ? null : _json.SerializeToString(jobItem.MediaSource); _saveJobItemCommand.GetParameter(index++).Value = jobItem.MediaSource == null ? null : _json.SerializeToString(jobItem.MediaSource);
_saveJobItemCommand.GetParameter(index++).Value = jobItem.IsMarkedForRemoval; _saveJobItemCommand.GetParameter(index++).Value = jobItem.IsMarkedForRemoval;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.JobItemIndex;
_saveJobItemCommand.Transaction = transaction; _saveJobItemCommand.Transaction = transaction;
@ -648,7 +650,7 @@ namespace MediaBrowser.Server.Implementations.Sync
info.TargetId = reader.GetString(8); info.TargetId = reader.GetString(8);
info.DateCreated = reader.GetDateTime(9); info.DateCreated = reader.GetDateTime(9).ToUniversalTime();
if (!reader.IsDBNull(10)) if (!reader.IsDBNull(10))
{ {
@ -676,7 +678,8 @@ namespace MediaBrowser.Server.Implementations.Sync
} }
info.IsMarkedForRemoval = reader.GetBoolean(13); info.IsMarkedForRemoval = reader.GetBoolean(13);
info.JobItemIndex = reader.GetInt32(14);
return info; return info;
} }

View File

@ -163,7 +163,10 @@ namespace MediaBrowser.Server.Implementations.TV
return new Tuple<Episode, DateTime>(nextUp, lastWatchedDate); return new Tuple<Episode, DateTime>(nextUp, lastWatchedDate);
} }
return new Tuple<Episode, DateTime>(null, lastWatchedDate); var firstEpisode = allEpisodes.LastOrDefault(i => i.LocationType != LocationType.Virtual && !i.IsPlayed(user));
// Return the first episode
return new Tuple<Episode, DateTime>(firstEpisode, DateTime.MinValue);
} }
private IEnumerable<Series> FilterSeries(NextUpQuery request, IEnumerable<Series> items) private IEnumerable<Series> FilterSeries(NextUpQuery request, IEnumerable<Series> items)

View File

@ -796,35 +796,35 @@ namespace MediaBrowser.Server.Startup.Common
private string GetCertificatePath(bool generateCertificate) private string GetCertificatePath(bool generateCertificate)
{ {
if (string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.CertificatePath)) if (!string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.CertificatePath))
{ {
// Generate self-signed cert // Custom cert
var certHost = GetHostnameFromExternalDns(ServerConfigurationManager.Configuration.WanDdns); return ServerConfigurationManager.Configuration.CertificatePath;
var certPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.ProgramDataPath, "ssl", "cert_" + certHost.GetMD5().ToString("N") + ".pfx");
if (generateCertificate)
{
if (!File.Exists(certPath))
{
Directory.CreateDirectory(Path.GetDirectoryName(certPath));
try
{
NetworkManager.GenerateSelfSignedSslCertificate(certPath, certHost);
}
catch (Exception ex)
{
Logger.ErrorException("Error creating ssl cert", ex);
return null;
}
}
}
return certPath;
} }
// Custom cert // Generate self-signed cert
return ServerConfigurationManager.Configuration.CertificatePath; var certHost = GetHostnameFromExternalDns(ServerConfigurationManager.Configuration.WanDdns);
var certPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.ProgramDataPath, "ssl", "cert_" + certHost.GetMD5().ToString("N") + ".pfx");
if (generateCertificate)
{
if (!File.Exists(certPath))
{
Directory.CreateDirectory(Path.GetDirectoryName(certPath));
try
{
NetworkManager.GenerateSelfSignedSslCertificate(certPath, certHost);
}
catch (Exception ex)
{
Logger.ErrorException("Error creating ssl cert", ex);
return null;
}
}
}
return certPath;
} }
/// <summary> /// <summary>