some initial work on cloud sync

This commit is contained in:
Luke Pulverenti 2015-02-05 00:29:37 -05:00
parent 1f1852f3cb
commit 7d415fc2fd
19 changed files with 333 additions and 568 deletions

View File

@ -211,6 +211,9 @@ namespace MediaBrowser.Api.Sync
throw new ArgumentException("The job item is not yet ready for transfer."); throw new ArgumentException("The job item is not yet ready for transfer.");
} }
var task = _syncManager.ReportSyncJobItemTransferBeginning(request.Id);
Task.WaitAll(task);
return ToStaticFileResult(jobItem.OutputPath); return ToStaticFileResult(jobItem.OutputPath);
} }

View File

@ -245,14 +245,13 @@ namespace MediaBrowser.Controller.Entities
protected virtual IEnumerable<string> GetIndexByOptions() protected virtual IEnumerable<string> GetIndexByOptions()
{ {
return new List<string> { return new List<string> {
{LocalizedStrings.Instance.GetString("NoneDispPref")}, {"None"},
{LocalizedStrings.Instance.GetString("PerformerDispPref")}, {"Performer"},
{LocalizedStrings.Instance.GetString("GenreDispPref")}, {"Genre"},
{LocalizedStrings.Instance.GetString("DirectorDispPref")}, {"Director"},
{LocalizedStrings.Instance.GetString("YearDispPref")}, {"Year"},
{LocalizedStrings.Instance.GetString("StudioDispPref")} {"Studio"}
}; };
} }
/// <summary> /// <summary>

View File

@ -81,10 +81,10 @@ namespace MediaBrowser.Controller.Entities.TV
protected override IEnumerable<string> GetIndexByOptions() protected override IEnumerable<string> GetIndexByOptions()
{ {
return new List<string> { return new List<string> {
{LocalizedStrings.Instance.GetString("NoneDispPref")}, {"None"},
{LocalizedStrings.Instance.GetString("PerformerDispPref")}, {"Performer"},
{LocalizedStrings.Instance.GetString("DirectorDispPref")}, {"Director"},
{LocalizedStrings.Instance.GetString("YearDispPref")}, {"Year"},
}; };
} }

View File

@ -133,10 +133,10 @@ namespace MediaBrowser.Controller.Entities.TV
protected override IEnumerable<string> GetIndexByOptions() protected override IEnumerable<string> GetIndexByOptions()
{ {
return new List<string> { return new List<string> {
{LocalizedStrings.Instance.GetString("NoneDispPref")}, {"None"},
{LocalizedStrings.Instance.GetString("PerformerDispPref")}, {"Performer"},
{LocalizedStrings.Instance.GetString("DirectorDispPref")}, {"Director"},
{LocalizedStrings.Instance.GetString("YearDispPref")}, {"Year"},
}; };
} }

View File

@ -1,287 +0,0 @@

