diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index d61e8d73ad..f21e69290e 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -131,17 +131,17 @@ namespace MediaBrowser.Api.Playback.Progressive
{
var args = "-vcodec " + codec;
+ if (state.EnableMpegtsM2TsMode)
+ {
+ args += " -mpegts_m2ts_mode 1";
+ }
+
// See if we can save come cpu cycles by avoiding encoding
if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
{
return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args;
}
- if (state.EnableMpegtsM2TsMode)
- {
- args += " -mpegts_m2ts_mode 1";
- }
-
const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
args += keyFrameArg;
diff --git a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs
index 810376f6c6..535e74feee 100644
--- a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs
+++ b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs
@@ -1,5 +1,7 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
using MediaBrowser.Model.Configuration;
+using System;
namespace MediaBrowser.Controller.Configuration
{
@@ -8,6 +10,11 @@ namespace MediaBrowser.Controller.Configuration
///
public interface IServerConfigurationManager : IConfigurationManager
{
+ ///
+ /// Occurs when [configuration updating].
+ ///
+ event EventHandler> ConfigurationUpdating;
+
///
/// Gets the application paths.
///
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 6a3709dda6..6a7557e3a5 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -191,6 +191,7 @@
+
diff --git a/MediaBrowser.Controller/Security/IEncryptionManager.cs b/MediaBrowser.Controller/Security/IEncryptionManager.cs
new file mode 100644
index 0000000000..bb4f77d83b
--- /dev/null
+++ b/MediaBrowser.Controller/Security/IEncryptionManager.cs
@@ -0,0 +1,20 @@
+
+namespace MediaBrowser.Controller.Security
+{
+ public interface IEncryptionManager
+ {
+ ///
+ /// Encrypts the string.
+ ///
+ /// The value.
+ /// System.String.
+ string EncryptString(string value);
+
+ ///
+ /// Decrypts the string.
+ ///
+ /// The value.
+ /// System.String.
+ string DecryptString(string value);
+ }
+}
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 486268e2b6..32b1a7e015 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -323,6 +323,9 @@ namespace MediaBrowser.Model.Configuration
public bool DownloadMovieSubtitles { get; set; }
public bool DownloadEpisodeSubtitles { get; set; }
+ public string OpenSubtitlesUsername { get; set; }
+ public string OpenSubtitlesPasswordHash { get; set; }
+
public SubtitleOptions()
{
SubtitleDownloadLanguages = new string[] { };
diff --git a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs
index 929cccd5ab..f76528c3f4 100644
--- a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs
+++ b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs
@@ -1,7 +1,9 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Subtitles;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
@@ -16,16 +18,52 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Subtitles
{
- public class OpenSubtitleDownloader : ISubtitleProvider
+ public class OpenSubtitleDownloader : ISubtitleProvider, IDisposable
{
private readonly ILogger _logger;
private readonly IHttpClient _httpClient;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient)
+ private readonly IServerConfigurationManager _config;
+ private readonly IEncryptionManager _encryption;
+
+ public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption)
{
_logger = logManager.GetLogger(GetType().Name);
_httpClient = httpClient;
+ _config = config;
+ _encryption = encryption;
+
+ _config.ConfigurationUpdating += _config_ConfigurationUpdating;
+ }
+
+ private const string PasswordHashPrefix = "h:";
+ void _config_ConfigurationUpdating(object sender, GenericEventArgs e)
+ {
+ var options = e.Argument.SubtitleOptions;
+
+ if (options != null &&
+ !string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash) &&
+ !options.OpenSubtitlesPasswordHash.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase))
+ {
+ options.OpenSubtitlesPasswordHash = EncryptPassword(options.OpenSubtitlesPasswordHash);
+ }
+ }
+
+ private string EncryptPassword(string password)
+ {
+ return PasswordHashPrefix + _encryption.EncryptString(password);
+ }
+
+ private string DecryptPassword(string password)
+ {
+ if (password == null ||
+ !password.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase))
+ {
+ return string.Empty;
+ }
+
+ return _encryption.DecryptString(password.Substring(2));
}
public string Name
@@ -35,7 +73,16 @@ namespace MediaBrowser.Providers.Subtitles
public IEnumerable SupportedMediaTypes
{
- get { return new[] { SubtitleMediaType.Episode, SubtitleMediaType.Movie }; }
+ get
+ {
+ if (string.IsNullOrWhiteSpace(_config.Configuration.SubtitleOptions.OpenSubtitlesUsername) ||
+ string.IsNullOrWhiteSpace(_config.Configuration.SubtitleOptions.OpenSubtitlesPasswordHash))
+ {
+ return new SubtitleMediaType[] { };
+ }
+
+ return new[] { SubtitleMediaType.Episode, SubtitleMediaType.Movie };
+ }
}
public Task GetSubtitles(string id, CancellationToken cancellationToken)
@@ -59,7 +106,10 @@ namespace MediaBrowser.Providers.Subtitles
var downloadsList = new[] { int.Parse(ossId, _usCulture) };
- var resultDownLoad = OpenSubtitles.DownloadSubtitles(downloadsList);
+ await Login(cancellationToken).ConfigureAwait(false);
+
+ var resultDownLoad = await OpenSubtitles.DownloadSubtitlesAsync(downloadsList, cancellationToken).ConfigureAwait(false);
+
if (!(resultDownLoad is MethodResponseSubtitleDownload))
{
throw new ApplicationException("Invalid response type");
@@ -77,6 +127,21 @@ namespace MediaBrowser.Providers.Subtitles
};
}
+ private async Task Login(CancellationToken cancellationToken)
+ {
+ var options = _config.Configuration.SubtitleOptions ?? new SubtitleOptions();
+
+ var user = options.OpenSubtitlesUsername ?? string.Empty;
+ var password = DecryptPassword(options.OpenSubtitlesPasswordHash);
+
+ var loginResponse = await OpenSubtitles.LogInAsync(user, password, "en", cancellationToken).ConfigureAwait(false);
+
+ if (!(loginResponse is MethodResponseLogIn))
+ {
+ throw new UnauthorizedAccessException("Authentication to OpenSubtitles failed.");
+ }
+ }
+
public async Task> SearchSubtitles(SubtitleSearchRequest request, CancellationToken cancellationToken)
{
var imdbIdText = request.GetProviderId(MetadataProviders.Imdb);
@@ -116,13 +181,7 @@ namespace MediaBrowser.Providers.Subtitles
Utilities.HttpClient = _httpClient;
OpenSubtitles.SetUserAgent("OS Test User Agent");
- var loginResponse = await OpenSubtitles.LogInAsync("", "", "en", cancellationToken).ConfigureAwait(false);
-
- if (!(loginResponse is MethodResponseLogIn))
- {
- _logger.Debug("Login error");
- return new List();
- }
+ await Login(cancellationToken).ConfigureAwait(false);
var subLanguageId = request.Language;
var hash = Utilities.ComputeHash(request.MediaPath);
@@ -178,5 +237,10 @@ namespace MediaBrowser.Providers.Subtitles
IsHashMatch = i.MovieHash == hasCopy
});
}
+
+ public void Dispose()
+ {
+ _config.ConfigurationUpdating -= _config_ConfigurationUpdating;
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
index da38616821..ab79c6a1af 100644
--- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
+++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Implementations.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
@@ -29,6 +30,8 @@ namespace MediaBrowser.Server.Implementations.Configuration
UpdateMetadataPath();
}
+ public event EventHandler> ConfigurationUpdating;
+
///
/// Gets the type of the configuration.
///
@@ -73,8 +76,8 @@ namespace MediaBrowser.Server.Implementations.Configuration
///
private void UpdateItemsByNamePath()
{
- ((ServerApplicationPaths) ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ?
- null :
+ ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ?
+ null :
Configuration.ItemsByNamePath;
}
@@ -105,13 +108,15 @@ namespace MediaBrowser.Server.Implementations.Configuration
///
public override void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
{
- var newConfig = (ServerConfiguration) newConfiguration;
+ var newConfig = (ServerConfiguration)newConfiguration;
ValidateItemByNamePath(newConfig);
ValidateTranscodingTempPath(newConfig);
ValidatePathSubstitutions(newConfig);
ValidateMetadataPath(newConfig);
+ EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs { Argument = newConfig }, Logger);
+
base.ReplaceConfiguration(newConfiguration);
}
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
index c464b2534b..52ddcd795f 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
@@ -17,8 +17,6 @@
"PasswordResetConfirmation": "Are you sure you wish to reset the password?",
"PasswordSaved": "Password saved.",
"PasswordMatchError": "Password and password confirmation must match.",
- "OptionOff": "Off",
- "OptionOn": "On",
"OptionRelease": "Official Release",
"OptionBeta": "Beta",
"OptionDev": "Dev (Unstable)",
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json
index c2e29649fd..d011d45d06 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -147,10 +147,8 @@
"ScheduledTasksTitle": "Scheduled Tasks",
"TabMyPlugins": "My Plugins",
"TabCatalog": "Catalog",
- "TabUpdates": "Updates",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatic Updates",
- "HeaderUpdateLevel": "Update Level",
"HeaderNowPlaying": "Now Playing",
"HeaderLatestAlbums": "Latest Albums",
"HeaderLatestSongs": "Latest Songs",
@@ -706,5 +704,13 @@
"OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.",
"OptionEstimateContentLength": "Estimate content length when transcoding",
"OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding",
- "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well."
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.",
+ "HeaderSubtitleDownloadingHelp": "Media Browser can inspect your video files for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Download subtitles for:",
+ "LabelRequireExternalSubtitles": "Download even if the video already contains graphical subtitles",
+ "LabelRequireExternalSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language."
}
\ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 3532ee3703..74b8bf2699 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -64,6 +64,7 @@
+
@@ -201,6 +202,7 @@
+
diff --git a/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs b/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs
new file mode 100644
index 0000000000..73a4e30048
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs
@@ -0,0 +1,36 @@
+using MediaBrowser.Controller.Security;
+using System;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.Security
+{
+ public class EncryptionManager : IEncryptionManager
+ {
+ ///
+ /// Encrypts the string.
+ ///
+ /// The value.
+ /// System.String.
+ /// value
+ public string EncryptString(string value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ return Encoding.Default.GetString(ProtectedData.Protect(Encoding.Default.GetBytes(value), null, DataProtectionScope.LocalMachine));
+ }
+
+ ///
+ /// Decrypts the string.
+ ///
+ /// The value.
+ /// System.String.
+ /// value
+ public string DecryptString(string value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ return Encoding.Default.GetString(ProtectedData.Unprotect(Encoding.Default.GetBytes(value), null, DataProtectionScope.LocalMachine));
+ }
+ }
+}
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index c79d84e5a7..9de3198518 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -29,6 +29,7 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
+using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Controller.Subtitles;
@@ -61,6 +62,7 @@ using MediaBrowser.Server.Implementations.Localization;
using MediaBrowser.Server.Implementations.MediaEncoder;
using MediaBrowser.Server.Implementations.Notifications;
using MediaBrowser.Server.Implementations.Persistence;
+using MediaBrowser.Server.Implementations.Security;
using MediaBrowser.Server.Implementations.ServerManager;
using MediaBrowser.Server.Implementations.Session;
using MediaBrowser.Server.Implementations.Themes;
@@ -533,6 +535,8 @@ namespace MediaBrowser.ServerApplication
NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager);
RegisterSingleInstance(NotificationManager);
+ RegisterSingleInstance(new EncryptionManager());
+
SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor);
RegisterSingleInstance(SubtitleManager);
diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs
index 2db493f021..58a0c84b0f 100644
--- a/MediaBrowser.WebDashboard/Api/DashboardService.cs
+++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs
@@ -585,6 +585,7 @@ namespace MediaBrowser.WebDashboard.Api
"medialibrarypage.js",
"metadataconfigurationpage.js",
"metadataimagespage.js",
+ "metadatasubtitles.js",
"moviegenres.js",
"moviecollections.js",
"movies.js",
@@ -605,7 +606,6 @@ namespace MediaBrowser.WebDashboard.Api
"playlist.js",
"plugincatalogpage.js",
"pluginspage.js",
- "pluginupdatespage.js",
"remotecontrol.js",
"scheduledtaskpage.js",
"scheduledtaskspage.js",
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 3072413f92..7f9d6919e0 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -328,6 +328,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
@@ -658,6 +661,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
@@ -1781,16 +1787,6 @@
PreserveNewest
-
-
- PreserveNewest
-
-
-
-
- PreserveNewest
-
-
PreserveNewest
diff --git a/OpenSubtitlesHandler/OpenSubtitles.cs b/OpenSubtitlesHandler/OpenSubtitles.cs
index 5353586c85..e810dad69c 100644
--- a/OpenSubtitlesHandler/OpenSubtitles.cs
+++ b/OpenSubtitlesHandler/OpenSubtitles.cs
@@ -551,6 +551,117 @@ namespace OpenSubtitlesHandler
}
return new MethodResponseError("Fail", "DownloadSubtitles call failed !");
}
+
+ public static async Task DownloadSubtitlesAsync(int[] subIDS, CancellationToken cancellationToken)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ if (subIDS == null)
+ {
+ OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle id passed"); ;
+ }
+ if (subIDS.Length == 0)
+ {
+ OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle id passed"); ;
+ }
+ // Method call ..
+ List parms = new List();
+ // Add token param
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ // Add subtitle search parameters. Each one will be like 'array' of structs.
+ XmlRpcValueArray array = new XmlRpcValueArray();
+ foreach (int id in subIDS)
+ {
+ array.Values.Add(new XmlRpcValueBasic(id, XmlRpcBasicValueType.Int));
+ }
+ // Add the array to the parameters
+ parms.Add(array);
+ // Call !
+ XmlRpcMethodCall call = new XmlRpcMethodCall("DownloadSubtitles", parms);
+ OSHConsole.WriteLine("Sending DownloadSubtitles request to the server ...", DebugCode.Good);
+ // Send the request to the server
+
+ var httpResponse = await Utilities.SendRequestAsync(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT, cancellationToken).ConfigureAwait(false);
+
+ string response = Utilities.GetStreamString(httpResponse);
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ // We expect Struct of 3 members:
+ //* the first is status
+ //* the second is [array of structs, each one includes subtitle file].
+ //* the third is [double basic value] represent seconds token by server.
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseSubtitleDownload R = new MethodResponseSubtitleDownload();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ if (MEMBER.Name == "status")
+ {
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Status= " + R.Status);
+ }
+ else if (MEMBER.Name == "seconds")
+ {
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Seconds= " + R.Seconds);
+ }
+ else if (MEMBER.Name == "data")
+ {
+ if (MEMBER.Data is XmlRpcValueArray)
+ {
+ OSHConsole.WriteLine("Download results:");
+ XmlRpcValueArray rarray = (XmlRpcValueArray)MEMBER.Data;
+ foreach (IXmlRpcValue subStruct in rarray.Values)
+ {
+ if (subStruct == null) continue;
+ if (!(subStruct is XmlRpcValueStruct)) continue;
+
+ SubtitleDownloadResult result = new SubtitleDownloadResult();
+ foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members)
+ {
+ // To avoid errors of arranged info or missing ones, let's do it with switch..
+ switch (submember.Name)
+ {
+ case "idsubtitlefile": result.IdSubtitleFile = (string)submember.Data.Data; break;
+ case "data": result.Data = (string)submember.Data.Data; break;
+ }
+ }
+ R.Results.Add(result);
+ OSHConsole.WriteLine("> IDSubtilteFile= " + result.ToString());
+ }
+ }
+ else// Unknown data ?
+ {
+ OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning);
+ }
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "DownloadSubtitles call failed !");
+ }
+
///
/// Returns comments for subtitles
///