Browse Source

Merge pull request #2695 from MediaBrowser/dev

Dev
Luke 8 years ago
parent
commit
1b0f6f6c56

+ 1 - 1
Emby.Drawing.ImageMagick/ImageMagickEncoder.cs

@@ -130,7 +130,7 @@ namespace Emby.Drawing.ImageMagick
                 string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase);
         }
 
-        public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
+        public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
         {
             // Even if the caller specified 100, don't use it because it takes forever
             quality = Math.Min(quality, 99);

+ 112 - 9
Emby.Drawing.Skia/SkiaEncoder.cs

@@ -184,7 +184,7 @@ namespace Emby.Drawing.Skia
         }
 
         private string[] TransparentImageTypes = new string[] { ".png", ".gif", ".webp" };
-        private SKBitmap Decode(string path, bool forceCleanBitmap = false)
+        private SKBitmap Decode(string path, bool forceCleanBitmap, out SKCodecOrigin origin)
         {
             var requiresTransparencyHack = TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty);
 
@@ -199,6 +199,8 @@ namespace Emby.Drawing.Skia
                     // decode
                     codec.GetPixels(bitmap.Info, bitmap.GetPixels());
 
+                    origin = codec.Origin;
+
                     return bitmap;
                 }
             }
@@ -207,7 +209,7 @@ namespace Emby.Drawing.Skia
 
             if (resultBitmap == null)
             {
-                return Decode(path, true);
+                return Decode(path, true, out origin);
             }
 
             // If we have to resize these they often end up distorted
@@ -215,27 +217,128 @@ namespace Emby.Drawing.Skia
             {
                 using (resultBitmap)
                 {
-                    return Decode(path, true);
+                    return Decode(path, true, out origin);
                 }
             }
 
+            origin = SKCodecOrigin.TopLeft;
             return resultBitmap;
         }
 
-        private SKBitmap GetBitmap(string path, bool cropWhitespace)
+        private SKBitmap GetBitmap(string path, bool cropWhitespace, bool forceAnalyzeBitmap, out SKCodecOrigin origin)
         {
             if (cropWhitespace)
             {
-                using (var bitmap = Decode(path))
+                using (var bitmap = Decode(path, forceAnalyzeBitmap, out origin))
                 {
                     return CropWhiteSpace(bitmap);
                 }
             }
 
-            return Decode(path);
+            return Decode(path, forceAnalyzeBitmap, out origin);
+        }
+
+        private SKBitmap GetBitmap(string path, bool cropWhitespace, bool autoOrient, ImageOrientation? orientation)
+        {
+            SKCodecOrigin origin;
+
+            if (autoOrient)
+            {
+                var bitmap = GetBitmap(path, cropWhitespace, true, out origin);
+
+                if (origin != SKCodecOrigin.TopLeft)
+                {
+                    using (bitmap)
+                    {
+                        return RotateAndFlip(bitmap, origin);
+                    }
+                }
+
+                return bitmap;
+            }
+
+            return GetBitmap(path, cropWhitespace, false, out origin);
+        }
+
+        private SKBitmap RotateAndFlip(SKBitmap original, SKCodecOrigin origin)
+        {
+            // these are the origins that represent a 90 degree turn in some fashion
+            var differentOrientations = new SKCodecOrigin[]
+            {
+                SKCodecOrigin.LeftBottom,
+                SKCodecOrigin.LeftTop,
+                SKCodecOrigin.RightBottom,
+                SKCodecOrigin.RightTop
+            };
+
+            // check if we need to turn the image
+            bool isDifferentOrientation = differentOrientations.Any(o => o == origin);
+
+            // define new width/height
+            var width = isDifferentOrientation ? original.Height : original.Width;
+            var height = isDifferentOrientation ? original.Width : original.Height;
+
+            var bitmap = new SKBitmap(width, height, true);
+
+            // todo: the stuff in this switch statement should be rewritten to use pointers
+            switch (origin)
+            {
+                case SKCodecOrigin.LeftBottom:
+
+                    for (var x = 0; x < original.Width; x++)
+                        for (var y = 0; y < original.Height; y++)
+                            bitmap.SetPixel(y, original.Width - 1 - x, original.GetPixel(x, y));
+                    break;
+
+                case SKCodecOrigin.RightTop:
+
+                    for (var x = 0; x < original.Width; x++)
+                        for (var y = 0; y < original.Height; y++)
+                            bitmap.SetPixel(original.Height - 1 - y, x, original.GetPixel(x, y));
+                    break;
+
+                case SKCodecOrigin.RightBottom:
+
+                    for (var x = 0; x < original.Width; x++)
+                        for (var y = 0; y < original.Height; y++)
+                            bitmap.SetPixel(original.Height - 1 - y, original.Width - 1 - x, original.GetPixel(x, y));
+
+                    break;
+
+                case SKCodecOrigin.LeftTop:
+
+                    for (var x = 0; x < original.Width; x++)
+                        for (var y = 0; y < original.Height; y++)
+                            bitmap.SetPixel(y, x, original.GetPixel(x, y));
+                    break;
+
+                case SKCodecOrigin.BottomLeft:
+
+                    for (var x = 0; x < original.Width; x++)
+                        for (var y = 0; y < original.Height; y++)
+                            bitmap.SetPixel(x, original.Height - 1 - y, original.GetPixel(x, y));
+                    break;
+
+                case SKCodecOrigin.BottomRight:
+
+                    for (var x = 0; x < original.Width; x++)
+                        for (var y = 0; y < original.Height; y++)
+                            bitmap.SetPixel(original.Width - 1 - x, original.Height - 1 - y, original.GetPixel(x, y));
+                    break;
+
+                case SKCodecOrigin.TopRight:
+
+                    for (var x = 0; x < original.Width; x++)
+                        for (var y = 0; y < original.Height; y++)
+                            bitmap.SetPixel(original.Width - 1 - x, y, original.GetPixel(x, y));
+                    break;
+
+            }
+
+            return bitmap;
         }
 