namespace MediaBrowser.Controller.Localization
{
public class BaseStrings : LocalizedStringData
{
public BaseStrings()
{
ThisVersion = "1.0002";
Prefix = LocalizedStrings.BasePrefix;
}
//Config Panel
public string ConfigConfig = "Configuration";
public string VersionConfig = "Version";
public string MediaOptionsConfig = "Media Options";
public string ThemesConfig = "Theme Options";
public string ParentalControlConfig = "Parental Control";
public string ContinueConfig = "Continue";
public string ResetDefaultsConfig = "Reset Defaults";
public string ClearCacheConfig = "Clear Cache";
public string UnlockConfig = "Unlock";
public string GeneralConfig = "General";
public string EnableScreenSaverConfig = "Screen Saver";
public string SSTimeOutConfig = "Timeout (mins)";
public string TrackingConfig = "Tracking";
public string AssumeWatchedIfOlderThanConfig = "Assume Played If Older Than";
public string MetadataConfig = "Metadata";
public string EnableInternetProvidersConfig = "Allow Internet Providers";
public string UpdatesConfig = "Updates";
public string AutomaticUpdatesConfig = "Check For Updates";
public string LoggingConfig = "Logging";
public string BetaUpdatesConfig = "Beta Updates";
public string GlobalConfig = "Global";
public string EnableEHSConfig = "Enable EHS";
public string ShowClockConfig = "Show Clock";
public string DimUnselectedPostersConfig = "Dim Unselected Posters";
public string HideFocusFrameConfig = "Hide Focus Frame";
public string AlwaysShowDetailsConfig = "Always Show Details";
public string ExcludeRemoteContentInSearchesConfig = "Exclude Remote Content In Searches";
public string EnhancedMouseSupportConfig = "Enhanced Mouse Support";
public string ViewsConfig = "Views";
public string PosterGridSpacingConfig = "Poster Grid Spacing";
public string ThumbWidthSplitConfig = "Thumb Width Split";
public string BreadcrumbCountConfig = "Breadcrumb Count";
public string ShowFanArtonViewsConfig = "Show Fan Art on Views";
public string ShowInitialFolderBackgroundConfig = "Show Initial Folder Background";
public string ShowThemeBackgroundConfig = "Show Theme Background";
public string ShowHDOverlayonPostersConfig = "Show HD Overlay on Posters";
public string ShowIcononRemoteContentConfig = "Show Icon on Remote Content";
public string EnableAdvancedCmdsConfig = "Enable Advanced Commands";
public string MediaTrackingConfig = "Media Tracking";
public string RememberFolderIndexingConfig = "Remember Folder Indexing";
public string ShowUnwatchedCountConfig = "Show Unplayed Count";
public string WatchedIndicatoronFoldersConfig = "Played Indicator on Folders";
public string HighlightUnwatchedItemsConfig = "Highlight Unplayed Items";
public string WatchedIndicatoronVideosConfig = "Played Indicator on Items";
public string WatchedIndicatorinDetailViewConfig = "Played Indicator in Detail View";
public string DefaultToFirstUnwatchedItemConfig = "Default To First Unplayed Item";
public string GeneralBehaviorConfig = "General Behavior";
public string AllowNestedMovieFoldersConfig = "Allow Nested Movie Folders";
public string AutoEnterSingleFolderItemsConfig = "Auto Enter Single Folder Items";
public string MultipleFileBehaviorConfig = "Multiple File Behavior";
public string TreatMultipleFilesAsSingleMovieConfig = "Treat Multiple Files As Single Movie";
public string MultipleFileSizeLimitConfig = "Multiple File Size Limit";
public string MBThemeConfig = "Media Browser Theme";
public string VisualThemeConfig = "Visual Theme";
public string ColorSchemeConfig = "Color Scheme *";
public string FontSizeConfig = "Font Size *";
public string RequiresRestartConfig = "* Requires a restart to take effect.";
public string ThemeSettingsConfig = "Theme Specific Settings";
public string ShowConfigButtonConfig = "Show Config Button";
public string AlphaBlendingConfig = "Alpha Blending";
public string SecurityPINConfig = "Security PIN";
public string PCUnlockedTxtConfig = "Parental Controls are Temporarily Unlocked. You cannot change values unless you re-lock.";
public string RelockBtnConfig = "Re-Lock";
public string EnableParentalBlocksConfig = "Enable Parental Blocks";
public string MaxAllowedRatingConfig = "Max Allowed Rating ";
public string BlockUnratedContentConfig = "Block Unrated Content";
public string HideBlockedContentConfig = "Hide Blocked Content";
public string UnlockonPINEntryConfig = "Unlock on PIN Entry";
public string UnlockPeriodHoursConfig = "Unlock Period (Hours)";
public string EnterNewPINConfig = "Enter New PIN";
public string RandomizeBackdropConfig = "Randomize";
public string RotateBackdropConfig = "Rotate";
public string UpdateLibraryConfig = "Update Library";
public string BackdropSettingsConfig = "Backdrop Settings";
public string BackdropRotationIntervalConfig = "Rotation Time";
public string BackdropTransitionIntervalConfig = "Transition Time";
public string BackdropLoadDelayConfig = "Load Delay";
public string AutoScrollTextConfig = "Auto Scroll Overview";
public string SortYearsAscConfig = "Sort by Year in Ascending Order";
public string AutoValidateConfig = "Automatically Validate Items";
public string SaveLocalMetaConfig = "Save Locally";
public string HideEmptyFoldersConfig = "Hide Empty TV Folders";
//EHS
public string RecentlyWatchedEHS = "last played";
public string RecentlyAddedEHS = "last added";
public string RecentlyAddedUnwatchedEHS = "last added unplayed";
public string WatchedEHS = "Played";
public string AddedEHS = "Added";
public string UnwatchedEHS = "Unplayed";
public string AddedOnEHS = "Added on";
public string OnEHS = "on";
public string OfEHS = "of";
public string NoItemsEHS = "No Items To Show";
public string VariousEHS = "(various)";
//Context menu
public string CloseCMenu = "Close";
public string PlayMenuCMenu = "Play Menu";
public string ItemMenuCMenu = "Item Menu";
public string PlayAllCMenu = "Play All";
public string PlayAllFromHereCMenu = "Play All From Here";
public string ResumeCMenu = "Resume";
public string MarkUnwatchedCMenu = "Mark Unplayed";
public string MarkWatchedCMenu = "Mark Played";
public string ShufflePlayCMenu = "Shuffle Play";
//Media Detail Page
public string GeneralDetail = "General";
public string ActorsDetail = "Actors";
public string ArtistsDetail = "Artists";
public string PlayDetail = "Play";
public string ResumeDetail = "Resume";
public string RefreshDetail = "Refresh";
public string PlayTrailersDetail = "Trailer";
public string CacheDetail = "Cache 2 xml";
public string DeleteDetail = "Delete";
public string TMDBRatingDetail = "TMDb Rating";
public string OutOfDetail = "out of";
public string DirectorDetail = "Director";
public string ComposerDetail = "Composer";
public string HostDetail = "Host";
public string RuntimeDetail = "Runtime";
public string NextItemDetail = "Next";
public string PreviousItemDetail = "Previous";
public string FirstAiredDetail = "First aired";
public string LastPlayedDetail = "Last played";
public string TrackNumberDetail = "Track";
public string DirectedByDetail = "Directed By: ";
public string WrittenByDetail = "Written By: ";
public string ComposedByDetail = "Composed By: ";
//Display Prefs
public string ViewDispPref = "View";
public string ViewSearch = "Search";
public string CoverFlowDispPref = "Cover Flow";
public string DetailDispPref = "Detail";
public string PosterDispPref = "Poster";
public string ThumbDispPref = "Thumb";
public string ThumbStripDispPref = "Thumb Strip";
public string ShowLabelsDispPref = "Show Labels";
public string VerticalScrollDispPref = "Vertical Scroll";
public string UseBannersDispPref = "Use Banners";
public string UseCoverflowDispPref = "Use Coverflow Style";
public string ThumbSizeDispPref = "Thumb Size";
public string NameDispPref = "Name";
public string DateDispPref = "Date";
public string RatingDispPref = "User Rating";
public string OfficialRatingDispPref = "Rating";
public string RuntimeDispPref = "Runtime";
public string UnWatchedDispPref = "Unplayed";
public string YearDispPref = "Year";
public string NoneDispPref = "None";
public string PerformerDispPref = "Performer";
public string ActorDispPref = "Actor";
public string GenreDispPref = "Genre";
public string DirectorDispPref = "Director";
public string StudioDispPref = "Studio";
//Dialog boxes
//public string BrokenEnvironmentDial = "Application will now close due to broken MediaCenterEnvironment object, possibly due to 5 minutes of idle time and/or running with TVPack installed.";
//public string InitialConfigDial = "Initial configuration is complete, please restart Media Browser";
//public string DeleteMediaDial = "Are you sure you wish to delete this media item?";
//public string DeleteMediaCapDial = "Delete Confirmation";
//public string NotDeletedDial = "Item NOT Deleted.";
//public string NotDeletedCapDial = "Delete Cancelled by User";
//public string NotDelInvalidPathDial = "The selected media item cannot be deleted due to an invalid path. Or you may not have sufficient access rights to perform this command.";
//public string DelFailedDial = "Delete Failed";
//public string NotDelUnknownDial = "The selected media item cannot be deleted due to an unknown error.";
//public string NotDelTypeDial = "The selected media item cannot be deleted due to its Item-Type or you have not enabled this feature in the configuration file.";
//public string FirstTimeDial = "As this is the first time you have run Media Browser please setup the inital configuration";
//public string FirstTimeCapDial = "Configure";
//public string EntryPointErrorDial = "Media Browser could not launch directly into ";
//public string EntryPointErrorCapDial = "Entrypoint Error";
//public string CriticalErrorDial = "Media Browser encountered a critical error and had to shut down: ";
//public string CriticalErrorCapDial = "Critical Error";
//public string ClearCacheErrorDial = "An error occured during the clearing of the cache, you may wish to manually clear it from {0} before restarting Media Browser";
//public string RestartMBDial = "Please restart Media Browser";
//public string ClearCacheDial = "Are you sure you wish to clear the cache?\nThis will erase all cached and downloaded information and images.";
//public string ClearCacheCapDial = "Clear Cache";
//public string CacheClearedDial = "Cache Cleared";
//public string ResetConfigDial = "Are you sure you wish to reset all configuration to defaults?";
//public string ResetConfigCapDial = "Reset Configuration";
//public string ConfigResetDial = "Configuration Reset";
//public string UpdateMBDial = "Please visit www.mediabrowser.tv/download to install the new version.";
//public string UpdateMBCapDial = "Update Available";
//public string UpdateMBExtDial = "There is an update available for Media Browser. Please update Media Browser next time you are at your MediaCenter PC.";
//public string DLUpdateFailDial = "Media Browser will operate normally and prompt you again the next time you load it.";
//public string DLUpdateFailCapDial = "Update Download Failed";
//public string UpdateSuccessDial = "Media Browser must now exit to apply the update. It will restart automatically when it is done";
//public string UpdateSuccessCapDial = "Update Downloaded";
//public string CustomErrorDial = "Customisation Error";
//public string ConfigErrorDial = "Reset to default?";
//public string ConfigErrorCapDial = "Error in configuration file";
//public string ContentErrorDial = "There was a problem playing the content. Check location exists";
//public string ContentErrorCapDial = "Content Error";
//public string CannotMaximizeDial = "We can not maximize the window! This is a known bug with Windows 7 and TV Pack, you will have to restart Media Browser!";
//public string IncorrectPINDial = "Incorrect PIN Entered";
//public string ContentProtected = "Content Protected";
//public string CantChangePINDial = "Cannot Change PIN";
//public string LibraryUnlockedDial = "Library Temporarily Unlocked. Will Re-Lock in {0} Hour(s) or on Application Re-Start";
//public string LibraryUnlockedCapDial = "Unlock";
//public string PINChangedDial = "PIN Successfully Changed";
//public string PINChangedCapDial = "PIN Change";
//public string EnterPINToViewDial = "Please Enter PIN to View Protected Content";
//public string EnterPINToPlayDial = "Please Enter PIN to Play Protected Content";
//public string EnterCurrentPINDial = "Please Enter CURRENT PIN.";
//public string EnterNewPINDial = "Please Enter NEW PIN (exactly 4 digits).";
//public string EnterPINDial = "Please Enter PIN to Unlock Library";
//public string NoContentDial = "No Content that can be played in this context.";
//public string FontsMissingDial = "CustomFonts.mcml as been patched with missing values";
//public string StyleMissingDial = "{0} has been patched with missing values";
//public string ManualRefreshDial = "Library Update Started. Will proceed in the background.";
//public string ForcedRebuildDial = "Your library is currently being migrated by the service. The service will re-start when it is finished and you may then run Media Browser.";
//public string ForcedRebuildCapDial = "Library Migration";
//public string RefreshFailedDial = "The last service refresh process failed. Please run a manual refresh from the service.";
//public string RefreshFailedCapDial = "Service Refresh Failed";
//public string RebuildNecDial = "This version of Media Browser requires a re-build of your library. It has started automatically in the service. Some information may be incomplete until this process finishes.";
//public string MigrateNecDial = "This version of Media Browser requires a migration of your library. It has started automatically in the service. The service will restart when it is complete and you may then run Media Browser.";
//public string RebuildFailedDial = "There was an error attempting to tell the service to re-build your library. Please run the service and do a manual refresh with the cache clear options selected.";
//public string MigrateFailedDial = "There was an error attempting to tell the service to re-build your library. Please run the service and do a manual refresh with the cache clear options selected.";
//public string RefreshFolderDial = "Refresh all contents too?";
//public string RefreshFolderCapDial = "Refresh Folder";
//Generic
public string Restartstr = "Restart";
public string Errorstr = "Error";
public string Playstr = "Play";
public string MinutesStr = "mins"; //Minutes abbreviation
public string HoursStr = "hrs"; //Hours abbreviation
public string EndsStr = "Ends";
public string KBsStr = "Kbps"; //Kilobytes per second
public string FrameRateStr = "fps"; //Frames per second
public string AtStr = "at"; //x at y, e.g. 1920x1080 at 25 fps
public string Rated = "Rated";
public string Or = "Or ";
public string Lower = "Lower";
public string Higher = "Higher";
public string Search = "Search";
public string Cancel = "Cancel";
public string TitleContains = "Title Contains ";
public string Any = "Any";
//Search
public string IncludeNested = "Include Subfolders";
public string UnwatchedOnly = "Include Only Unwatched";
public string FilterByRated = "Filter by Rating";
//Profiler
public string WelcomeProf = "Welcome to Media Browser";
public string ProfilerTimeProf = "{1} took {2} seconds.";
public string RefreshProf = "Refresh";
public string SetWatchedProf = "Set Played {0}";
public string RefreshFolderProf = "Refresh Folder and all Contents of";
public string ClearWatchedProf = "Clear Played {0}";
public string FullRefreshProf = "Full Library Refresh";
public string FullValidationProf = "Full Library Validation";
public string FastRefreshProf = "Fast Metadata refresh";
public string SlowRefresh = "Slow Metadata refresh";
public string ImageRefresh = "Image refresh";
public string PluginUpdateProf = "An update is available for plug-in {0}";
public string NoPluginUpdateProf = "No Plugin Updates Currently Available.";
public string LibraryUnLockedProf = "Library Temporarily UnLocked. Will Re-Lock in {0} Hour(s)";
public string LibraryReLockedProf = "Library Re-Locked";
//Messages
public string FullRefreshMsg = "Updating Media Library...";
public string FullRefreshFinishedMsg = "Library update complete";
}
}

