create sync job items pages

pull/702/head
Luke Pulverenti 10 years ago
parent 5e6354854d
commit 8f26921d00

@ -28,6 +28,11 @@ namespace MediaBrowser.Api.Sync
public string Id { get; set; } public string Id { get; set; }
} }
[Route("/Sync/Jobs/{Id}", "POST", Summary = "Updates a sync job.")]
public class UpdateSyncJob : SyncJob, IReturnVoid
{
}
[Route("/Sync/JobItems", "GET", Summary = "Gets sync job items.")] [Route("/Sync/JobItems", "GET", Summary = "Gets sync job items.")]
public class GetSyncJobItems : SyncJobItemQuery, IReturn<QueryResult<SyncJobItem>> public class GetSyncJobItems : SyncJobItemQuery, IReturn<QueryResult<SyncJobItem>>
{ {
@ -118,9 +123,9 @@ namespace MediaBrowser.Api.Sync
return ToOptimizedResult(result); return ToOptimizedResult(result);
} }
public object Get(GetSyncJobs request) public async Task<object> Get(GetSyncJobs request)
{ {
var result = _syncManager.GetJobs(request); var result = await _syncManager.GetJobs(request).ConfigureAwait(false);
return ToOptimizedResult(result); return ToOptimizedResult(result);
} }
@ -193,7 +198,7 @@ namespace MediaBrowser.Api.Sync
} }
}; };
var dtos = request.ItemIds.Split(',') var dtos = request.ItemIds.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(_libraryManager.GetItemById) .Select(_libraryManager.GetItemById)
.Where(i => i != null) .Where(i => i != null)
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions)) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions))
@ -231,5 +236,12 @@ namespace MediaBrowser.Api.Sync
return ToOptimizedResult(response); return ToOptimizedResult(response);
} }
public void Post(UpdateSyncJob request)
{
var task = _syncManager.UpdateJob(request);
Task.WaitAll(task);
}
} }
} }

@ -2,9 +2,9 @@
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Sync; using MediaBrowser.Model.Sync;
using MediaBrowser.Model.Users;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Sync namespace MediaBrowser.Controller.Sync
{ {
@ -21,7 +21,7 @@ namespace MediaBrowser.Controller.Sync
/// Gets the jobs. /// Gets the jobs.
/// </summary> /// </summary>
/// <returns>QueryResult&lt;SyncJob&gt;.</returns> /// <returns>QueryResult&lt;SyncJob&gt;.</returns>
QueryResult<SyncJob> GetJobs(SyncJobQuery query); Task<QueryResult<SyncJob>> GetJobs(SyncJobQuery query);
/// <summary> /// <summary>
/// Gets the job items. /// Gets the job items.
@ -37,6 +37,13 @@ namespace MediaBrowser.Controller.Sync
/// <returns>SyncJob.</returns> /// <returns>SyncJob.</returns>
SyncJob GetJob(string id); SyncJob GetJob(string id);
/// <summary>
/// Updates the job.
/// </summary>
/// <param name="job">The job.</param>
/// <returns>Task.</returns>
Task UpdateJob(SyncJob job);
/// <summary> /// <summary>
/// Cancels the job. /// Cancels the job.
/// </summary> /// </summary>

@ -18,6 +18,13 @@ namespace MediaBrowser.Controller.Sync
/// <returns>IEnumerable&lt;SyncTarget&gt;.</returns> /// <returns>IEnumerable&lt;SyncTarget&gt;.</returns>
IEnumerable<SyncTarget> GetSyncTargets(); IEnumerable<SyncTarget> GetSyncTargets();
/// <summary>
/// Gets the synchronize targets.
/// </summary>
/// <param name="userId">The user identifier.</param>
/// <returns>IEnumerable&lt;SyncTarget&gt;.</returns>
IEnumerable<SyncTarget> GetSyncTargets(string userId);
/// <summary> /// <summary>
/// Gets the device profile. /// Gets the device profile.
/// </summary> /// </summary>

@ -18,5 +18,10 @@ namespace MediaBrowser.Model.Devices
/// </summary> /// </summary>
/// <value><c>null</c> if [supports synchronize] contains no value, <c>true</c> if [supports synchronize]; otherwise, <c>false</c>.</value> /// <value><c>null</c> if [supports synchronize] contains no value, <c>true</c> if [supports synchronize]; otherwise, <c>false</c>.</value>
public bool? SupportsSync { get; set; } public bool? SupportsSync { get; set; }
/// <summary>
/// Gets or sets the user identifier.
/// </summary>
/// <value>The user identifier.</value>
public string UserId { get; set; }
} }
} }

@ -89,7 +89,6 @@ namespace MediaBrowser.Model.Sync
public string ParentName { get; set; } public string ParentName { get; set; }
public string PrimaryImageItemId { get; set; } public string PrimaryImageItemId { get; set; }
public string PrimaryImageTag { get; set; } public string PrimaryImageTag { get; set; }
public double? PrimaryImageAspectRatio { get; set; }
public SyncJob() public SyncJob()
{ {

@ -22,6 +22,12 @@ namespace MediaBrowser.Model.Sync
/// <value>The item identifier.</value> /// <value>The item identifier.</value>
public string ItemId { get; set; } public string ItemId { get; set; }
/// <summary>
/// Gets or sets the name of the item.
/// </summary>
/// <value>The name of the item.</value>
public string ItemName { get; set; }
/// <summary> /// <summary>
/// Gets or sets the media source identifier. /// Gets or sets the media source identifier.
/// </summary> /// </summary>
@ -57,5 +63,15 @@ namespace MediaBrowser.Model.Sync
/// </summary> /// </summary>
/// <value>The date created.</value> /// <value>The date created.</value>
public DateTime DateCreated { get; set; } public DateTime DateCreated { get; set; }
/// <summary>
/// Gets or sets the primary image item identifier.
/// </summary>
/// <value>The primary image item identifier.</value>
public string PrimaryImageItemId { get; set; }
/// <summary>
/// Gets or sets the primary image tag.
/// </summary>
/// <value>The primary image tag.</value>
public string PrimaryImageTag { get; set; }
} }
} }

@ -29,6 +29,11 @@ namespace MediaBrowser.Model.Sync
/// </summary> /// </summary>
/// <value>The status.</value> /// <value>The status.</value>
public List<SyncJobItemStatus> Statuses { get; set; } public List<SyncJobItemStatus> Statuses { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [add metadata].
/// </summary>
/// <value><c>true</c> if [add metadata]; otherwise, <c>false</c>.</value>
public bool AddMetadata { get; set; }
public SyncJobItemQuery() public SyncJobItemQuery()
{ {

@ -7,7 +7,8 @@ namespace MediaBrowser.Model.Sync
Converting = 1, Converting = 1,
Transferring = 2, Transferring = 2,
Synced = 3, Synced = 3,
Failed = 4, RemovedFromDevice = 4,
RemovedFromDevice = 5 Failed = 5,
Cancelled = 6
} }
} }

@ -23,5 +23,10 @@ namespace MediaBrowser.Model.Sync
/// </summary> /// </summary>
/// <value>The target identifier.</value> /// <value>The target identifier.</value>
public string TargetId { get; set; } public string TargetId { get; set; }
/// <summary>
/// Gets or sets the user identifier.
/// </summary>
/// <value>The user identifier.</value>
public string UserId { get; set; }
} }
} }

@ -6,16 +6,16 @@ namespace MediaBrowser.Model.Sync
/// <summary> /// <summary>
/// The good /// The good
/// </summary> /// </summary>
Good = 0, Low = 0,
/// <summary> /// <summary>
/// The better /// The better
/// </summary> /// </summary>
Better = 1, Medium = 1,
/// <summary> /// <summary>
/// The best /// The best
/// </summary> /// </summary>
Best = 2 High = 2
} }
} }