-        public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
+        public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
         {
             if (string.IsNullOrWhiteSpace(inputPath))
             {
@@ -253,7 +356,7 @@ namespace Emby.Drawing.Skia
             var blur = options.Blur ?? 0;
             var hasIndicator = options.AddPlayedIndicator || options.UnplayedCount.HasValue || !options.PercentPlayed.Equals(0);
 
-            using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace))
+            using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace, autoOrient, orientation))
             {
                 if (bitmap == null)
                 {
@@ -265,7 +368,7 @@ namespace Emby.Drawing.Skia
                 var originalImageSize = new ImageSize(bitmap.Width, bitmap.Height);
                 ImageHelper.SaveImageSize(inputPath, dateModified, originalImageSize);
 
-                if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize))
+                if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize) && !autoOrient)
                 {
                     // Just spit out the original file if all the options are default
                     return inputPath;

+ 13 - 15
Emby.Drawing/ImageProcessor.cs

@@ -217,14 +217,23 @@ namespace Emby.Drawing
                 dateModified = tuple.Item2;
             }
 
-            if (options.HasDefaultOptions(originalImagePath))
+            var photo = item as Photo;
+            var autoOrient = false;
+            ImageOrientation? orientation = null;
+            if (photo != null && photo.Orientation.HasValue && photo.Orientation.Value != ImageOrientation.TopLeft)
+            {
+                autoOrient = true;
+                orientation = photo.Orientation;
+            }
+
+            if (options.HasDefaultOptions(originalImagePath) && !autoOrient)
             {
                 // Just spit out the original file if all the options are default
                 return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
             }
 
             ImageSize? originalImageSize = GetSavedImageSize(originalImagePath, dateModified);
-            if (originalImageSize.HasValue && options.HasDefaultOptions(originalImagePath, originalImageSize.Value))
+            if (originalImageSize.HasValue && options.HasDefaultOptions(originalImagePath, originalImageSize.Value) && !autoOrient)
             {
                 // Just spit out the original file if all the options are default
                 _logger.Info("Returning original image {0}", originalImagePath);
@@ -243,7 +252,6 @@ namespace Emby.Drawing
 
                 if (!_fileSystem.FileExists(cacheFilePath))
                 {
-                    _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
                     var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
                     _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
 
@@ -252,13 +260,14 @@ namespace Emby.Drawing
                         item = _libraryManager().GetItemById(options.ItemId);
                     }
 
-                    var resultPath =_imageEncoder.EncodeImage(originalImagePath, dateModified, tmpPath, AutoOrient(item), quality, options, outputFormat);
+                    var resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, tmpPath, autoOrient, orientation, quality, options, outputFormat);
 
                     if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
                     {
                         return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
                     }
 