View File

@ -1,51 +0,0 @@
using System.IO;
using System.Xml.Serialization;
namespace MediaBrowser.Controller.Localization
{
/// <summary>
/// Class LocalizedStringData
/// </summary>
public class LocalizedStringData
{
/// <summary>
/// The this version
/// </summary>
[XmlIgnore]
public string ThisVersion = "1.0000";
/// <summary>
/// The prefix
/// </summary>
[XmlIgnore]
public string Prefix = "";
/// <summary>
/// The file name
/// </summary>
public string FileName; //this is public so it will serialize and we know where to save ourselves
/// <summary>
/// The version
/// </summary>
public string Version = ""; //this will get saved so we can check it against us for changes
/// <summary>
/// Saves this instance.
/// </summary>
public void Save()
{
Save(FileName);
}
/// <summary>
/// Saves the specified file.
/// </summary>
/// <param name="file">The file.</param>
public void Save(string file)
{
var xs = new XmlSerializer(GetType());
using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None))
{
xs.Serialize(fs, this);
}
}
}
}

View File

@ -1,166 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
namespace MediaBrowser.Controller.Localization
{
/// <summary>
/// Class LocalizedStrings
/// </summary>
public class LocalizedStrings
{
public static IServerApplicationPaths ApplicationPaths;
/// <summary>
/// Gets the list of Localized string files
/// </summary>
/// <value>The string files.</value>
public static IEnumerable<LocalizedStringData> StringFiles { get; set; }
/// <summary>
/// The base prefix
/// </summary>
public const string BasePrefix = "base-";
/// <summary>
/// The local strings
/// </summary>
protected ConcurrentDictionary<string, string> LocalStrings = new ConcurrentDictionary<string, string>();
/// <summary>
/// The _instance
/// </summary>
private static LocalizedStrings _instance;
private readonly IServerApplicationPaths _appPaths;
/// <summary>
/// Gets the instance.
/// </summary>
/// <value>The instance.</value>
public static LocalizedStrings Instance { get { return _instance ?? (_instance = new LocalizedStrings(ApplicationPaths)); } }
/// <summary>
/// Initializes a new instance of the <see cref="LocalizedStrings" /> class.
/// </summary>
public LocalizedStrings(IServerApplicationPaths appPaths)
{
_appPaths = appPaths;
foreach (var stringObject in StringFiles)
{
AddStringData(LoadFromFile(GetFileName(stringObject),stringObject.GetType()));
}
}
/// <summary>
/// Gets the name of the file.
/// </summary>
/// <param name="stringObject">The string object.</param>
/// <returns>System.String.</returns>
protected string GetFileName(LocalizedStringData stringObject)
{
var path = _appPaths.LocalizationPath;
var name = Path.Combine(path, stringObject.Prefix + "strings-" + CultureInfo.CurrentCulture + ".xml");
if (File.Exists(name))
{
return name;
}
name = Path.Combine(path, stringObject.Prefix + "strings-" + CultureInfo.CurrentCulture.Parent + ".xml");
if (File.Exists(name))
{
return name;
}
//just return default
return Path.Combine(path, stringObject.Prefix + "strings-en.xml");
}
/// <summary>
/// Loads from file.
/// </summary>
/// <param name="file">The file.</param>
/// <param name="t">The t.</param>
/// <returns>LocalizedStringData.</returns>
protected LocalizedStringData LoadFromFile(string file, Type t)
{
return new BaseStrings {FileName = file};
//var xs = new XmlSerializer(t);
//var strings = (LocalizedStringData)Activator.CreateInstance(t);
//strings.FileName = file;
//Logger.Info("Using String Data from {0}", file);
//if (File.Exists(file))
//{
// using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
// {
// strings = (LocalizedStringData)xs.Deserialize(fs);
// }
//}
//else
//{
// strings.Save(); //brand new - save it
//}
//if (strings.ThisVersion != strings.Version && file.ToLower().Contains("-en.xml"))
//{
// //only re-save the english version as that is the one defined internally
// strings = new BaseStrings {FileName = file};
// strings.Save();
//}
//return strings;
}
/// <summary>
/// Adds the string data.
/// </summary>
/// <param name="stringData">The string data.</param>
public void AddStringData(object stringData )
{
//translate our object definition into a dictionary for lookups
// and a reverse dictionary so we can lookup keys by value
foreach (var field in stringData.GetType().GetFields().Where(f => f != null && f.FieldType == typeof(string)))
{
string value;
try
{
value = field.GetValue(stringData) as string;
}
catch (TargetException)
{
//Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
continue;
}
catch (FieldAccessException)
{
//Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
continue;
}
catch (NotSupportedException)
{
//Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
continue;
}
LocalStrings.TryAdd(field.Name, value);
}
}
/// <summary>
/// Gets the string.
/// </summary>
/// <param name="key">The key.</param>
/// <returns>System.String.</returns>
public string GetString(string key)
{
string value;
LocalStrings.TryGetValue(key, out value);
return value;
}
}
}