@ -105,7 +105,12 @@ namespace MediaBrowser.Server.Implementations.Devices
var val = query.SupportsUniqueIdentifier.Value; var val = query.SupportsUniqueIdentifier.Value;
devices = devices.Where(i => GetCapabilities(i.Id).SupportsUniqueIdentifier == val); devices = devices.Where(i => GetCapabilities(i.Id).SupportsUniqueIdentifier == val);
} }
if (!string.IsNullOrWhiteSpace(query.UserId))
{
devices = devices.Where(i => CanAccessDevice(query.UserId, i.Id));
}
var array = devices.ToArray(); var array = devices.ToArray();
return new QueryResult<DeviceInfo> return new QueryResult<DeviceInfo>

@ -40,11 +40,11 @@
"LabelStopping": "Stoppe", "LabelStopping": "Stoppe",
"LabelCancelled": "(abgebrochen)", "LabelCancelled": "(abgebrochen)",
"LabelFailed": "(fehlgeschlagen)", "LabelFailed": "(fehlgeschlagen)",
"ButtonHelp": "Help", "ButtonHelp": "Hilfe",
"HeaderLibraryAccess": "Bibliothekszugriff", "HeaderLibraryAccess": "Bibliothekszugriff",
"HeaderChannelAccess": "Channelzugriff", "HeaderChannelAccess": "Channelzugriff",
"HeaderDeviceAccess": "Device Access", "HeaderDeviceAccess": "Ger\u00e4te Zugang",
"HeaderSelectDevices": "Select Devices", "HeaderSelectDevices": "Ger\u00e4t w\u00e4hlen",
"LabelAbortedByServerShutdown": "(Durch herunterfahrenden Server abgebrochen)", "LabelAbortedByServerShutdown": "(Durch herunterfahrenden Server abgebrochen)",
"LabelScheduledTaskLastRan": "Zuletzt ausgef\u00fchrt vor: {0}. Ben\u00f6tigte Zeit: {1}.", "LabelScheduledTaskLastRan": "Zuletzt ausgef\u00fchrt vor: {0}. Ben\u00f6tigte Zeit: {1}.",
"HeaderDeleteTaskTrigger": "Entferne Aufgabenausl\u00f6ser", "HeaderDeleteTaskTrigger": "Entferne Aufgabenausl\u00f6ser",
@ -254,7 +254,7 @@
"ButtonMoveRight": "Nach rechts", "ButtonMoveRight": "Nach rechts",
"ButtonBrowseOnlineImages": "Durchsuche Onlinebilder", "ButtonBrowseOnlineImages": "Durchsuche Onlinebilder",
"HeaderDeleteItem": "L\u00f6sche Element", "HeaderDeleteItem": "L\u00f6sche Element",
"ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?", "ConfirmDeleteItem": "L\u00f6schen dieses Eintrages bedeutet das L\u00f6schen der Datei und das Entfernen aus der Medien-Bibliothek. M\u00f6chten Sie wirklich fortfahren?",
"MessagePleaseEnterNameOrId": "Bitte gib einen Namen oder eine externe Id an.", "MessagePleaseEnterNameOrId": "Bitte gib einen Namen oder eine externe Id an.",
"MessageValueNotCorrect": "Der eingegeben Wert ist nicht korrekt. Bitte versuche es noch einmal.", "MessageValueNotCorrect": "Der eingegeben Wert ist nicht korrekt. Bitte versuche es noch einmal.",
"MessageItemSaved": "Element gespeichert", "MessageItemSaved": "Element gespeichert",
@ -417,7 +417,7 @@
"HeaderMediaLocations": "Medienquellen", "HeaderMediaLocations": "Medienquellen",
"LabelFolderTypeValue": "Verzeichnistyp: {0}", "LabelFolderTypeValue": "Verzeichnistyp: {0}",
"LabelPathSubstitutionHelp": "Optional: Die Pfadersetzung kann Serverpfade zu Netzwerkfreigaben umleiten, die von Endger\u00e4ten f\u00fcr die direkte Wiedergabe genutzt werden k\u00f6nnen.", "LabelPathSubstitutionHelp": "Optional: Die Pfadersetzung kann Serverpfade zu Netzwerkfreigaben umleiten, die von Endger\u00e4ten f\u00fcr die direkte Wiedergabe genutzt werden k\u00f6nnen.",
"FolderTypeUnset": "Unset (mixed content)", "FolderTypeUnset": "Keine Auswahl (gemischter Inhalt)",
"FolderTypeMovies": "Filme", "FolderTypeMovies": "Filme",
"FolderTypeMusic": "Musik", "FolderTypeMusic": "Musik",
"FolderTypeAdultVideos": "Videos f\u00fcr Erwachsene", "FolderTypeAdultVideos": "Videos f\u00fcr Erwachsene",
@ -593,7 +593,7 @@
"WebClientTourMobile2": "und steuert einfach andere Ger\u00e4te und Media Browser Anwendungen", "WebClientTourMobile2": "und steuert einfach andere Ger\u00e4te und Media Browser Anwendungen",
"MessageEnjoyYourStay": "Genie\u00dfe deinen Aufenthalt", "MessageEnjoyYourStay": "Genie\u00dfe deinen Aufenthalt",
"DashboardTourDashboard": "Die Server\u00fcbersicht erlaubt es dir deinen Server und dessen Benutzer im Blick zu behalten. Somit wei\u00dft du immer wer gerade was macht und wo er sich befindet.", "DashboardTourDashboard": "Die Server\u00fcbersicht erlaubt es dir deinen Server und dessen Benutzer im Blick zu behalten. Somit wei\u00dft du immer wer gerade was macht und wo er sich befindet.",
"DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.", "DashboardTourHelp": "Die In-App-Hilfe Schaltfl\u00e4che bietet eine schnelle M\u00f6glichkeit um eine Wiki-Seite zum aktuellen Inhalt zu \u00f6ffnen.",
"DashboardTourUsers": "Erstelle einfach Benutzeraccounts f\u00fcr Freunde und Familie. Jeder mit seinen individuellen Einstellungen bei Berechtigungen, Blibliothekenzugriff, Kindersicherung und mehr.", "DashboardTourUsers": "Erstelle einfach Benutzeraccounts f\u00fcr Freunde und Familie. Jeder mit seinen individuellen Einstellungen bei Berechtigungen, Blibliothekenzugriff, Kindersicherung und mehr.",
"DashboardTourCinemaMode": "Der Kino-Modus bringt das Kinoerlebnis direkt in dein Wohnzimmer, mit der F\u00e4higkeit Trailer und benutzerdefinierte Intros vor dem Hauptfilm zu spielen.", "DashboardTourCinemaMode": "Der Kino-Modus bringt das Kinoerlebnis direkt in dein Wohnzimmer, mit der F\u00e4higkeit Trailer und benutzerdefinierte Intros vor dem Hauptfilm zu spielen.",
"DashboardTourChapters": "Aktiviere die Bildgenerierung f\u00fcr die Kapitel deiner Videos f\u00fcr eine bessere Darstellung w\u00e4hrend des Ansehens.", "DashboardTourChapters": "Aktiviere die Bildgenerierung f\u00fcr die Kapitel deiner Videos f\u00fcr eine bessere Darstellung w\u00e4hrend des Ansehens.",
@ -656,5 +656,5 @@
"LabelItemLimitHelp": "Optional. Legen Sie die maximale Anzahl der zu synchronisierenden Eintr\u00e4ge fest.", "LabelItemLimitHelp": "Optional. Legen Sie die maximale Anzahl der zu synchronisierenden Eintr\u00e4ge fest.",
"MessageBookPluginRequired": "Setzt die Installation des Bookshelf-Plugins voraus.", "MessageBookPluginRequired": "Setzt die Installation des Bookshelf-Plugins voraus.",
"MessageGamePluginRequired": "Setzt die Installation des GameBrowser-Plugins voraus.", "MessageGamePluginRequired": "Setzt die Installation des GameBrowser-Plugins voraus.",
"MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders." "MessageUnsetContentHelp": "Inhalte werden als Verzeichnisse dargestellt. F\u00fcr eine besser Anzeige nutzen Sie nach M\u00f6glichkeit den Meta-Data Manager und w\u00e4hlen Sie einen Medien-Typen f\u00fcr Unterverzeichnisse."
} }