+                    _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
                     CopyFile(tmpPath, cacheFilePath);
 
                     return new Tuple<string, string, DateTime>(tmpPath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(tmpPath));
@@ -288,17 +297,6 @@ namespace Emby.Drawing
             }
         }
 
-        private bool AutoOrient(IHasImages item)
-        {
-            var photo = item as Photo;
-            if (photo != null && photo.Orientation.HasValue)
-            {
-                return true;
-            }
-
-            return false;
-        }
-
         //private static  int[][] OPERATIONS = new int[][] {
         // TopLeft
         //new int[] {  0, NONE},

+ 1 - 1
Emby.Drawing/NullImageEncoder.cs

@@ -32,7 +32,7 @@ namespace Emby.Drawing
             throw new NotImplementedException();
         }
 
-        public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
+        public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
         {
             throw new NotImplementedException();
         }

+ 2 - 2
Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs

@@ -123,7 +123,7 @@ namespace Emby.Server.Implementations.Activity
                 return;
             }
 
-            if (item.IsThemeMedia)
+            if (e.Item != null && e.Item.IsThemeMedia)
             {
                 // Don't report theme song or local trailer playback
                 return;
@@ -155,7 +155,7 @@ namespace Emby.Server.Implementations.Activity
                 return;
             }
 
-            if (item.IsThemeMedia)
+            if (e.Item != null && e.Item.IsThemeMedia)
             {
                 // Don't report theme song or local trailer playback
                 return;

+ 3 - 2
Emby.Server.Implementations/Notifications/Notifications.cs

@@ -23,6 +23,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Model.Threading;
+using MediaBrowser.Model.Dto;
 
 namespace Emby.Server.Implementations.Notifications
 {
@@ -260,7 +261,7 @@ namespace Emby.Server.Implementations.Notifications
 
             var item = e.MediaInfo;
 
-            if ( item.IsThemeMedia)
+            if (e.Item != null && e.Item.IsThemeMedia)
             {
                 // Don't report theme song or local trailer playback
                 return;
@@ -430,7 +431,7 @@ namespace Emby.Server.Implementations.Notifications
             return name;
         }
 
-        public static string GetItemName(BaseItemInfo item)
+        public static string GetItemName(BaseItemDto item)
         {
             var name = item.Name;
 

+ 50 - 150
Emby.Server.Implementations/Session/SessionManager.cs

@@ -338,7 +338,7 @@ namespace Emby.Server.Implementations.Session
                         }
                     }
 
-                    info.Item = GetItemInfo(libraryItem, libraryItem, mediaSource);
+                    info.Item = GetItemInfo(libraryItem, mediaSource);
 
                     info.Item.RunTimeTicks = runtimeTicks;
                 }
@@ -813,7 +813,7 @@ namespace Emby.Server.Implementations.Session
                         mediaSource = await GetMediaSource(hasMediaSources, info.MediaSourceId, info.LiveStreamId).ConfigureAwait(false);
                     }
 
-                    info.Item = GetItemInfo(libraryItem, libraryItem, mediaSource);
+                    info.Item = GetItemInfo(libraryItem, mediaSource);
                 }
                 else
                 {
@@ -1637,165 +1637,65 @@ namespace Emby.Server.Implementations.Session
             return dto;
         }
 
+        private DtoOptions _itemInfoDtoOptions;
+
         /// <summary>
         /// Converts a BaseItem to a BaseItemInfo
         /// </summary>