View File

@ -313,9 +313,6 @@
<Compile Include="Library\ILibraryManager.cs" /> <Compile Include="Library\ILibraryManager.cs" />
<Compile Include="Library\IUserManager.cs" /> <Compile Include="Library\IUserManager.cs" />
<Compile Include="Library\Profiler.cs" /> <Compile Include="Library\Profiler.cs" />
<Compile Include="Localization\BaseStrings.cs" />
<Compile Include="Localization\LocalizedStringData.cs" />
<Compile Include="Localization\LocalizedStrings.cs" />
<Compile Include="Persistence\IDisplayPreferencesRepository.cs" /> <Compile Include="Persistence\IDisplayPreferencesRepository.cs" />
<Compile Include="Persistence\IItemRepository.cs" /> <Compile Include="Persistence\IItemRepository.cs" />
<Compile Include="Persistence\IRepository.cs" /> <Compile Include="Persistence\IRepository.cs" />
@ -344,6 +341,7 @@
<Compile Include="Subtitles\SubtitleResponse.cs" /> <Compile Include="Subtitles\SubtitleResponse.cs" />
<Compile Include="Subtitles\SubtitleSearchRequest.cs" /> <Compile Include="Subtitles\SubtitleSearchRequest.cs" />
<Compile Include="Sync\ICloudSyncProvider.cs" /> <Compile Include="Sync\ICloudSyncProvider.cs" />
<Compile Include="Sync\IServerSyncProvider.cs" />
<Compile Include="Sync\ISyncManager.cs" /> <Compile Include="Sync\ISyncManager.cs" />
<Compile Include="Sync\ISyncProvider.cs" /> <Compile Include="Sync\ISyncProvider.cs" />
<Compile Include="Sync\ISyncRepository.cs" /> <Compile Include="Sync\ISyncRepository.cs" />