@ -40,11 +40,11 @@
"LabelStopping": "Sto fermando", "LabelStopping": "Sto fermando",
"LabelCancelled": "(cancellato)", "LabelCancelled": "(cancellato)",
"LabelFailed": "(fallito)", "LabelFailed": "(fallito)",
"ButtonHelp": "Help", "ButtonHelp": "Aiuto",
"HeaderLibraryAccess": "Accesso libreria", "HeaderLibraryAccess": "Accesso libreria",
"HeaderChannelAccess": "Accesso canali", "HeaderChannelAccess": "Accesso canali",
"HeaderDeviceAccess": "Device Access", "HeaderDeviceAccess": "Accesso dispositivo",
"HeaderSelectDevices": "Select Devices", "HeaderSelectDevices": "Seleziona periferiche",
"LabelAbortedByServerShutdown": "(Interrotto dalla chiusura del server)", "LabelAbortedByServerShutdown": "(Interrotto dalla chiusura del server)",
"LabelScheduledTaskLastRan": "Ultima esecuzione {0}, taking {1}.", "LabelScheduledTaskLastRan": "Ultima esecuzione {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Elimina Operazione pianificata", "HeaderDeleteTaskTrigger": "Elimina Operazione pianificata",
@ -254,7 +254,7 @@
"ButtonMoveRight": "Muovi a destra", "ButtonMoveRight": "Muovi a destra",
"ButtonBrowseOnlineImages": "Sfoglia le immagini Online", "ButtonBrowseOnlineImages": "Sfoglia le immagini Online",
"HeaderDeleteItem": "Elimina elemento", "HeaderDeleteItem": "Elimina elemento",
"ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?", "ConfirmDeleteItem": "L'eliminazione di questo articolo sar\u00e0 eliminarlo sia dal file system e la vostra libreria multimediale. Sei sicuro di voler continuare?",
"MessagePleaseEnterNameOrId": "Inserisci il nome o id esterno.", "MessagePleaseEnterNameOrId": "Inserisci il nome o id esterno.",
"MessageValueNotCorrect": "Il valore inserito non \u00e8 corretto.Riprova di nuovo.", "MessageValueNotCorrect": "Il valore inserito non \u00e8 corretto.Riprova di nuovo.",
"MessageItemSaved": "Elemento salvato.", "MessageItemSaved": "Elemento salvato.",
@ -401,7 +401,7 @@
"LabelYear": "Anno:", "LabelYear": "Anno:",
"LabelDateOfBirth": "Data nascita:", "LabelDateOfBirth": "Data nascita:",
"LabelBirthYear": "Anno nascita:", "LabelBirthYear": "Anno nascita:",
"LabelBirthDate": "Birth date:", "LabelBirthDate": "Data nascita:",
"LabelDeathDate": "Anno morte:", "LabelDeathDate": "Anno morte:",
"HeaderRemoveMediaLocation": "Rimuovi percorso media", "HeaderRemoveMediaLocation": "Rimuovi percorso media",
"MessageConfirmRemoveMediaLocation": "Sei sicuro di voler rimuovere questa posizione?", "MessageConfirmRemoveMediaLocation": "Sei sicuro di voler rimuovere questa posizione?",
@ -417,7 +417,7 @@
"HeaderMediaLocations": "Posizioni Media", "HeaderMediaLocations": "Posizioni Media",
"LabelFolderTypeValue": "Tipo cartella: {0}", "LabelFolderTypeValue": "Tipo cartella: {0}",
"LabelPathSubstitutionHelp": "Opzionale: cambio Path pu\u00f2 mappare i percorsi del server a condivisioni di rete che i clienti possono accedere per la riproduzione diretta.", "LabelPathSubstitutionHelp": "Opzionale: cambio Path pu\u00f2 mappare i percorsi del server a condivisioni di rete che i clienti possono accedere per la riproduzione diretta.",
"FolderTypeUnset": "Unset (mixed content)", "FolderTypeUnset": "Disinserito (contenuto misto)",
"FolderTypeMovies": "Film", "FolderTypeMovies": "Film",
"FolderTypeMusic": "Musica", "FolderTypeMusic": "Musica",
"FolderTypeAdultVideos": "Video per adulti", "FolderTypeAdultVideos": "Video per adulti",
@ -426,7 +426,7 @@
"FolderTypeHomeVideos": "Video personali", "FolderTypeHomeVideos": "Video personali",
"FolderTypeGames": "Giochi", "FolderTypeGames": "Giochi",
"FolderTypeBooks": "Libri", "FolderTypeBooks": "Libri",
"FolderTypeTvShows": "TV", "FolderTypeTvShows": "Tv",
"TabMovies": "Film", "TabMovies": "Film",
"TabSeries": "Serie TV", "TabSeries": "Serie TV",
"TabEpisodes": "Episodi", "TabEpisodes": "Episodi",
@ -593,7 +593,7 @@
"WebClientTourMobile2": "e controlla facilmente altri dispositivi e applicazioni Media Browser", "WebClientTourMobile2": "e controlla facilmente altri dispositivi e applicazioni Media Browser",
"MessageEnjoyYourStay": "Godetevi il vostro soggiorno", "MessageEnjoyYourStay": "Godetevi il vostro soggiorno",
"DashboardTourDashboard": "Il pannello di controllo del server consente di monitorare il vostro server e gli utenti. Potrai sempre sapere chi sta facendo cosa e dove sono.", "DashboardTourDashboard": "Il pannello di controllo del server consente di monitorare il vostro server e gli utenti. Potrai sempre sapere chi sta facendo cosa e dove sono.",
"DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.", "DashboardTourHelp": "In-app help offre pulsanti facili da aprire le pagine wiki relative al contenuto sullo schermo.",
"DashboardTourUsers": "Facile creazione di account utente per i vostri amici e la famiglia, ognuno con le proprie autorizzazioni, accesso alla libreria, controlli parentali e altro ancora.", "DashboardTourUsers": "Facile creazione di account utente per i vostri amici e la famiglia, ognuno con le proprie autorizzazioni, accesso alla libreria, controlli parentali e altro ancora.",
"DashboardTourCinemaMode": "Modalit\u00e0 Cinema porta l'esperienza del teatro direttamente nel tuo salotto con la possibilit\u00e0 di giocare trailer e intro personalizzati prima la caratteristica principale.", "DashboardTourCinemaMode": "Modalit\u00e0 Cinema porta l'esperienza del teatro direttamente nel tuo salotto con la possibilit\u00e0 di giocare trailer e intro personalizzati prima la caratteristica principale.",
"DashboardTourChapters": "Abilita capitolo generazione di immagini per i vostri video per una presentazione pi\u00f9 gradevole durante la visualizzazione.", "DashboardTourChapters": "Abilita capitolo generazione di immagini per i vostri video per una presentazione pi\u00f9 gradevole durante la visualizzazione.",
@ -617,7 +617,7 @@
"MessageInvitationSentToUser": "Una e-mail \u00e8 stata inviata a {0}, invitandoli ad accettare l'invito di condivisione.", "MessageInvitationSentToUser": "Una e-mail \u00e8 stata inviata a {0}, invitandoli ad accettare l'invito di condivisione.",
"MessageInvitationSentToNewUser": "Una e-mail \u00e8 stata inviata a {0} invitandoli a firmare con Media Browser.", "MessageInvitationSentToNewUser": "Una e-mail \u00e8 stata inviata a {0} invitandoli a firmare con Media Browser.",
"HeaderConnectionFailure": "Errore di connessione", "HeaderConnectionFailure": "Errore di connessione",
"MessageUnableToConnectToServer": "We're unable to connect to the selected server right now. Please try again later.", "MessageUnableToConnectToServer": "Non siamo in grado di connettersi al server selezionato al momento. Si prega di riprovare pi\u00f9 tardi.",
"ButtonSelectServer": "Selezionare il server", "ButtonSelectServer": "Selezionare il server",
"MessagePluginConfigurationRequiresLocalAccess": "Per configurare questo plugin si prega di accedere al proprio server locale direttamente.", "MessagePluginConfigurationRequiresLocalAccess": "Per configurare questo plugin si prega di accedere al proprio server locale direttamente.",
"MessageLoggedOutParentalControl": "L'accesso \u00e8 attualmente limitato. Si prega di riprovare pi\u00f9 tardi.", "MessageLoggedOutParentalControl": "L'accesso \u00e8 attualmente limitato. Si prega di riprovare pi\u00f9 tardi.",
@ -635,26 +635,26 @@
"ButtonLinkMyMediaBrowserAccount": "Collega il mio account", "ButtonLinkMyMediaBrowserAccount": "Collega il mio account",
"MessageConnectAccountRequiredToInviteGuest": "Per invitare gli ospiti \u00e8 necessario collegare prima il tuo account browser media a questo server.", "MessageConnectAccountRequiredToInviteGuest": "Per invitare gli ospiti \u00e8 necessario collegare prima il tuo account browser media a questo server.",
"ButtonSync": "Sinc.", "ButtonSync": "Sinc.",
"SyncMedia": "Sync Media", "SyncMedia": "Sync media",
"HeaderCancelSyncJob": "Cancel Sync", "HeaderCancelSyncJob": "Cancel Sync",
"CancelSyncJobConfirmation": "Are you sure you wish to cancel this sync job?", "CancelSyncJobConfirmation": "Sei sicuro di voler annullare questo lavoro di sincronizzazione?",
"TabSync": "Sinc", "TabSync": "Sinc",
"MessagePleaseSelectDeviceToSyncTo": "Please select a device to sync to.", "MessagePleaseSelectDeviceToSyncTo": "Selezionare un dispositivo per la sincronizzazione",
"MessageSyncJobCreated": "Sync job created.", "MessageSyncJobCreated": "Sync job created.",
"LabelSyncTo": "Sync to:", "LabelSyncTo": "Sync to:",
"LabelSyncJobName": "Sync job name:", "LabelSyncJobName": "Sync job name:",
"LabelQuality": "Quality:", "LabelQuality": "Qualit\u00e0:",
"OptionHigh": "High", "OptionHigh": "Alto",
"OptionMedium": "Medium", "OptionMedium": "Medio",
"OptionLow": "Low", "OptionLow": "Basso",
"HeaderSettings": "Settings", "HeaderSettings": "Configurazione",
"OptionAutomaticallySyncNewContent": "Automatically sync new content", "OptionAutomaticallySyncNewContent": "Sincronizza automaticamente nuovi contenuti",
"OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.", "OptionAutomaticallySyncNewContentHelp": "Nuovi contenuti aggiunti a questa categoria viene sincronizzata automaticamente al dispositivo.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only", "OptionSyncUnwatchedVideosOnly": "Sincronizza solo i video non visti",
"OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.", "OptionSyncUnwatchedVideosOnlyHelp": "Solo i video non visti saranno sincronizzati, e video saranno rimossi dal dispositivo in cui sono guardato.",
"LabelItemLimit": "Item limit:", "LabelItemLimit": "limite elementi:",
"LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.", "LabelItemLimitHelp": "Opzionale. Impostare un limite al numero di elementi che verranno sincronizzati.",
"MessageBookPluginRequired": "Requires installation of the Bookshelf plugin", "MessageBookPluginRequired": "Richiede l'installazione del plugin Bookshelf",
"MessageGamePluginRequired": "Requires installation of the GameBrowser plugin", "MessageGamePluginRequired": "Richiede l'installazione del plugin GameBrowser",
"MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders." "MessageUnsetContentHelp": "Il contenuto verr\u00e0 visualizzato come pianura cartelle. Per ottenere i migliori risultati utilizzare il gestore di metadati per impostare i tipi di contenuto di sottocartelle."
} }