-        /// <param name="item">The item.</param>
-        /// <param name="chapterOwner">The chapter owner.</param>
-        /// <param name="mediaSource">The media source.</param>
-        /// <returns>BaseItemInfo.</returns>
-        /// <exception cref="System.ArgumentNullException">item</exception>
-        private BaseItemInfo GetItemInfo(BaseItem item, BaseItem chapterOwner, MediaSourceInfo mediaSource)
+        private BaseItemDto GetItemInfo(BaseItem item, MediaSourceInfo mediaSource)
         {
             if (item == null)
             {
                 throw new ArgumentNullException("item");
             }
 
-            var info = new BaseItemInfo
-            {
-                Id = GetDtoId(item),
-                Name = item.Name,
-                MediaType = item.MediaType,
-                Type = item.GetClientTypeName(),
-                RunTimeTicks = item.RunTimeTicks,
-                IndexNumber = item.IndexNumber,
-                ParentIndexNumber = item.ParentIndexNumber,
-                PremiereDate = item.PremiereDate,
-                ProductionYear = item.ProductionYear,
-                IsThemeMedia = item.IsThemeMedia
-            };
-
-            info.PrimaryImageTag = GetImageCacheTag(item, ImageType.Primary);
-            if (info.PrimaryImageTag != null)
-            {
-                info.PrimaryImageItemId = GetDtoId(item);
-            }
-
-            var episode = item as Episode;
-            if (episode != null)
-            {
-                info.IndexNumberEnd = episode.IndexNumberEnd;
-            }
-
-            var hasSeries = item as IHasSeries;
-            if (hasSeries != null)
-            {
-                info.SeriesName = hasSeries.SeriesName;
-            }
-
-            var recording = item as ILiveTvRecording;
-            if (recording != null)
-            {
-                if (recording.IsSeries)
-                {
-                    info.Name = recording.EpisodeTitle;
-                    info.SeriesName = recording.Name;
-
-                    if (string.IsNullOrWhiteSpace(info.Name))
-                    {
-                        info.Name = recording.Name;
-                    }
-                }
-            }
-
-            var audio = item as Audio;
-            if (audio != null)
-            {
-                info.Album = audio.Album;
-                info.Artists = audio.Artists;
-
-                if (info.PrimaryImageTag == null)
-                {
-                    var album = audio.AlbumEntity;
-
-                    if (album != null && album.HasImage(ImageType.Primary))
-                    {
-                        info.PrimaryImageTag = GetImageCacheTag(album, ImageType.Primary);
-                        if (info.PrimaryImageTag != null)
-                        {
-                            info.PrimaryImageItemId = GetDtoId(album);
-                        }
-                    }
-                }
-            }
-
-            var musicVideo = item as MusicVideo;
-            if (musicVideo != null)
-            {
-                info.Album = musicVideo.Album;
-                info.Artists = musicVideo.Artists.ToList();
-            }
-
-            var backropItem = item.HasImage(ImageType.Backdrop) ? item : null;
-            var thumbItem = item.HasImage(ImageType.Thumb) ? item : null;
-            var logoItem = item.HasImage(ImageType.Logo) ? item : null;
-
-            if (thumbItem == null)
-            {
-                if (episode != null)
-                {
-                    var series = episode.Series;
-
-                    if (series != null && series.HasImage(ImageType.Thumb))
-                    {
-                        thumbItem = series;
-                    }
-                }
-            }
+            var dtoOptions = _itemInfoDtoOptions;
 
-            if (backropItem == null)
+            if (_itemInfoDtoOptions == null)
             {
-                if (episode != null)
+                dtoOptions = new DtoOptions
                 {
-                    var series = episode.Series;
-
-                    if (series != null && series.HasImage(ImageType.Backdrop))
-                    {
-                        backropItem = series;
-                    }
-                }
-            }
-
-            if (backropItem == null)
-            {
-                backropItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Backdrop));
-            }
-
-            if (thumbItem == null)
-            {
-                thumbItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Thumb));
-            }
-
-            if (logoItem == null)
-            {
-                logoItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Logo));
-            }
-
-            if (thumbItem != null)
-            {
-                info.ThumbImageTag = GetImageCacheTag(thumbItem, ImageType.Thumb);
-                info.ThumbItemId = GetDtoId(thumbItem);
-            }
-
-            if (backropItem != null)
-            {
-                info.BackdropImageTag = GetImageCacheTag(backropItem, ImageType.Backdrop);
-                info.BackdropItemId = GetDtoId(backropItem);
-            }
-
-            if (logoItem != null)
-            {
-                info.LogoImageTag = GetImageCacheTag(logoItem, ImageType.Logo);
-                info.LogoItemId = GetDtoId(logoItem);
-            }
-
-            if (chapterOwner != null)
-            {
-                info.ChapterImagesItemId = chapterOwner.Id.ToString("N");
-
-                info.Chapters = _dtoService.GetChapterInfoDtos(chapterOwner).ToList();
-            }
+                    AddProgramRecordingInfo = false
+                };
+
+                dtoOptions.Fields.Remove(ItemFields.BasicSyncInfo);
+                dtoOptions.Fields.Remove(ItemFields.SyncInfo);
+                dtoOptions.Fields.Remove(ItemFields.CanDelete);
+                dtoOptions.Fields.Remove(ItemFields.CanDownload);
+                dtoOptions.Fields.Remove(ItemFields.ChildCount);
+                dtoOptions.Fields.Remove(ItemFields.CustomRating);
+                dtoOptions.Fields.Remove(ItemFields.DateLastMediaAdded);
+                dtoOptions.Fields.Remove(ItemFields.DateLastRefreshed);
+                dtoOptions.Fields.Remove(ItemFields.DateLastSaved);
+                dtoOptions.Fields.Remove(ItemFields.DisplayMediaType);
+                dtoOptions.Fields.Remove(ItemFields.DisplayPreferencesId);
+                dtoOptions.Fields.Remove(ItemFields.Etag);
+                dtoOptions.Fields.Remove(ItemFields.ExternalEtag);
+                dtoOptions.Fields.Remove(ItemFields.IndexOptions);
+                dtoOptions.Fields.Remove(ItemFields.InheritedParentalRatingValue);
+                dtoOptions.Fields.Remove(ItemFields.ItemCounts);
+                dtoOptions.Fields.Remove(ItemFields.Keywords);
+                dtoOptions.Fields.Remove(ItemFields.MediaSourceCount);
+                dtoOptions.Fields.Remove(ItemFields.MediaStreams);
+                dtoOptions.Fields.Remove(ItemFields.MediaSources);
+                dtoOptions.Fields.Remove(ItemFields.People);
+                dtoOptions.Fields.Remove(ItemFields.PlayAccess);
+                dtoOptions.Fields.Remove(ItemFields.People);
+                dtoOptions.Fields.Remove(ItemFields.ProductionLocations);
+                dtoOptions.Fields.Remove(ItemFields.RecursiveItemCount);
+                dtoOptions.Fields.Remove(ItemFields.RemoteTrailers);
+                dtoOptions.Fields.Remove(ItemFields.SeasonUserData);
+                dtoOptions.Fields.Remove(ItemFields.SeriesGenres);
+                dtoOptions.Fields.Remove(ItemFields.Settings);
+                dtoOptions.Fields.Remove(ItemFields.SortName);
+                dtoOptions.Fields.Remove(ItemFields.Tags);
+                dtoOptions.Fields.Remove(ItemFields.ThemeSongIds);
+                dtoOptions.Fields.Remove(ItemFields.ThemeVideoIds);
+
+                _itemInfoDtoOptions = dtoOptions;
+            }
+
+            var info = _dtoService.GetBaseItemDto(item, dtoOptions);
 
             if (mediaSource != null)
             {
@@ -1837,7 +1737,7 @@ namespace Emby.Server.Implementations.Session
             //ReportNowViewingItem(sessionId, info);
         }
 