View File

@ -0,0 +1,52 @@
using MediaBrowser.Model.Sync;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Sync
{
public interface IServerSyncProvider : ISyncProvider
{
/// <summary>
/// Gets the server item ids.
/// </summary>
/// <param name="serverId">The server identifier.</param>
/// <param name="target">The target.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;List&lt;System.String&gt;&gt;.</returns>
Task<List<string>> GetServerItemIds(string serverId, SyncTarget target, CancellationToken cancellationToken);
/// <summary>
/// Removes the item.
/// </summary>
/// <param name="serverId">The server identifier.</param>
/// <param name="itemId">The item identifier.</param>
/// <param name="target">The target.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task DeleteItem(string serverId, string itemId, SyncTarget target, CancellationToken cancellationToken);
/// <summary>
/// Transfers the file.
/// </summary>
/// <param name="serverId">The server identifier.</param>
/// <param name="itemId">The item identifier.</param>
/// <param name="path">The path.</param>
/// <param name="target">The target.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task TransferItemFile(string serverId, string itemId, string path, SyncTarget target, CancellationToken cancellationToken);
/// <summary>
/// Transfers the related file.
/// </summary>
/// <param name="serverId">The server identifier.</param>
/// <param name="itemId">The item identifier.</param>
/// <param name="path">The path.</param>
/// <param name="type">The type.</param>
/// <param name="target">The target.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task TransferRelatedFile(string serverId, string itemId, string path, ItemFileType type, SyncTarget target, CancellationToken cancellationToken);
}
}

View File