@ -41,6 +41,8 @@
"LabelCancelled": "(cancelled)", "LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)", "LabelFailed": "(failed)",
"ButtonHelp": "Help", "ButtonHelp": "Help",
"ButtonSave": "Save",
"MessageNoSyncJobsFound": "No sync jobs found. Create sync jobs using the Sync buttons found throughout the web interface.",
"HeaderLibraryAccess": "Library Access", "HeaderLibraryAccess": "Library Access",
"HeaderChannelAccess": "Channel Access", "HeaderChannelAccess": "Channel Access",
"HeaderDeviceAccess": "Device Access", "HeaderDeviceAccess": "Device Access",
@ -664,5 +666,13 @@
"LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.", "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
"MessageBookPluginRequired": "Requires installation of the Bookshelf plugin", "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
"MessageGamePluginRequired": "Requires installation of the GameBrowser plugin", "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
"MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders." "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders.",
"SyncJobItemStatusQueued": "Queued",
"SyncJobItemStatusConverting": "Converting",
"SyncJobItemStatusTransferring": "Transferring",
"SyncJobItemStatusSynced": "Synced",
"SyncJobItemStatusFailed": "Failed",
"SyncJobItemStatusRemovedFromDevice": "Removed from device",
"SyncJobItemStatusCancelled": "Cancelled",
"MessageJobItemHasNoActions": "d"
} }

@ -43,8 +43,8 @@
"ButtonHelp": "Ajuda", "ButtonHelp": "Ajuda",
"HeaderLibraryAccess": "Acesso \u00e0 Biblioteca", "HeaderLibraryAccess": "Acesso \u00e0 Biblioteca",
"HeaderChannelAccess": "Acesso ao Canal", "HeaderChannelAccess": "Acesso ao Canal",
"HeaderDeviceAccess": "Device Access", "HeaderDeviceAccess": "Acesso ao Dispositivo",
"HeaderSelectDevices": "Select Devices", "HeaderSelectDevices": "Selecionar Dispositivos",
"LabelAbortedByServerShutdown": "(Abortada pelo desligamento do servidor)", "LabelAbortedByServerShutdown": "(Abortada pelo desligamento do servidor)",
"LabelScheduledTaskLastRan": "\u00daltima execu\u00e7\u00e3o {0}, demorando {1}.", "LabelScheduledTaskLastRan": "\u00daltima execu\u00e7\u00e3o {0}, demorando {1}.",
"HeaderDeleteTaskTrigger": "Excluir Disparador da Tarefa", "HeaderDeleteTaskTrigger": "Excluir Disparador da Tarefa",