-        public void ReportNowViewingItem(string sessionId, BaseItemInfo item)
+        public void ReportNowViewingItem(string sessionId, BaseItemDto item)
         {
             //var session = GetSession(sessionId);
 

+ 2 - 21
MediaBrowser.Api/Session/SessionsService.cs

@@ -98,7 +98,7 @@ namespace MediaBrowser.Api.Session
 
     [Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")]
     [Authenticated]
-    public class SendPlaystateCommand : IReturnVoid
+    public class SendPlaystateCommand : PlaystateRequest, IReturnVoid
     {
         /// <summary>
         /// Gets or sets the id.
@@ -106,19 +106,6 @@ namespace MediaBrowser.Api.Session
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
         public string Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the position to seek to
-        /// </summary>
-        [ApiMember(Name = "SeekPositionTicks", Description = "The position to seek to.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public long? SeekPositionTicks { get; set; }
-
-        /// <summary>
-        /// Gets or sets the play command.
-        /// </summary>
-        /// <value>The play command.</value>
-        [ApiMember(Name = "Command", Description = "The command to send - stop, pause, unpause, nexttrack, previoustrack, seek, fullscreen.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public PlaystateCommand Command { get; set; }
     }
 
     [Route("/Sessions/{Id}/System/{Command}", "POST", Summary = "Issues a system command to a client")]
@@ -414,13 +401,7 @@ namespace MediaBrowser.Api.Session
 
         public void Post(SendPlaystateCommand request)
         {
-            var command = new PlaystateRequest
-            {
-                Command = request.Command,
-                SeekPositionTicks = request.SeekPositionTicks
-            };
-
-            var task = _sessionManager.SendPlaystateCommand(GetSession(_sessionContext).Result.Id, request.Id, command, CancellationToken.None);
+            var task = _sessionManager.SendPlaystateCommand(GetSession(_sessionContext).Result.Id, request.Id, request, CancellationToken.None);
 
             Task.WaitAll(task);
         }

+ 1 - 1
MediaBrowser.Controller/Drawing/IImageEncoder.cs

@@ -19,7 +19,7 @@ namespace MediaBrowser.Controller.Drawing
         /// <summary>
         /// Encodes the image.
         /// </summary>
-        string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
+        string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
 
         /// <summary>
         /// Creates the image collage.

+ 2 - 0
MediaBrowser.Controller/Entities/InternalItemsQuery.cs

@@ -149,6 +149,7 @@ namespace MediaBrowser.Controller.Entities
 
         public string[] PresetViews { get; set; }
         public TrailerType[] TrailerTypes { get; set; }
+        public SourceType[] SourceTypes { get; set; }
 
         public DayOfWeek[] AirDays { get; set; }
         public SeriesStatus[] SeriesStatuses { get; set; }
@@ -214,6 +215,7 @@ namespace MediaBrowser.Controller.Entities
             ExcludeInheritedTags = new string[] { };
             PresetViews = new string[] { };
             TrailerTypes = new TrailerType[] { };
+            SourceTypes = new SourceType[] { };
             AirDays = new DayOfWeek[] { };
             SeriesStatuses = new SeriesStatus[] { };
             OrderBy = new List<Tuple<string, SortOrder>>();

+ 2 - 2
MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs

@@ -1,5 +1,5 @@
 using MediaBrowser.Controller.Entities;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Dto;
 using System;
 using System.Collections.Generic;
 
@@ -13,7 +13,7 @@ namespace MediaBrowser.Controller.Library
         public List<User> Users { get; set; }
         public long? PlaybackPositionTicks { get; set; }
         public BaseItem Item { get; set; }
-        public BaseItemInfo MediaInfo { get; set; }
+        public BaseItemDto MediaInfo { get; set; }
         public string MediaSourceId { get; set; }
         public bool IsPaused { get; set; }
         public bool IsAutomated { get; set; }

+ 1 - 1
MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs

@@ -1604,7 +1604,7 @@ namespace MediaBrowser.Controller.MediaEncoding
                 }
 
                 // Only do this for video files due to sometimes unpredictable codec names coming from BDInfo
-                if (state.VideoType == VideoType.VideoFile && string.IsNullOrWhiteSpace(encodingOptions.HardwareAccelerationType))
+                if (state.VideoType == VideoType.VideoFile && state.RunTimeTicks.HasValue && string.IsNullOrWhiteSpace(encodingOptions.HardwareAccelerationType))
                 {
                     foreach (var stream in state.MediaSource.MediaStreams)
                     {

+ 2 - 2
MediaBrowser.Controller/Session/ISessionManager.cs

@@ -1,7 +1,7 @@
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Security;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Events;
 using MediaBrowser.Model.Session;
 using MediaBrowser.Model.Users;
@@ -249,7 +249,7 @@ namespace MediaBrowser.Controller.Session
         /// </summary>
         /// <param name="sessionId">The session identifier.</param>
         /// <param name="item">The item.</param>
-        void ReportNowViewingItem(string sessionId, BaseItemInfo item);
+        void ReportNowViewingItem(string sessionId, BaseItemDto item);
 
         /// <summary>
         /// Authenticates the new session.

+ 3 - 3
MediaBrowser.Controller/Session/SessionInfo.cs

@@ -1,4 +1,4 @@
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Session;
 using System;
 using System.Collections.Generic;
@@ -100,13 +100,13 @@ namespace MediaBrowser.Controller.Session
         /// Gets or sets the name of the now viewing item.
         /// </summary>
         /// <value>The name of the now viewing item.</value>
-        public BaseItemInfo NowViewingItem { get; set; }
+        public BaseItemDto NowViewingItem { get; set; }
 
         /// <summary>
         /// Gets or sets the now playing item.
         /// </summary>
         /// <value>The now playing item.</value>
-        public BaseItemInfo NowPlayingItem { get; set; }
+        public BaseItemDto NowPlayingItem { get; set; }
 
         public BaseItem FullNowPlayingItem { get; set; }
 

+ 9 - 2
MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs

@@ -17,9 +17,16 @@ namespace MediaBrowser.LocalMetadata.Parsers
             {
                 case "CollectionItems":
 
-                    using (var subReader = reader.ReadSubtree())
+                    if (!reader.IsEmptyElement)
                     {
-                        FetchFromCollectionItemsNode(subReader, item);
+                        using (var subReader = reader.ReadSubtree())
+                        {
+                            FetchFromCollectionItemsNode(subReader, item);
+                        }
+                    }
+                    else
+                    {
+                        reader.Read();
                     }
                     break;
 

+ 0 - 178
MediaBrowser.Model/Entities/BaseItemInfo.cs

@@ -1,178 +0,0 @@
-using MediaBrowser.Model.Dto;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using MediaBrowser.Model.Serialization;
-
-namespace MediaBrowser.Model.Entities
-{
-    /// <summary>
-    /// This is a stub class containing only basic information about an item
-    /// </summary>
-    [DebuggerDisplay("Name = {Name}, ID = {Id}, Type = {Type}")]
-    public class BaseItemInfo
-    {
-        /// <summary>
-        /// Gets or sets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        public string Name { get; set; }
-
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        public string Id { get; set; }
-
-        /// <summary>
-        /// Gets or sets the type.
-        /// </summary>
-        /// <value>The type.</value>
-        public string Type { get; set; }
-
-        /// <summary>
-        /// Gets or sets the type of the media.
-        /// </summary>
-        /// <value>The type of the media.</value>
-        public string MediaType { get; set; }
-
-        /// <summary>
-        /// Gets or sets the run time ticks.
-        /// </summary>
-        /// <value>The run time ticks.</value>
-        public long? RunTimeTicks { get; set; }
-
-        /// <summary>
-        /// Gets or sets the primary image tag.
-        /// </summary>
-        /// <value>The primary image tag.</value>
-        public string PrimaryImageTag { 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 logo image tag.
-        /// </summary>
-        /// <value>The logo image tag.</value>
-        public string LogoImageTag { get; set; }
-
-        /// <summary>
-        /// Gets or sets the logo item identifier.
-        /// </summary>
-        /// <value>The logo item identifier.</value>
-        public string LogoItemId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the thumb image tag.
-        /// </summary>
-        /// <value>The thumb image tag.</value>
-        public string ThumbImageTag { get; set; }
-
-        /// <summary>
-        /// Gets or sets the thumb item identifier.
-        /// </summary>
-        /// <value>The thumb item identifier.</value>
-        public string ThumbItemId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the thumb image tag.
-        /// </summary>
-        /// <value>The thumb image tag.</value>
-        public string BackdropImageTag { get; set; }
-
-        /// <summary>
-        /// Gets or sets the thumb item identifier.
-        /// </summary>
-        /// <value>The thumb item identifier.</value>
-        public string BackdropItemId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the premiere date.
-        /// </summary>
-        /// <value>The premiere date.</value>
-        public DateTime? PremiereDate { get; set; }
-
-        /// <summary>
-        /// Gets or sets the production year.
-        /// </summary>
-        /// <value>The production year.</value>
-        public int? ProductionYear { get; set; }
-
-        /// <summary>
-        /// Gets or sets the index number.
-        /// </summary>
-        /// <value>The index number.</value>
-        public int? IndexNumber { get; set; }
-
-        /// <summary>
-        /// Gets or sets the index number end.
-        /// </summary>
-        /// <value>The index number end.</value>
-        public int? IndexNumberEnd { get; set; }
-
-        /// <summary>
-        /// Gets or sets the parent index number.
-        /// </summary>
-        /// <value>The parent index number.</value>
-        public int? ParentIndexNumber { get; set; }
-
-        /// <summary>
-        /// Gets or sets the name of the series.
-        /// </summary>
-        /// <value>The name of the series.</value>
-        public string SeriesName { get; set; }
-
-        /// <summary>
-        /// Gets or sets the album.
-        /// </summary>
-        /// <value>The album.</value>
-        public string Album { get; set; }
-
-        public bool IsThemeMedia { get; set; }
-
-        /// <summary>
-        /// Gets or sets the artists.
-        /// </summary>
-        /// <value>The artists.</value>
-        public List<string> Artists { get; set; }
-
-        /// <summary>
-        /// Gets or sets the media streams.
-        /// </summary>
-        /// <value>The media streams.</value>
-        public List<MediaStream> MediaStreams { get; set; }
-
-        /// <summary>
-        /// Gets or sets the chapter images item identifier.
-        /// </summary>
-        /// <value>The chapter images item identifier.</value>
-        public string ChapterImagesItemId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the chapters.
-        /// </summary>
-        /// <value>The chapters.</value>
-        public List<ChapterInfoDto> Chapters { get; set; }
-
-        /// <summary>
-        /// Gets a value indicating whether this instance has primary image.
-        /// </summary>
-        /// <value><c>true</c> if this instance has primary image; otherwise, <c>false</c>.</value>
-        [IgnoreDataMember]
-        public bool HasPrimaryImage
-        {
-            get { return PrimaryImageTag != null; }
-        }
-
-        public BaseItemInfo()
-        {
-            Artists = new List<string>();
-            MediaStreams = new List<MediaStream>();
-            Chapters = new List<ChapterInfoDto>();
-        }
-    }
-}

+ 0 - 1
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -322,7 +322,6 @@
     <Compile Include="Querying\EpisodeQuery.cs" />
     <Compile Include="Querying\ItemCountsQuery.cs" />
     <Compile Include="Querying\ItemsByNameQuery.cs" />
-    <Compile Include="Entities\BaseItemInfo.cs" />
     <Compile Include="Querying\LatestItemsQuery.cs" />
     <Compile Include="Querying\MovieRecommendationQuery.cs" />
     <Compile Include="Querying\NextUpQuery.cs" />

+ 4 - 2
MediaBrowser.Model/Session/PlaybackProgressInfo.cs

@@ -1,4 +1,4 @@
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Dto;
 
 namespace MediaBrowser.Model.Session
 {
@@ -17,7 +17,7 @@ namespace MediaBrowser.Model.Session
         /// Gets or sets the item.
         /// </summary>
         /// <value>The item.</value>
-        public BaseItemInfo Item { get; set; }
+        public BaseItemDto Item { get; set; }
 
         /// <summary>
         /// Gets or sets the item identifier.
@@ -67,6 +67,8 @@ namespace MediaBrowser.Model.Session
         /// <value>The position ticks.</value>
         public long? PositionTicks { get; set; }
 
+        public long? playbackStartTimeTicks { get; set; }
+
         /// <summary>
         /// Gets or sets the volume level.
         /// </summary>

+ 2 - 2
MediaBrowser.Model/Session/PlaybackStopInfo.cs

@@ -1,4 +1,4 @@
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Dto;
 
 namespace MediaBrowser.Model.Session
 {
@@ -11,7 +11,7 @@ namespace MediaBrowser.Model.Session
         /// Gets or sets the item.
         /// </summary>
         /// <value>The item.</value>
-        public BaseItemInfo Item { get; set; }
+        public BaseItemDto Item { get; set; }
         /// <summary>
         /// Gets or sets the item identifier.
         /// </summary>

+ 3 - 3
MediaBrowser.Model/Session/SessionInfoDto.cs

@@ -1,4 +1,4 @@
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Dto;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
@@ -72,7 +72,7 @@ namespace MediaBrowser.Model.Session
         /// Gets or sets the now viewing item.
         /// </summary>
         /// <value>The now viewing item.</value>
-        public BaseItemInfo NowViewingItem { get; set; }
+        public BaseItemDto NowViewingItem { get; set; }
         
         /// <summary>
         /// Gets or sets the name of the device.
@@ -84,7 +84,7 @@ namespace MediaBrowser.Model.Session
         /// Gets or sets the now playing item.
         /// </summary>
         /// <value>The now playing item.</value>
-        public BaseItemInfo NowPlayingItem { get; set; }
+        public BaseItemDto NowPlayingItem { get; set; }
 
         /// <summary>
         /// Gets or sets the device id.

+ 1 - 1
Nuget/MediaBrowser.Common.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common</id>
-        <version>3.0.702</version>
+        <version>3.0.703</version>
         <title>Emby.Common</title>
         <authors>Emby Team</authors>
         <owners>ebr,Luke,scottisafool</owners>

+ 2 - 2
Nuget/MediaBrowser.Server.Core.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.702</version>
+        <version>3.0.703</version>
         <title>Emby.Server.Core</title>
         <authors>Emby Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains core components required to build plugins for Emby Server.</description>
         <copyright>Copyright © Emby 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.702" />
+            <dependency id="MediaBrowser.Common" version="3.0.703" />
         </dependencies>
     </metadata>
     <files>

+ 1 - 1
SharedVersion.cs

@@ -1,3 +1,3 @@
 using System.Reflection;
 
-[assembly: AssemblyVersion("3.2.19.6")]
+[assembly: AssemblyVersion("3.2.19.7")]