diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index bb9d2b8645..7c5f7cde40 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -192,13 +192,13 @@ namespace MediaBrowser.Api
_activeTranscodingJobs.Add(job);
- ReportTranscodingProgress(job, state, null, null, null, null);
+ ReportTranscodingProgress(job, state, null, null, null, null, null);
return job;
}
}
- public void ReportTranscodingProgress(TranscodingJob job, StreamState state, TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded)
+ public void ReportTranscodingProgress(TranscodingJob job, StreamState state, TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
{
var ticks = transcodingPosition.HasValue ? transcodingPosition.Value.Ticks : (long?)null;
@@ -208,6 +208,7 @@ namespace MediaBrowser.Api
job.CompletionPercentage = percentComplete;
job.TranscodingPositionTicks = ticks;
job.BytesTranscoded = bytesTranscoded;
+ job.BitRate = bitRate;
}
var deviceId = state.Request.DeviceId;
@@ -219,7 +220,7 @@ namespace MediaBrowser.Api
_sessionManager.ReportTranscodingInfo(deviceId, new TranscodingInfo
{
- Bitrate = state.TotalOutputBitrate,
+ Bitrate = bitRate ?? state.TotalOutputBitrate,
AudioCodec = audioCodec,
VideoCodec = videoCodec,
Container = state.OutputContainer,
@@ -694,6 +695,7 @@ namespace MediaBrowser.Api
public long? BytesDownloaded { get; set; }
public long? BytesTranscoded { get; set; }
+ public int? BitRate { get; set; }
public long? TranscodingPositionTicks { get; set; }
public long? DownloadPositionTicks { get; set; }
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index ac967e1949..f52505c04b 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -22,6 +22,8 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
namespace MediaBrowser.Api.Playback
{
@@ -69,6 +71,9 @@ namespace MediaBrowser.Api.Playback
protected IZipClient ZipClient { get; private set; }
protected IJsonSerializer JsonSerializer { get; private set; }
+ public static IServerApplicationHost AppHost;
+ public static IHttpClient HttpClient;
+
///
/// Initializes a new instance of the class.
///
@@ -1112,6 +1117,7 @@ namespace MediaBrowser.Api.Playback
}
StartThrottler(state, transcodingJob);
+ ReportUsage(state);
return transcodingJob;
}
@@ -1131,7 +1137,7 @@ namespace MediaBrowser.Api.Playback
return state.InputProtocol == MediaProtocol.File &&
state.RunTimeTicks.HasValue &&
state.RunTimeTicks.Value >= TimeSpan.FromMinutes(5).Ticks &&
- state.IsInputVideo &&
+ state.IsInputVideo &&
state.VideoType == VideoType.VideoFile &&
!string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) &&
string.Equals(GetVideoEncoder(state), "libx264", StringComparison.OrdinalIgnoreCase);
@@ -1172,6 +1178,7 @@ namespace MediaBrowser.Api.Playback
double? percent = null;
TimeSpan? transcodingPosition = null;
long? bytesTranscoded = null;
+ int? bitRate = null;
var parts = line.Split(' ');
@@ -1235,11 +1242,32 @@ namespace MediaBrowser.Api.Playback
}
}
}
+ else if (part.StartsWith("bitrate=", StringComparison.OrdinalIgnoreCase))
+ {
+ var rate = part.Split(new[] { '=' }, 2).Last();
+
+ int? scale = null;
+ if (rate.IndexOf("kbits/s", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ scale = 1024;
+ rate = rate.Replace("kbits/s", string.Empty, StringComparison.OrdinalIgnoreCase);
+ }
+
+ if (scale.HasValue)
+ {
+ float val;
+
+ if (float.TryParse(rate, NumberStyles.Any, UsCulture, out val))
+ {
+ bitRate = (int)Math.Ceiling(val * scale.Value);
+ }
+ }
+ }
}
if (framerate.HasValue || percent.HasValue)
{
- ApiEntryPoint.Instance.ReportTranscodingProgress(transcodingJob, state, transcodingPosition, framerate, percent, bytesTranscoded);
+ ApiEntryPoint.Instance.ReportTranscodingProgress(transcodingJob, state, transcodingPosition, framerate, percent, bytesTranscoded, bitRate);
}
}
@@ -2197,6 +2225,121 @@ namespace MediaBrowser.Api.Playback
}
}
+ private async void ReportUsage(StreamState state)
+ {
+ try
+ {
+ await ReportUsageInternal(state).ConfigureAwait(false);
+ }
+ catch
+ {
+
+ }
+ }
+
+ private Task ReportUsageInternal(StreamState state)
+ {
+ if (!ServerConfigurationManager.Configuration.EnableAnonymousUsageReporting)
+ {
+ return Task.FromResult(true);
+ }
+
+ if (!string.Equals(MediaEncoder.EncoderLocationType, "Default", StringComparison.OrdinalIgnoreCase))
+ {
+ return Task.FromResult(true);
+ }
+
+ var dict = new Dictionary();
+
+ var outputAudio = GetAudioEncoder(state);
+ if (!string.IsNullOrWhiteSpace(outputAudio))
+ {
+ dict["outputAudio"] = outputAudio;
+ }
+
+ var outputVideo = GetVideoEncoder(state);
+ if (!string.IsNullOrWhiteSpace(outputVideo))
+ {
+ dict["outputVideo"] = outputVideo;
+ }
+
+ if (ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase) &&
+ ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ {
+ return Task.FromResult(true);
+ }
+
+ dict["id"] = AppHost.SystemId;
+ dict["type"] = state.VideoRequest == null ? "Audio" : "Video";
+
+ var audioStream = state.AudioStream;
+ if (audioStream != null && !string.IsNullOrWhiteSpace(audioStream.Codec))
+ {
+ dict["inputAudio"] = audioStream.Codec;
+ }
+
+ var videoStream = state.VideoStream;
+ if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
+ {
+ dict["inputVideo"] = videoStream.Codec;
+ }
+
+ var cert = GetType().Assembly.GetModules().First().GetSignerCertificate();
+ if (cert != null)
+ {
+ dict["assemblySig"] = cert.GetCertHashString();
+ dict["certSubject"] = cert.Subject ?? string.Empty;
+ dict["certIssuer"] = cert.Issuer ?? string.Empty;
+ }
+ else
+ {
+ return Task.FromResult(true);
+ }
+
+ if (state.SupportedAudioCodecs.Count > 0)
+ {
+ dict["supportedAudioCodecs"] = string.Join(",", state.SupportedAudioCodecs.ToArray());
+ }
+
+ var auth = AuthorizationContext.GetAuthorizationInfo(Request);
+
+ dict["appName"] = auth.Client ?? string.Empty;
+ dict["appVersion"] = auth.Version ?? string.Empty;
+ dict["device"] = auth.Device ?? string.Empty;
+ dict["deviceId"] = auth.DeviceId ?? string.Empty;
+ dict["context"] = "streaming";
+
+ //Logger.Info(JsonSerializer.SerializeToString(dict));
+ if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ {
+ var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
+ list.Add(outputAudio);
+ ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
+ }
+
+ if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ {
+ var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
+ list.Add(outputVideo);
+ ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
+ }
+
+ ServerConfigurationManager.SaveConfiguration();
+
+ //Logger.Info(JsonSerializer.SerializeToString(dict));
+ var options = new HttpRequestOptions()
+ {
+ Url = "https://mb3admin.com/admin/service/transcoding/report",
+ CancellationToken = CancellationToken.None,
+ LogRequest = false,
+ LogErrors = false
+ };
+ options.RequestContent = JsonSerializer.SerializeToString(dict);
+ options.RequestContentType = "application/json";
+
+ return HttpClient.Post(options);
+ }
+
///
/// Adds the dlna headers.
///
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index edfec902b8..87937869d5 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -171,8 +171,10 @@ namespace MediaBrowser.Controller.Persistence
QueryResult> GetAlbumArtists(InternalItemsQuery query);
QueryResult> GetAllArtists(InternalItemsQuery query);
+ List GetGameGenreNames();
+ List GetMusicGenreNames();
List GetStudioNames();
-
+ List GetGenreNames();
List GetAllArtistNames();
}
}
diff --git a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
index 76797c0e3a..e4f6d337fe 100644
--- a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
@@ -65,14 +65,26 @@ namespace MediaBrowser.Dlna.Profiles
{
new DirectPlayProfile
{
- Container = "mp3,wma",
- Type = DlnaProfileType.Audio
+ Container = "m4v,ts,mkv,avi,mpg,mpeg,mp4",
+ VideoCodec = "h264",
+ AudioCodec = "aac,mp3,ac3",
+ Type = DlnaProfileType.Video
},
new DirectPlayProfile
{
- Container = "avi,mp4",
- Type = DlnaProfileType.Video
+ Container = "mp3,wma,aac,wav",
+ Type = DlnaProfileType.Audio
+ }
+ };
+
+ ResponseProfiles = new[]
+ {
+ new ResponseProfile
+ {
+ Container = "m4v",
+ Type = DlnaProfileType.Video,
+ MimeType = "video/mp4"
}
};
}
diff --git a/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs b/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs
index f8451bdfd8..fb498c4ce4 100644
--- a/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs
@@ -24,6 +24,8 @@ namespace MediaBrowser.Dlna.Profiles
Type = DlnaProfileType.Audio
},
};
+
+ ResponseProfiles = new ResponseProfile[] { };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs b/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs
index 585f8652e6..c2a007a31a 100644
--- a/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs
@@ -112,6 +112,8 @@ namespace MediaBrowser.Dlna.Profiles
}
}
};
+
+ ResponseProfiles = new ResponseProfile[] { };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs b/MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs
index 45cbbef6cb..2c1919c00e 100644
--- a/MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs
+++ b/MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs
@@ -11,7 +11,7 @@ namespace MediaBrowser.Dlna.Profiles
Name = "foobar2000";
SupportedMediaTypes = "Audio";
-
+
Identification = new DeviceIdentification
{
FriendlyName = @"foobar",
@@ -70,6 +70,8 @@ namespace MediaBrowser.Dlna.Profiles
Type = DlnaProfileType.Audio
}
};
+
+ ResponseProfiles = new ResponseProfile[] { };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/LgTvProfile.cs b/MediaBrowser.Dlna/Profiles/LgTvProfile.cs
index ab9a6a51ff..af81fabe43 100644
--- a/MediaBrowser.Dlna/Profiles/LgTvProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/LgTvProfile.cs
@@ -198,6 +198,8 @@ namespace MediaBrowser.Dlna.Profiles
Method = SubtitleDeliveryMethod.External
}
};
+
+ ResponseProfiles = new ResponseProfile[] { };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs b/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs
index da00d9e86e..2488cf5423 100644
--- a/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs
+++ b/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs
@@ -30,6 +30,8 @@ namespace MediaBrowser.Dlna.Profiles
Type = DlnaProfileType.Video
}
};
+
+ ResponseProfiles = new ResponseProfile[] { };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/MediaMonkeyProfile.cs b/MediaBrowser.Dlna/Profiles/MediaMonkeyProfile.cs
index 7163252db2..eef847852d 100644
--- a/MediaBrowser.Dlna/Profiles/MediaMonkeyProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/MediaMonkeyProfile.cs
@@ -70,6 +70,8 @@ namespace MediaBrowser.Dlna.Profiles
Type = DlnaProfileType.Audio
}
};
+
+ ResponseProfiles = new ResponseProfile[] { };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs b/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs
index c98609393a..0e1210afbb 100644
--- a/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs
@@ -200,6 +200,8 @@ namespace MediaBrowser.Dlna.Profiles
}
}
};
+
+ ResponseProfiles = new ResponseProfile[] { };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs
index dbade81705..cfc793c01e 100644
--- a/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs
+++ b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs
@@ -181,6 +181,8 @@ namespace MediaBrowser.Dlna.Profiles
}
}
};
+
+ ResponseProfiles = new ResponseProfile[] { };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Default.xml b/MediaBrowser.Dlna/Profiles/Xml/Default.xml
index 8fae686325..732b5baded 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Default.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Default.xml
@@ -29,8 +29,8 @@
false
-
-
+
+
@@ -39,6 +39,10 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs
index cd1575fa58..f42582270f 100644
--- a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs
@@ -51,7 +51,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
var metadata = string.Empty;
var vn = string.Empty;
- if (!string.IsNullOrWhiteSpace(state.AlbumCoverPath))
+ var hasArt = !string.IsNullOrWhiteSpace(state.AlbumCoverPath);
+ hasArt = false;
+
+ if (hasArt)
{
albumCoverInput = " -i \"" + state.AlbumCoverPath + "\"";
mapArgs = " -map 0:a -map 1:v -c:v copy";
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index e90f6bdc36..f488be11a7 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -123,10 +123,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
return "System";
}
+ if (IsDefaultPath(FFMpegPath))
+ {
+ return "Default";
+ }
+
return "Custom";
}
}
+ private bool IsDefaultPath(string path)
+ {
+ var parentPath = Path.Combine(ConfigurationManager.ApplicationPaths.ProgramDataPath, "ffmpeg", "20160410");
+
+ return FileSystem.ContainsSubPath(parentPath, path);
+ }
+
private bool IsSystemInstalledPath(string path)
{
if (path.IndexOf("/", StringComparison.Ordinal) == -1 && path.IndexOf("\\", StringComparison.Ordinal) == -1)
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 303ba1acf7..63d452bcee 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -202,6 +202,7 @@ namespace MediaBrowser.Model.Configuration
public bool DisplaySpecialsWithinSeasons { get; set; }
public bool DisplayCollectionsView { get; set; }
public string[] LocalNetworkAddresses { get; set; }
+ public string[] CodecsUsed { get; set; }
///
/// Initializes a new instance of the class.
@@ -210,6 +211,7 @@ namespace MediaBrowser.Model.Configuration
{
LocalNetworkAddresses = new string[] { };
Migrations = new string[] { };
+ CodecsUsed = new string[] { };
SqliteCacheSize = 0;
EnableLocalizedGuids = true;
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
index 2109f8d59e..39992b65dd 100644
--- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
+++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
@@ -43,13 +43,6 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_providerManager = providerManager;
}
- public Task OrganizeEpisodeFile(string path, CancellationToken cancellationToken)
- {
- var options = _config.GetAutoOrganizeOptions();
-
- return OrganizeEpisodeFile(path, options, false, cancellationToken);
- }
-
public async Task OrganizeEpisodeFile(string path, AutoOrganizeOptions options, bool overwriteExisting, CancellationToken cancellationToken)
{
_logger.Info("Sorting file {0}", path);
@@ -63,6 +56,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
FileSize = new FileInfo(path).Length
};
+ try
+ {
if (_libraryMonitor.IsPathLocked(path))
{
result.Status = FileSortingStatus.Failure;
@@ -148,6 +143,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
}
await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ result.Status = FileSortingStatus.Failure;
+ result.StatusMessage = ex.Message;
+ }
return result;
}
@@ -156,6 +157,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
var result = _organizationService.GetResult(request.ResultId);
+ try
+ {
Series series = null;
if (request.NewSeriesProviderIds.Count > 0)
@@ -207,6 +210,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
cancellationToken).ConfigureAwait(false);
await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ result.Status = FileSortingStatus.Failure;
+ result.StatusMessage = ex.Message;
+ }
return result;
}
@@ -263,16 +272,15 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var originalExtractedSeriesString = result.ExtractedName;
+ try
+ {
// Proceed to sort the file
var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options.TvOptions, cancellationToken).ConfigureAwait(false);
if (string.IsNullOrEmpty(newPath))
{
var msg = string.Format("Unable to sort {0} because target path could not be determined.", sourcePath);
- result.Status = FileSortingStatus.Failure;
- result.StatusMessage = msg;
- _logger.Warn(msg);
- return;
+ throw new Exception(msg);
}
_logger.Info("Sorting file {0} to new path {1}", sourcePath, newPath);
@@ -347,6 +355,14 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
}
}
}
+ }
+ catch (Exception ex)
+ {
+ result.Status = FileSortingStatus.Failure;
+ result.StatusMessage = ex.Message;
+ _logger.Warn(ex.Message);
+ return;
+ }
if (rememberCorrection)
{
@@ -505,7 +521,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
}
catch (Exception ex)
{
- var errorMsg = string.Format("Failed to move file from {0} to {1}", result.OriginalPath, result.TargetPath);
+ var errorMsg = string.Format("Failed to move file from {0} to {1}: {2}", result.OriginalPath, result.TargetPath, ex.Message);
result.Status = FileSortingStatus.Failure;
result.StatusMessage = errorMsg;
@@ -616,7 +632,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber);
_logger.Warn(msg);
- return null;
+ throw new Exception(msg);
}
var episodeName = episode.Name;
@@ -715,6 +731,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var pattern = endingEpisodeNumber.HasValue ? options.MultiEpisodeNamePattern : options.EpisodeNamePattern;
+ if (string.IsNullOrWhiteSpace(pattern))
+ {
+ throw new Exception("GetEpisodeFileName: Configured episode name pattern is empty!");
+ }
+
var result = pattern.Replace("%sn", seriesName)
.Replace("%s.n", seriesName.Replace(" ", "."))
.Replace("%s_n", seriesName.Replace(" ", "_"))
@@ -759,8 +780,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
// There may be cases where reducing the title length may still not be sufficient to
// stay below maxLength
var msg = string.Format("Unable to generate an episode file name shorter than {0} characters to constrain to the max path limit", maxLength);
- _logger.Warn(msg);
- return string.Empty;
+ throw new Exception(msg);
}
return result;
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs
index 60d515e120..9e16613e62 100644
--- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs
+++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs
@@ -112,8 +112,13 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor, _providerManager);
- await organizer.OrganizeEpisodeFile(result.OriginalPath, GetAutoOrganizeOptions(), true, CancellationToken.None)
+ var organizeResult = await organizer.OrganizeEpisodeFile(result.OriginalPath, GetAutoOrganizeOptions(), true, CancellationToken.None)
.ConfigureAwait(false);
+
+ if (organizeResult.Status != FileSortingStatus.Success)
+ {
+ throw new Exception(result.StatusMessage);
+ }
}
public Task ClearLog()
@@ -126,7 +131,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor, _providerManager);
- await organizer.OrganizeWithCorrection(request, GetAutoOrganizeOptions(), CancellationToken.None).ConfigureAwait(false);
+ var result = await organizer.OrganizeWithCorrection(request, GetAutoOrganizeOptions(), CancellationToken.None).ConfigureAwait(false);
+
+ if (result.Status != FileSortingStatus.Success)
+ {
+ throw new Exception(result.StatusMessage);
+ }
}
public QueryResult GetSmartMatchInfos(FileOrganizationResultQuery query)
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs
index 8be2e436fe..f3891180e2 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Persistence;
namespace MediaBrowser.Server.Implementations.Library.Validators
{
@@ -16,16 +17,18 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
///
private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger;
+ private readonly IItemRepository _itemRepo;
///
/// Initializes a new instance of the class.
///
/// The library manager.
/// The logger.
- public GameGenresPostScanTask(ILibraryManager libraryManager, ILogger logger)
+ public GameGenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_logger = logger;
+ _itemRepo = itemRepo;
}
///
@@ -36,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// Task.
public Task Run(IProgress progress, CancellationToken cancellationToken)
{
- return new GameGenresValidator(_libraryManager, _logger).Run(progress, cancellationToken);
+ return new GameGenresValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs
index 72864790b8..b06c0b3b9b 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs
@@ -5,6 +5,7 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Persistence;
namespace MediaBrowser.Server.Implementations.Library.Validators
{
@@ -19,11 +20,13 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// The _logger
///
private readonly ILogger _logger;
+ private readonly IItemRepository _itemRepo;
- public GameGenresValidator(ILibraryManager libraryManager, ILogger logger)
+ public GameGenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_logger = logger;
+ _itemRepo = itemRepo;
}
///
@@ -34,21 +37,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// Task.
public async Task Run(IProgress progress, CancellationToken cancellationToken)
{
- var items = _libraryManager.GetGameGenres(new InternalItemsQuery
- {
- IncludeItemTypes = new[] { typeof(Game).Name }
- })
- .Items
- .Select(i => i.Item1)
- .ToList();
+ var names = _itemRepo.GetGameGenreNames();
var numComplete = 0;
- var count = items.Count;
+ var count = names.Count;
- foreach (var item in items)
+ foreach (var name in names)
{
try
{
+ var item = _libraryManager.GetGameGenre(name);
+
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
@@ -58,7 +57,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
}
catch (Exception ex)
{
- _logger.ErrorException("Error refreshing {0}", ex, item.Name);
+ _logger.ErrorException("Error refreshing {0}", ex, name);
}
numComplete++;
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs
index a1c34676c8..ed2429769c 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs
@@ -2,6 +2,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Logging;
namespace MediaBrowser.Server.Implementations.Library.Validators
@@ -13,16 +14,18 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
///
private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger;
+ private readonly IItemRepository _itemRepo;
///
/// Initializes a new instance of the class.
///
/// The library manager.
/// The logger.
- public GenresPostScanTask(ILibraryManager libraryManager, ILogger logger)
+ public GenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_logger = logger;
+ _itemRepo = itemRepo;
}
///
@@ -33,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// Task.
public Task Run(IProgress progress, CancellationToken cancellationToken)
{
- return new GenresValidator(_libraryManager, _logger).Run(progress, cancellationToken);
+ return new GenresValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs
index 6a62d7fe47..f35bb51363 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs
@@ -6,6 +6,7 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Persistence;
namespace MediaBrowser.Server.Implementations.Library.Validators
{
@@ -15,16 +16,18 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// The _library manager
///
private readonly ILibraryManager _libraryManager;
+ private readonly IItemRepository _itemRepo;
///
/// The _logger
///
private readonly ILogger _logger;
- public GenresValidator(ILibraryManager libraryManager, ILogger logger)
+ public GenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_logger = logger;
+ _itemRepo = itemRepo;
}
///
@@ -35,21 +38,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// Task.
public async Task Run(IProgress progress, CancellationToken cancellationToken)
{
- var items = _libraryManager.GetGenres(new InternalItemsQuery
- {
- ExcludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicArtist).Name, typeof(MusicAlbum).Name, typeof(MusicVideo).Name, typeof(Game).Name }
- })
- .Items
- .Select(i => i.Item1)
- .ToList();
+ var names = _itemRepo.GetGenreNames();
var numComplete = 0;
- var count = items.Count;
+ var count = names.Count;
- foreach (var item in items)
+ foreach (var name in names)
{
try
{
+ var item = _libraryManager.GetGenre(name);
+
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
@@ -59,7 +58,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
}
catch (Exception ex)
{
- _logger.ErrorException("Error refreshing {0}", ex, item.Name);
+ _logger.ErrorException("Error refreshing {0}", ex, name);
}
numComplete++;
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs
index dbcab0832a..777532ff87 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Persistence;
namespace MediaBrowser.Server.Implementations.Library.Validators
{
@@ -16,16 +17,18 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
///
private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger;
+ private readonly IItemRepository _itemRepo;
///
/// Initializes a new instance of the class.
///
/// The library manager.
/// The logger.
- public MusicGenresPostScanTask(ILibraryManager libraryManager, ILogger logger)
+ public MusicGenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_logger = logger;
+ _itemRepo = itemRepo;
}
///
@@ -36,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// Task.
public Task Run(IProgress progress, CancellationToken cancellationToken)
{
- return new MusicGenresValidator(_libraryManager, _logger).Run(progress, cancellationToken);
+ return new MusicGenresValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs
index 2668d84e95..2be99f106e 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs
@@ -6,6 +6,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Persistence;
namespace MediaBrowser.Server.Implementations.Library.Validators
{
@@ -20,11 +21,13 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// The _logger
///
private readonly ILogger _logger;
+ private readonly IItemRepository _itemRepo;
- public MusicGenresValidator(ILibraryManager libraryManager, ILogger logger)
+ public MusicGenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_logger = logger;
+ _itemRepo = itemRepo;
}
///
@@ -35,21 +38,17 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// Task.
public async Task Run(IProgress progress, CancellationToken cancellationToken)
{
- var items = _libraryManager.GetMusicGenres(new InternalItemsQuery
- {
- IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicArtist).Name, typeof(MusicAlbum).Name, typeof(MusicVideo).Name }
- })
- .Items
- .Select(i => i.Item1)
- .ToList();
+ var names = _itemRepo.GetMusicGenreNames();
var numComplete = 0;
- var count = items.Count;
+ var count = names.Count;
- foreach (var item in items)
+ foreach (var name in names)
{
try
{
+ var item = _libraryManager.GetMusicGenre(name);
+
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
@@ -59,7 +58,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
}
catch (Exception ex)
{
- _logger.ErrorException("Error refreshing {0}", ex, item.Name);
+ _logger.ErrorException("Error refreshing {0}", ex, name);
}
numComplete++;
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 3d8e7a3d6d..6acb0783eb 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -1139,7 +1139,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
var organize = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager);
- var result = await organize.OrganizeEpisodeFile(path, CancellationToken.None).ConfigureAwait(false);
+ var result = await organize.OrganizeEpisodeFile(path, _config.GetAutoOrganizeOptions(), false, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 442465430d..7fa9ee32c2 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -46,7 +46,7 @@
..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll
- ..\packages\Emby.XmlTv.1.0.0.55\lib\net45\Emby.XmlTv.dll
+ ..\packages\Emby.XmlTv.1.0.0.56\lib\net45\Emby.XmlTv.dll
True
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
index 2ac625ebc7..c3eee6d354 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
@@ -3882,18 +3882,36 @@ namespace MediaBrowser.Server.Implementations.Persistence
public List GetStudioNames()
{
- return GetItemValueNames(new[] { 3 });
+ return GetItemValueNames(new[] { 3 }, new List(), new List());
}
public List GetAllArtistNames()
{
- return GetItemValueNames(new[] { 0, 1 });
+ return GetItemValueNames(new[] { 0, 1 }, new List(), new List());
}
- private List GetItemValueNames(int[] itemValueTypes)
+ public List GetMusicGenreNames()
+ {
+ return GetItemValueNames(new[] { 2 }, new List { "Audio", "MusicVideo", "MusicAlbum", "MusicArtist" }, new List());
+ }
+
+ public List GetGameGenreNames()
+ {
+ return GetItemValueNames(new[] { 2 }, new List { "Game" }, new List());
+ }
+
+ public List GetGenreNames()
+ {
+ return GetItemValueNames(new[] { 2 }, new List(), new List { "Audio", "MusicVideo", "MusicAlbum", "MusicArtist", "Game", "GameSystem" });
+ }
+
+ private List GetItemValueNames(int[] itemValueTypes, List withItemTypes, List excludeItemTypes)
{
CheckDisposed();
+ withItemTypes = withItemTypes.SelectMany(MapIncludeItemTypes).ToList();
+ excludeItemTypes = excludeItemTypes.SelectMany(MapIncludeItemTypes).ToList();
+
var now = DateTime.UtcNow;
var typeClause = itemValueTypes.Length == 1 ?
@@ -3904,7 +3922,20 @@ namespace MediaBrowser.Server.Implementations.Persistence
using (var cmd = _connection.CreateCommand())
{
- cmd.CommandText = "Select Value From ItemValues where " + typeClause + " Group By CleanValue";
+ cmd.CommandText = "Select Value From ItemValues where " + typeClause;
+
+ if (withItemTypes.Count > 0)
+ {
+ var typeString = string.Join(",", withItemTypes.Select(i => "'" + i + "'").ToArray());
+ cmd.CommandText += " AND ItemId In (select guid from typedbaseitems where type in (" + typeString + "))";
+ }
+ if (excludeItemTypes.Count > 0)
+ {
+ var typeString = string.Join(",", excludeItemTypes.Select(i => "'" + i + "'").ToArray());
+ cmd.CommandText += " AND ItemId not In (select guid from typedbaseitems where type in (" + typeString + "))";
+ }
+
+ cmd.CommandText += " Group By CleanValue";
var commandBehavior = CommandBehavior.SequentialAccess | CommandBehavior.SingleResult;
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index bac5a7c5d0..746dc7f62e 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -1,7 +1,7 @@
-
+
diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
index 9eb8a47366..8cb1d4f0db 100644
--- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
+++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
@@ -101,6 +101,7 @@ using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Api.Playback;
using MediaBrowser.Common.Implementations.Updates;
namespace MediaBrowser.Server.Startup.Common
@@ -766,6 +767,8 @@ namespace MediaBrowser.Server.Startup.Common
BaseItem.CollectionManager = CollectionManager;
BaseItem.MediaSourceManager = MediaSourceManager;
CollectionFolder.XmlSerializer = XmlSerializer;
+ BaseStreamingService.AppHost = this;
+ BaseStreamingService.HttpClient = HttpClient;
}
///