@ -63,16 +63,16 @@
"TabPreferences": "Einstellungen", "TabPreferences": "Einstellungen",
"TabPassword": "Passwort", "TabPassword": "Passwort",
"TabLibraryAccess": "Bibliothekenzugriff", "TabLibraryAccess": "Bibliothekenzugriff",
"TabAccess": "Access", "TabAccess": "Zugang",
"TabImage": "Bild", "TabImage": "Bild",
"TabProfile": "Profil", "TabProfile": "Profil",
"TabMetadata": "Metadata", "TabMetadata": "Metadata",
"TabImages": "Bilder", "TabImages": "Bilder",
"TabNotifications": "Benachrichtigungen", "TabNotifications": "Benachrichtigungen",
"TabCollectionTitles": "Titel", "TabCollectionTitles": "Titel",
"HeaderDeviceAccess": "Device Access", "HeaderDeviceAccess": "Ger\u00e4te Zugang",
"OptionEnableAccessFromAllDevices": "Enable access from all devices", "OptionEnableAccessFromAllDevices": "Zugriff von allen Ger\u00e4ten erlauben",
"DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "DeviceAccessHelp": "Dies wird nur auf Ger\u00e4te angewandt die eindeutig identifiziert werden k\u00f6nnen und verhindert nicht den Web-Zugriff. Gefilterter Zugriff auf Ger\u00e4te verhindert die Nutzung neuer Ger\u00e4te solange, bis der Zugriff f\u00fcr diese freigegeben wird.",
"LabelDisplayMissingEpisodesWithinSeasons": "Zeige fehlende Episoden innerhalb von Staffeln", "LabelDisplayMissingEpisodesWithinSeasons": "Zeige fehlende Episoden innerhalb von Staffeln",
"LabelUnairedMissingEpisodesWithinSeasons": "Zeige noch nicht ausgestahlte Episoden innerhalb von Staffeln", "LabelUnairedMissingEpisodesWithinSeasons": "Zeige noch nicht ausgestahlte Episoden innerhalb von Staffeln",
"HeaderVideoPlaybackSettings": "Videowiedergabe Einstellungen", "HeaderVideoPlaybackSettings": "Videowiedergabe Einstellungen",
@ -380,8 +380,8 @@
"LabelMaxScreenshotsPerItem": "Maximale Anzahl von Screenshots pro Element:", "LabelMaxScreenshotsPerItem": "Maximale Anzahl von Screenshots pro Element:",
"LabelMinBackdropDownloadWidth": "Minimale Breite f\u00fcr zu herunterladende Hintergr\u00fcnde:", "LabelMinBackdropDownloadWidth": "Minimale Breite f\u00fcr zu herunterladende Hintergr\u00fcnde:",
"LabelMinScreenshotDownloadWidth": "Minimale Breite f\u00fcr zu herunterladende Screenshot:", "LabelMinScreenshotDownloadWidth": "Minimale Breite f\u00fcr zu herunterladende Screenshot:",
"ButtonAddScheduledTaskTrigger": "F\u00fcge Task Ausl\u00f6ser hinzu", "ButtonAddScheduledTaskTrigger": "Ausl\u00f6ser hinzuf\u00fcgen",
"HeaderAddScheduledTaskTrigger": "F\u00fcge Task Ausl\u00f6ser hinzu", "HeaderAddScheduledTaskTrigger": "Ausl\u00f6ser hinzuf\u00fcgen",
"ButtonAdd": "Hinzuf\u00fcgen", "ButtonAdd": "Hinzuf\u00fcgen",
"LabelTriggerType": "Ausl\u00f6ser Typ:", "LabelTriggerType": "Ausl\u00f6ser Typ:",
"OptionDaily": "T\u00e4glich", "OptionDaily": "T\u00e4glich",
@ -1261,7 +1261,7 @@
"HeaderTrailerReel": "Trailer Rolle", "HeaderTrailerReel": "Trailer Rolle",
"OptionPlayUnwatchedTrailersOnly": "Spiele nur bisher nicht gesehene Trailer", "OptionPlayUnwatchedTrailersOnly": "Spiele nur bisher nicht gesehene Trailer",
"HeaderTrailerReelHelp": "Starte eine Trailer Rolle, um dir eine lang andauernde Playlist mit Trailern anzuschauen.", "HeaderTrailerReelHelp": "Starte eine Trailer Rolle, um dir eine lang andauernde Playlist mit Trailern anzuschauen.",
"MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "MessageNoTrailersFound": "Keine Trailer gefunden. Installieren Sie den Trailer-Channel um Ihre Film-Bibliothek mit Trailer aus dem Internet zu erweitern.",
"HeaderNewUsers": "Neue Benutzer", "HeaderNewUsers": "Neue Benutzer",
"ButtonSignUp": "Anmeldung", "ButtonSignUp": "Anmeldung",
"ButtonForgotPassword": "Passwort vergessen?", "ButtonForgotPassword": "Passwort vergessen?",