@ -167,5 +167,19 @@ namespace MediaBrowser.Controller.Sync
/// <param name="job">The job.</param> /// <param name="job">The job.</param>
/// <returns>VideoOptions.</returns> /// <returns>VideoOptions.</returns>
VideoOptions GetVideoOptions(SyncJobItem jobItem, SyncJob job); VideoOptions GetVideoOptions(SyncJobItem jobItem, SyncJob job);
/// <summary>
/// Reports the synchronize job item transfer beginning.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>Task.</returns>
Task ReportSyncJobItemTransferBeginning(string id);
/// <summary>
/// Reports the synchronize job item transfer failed.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>Task.</returns>
Task ReportSyncJobItemTransferFailed(string id);
} }
} }

View File

@ -20,6 +20,7 @@ namespace MediaBrowser.Dlna.PlayTo
{ {
ItemId = item.Id.ToString("N"), ItemId = item.Id.ToString("N"),
MediaType = DlnaProfileType.Photo, MediaType = DlnaProfileType.Photo,
DeviceProfile = profile
}, },
Profile = profile Profile = profile

View File

@ -108,7 +108,8 @@ namespace MediaBrowser.Model.Dlna
MediaType = DlnaProfileType.Audio, MediaType = DlnaProfileType.Audio,
MediaSource = item, MediaSource = item,
RunTimeTicks = item.RunTimeTicks, RunTimeTicks = item.RunTimeTicks,
Context = options.Context Context = options.Context,
DeviceProfile = options.Profile
}; };
int? maxBitrateSetting = options.GetMaxBitrate(); int? maxBitrateSetting = options.GetMaxBitrate();
@ -240,7 +241,8 @@ namespace MediaBrowser.Model.Dlna
MediaType = DlnaProfileType.Video, MediaType = DlnaProfileType.Video,
MediaSource = item, MediaSource = item,
RunTimeTicks = item.RunTimeTicks, RunTimeTicks = item.RunTimeTicks,
Context = options.Context Context = options.Context,
DeviceProfile = options.Profile
}; };
int? audioStreamIndex = options.AudioStreamIndex ?? item.DefaultAudioStreamIndex; int? audioStreamIndex = options.AudioStreamIndex ?? item.DefaultAudioStreamIndex;
@ -265,7 +267,7 @@ namespace MediaBrowser.Model.Dlna
if (subtitleStream != null) if (subtitleStream != null)
{ {
SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options); SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile);
playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method; playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
playlistItem.SubtitleFormat = subtitleProfile.Format; playlistItem.SubtitleFormat = subtitleProfile.Format;
@ -290,7 +292,7 @@ namespace MediaBrowser.Model.Dlna
{ {
if (subtitleStream != null) if (subtitleStream != null)
{ {
SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options); SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile);
playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method; playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
playlistItem.SubtitleFormat = subtitleProfile.Format; playlistItem.SubtitleFormat = subtitleProfile.Format;
@ -524,7 +526,7 @@ namespace MediaBrowser.Model.Dlna
{ {
if (subtitleStream != null) if (subtitleStream != null)
{ {
SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options); SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile);
if (subtitleProfile.Method != SubtitleDeliveryMethod.External && subtitleProfile.Method != SubtitleDeliveryMethod.Embed) if (subtitleProfile.Method != SubtitleDeliveryMethod.External && subtitleProfile.Method != SubtitleDeliveryMethod.Embed)
{ {
@ -535,10 +537,10 @@ namespace MediaBrowser.Model.Dlna
return IsAudioEligibleForDirectPlay(item, maxBitrate); return IsAudioEligibleForDirectPlay(item, maxBitrate);
} }
private SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, VideoOptions options) public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, DeviceProfile deviceProfile)
{ {
// Look for an external profile that matches the stream type (text/graphical) // Look for an external profile that matches the stream type (text/graphical)
foreach (SubtitleProfile profile in options.Profile.SubtitleProfiles) foreach (SubtitleProfile profile in deviceProfile.SubtitleProfiles)
{ {
if (profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format)) if (profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format))
{ {
@ -546,13 +548,11 @@ namespace MediaBrowser.Model.Dlna
} }
} }
if (subtitleStream.IsTextSubtitleStream) foreach (SubtitleProfile profile in deviceProfile.SubtitleProfiles)
{ {
SubtitleProfile embedProfile = GetSubtitleProfile(options.Profile.SubtitleProfiles, SubtitleDeliveryMethod.Embed); if (profile.Method == SubtitleDeliveryMethod.Embed && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format))
if (embedProfile != null)
{ {
return embedProfile; return profile;
} }
} }
@ -563,19 +563,6 @@ namespace MediaBrowser.Model.Dlna
}; };
} }
private SubtitleProfile GetSubtitleProfile(SubtitleProfile[] profiles, SubtitleDeliveryMethod method)
{
foreach (SubtitleProfile profile in profiles)
{
if (method == profile.Method)
{
return profile;
}
}
return null;
}
private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, int? maxBitrate) private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, int? maxBitrate)
{ {
// Honor the max bitrate setting // Honor the max bitrate setting

View File

@ -54,6 +54,7 @@ namespace MediaBrowser.Model.Dlna
public float? MaxFramerate { get; set; } public float? MaxFramerate { get; set; }
public DeviceProfile DeviceProfile { get; set; }
public string DeviceProfileId { get; set; } public string DeviceProfileId { get; set; }
public string DeviceId { get; set; } public string DeviceId { get; set; }
@ -160,11 +161,6 @@ namespace MediaBrowser.Model.Dlna
List<SubtitleStreamInfo> list = new List<SubtitleStreamInfo>(); List<SubtitleStreamInfo> list = new List<SubtitleStreamInfo>();
if (SubtitleDeliveryMethod != SubtitleDeliveryMethod.External)
{
return list;
}
// HLS will preserve timestamps so we can just grab the full subtitle stream // HLS will preserve timestamps so we can just grab the full subtitle stream
long startPositionTicks = StringHelper.EqualsIgnoreCase(Protocol, "hls") long startPositionTicks = StringHelper.EqualsIgnoreCase(Protocol, "hls")
? 0 ? 0
@ -175,7 +171,7 @@ namespace MediaBrowser.Model.Dlna
{ {
foreach (MediaStream stream in MediaSource.MediaStreams) foreach (MediaStream stream in MediaSource.MediaStreams)
{ {
if (stream.Type == MediaStreamType.Subtitle && stream.IsTextSubtitleStream && stream.Index == SubtitleStreamIndex.Value) if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value)
{ {
AddSubtitle(list, stream, baseUrl, startPositionTicks); AddSubtitle(list, stream, baseUrl, startPositionTicks);
} }
@ -186,7 +182,7 @@ namespace MediaBrowser.Model.Dlna
{ {
foreach (MediaStream stream in MediaSource.MediaStreams) foreach (MediaStream stream in MediaSource.MediaStreams)
{ {
if (stream.Type == MediaStreamType.Subtitle && stream.IsTextSubtitleStream && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value)) if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value))
{ {
AddSubtitle(list, stream, baseUrl, startPositionTicks); AddSubtitle(list, stream, baseUrl, startPositionTicks);
} }
@ -198,6 +194,13 @@ namespace MediaBrowser.Model.Dlna
private void AddSubtitle(List<SubtitleStreamInfo> list, MediaStream stream, string baseUrl, long startPositionTicks) private void AddSubtitle(List<SubtitleStreamInfo> list, MediaStream stream, string baseUrl, long startPositionTicks)
{ {
var subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, DeviceProfile);
if (subtitleProfile.Method != SubtitleDeliveryMethod.External)
{
return;
}
string url = string.Format("{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", string url = string.Format("{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}",
baseUrl, baseUrl,
ItemId, ItemId,

View File

@ -614,7 +614,6 @@
"PleaseUpdateManually": "Please shutdown the server and update manually.", "PleaseUpdateManually": "Please shutdown the server and update manually.",
"NewServerVersionAvailable": "A new version of Media Browser Server is available!", "NewServerVersionAvailable": "A new version of Media Browser Server is available!",
"ServerUpToDate": "Media Browser Server is up to date", "ServerUpToDate": "Media Browser Server is up to date",
"ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
"LabelComponentsUpdated": "The following components have been installed or updated:", "LabelComponentsUpdated": "The following components have been installed or updated:",
"MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.", "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.",
"LabelDownMixAudioScale": "Audio boost when downmixing:", "LabelDownMixAudioScale": "Audio boost when downmixing:",

View File

@ -306,6 +306,7 @@
<Compile Include="Sorting\VideoBitRateComparer.cs" /> <Compile Include="Sorting\VideoBitRateComparer.cs" />
<Compile Include="Sync\AppSyncProvider.cs" /> <Compile Include="Sync\AppSyncProvider.cs" />
<Compile Include="Sync\CloudSyncProvider.cs" /> <Compile Include="Sync\CloudSyncProvider.cs" />
<Compile Include="Sync\MediaSync.cs" />
<Compile Include="Sync\SyncRegistrationInfo.cs" /> <Compile Include="Sync\SyncRegistrationInfo.cs" />
<Compile Include="Sync\SyncConfig.cs" /> <Compile Include="Sync\SyncConfig.cs" />
<Compile Include="Sync\SyncJobProcessor.cs" /> <Compile Include="Sync\SyncJobProcessor.cs" />

View File

@ -2,12 +2,15 @@
using MediaBrowser.Controller.Sync; using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Sync; using MediaBrowser.Model.Sync;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Sync namespace MediaBrowser.Server.Implementations.Sync
{ {
public class CloudSyncProvider : ISyncProvider public class CloudSyncProvider : IServerSyncProvider
{ {
private ICloudSyncProvider[] _providers = {}; private ICloudSyncProvider[] _providers = {};
@ -35,5 +38,25 @@ namespace MediaBrowser.Server.Implementations.Sync
{ {
get { return "Cloud Sync"; } get { return "Cloud Sync"; }
} }
public Task<List<string>> GetServerItemIds(string serverId, SyncTarget target, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task DeleteItem(string serverId, string itemId, SyncTarget target, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task TransferItemFile(string serverId, string itemId, string path, SyncTarget target, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task TransferRelatedFile(string serverId, string itemId, string path, ItemFileType type, SyncTarget target, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
} }
} }

View File

@ -0,0 +1,174 @@
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Sync;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Sync
{
public class MediaSync
{
private readonly ISyncManager _syncManager;
private readonly IServerApplicationHost _appHost;
private readonly ILogger _logger;
public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost)
{
_logger = logger;
_syncManager = syncManager;
_appHost = appHost;
}
public async Task Sync(IServerSyncProvider provider,
SyncTarget target,
IProgress<double> progress,
CancellationToken cancellationToken)
{
var serverId = _appHost.SystemId;
await SyncData(provider, serverId, target, cancellationToken).ConfigureAwait(false);
progress.Report(2);
// Do the data sync twice so the server knows what was removed from the device
await SyncData(provider, serverId, target, cancellationToken).ConfigureAwait(false);
progress.Report(3);
var innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(pct =>
{
var totalProgress = pct * .97;
totalProgress += 1;
progress.Report(totalProgress);
});
await GetNewMedia(provider, target, serverId, innerProgress, cancellationToken);
progress.Report(100);
}
private async Task SyncData(IServerSyncProvider provider,
string serverId,
SyncTarget target,
CancellationToken cancellationToken)
{
var localIds = await provider.GetServerItemIds(serverId, target, cancellationToken).ConfigureAwait(false);
var result = await _syncManager.SyncData(new SyncDataRequest
{
TargetId = target.Id,
LocalItemIds = localIds
}).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
foreach (var itemIdToRemove in result.ItemIdsToRemove)
{
try
{
await RemoveItem(provider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error deleting item from sync target. Id: {0}", ex, itemIdToRemove);
}
}
}
private async Task GetNewMedia(IServerSyncProvider provider,
SyncTarget target,
string serverId,
IProgress<double> progress,
CancellationToken cancellationToken)
{
var jobItems = _syncManager.GetReadySyncItems(target.Id);
var numComplete = 0;
double startingPercent = 0;
double percentPerItem = 1;
if (jobItems.Count > 0)
{
percentPerItem /= jobItems.Count;
}
foreach (var jobItem in jobItems)
{
cancellationToken.ThrowIfCancellationRequested();
var currentPercent = startingPercent;
var innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(pct =>
{
var totalProgress = pct * percentPerItem;
totalProgress += currentPercent;
progress.Report(totalProgress);
});
await GetItem(provider, target, serverId, jobItem, innerProgress, cancellationToken).ConfigureAwait(false);
numComplete++;
startingPercent = numComplete;
startingPercent /= jobItems.Count;
startingPercent *= 100;
progress.Report(startingPercent);
}
}
private async Task GetItem(IServerSyncProvider provider,
SyncTarget target,
string serverId,
SyncedItem jobItem,
IProgress<double> progress,
CancellationToken cancellationToken)
{
var libraryItem = jobItem.Item;
var internalSyncJobItem = _syncManager.GetJobItem(jobItem.SyncJobItemId);
var fileTransferProgress = new ActionableProgress<double>();
fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92));
await _syncManager.ReportSyncJobItemTransferBeginning(internalSyncJobItem.Id);
var transferSuccess = false;
Exception transferException = null;
try
{
await provider.TransferItemFile(serverId, libraryItem.Id, internalSyncJobItem.OutputPath, target, cancellationToken)
.ConfigureAwait(false);
progress.Report(92);
transferSuccess = true;
progress.Report(99);
}
catch (Exception ex)
{
_logger.ErrorException("Error transferring sync job file", ex);
transferException = ex;
}
if (transferSuccess)
{
await _syncManager.ReportSyncJobItemTransferred(jobItem.SyncJobItemId).ConfigureAwait(false);
}
else
{
await _syncManager.ReportSyncJobItemTransferFailed(jobItem.SyncJobItemId).ConfigureAwait(false);
throw transferException;
}
}
private Task RemoveItem(IServerSyncProvider provider,
string serverId,
string itemId,
SyncTarget target,
CancellationToken cancellationToken)
{
return provider.DeleteItem(serverId, itemId, target, cancellationToken);
}
}
}

View File

@ -870,6 +870,32 @@ namespace MediaBrowser.Server.Implementations.Sync
await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false);
} }
public async Task ReportSyncJobItemTransferBeginning(string id)
{
var jobItem = _repo.GetJobItem(id);
jobItem.Status = SyncJobItemStatus.Transferring;
await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
var processor = GetSyncJobProcessor();
await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false);
}
public async Task ReportSyncJobItemTransferFailed(string id)
{
var jobItem = _repo.GetJobItem(id);
jobItem.Status = SyncJobItemStatus.ReadyToTransfer;
await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
var processor = GetSyncJobProcessor();
await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false);
}
public QueryResult<string> GetLibraryItemIds(SyncJobItemQuery query) public QueryResult<string> GetLibraryItemIds(SyncJobItemQuery query)
{ {
return _repo.GetLibraryItemIds(query); return _repo.GetLibraryItemIds(query);

View File

@ -536,8 +536,6 @@ namespace MediaBrowser.Server.Startup.Common
SetStaticProperties(); SetStaticProperties();
SetKernelProperties();
await ((UserManager)UserManager).Initialize().ConfigureAwait(false); await ((UserManager)UserManager).Initialize().ConfigureAwait(false);
} }
@ -573,14 +571,6 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance(MediaEncoder); RegisterSingleInstance(MediaEncoder);
} }
/// <summary>
/// Sets the kernel properties.
/// </summary>
private void SetKernelProperties()
{
LocalizedStrings.StringFiles = GetExports<LocalizedStringData>();
}
/// <summary> /// <summary>
/// Gets the user repository. /// Gets the user repository.
/// </summary> /// </summary>
@ -698,7 +688,6 @@ namespace MediaBrowser.Server.Startup.Common
BaseItem.ItemRepository = ItemRepository; BaseItem.ItemRepository = ItemRepository;
User.XmlSerializer = XmlSerializer; User.XmlSerializer = XmlSerializer;
User.UserManager = UserManager; User.UserManager = UserManager;
LocalizedStrings.ApplicationPaths = ApplicationPaths;
Folder.UserManager = UserManager; Folder.UserManager = UserManager;
BaseItem.FileSystem = FileSystemManager; BaseItem.FileSystem = FileSystemManager;
BaseItem.UserDataManager = UserDataManager; BaseItem.UserDataManager = UserDataManager;