@ -37,7 +37,7 @@
"ButtonOk": "OK", "ButtonOk": "OK",
"ButtonCancel": "Annulla", "ButtonCancel": "Annulla",
"ButtonNew": "Nuovo", "ButtonNew": "Nuovo",
"FolderTypeMixed": "Mixed content", "FolderTypeMixed": "contenuto misto",
"FolderTypeMovies": "Film", "FolderTypeMovies": "Film",
"FolderTypeMusic": "Musica", "FolderTypeMusic": "Musica",
"FolderTypeAdultVideos": "Video per adulti", "FolderTypeAdultVideos": "Video per adulti",
@ -46,9 +46,9 @@
"FolderTypeHomeVideos": "Video personali", "FolderTypeHomeVideos": "Video personali",
"FolderTypeGames": "Giochi", "FolderTypeGames": "Giochi",
"FolderTypeBooks": "Libri", "FolderTypeBooks": "Libri",
"FolderTypeTvShows": "TV", "FolderTypeTvShows": "Tv",
"FolderTypeInherit": "Inherit", "FolderTypeInherit": "ereditare",
"LabelContentType": "Content type:", "LabelContentType": "Tipo di contenuto:",
"HeaderSetupLibrary": "Configura la tua libreria", "HeaderSetupLibrary": "Configura la tua libreria",
"ButtonAddMediaFolder": "Aggiungi cartella", "ButtonAddMediaFolder": "Aggiungi cartella",
"LabelFolderType": "Tipo cartella", "LabelFolderType": "Tipo cartella",
@ -63,16 +63,16 @@
"TabPreferences": "Preferenze", "TabPreferences": "Preferenze",
"TabPassword": "Password", "TabPassword": "Password",
"TabLibraryAccess": "Accesso libreria", "TabLibraryAccess": "Accesso libreria",
"TabAccess": "Access", "TabAccess": "Accesso",
"TabImage": "Immagine", "TabImage": "Immagine",
"TabProfile": "Profilo", "TabProfile": "Profilo",
"TabMetadata": "Metadata", "TabMetadata": "Metadata",
"TabImages": "Immagini", "TabImages": "Immagini",
"TabNotifications": "Notifiche", "TabNotifications": "Notifiche",
"TabCollectionTitles": "Titolo", "TabCollectionTitles": "Titolo",
"HeaderDeviceAccess": "Device Access", "HeaderDeviceAccess": "Accesso dispositivo",
"OptionEnableAccessFromAllDevices": "Enable access from all devices", "OptionEnableAccessFromAllDevices": "Abilitare l'accesso da tutti i dispositivi",
"DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "DeviceAccessHelp": "Questo vale solo per i dispositivi che possono essere identificati in modo univoco e non impedire l'accesso del browser. Filtraggio di accesso al dispositivo dell'utente impedir\u00e0 loro di usare nuovi dispositivi fino a quando non sono state approvate qui.",
"LabelDisplayMissingEpisodesWithinSeasons": "Visualizza gli episodi mancanti nelle stagioni", "LabelDisplayMissingEpisodesWithinSeasons": "Visualizza gli episodi mancanti nelle stagioni",
"LabelUnairedMissingEpisodesWithinSeasons": "Visualizzare episodi mai andati in onda all'interno stagioni", "LabelUnairedMissingEpisodesWithinSeasons": "Visualizzare episodi mai andati in onda all'interno stagioni",
"HeaderVideoPlaybackSettings": "Impostazioni di riproduzione video", "HeaderVideoPlaybackSettings": "Impostazioni di riproduzione video",
@ -247,10 +247,10 @@
"HeaderFeatureAccess": "Caratteristiche di accesso", "HeaderFeatureAccess": "Caratteristiche di accesso",
"OptionAllowMediaPlayback": "Consenti la riproduzione", "OptionAllowMediaPlayback": "Consenti la riproduzione",
"OptionAllowBrowsingLiveTv": "Consenti la navigazione sulla Tv indiretta", "OptionAllowBrowsingLiveTv": "Consenti la navigazione sulla Tv indiretta",
"OptionAllowDeleteLibraryContent": "Allow deletion of library content", "OptionAllowDeleteLibraryContent": "Consenti cancellazione di contenuti biblioteca",
"OptionAllowManageLiveTv": "Consenti la modifica delle operazioni pianificate della TV", "OptionAllowManageLiveTv": "Consenti la modifica delle operazioni pianificate della TV",
"OptionAllowRemoteControlOthers": "Allow remote control of other users", "OptionAllowRemoteControlOthers": "Consenti controllo remoto di altri utenti",
"OptionAllowRemoteSharedDevices": "Allow remote control of shared devices", "OptionAllowRemoteSharedDevices": "Consenti controllo remoto di dispositivi condivisi",
"OptionAllowRemoteSharedDevicesHelp": "Dispositivi DLNA sono considerati condivisa fino a quando un utente inizia controllarlo.", "OptionAllowRemoteSharedDevicesHelp": "Dispositivi DLNA sono considerati condivisa fino a quando un utente inizia controllarlo.",
"HeaderRemoteControl": "telecomando", "HeaderRemoteControl": "telecomando",
"OptionMissingTmdbId": "Tmdb Id mancante", "OptionMissingTmdbId": "Tmdb Id mancante",
@ -380,8 +380,8 @@
"LabelMaxScreenshotsPerItem": "Massimo numero di foto per oggetto:", "LabelMaxScreenshotsPerItem": "Massimo numero di foto per oggetto:",
"LabelMinBackdropDownloadWidth": "Massima larghezza sfondo:", "LabelMinBackdropDownloadWidth": "Massima larghezza sfondo:",
"LabelMinScreenshotDownloadWidth": "Minima larghezza foto:", "LabelMinScreenshotDownloadWidth": "Minima larghezza foto:",
"ButtonAddScheduledTaskTrigger": "Aggiungi operazione:", "ButtonAddScheduledTaskTrigger": "Aggiungi operazione",
"HeaderAddScheduledTaskTrigger": "Aggiungi operazione:", "HeaderAddScheduledTaskTrigger": "Aggiungi operazione",
"ButtonAdd": "Aggiungi", "ButtonAdd": "Aggiungi",
"LabelTriggerType": "Tipo Evento:", "LabelTriggerType": "Tipo Evento:",
"OptionDaily": "Giornal.", "OptionDaily": "Giornal.",
@ -1261,7 +1261,7 @@
"HeaderTrailerReel": "Trailer b.", "HeaderTrailerReel": "Trailer b.",
"OptionPlayUnwatchedTrailersOnly": "Riproduci solo i trailer non visti", "OptionPlayUnwatchedTrailersOnly": "Riproduci solo i trailer non visti",
"HeaderTrailerReelHelp": "Inizia a riprodurre una lunga playlist di trailer", "HeaderTrailerReelHelp": "Inizia a riprodurre una lunga playlist di trailer",
"MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.", "MessageNoTrailersFound": "Nessun Trailer trovato.Installa Il plug in dei trailer per importare la libreria dei trailer da internet",
"HeaderNewUsers": "Nuovo Utente", "HeaderNewUsers": "Nuovo Utente",
"ButtonSignUp": "Iscriviti", "ButtonSignUp": "Iscriviti",
"ButtonForgotPassword": "Dimenticato la password?", "ButtonForgotPassword": "Dimenticato la password?",
@ -1288,15 +1288,15 @@
"HeaderParentalRatings": "Valutazioni genitori", "HeaderParentalRatings": "Valutazioni genitori",
"HeaderVideoTypes": "Tipi Video", "HeaderVideoTypes": "Tipi Video",
"HeaderYears": "Anni", "HeaderYears": "Anni",
"HeaderAddTag": "Add Tag", "HeaderAddTag": "Aggiungi Tag",
"LabelBlockItemsWithTags": "Block items with tags:", "LabelBlockItemsWithTags": "Oggetti di blocco con tag:",
"LabelTag": "Tag:", "LabelTag": "Tag:",
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image", "LabelEnableSingleImageInDidlLimit": "Limitato a singola immagine incorporata",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.", "LabelEnableSingleImageInDidlLimitHelp": "Alcuni dispositivi non renderanno correttamente se pi\u00f9 immagini sono incorporati all'interno didl.",
"TabActivity": "Activity", "TabActivity": "Attivit\u00e0",
"TitleSync": "Sync", "TitleSync": "Sync",
"OptionAllowSyncContent": "Allow syncing media to devices", "OptionAllowSyncContent": "Consenti sincronizzazione media per dispositivi",
"NameSeasonUnknown": "Season Unknown", "NameSeasonUnknown": "Stagione sconosciuto",
"NameSeasonNumber": "Season {0}", "NameSeasonNumber": "Stagione {0}",
"LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)" "LabelNewUserNameHelp": "I nomi utente possono contenere lettere (az), numeri (0-9), trattini (-), underscore (_), apostrofi ('), e periodi (.)"
} }

@ -70,9 +70,9 @@
"TabImages": "Imagens", "TabImages": "Imagens",
"TabNotifications": "Notifica\u00e7\u00f5es", "TabNotifications": "Notifica\u00e7\u00f5es",
"TabCollectionTitles": "T\u00edtulos", "TabCollectionTitles": "T\u00edtulos",
"HeaderDeviceAccess": "Device Access", "HeaderDeviceAccess": "Acesso ao Dispositivo",
"OptionEnableAccessFromAllDevices": "Enable access from all devices", "OptionEnableAccessFromAllDevices": "Ativar o acesso de todos os dispositivos",
"DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.", "DeviceAccessHelp": "Isto apenas aplica para dispositivos que podem ser identificados como \u00fanicos e n\u00e3o evitar\u00e3o o acesso do navegador. Filtrar o acesso ao dispositivo do usu\u00e1rio evitar\u00e1 que sejam usados novos dispositivos at\u00e9 que sejam aprovados aqui.",
"LabelDisplayMissingEpisodesWithinSeasons": "Exibir epis\u00f3dios que faltam dentro das temporadas", "LabelDisplayMissingEpisodesWithinSeasons": "Exibir epis\u00f3dios que faltam dentro das temporadas",
"LabelUnairedMissingEpisodesWithinSeasons": "Exibir epis\u00f3dios por estrear dentro das temporadas", "LabelUnairedMissingEpisodesWithinSeasons": "Exibir epis\u00f3dios por estrear dentro das temporadas",
"HeaderVideoPlaybackSettings": "Ajustes da Reprodu\u00e7\u00e3o de V\u00eddeo", "HeaderVideoPlaybackSettings": "Ajustes da Reprodu\u00e7\u00e3o de V\u00eddeo",

@ -19,7 +19,7 @@
"TitleMediaBrowser": "Media Browser", "TitleMediaBrowser": "Media Browser",
"ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.", "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.",
"TellUsAboutYourself": "Tell us about yourself", "TellUsAboutYourself": "Tell us about yourself",
"ButtonQuickStartGuide": "Quick start guide", "ButtonQuickStartGuide": "Quick start guide",
"LabelYourFirstName": "Your first name:", "LabelYourFirstName": "Your first name:",
"MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.",
"UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
@ -38,6 +38,7 @@
"ButtonOk": "Ok", "ButtonOk": "Ok",
"ButtonCancel": "Cancel", "ButtonCancel": "Cancel",
"ButtonNew": "New", "ButtonNew": "New",
"HeaderSyncJobInfo": "Sync Job",
"FolderTypeMixed": "Mixed content", "FolderTypeMixed": "Mixed content",
"FolderTypeMovies": "Movies", "FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music", "FolderTypeMusic": "Music",
@ -1315,5 +1316,6 @@
"OptionAllowSyncContent": "Allow syncing media to devices", "OptionAllowSyncContent": "Allow syncing media to devices",
"NameSeasonUnknown": "Season Unknown", "NameSeasonUnknown": "Season Unknown",
"NameSeasonNumber": "Season {0}", "NameSeasonNumber": "Season {0}",
"LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)" "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)",
"TabSyncJobs": "Sync Jobs"
} }

@ -302,7 +302,6 @@
<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\MockSyncProvider.cs" />
<Compile Include="Sync\SyncJobProcessor.cs" /> <Compile Include="Sync\SyncJobProcessor.cs" />
<Compile Include="Sync\SyncManager.cs" /> <Compile Include="Sync\SyncManager.cs" />
<Compile Include="Sync\SyncRepository.cs" /> <Compile Include="Sync\SyncRepository.cs" />

@ -30,6 +30,20 @@ namespace MediaBrowser.Server.Implementations.Sync
}); });
} }
public IEnumerable<SyncTarget> GetSyncTargets(string userId)
{
return _deviceManager.GetDevices(new DeviceQuery
{
SupportsSync = true,
UserId = userId
}).Items.Select(i => new SyncTarget
{
Id = i.Id,
Name = i.Name
});
}
public DeviceProfile GetDeviceProfile(SyncTarget target) public DeviceProfile GetDeviceProfile(SyncTarget target)
{ {
return new DeviceProfile(); return new DeviceProfile();

@ -2,7 +2,6 @@
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;
@ -10,7 +9,7 @@ namespace MediaBrowser.Server.Implementations.Sync
{ {
public class CloudSyncProvider : ISyncProvider public class CloudSyncProvider : ISyncProvider
{ {
private ICloudSyncProvider[] _providers = new ICloudSyncProvider[] {}; private ICloudSyncProvider[] _providers = {};
public CloudSyncProvider(IApplicationHost appHost) public CloudSyncProvider(IApplicationHost appHost)
{ {
@ -22,6 +21,11 @@ namespace MediaBrowser.Server.Implementations.Sync
return new List<SyncTarget>(); return new List<SyncTarget>();
} }
public IEnumerable<SyncTarget> GetSyncTargets(string userId)
{
return new List<SyncTarget>();
}
public DeviceProfile GetDeviceProfile(SyncTarget target) public DeviceProfile GetDeviceProfile(SyncTarget target)
{ {
return new DeviceProfile(); return new DeviceProfile();

@ -1,33 +0,0 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Sync;
using System.Collections.Generic;
namespace MediaBrowser.Server.Implementations.Sync
{
public class MockSyncProvider : ISyncProvider
{
public string Name
{
get { return "Test Sync"; }
}
public IEnumerable<SyncTarget> GetSyncTargets()
{
return new List<SyncTarget>
{
new SyncTarget
{
Id = GetType().Name.GetMD5().ToString("N"),
Name = Name
}
};
}
public DeviceProfile GetDeviceProfile(SyncTarget target)
{
return new DeviceProfile();
}
}
}

@ -81,6 +81,7 @@ namespace MediaBrowser.Server.Implementations.Sync
{ {
Id = Guid.NewGuid().ToString("N"), Id = Guid.NewGuid().ToString("N"),
ItemId = itemId, ItemId = itemId,
ItemName = GetSyncJobItemName(item),
JobId = job.Id, JobId = job.Id,
TargetId = job.TargetId, TargetId = job.TargetId,
DateCreated = DateTime.UtcNow DateCreated = DateTime.UtcNow
@ -98,6 +99,11 @@ namespace MediaBrowser.Server.Implementations.Sync
await UpdateJobStatus(job, jobItems).ConfigureAwait(false); await UpdateJobStatus(job, jobItems).ConfigureAwait(false);
} }
private string GetSyncJobItemName(BaseItem item)
{
return item.Name;
}
public Task UpdateJobStatus(string id) public Task UpdateJobStatus(string id)
{ {
var job = _syncRepo.GetJob(id); var job = _syncRepo.GetJob(id);

@ -73,11 +73,7 @@ namespace MediaBrowser.Server.Implementations.Sync
if (string.IsNullOrWhiteSpace(request.Name)) if (string.IsNullOrWhiteSpace(request.Name))
{ {
if (request.Category.HasValue) if (request.ItemIds.Count == 1)
{
request.Name = request.Category.Value.ToString();
}
else if (request.ItemIds.Count == 1)
{ {
request.Name = GetDefaultName(_libraryManager.GetItemById(request.ItemIds[0])); request.Name = GetDefaultName(_libraryManager.GetItemById(request.ItemIds[0]));
} }
@ -132,21 +128,49 @@ namespace MediaBrowser.Server.Implementations.Sync
}; };
} }
public QueryResult<SyncJob> GetJobs(SyncJobQuery query) public Task UpdateJob(SyncJob job)
{
// Get fresh from the db and only update the fields that are supported to be changed.
var instance = _repo.GetJob(job.Id);
instance.Name = job.Name;
instance.Quality = job.Quality;
instance.UnwatchedOnly = job.UnwatchedOnly;
instance.SyncNewContent = job.SyncNewContent;
instance.ItemLimit = job.ItemLimit;
return _repo.Update(instance);
}
public async Task<QueryResult<SyncJob>> GetJobs(SyncJobQuery query)
{ {
var result = _repo.GetJobs(query); var result = _repo.GetJobs(query);
result.Items.ForEach(FillMetadata); foreach (var item in result.Items)
{
await FillMetadata(item).ConfigureAwait(false);
}
return result; return result;
} }
private void FillMetadata(SyncJob job) private async Task FillMetadata(SyncJob job)
{ {
var item = job.RequestedItemIds var item = job.RequestedItemIds
.Select(_libraryManager.GetItemById) .Select(_libraryManager.GetItemById)
.FirstOrDefault(i => i != null); .FirstOrDefault(i => i != null);
if (item == null)
{
var processor = new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager);
var user = _userManager.GetUserById(job.UserId);
item = (await processor
.GetItemsForSync(job.Category, job.ParentId, job.RequestedItemIds, user, job.UnwatchedOnly).ConfigureAwait(false))
.FirstOrDefault();
}
if (item != null) if (item != null)
{ {
var hasSeries = item as IHasSeries; var hasSeries = item as IHasSeries;
@ -162,13 +186,25 @@ namespace MediaBrowser.Server.Implementations.Sync
} }
var primaryImage = item.GetImageInfo(ImageType.Primary, 0); var primaryImage = item.GetImageInfo(ImageType.Primary, 0);
var itemWithImage = item;
if (primaryImage == null)
{
var parentWithImage = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary));
if (parentWithImage != null)
{
itemWithImage = parentWithImage;
primaryImage = parentWithImage.GetImageInfo(ImageType.Primary, 0);
}
}
if (primaryImage != null) if (primaryImage != null)
{ {
try try
{ {
job.PrimaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary); job.PrimaryImageTag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Primary);
job.PrimaryImageItemId = item.Id.ToString("N"); job.PrimaryImageItemId = itemWithImage.Id.ToString("N");
} }
catch (Exception ex) catch (Exception ex)
@ -179,6 +215,44 @@ namespace MediaBrowser.Server.Implementations.Sync
} }
} }
private void FillMetadata(SyncJobItem jobItem)
{
var item = _libraryManager.GetItemById(jobItem.ItemId);
if (item == null)
{
return;
}
var primaryImage = item.GetImageInfo(ImageType.Primary, 0);
var itemWithImage = item;
if (primaryImage == null)
{
var parentWithImage = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary));
if (parentWithImage != null)
{
itemWithImage = parentWithImage;
primaryImage = parentWithImage.GetImageInfo(ImageType.Primary, 0);
}
}
if (primaryImage != null)
{
try
{
jobItem.PrimaryImageTag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Primary);
jobItem.PrimaryImageItemId = itemWithImage.Id.ToString("N");
}
catch (Exception ex)
{
_logger.ErrorException("Error getting image info", ex);
}
}
}
public Task CancelJob(string id) public Task CancelJob(string id)
{ {
return _repo.DeleteJob(id); return _repo.DeleteJob(id);
@ -198,7 +272,7 @@ namespace MediaBrowser.Server.Implementations.Sync
private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider, string userId) private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider, string userId)
{ {
return provider.GetSyncTargets().Select(i => new SyncTarget return provider.GetSyncTargets(userId).Select(i => new SyncTarget
{ {
Name = i.Name, Name = i.Name,
Id = GetSyncTargetId(provider, i) Id = GetSyncTargetId(provider, i)
@ -330,7 +404,14 @@ namespace MediaBrowser.Server.Implementations.Sync
public QueryResult<SyncJobItem> GetJobItems(SyncJobItemQuery query) public QueryResult<SyncJobItem> GetJobItems(SyncJobItemQuery query)
{ {
return _repo.GetJobItems(query); var result = _repo.GetJobItems(query);
if (query.AddMetadata)
{
result.Items.ForEach(FillMetadata);
}
return result;
} }
private SyncedItem GetJobItemInfo(SyncJobItem jobItem) private SyncedItem GetJobItemInfo(SyncJobItem jobItem)
@ -449,7 +530,7 @@ namespace MediaBrowser.Server.Implementations.Sync
} }
response.ItemIdsToRemove = response.ItemIdsToRemove.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); response.ItemIdsToRemove = response.ItemIdsToRemove.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
return response; return response;
} }

@ -36,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public async Task Initialize() public async Task Initialize()
{ {
var dbFile = Path.Combine(_appPaths.DataPath, "sync9.db"); var dbFile = Path.Combine(_appPaths.DataPath, "sync10.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
@ -45,7 +45,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, MediaSourceId TEXT, JobId TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT)", "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT)",
"create index if not exists idx_SyncJobItems on SyncJobs(Id)", "create index if not exists idx_SyncJobItems on SyncJobs(Id)",
//pragmas //pragmas
@ -90,21 +90,22 @@ 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, MediaSourceId, JobId, OutputPath, Status, TargetId, DateCreated, Progress) values (@Id, @ItemId, @MediaSourceId, @JobId, @OutputPath, @Status, @TargetId, @DateCreated, @Progress)"; _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, OutputPath, Status, TargetId, DateCreated, Progress) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @OutputPath, @Status, @TargetId, @DateCreated, @Progress)";
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Id"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Id");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@ItemId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@ItemId");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@MediaSourceId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@ItemName");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@JobId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@MediaSourceId");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@OutputPath"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@JobId");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Status"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@OutputPath");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@TargetId"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Status");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@DateCreated"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@TargetId");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Progress"); _saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@DateCreated");
_saveJobItemCommand.Parameters.Add(_saveJobItemCommand, "@Progress");
} }
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, MediaSourceId, JobId, OutputPath, Status, TargetId, DateCreated, Progress from SyncJobItems"; private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, OutputPath, Status, TargetId, DateCreated, Progress from SyncJobItems";
public SyncJob GetJob(string id) public SyncJob GetJob(string id)
{ {
@ -366,6 +367,11 @@ namespace MediaBrowser.Server.Implementations.Sync
whereClauses.Add("TargetId=@TargetId"); whereClauses.Add("TargetId=@TargetId");
cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId; cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId;
} }
if (!string.IsNullOrWhiteSpace(query.UserId))
{
whereClauses.Add("UserId=@UserId");
cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId;
}
var whereTextWithoutPaging = whereClauses.Count == 0 ? var whereTextWithoutPaging = whereClauses.Count == 0 ?
string.Empty : string.Empty :
@ -547,6 +553,7 @@ namespace MediaBrowser.Server.Implementations.Sync
_saveJobItemCommand.GetParameter(index++).Value = new Guid(jobItem.Id); _saveJobItemCommand.GetParameter(index++).Value = new Guid(jobItem.Id);
_saveJobItemCommand.GetParameter(index++).Value = jobItem.ItemId; _saveJobItemCommand.GetParameter(index++).Value = jobItem.ItemId;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.ItemName;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.MediaSourceId; _saveJobItemCommand.GetParameter(index++).Value = jobItem.MediaSourceId;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.JobId; _saveJobItemCommand.GetParameter(index++).Value = jobItem.JobId;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.OutputPath; _saveJobItemCommand.GetParameter(index++).Value = jobItem.OutputPath;
@ -602,28 +609,33 @@ namespace MediaBrowser.Server.Implementations.Sync
if (!reader.IsDBNull(2)) if (!reader.IsDBNull(2))
{ {
info.MediaSourceId = reader.GetString(2); info.ItemName = reader.GetString(2);
} }
info.JobId = reader.GetString(3); if (!reader.IsDBNull(3))
if (!reader.IsDBNull(4))
{ {
info.OutputPath = reader.GetString(4); info.MediaSourceId = reader.GetString(3);
} }
info.JobId = reader.GetString(4);
if (!reader.IsDBNull(5)) if (!reader.IsDBNull(5))
{ {
info.Status = (SyncJobItemStatus)Enum.Parse(typeof(SyncJobItemStatus), reader.GetString(5), true); info.OutputPath = reader.GetString(5);
} }
info.TargetId = reader.GetString(6); if (!reader.IsDBNull(6))
{
info.Status = (SyncJobItemStatus)Enum.Parse(typeof(SyncJobItemStatus), reader.GetString(6), true);
}
info.DateCreated = reader.GetDateTime(7); info.TargetId = reader.GetString(7);
if (!reader.IsDBNull(8)) info.DateCreated = reader.GetDateTime(8);
if (!reader.IsDBNull(9))
{ {
info.Progress = reader.GetDouble(8); info.Progress = reader.GetDouble(9);
} }
return info; return info;

@ -334,6 +334,7 @@ namespace MediaBrowser.WebDashboard.Api
"chromecast.js", "chromecast.js",
"backdrops.js", "backdrops.js",
"sync.js", "sync.js",
"syncjob.js",
"playlistmanager.js", "playlistmanager.js",
"mediaplayer.js", "mediaplayer.js",

@ -93,6 +93,12 @@
<Content Include="dashboard-ui\forgotpasswordpin.html"> <Content Include="dashboard-ui\forgotpasswordpin.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\mysync.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\mysyncjob.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\forgotpassword.js"> <Content Include="dashboard-ui\scripts\forgotpassword.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -102,6 +108,9 @@
<Content Include="dashboard-ui\scripts\selectserver.js"> <Content Include="dashboard-ui\scripts\selectserver.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\scripts\syncjob.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\syncsettings.js"> <Content Include="dashboard-ui\scripts\syncsettings.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -114,6 +123,9 @@
<Content Include="dashboard-ui\selectserver.html"> <Content Include="dashboard-ui\selectserver.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\syncjob.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\syncsettings.html"> <Content Include="dashboard-ui\syncsettings.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>

Loading…
Cancel
Save