Luke Pulverenti пре 10 година
родитељ
комит
504e2099e2
31 измењених фајлова са 124 додато и 101 уклоњено
  1. 2 2
      MediaBrowser.Api/UserLibrary/ArtistsService.cs
  2. 10 35
      MediaBrowser.Api/UserLibrary/ItemsService.cs
  3. 14 3
      MediaBrowser.Controller/Entities/Folder.cs
  4. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Default.xml
  5. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
  6. 0 2
      MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
  7. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml
  8. 0 2
      MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
  9. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
  10. 0 2
      MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml
  11. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
  12. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml
  13. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
  14. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
  15. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
  16. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
  17. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
  18. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
  19. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
  20. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
  21. 0 2
      MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
  22. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
  23. 0 2
      MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
  24. 0 2
      MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
  25. 20 11
      MediaBrowser.Model/ApiClient/IApiClient.cs
  26. 11 0
      MediaBrowser.Model/Dlna/AudioOptions.cs
  27. 0 2
      MediaBrowser.Model/Dlna/DeviceProfile.cs
  28. 5 4
      MediaBrowser.Model/Dlna/StreamBuilder.cs
  29. 9 2
      MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
  30. 30 0
      MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
  31. 23 0
      MediaBrowser.Server.Implementations/Sync/SyncRepository.cs

+ 2 - 2
MediaBrowser.Api/UserLibrary/ArtistsService.cs

@@ -130,8 +130,8 @@ namespace MediaBrowser.Api.UserLibrary
             if (request is GetAlbumArtists)
             if (request is GetAlbumArtists)
             {
             {
                 return items
                 return items
+                    .Where(i => !i.IsFolder)
                     .OfType<IHasAlbumArtist>()
                     .OfType<IHasAlbumArtist>()
-                    .Where(i => !(i is MusicAlbum))
                     .SelectMany(i => i.AlbumArtists)
                     .SelectMany(i => i.AlbumArtists)
                     .Distinct(StringComparer.OrdinalIgnoreCase)
                     .Distinct(StringComparer.OrdinalIgnoreCase)
                     .Select(name =>
                     .Select(name =>
@@ -150,8 +150,8 @@ namespace MediaBrowser.Api.UserLibrary
             }
             }
 
 
             return items
             return items
+                .Where(i => !i.IsFolder)
                 .OfType<IHasArtist>()
                 .OfType<IHasArtist>()
-                .Where(i => !(i is MusicAlbum))
                 .SelectMany(i => i.AllArtists)
                 .SelectMany(i => i.AllArtists)
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .Select(name =>
                 .Select(name =>

+ 10 - 35
MediaBrowser.Api/UserLibrary/ItemsService.cs

@@ -169,8 +169,6 @@ namespace MediaBrowser.Api.UserLibrary
         [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
         [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
         public string ExcludeLocationTypes { get; set; }
         public string ExcludeLocationTypes { get; set; }
 
 
-        public bool IncludeIndexContainers { get; set; }
-
         [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
         [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
         public bool? IsMissing { get; set; }
         public bool? IsMissing { get; set; }
 
 
@@ -396,52 +394,29 @@ namespace MediaBrowser.Api.UserLibrary
 
 
             else if (request.Recursive)
             else if (request.Recursive)
             {
             {
-                if (user == null)
-                {
-                    items = ((Folder)item).GetRecursiveChildren();
+                var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
 
 
-                    items = _libraryManager.ReplaceVideosWithPrimaryVersions(items);
-                }
-                else
-                {
-                    var result = await ((Folder)item).GetItems(GetItemsQuery(request, user));
-
-                    return new Tuple<QueryResult<BaseItem>, bool>(result, true);
-                }
+                return new Tuple<QueryResult<BaseItem>, bool>(result, true);
             }
             }
             else
             else
             {
             {
                 if (user == null)
                 if (user == null)
                 {
                 {
-                    items = ((Folder)item).Children;
+                    var result = await ((Folder)item).GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
 
 
-                    items = _libraryManager.ReplaceVideosWithPrimaryVersions(items);
+                    return new Tuple<QueryResult<BaseItem>, bool>(result, true);
                 }
                 }
-                else
-                {
-                    var userRoot = item as UserRootFolder;
 
 
-                    if (userRoot == null)
-                    {
-                        var result = await ((Folder)item).GetItems(GetItemsQuery(request, user));
+                var userRoot = item as UserRootFolder;
 
 
-                        return new Tuple<QueryResult<BaseItem>, bool>(result, true);
-                    }
+                if (userRoot == null)
+                {
+                    var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
 
 
-                    items = ((Folder)item).GetChildren(user, true);
+                    return new Tuple<QueryResult<BaseItem>, bool>(result, true);
                 }
                 }
-            }
-
-            if (request.IncludeIndexContainers)
-            {
-                var list = items.ToList();
-
-                var containers = list.Select(i => i.IndexContainer)
-                    .Where(i => i != null);
-
-                list.AddRange(containers);
 
 
-                items = list.Distinct();
+                items = ((Folder)item).GetChildren(user, true);
             }
             }
 
 
             return new Tuple<QueryResult<BaseItem>, bool>(new QueryResult<BaseItem>
             return new Tuple<QueryResult<BaseItem>, bool>(new QueryResult<BaseItem>

+ 14 - 3
MediaBrowser.Controller/Entities/Folder.cs

@@ -787,9 +787,20 @@ namespace MediaBrowser.Controller.Entities
 
 
             Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
             Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
 
 
-            var items = query.Recursive
-                ? GetRecursiveChildren(user, filter)
-                : GetChildren(user, true).Where(filter);
+            IEnumerable<BaseItem> items;
+
+            if (query.User == null)
+            {
+                items = query.Recursive
+                   ? GetRecursiveChildren(filter)
+                   : Children.Where(filter);
+            }
+            else
+            {
+                items = query.Recursive
+                   ? GetRecursiveChildren(user, filter)
+                   : GetChildren(user, true).Where(filter);
+            }
 
 
             var result = PostFilterAndSort(items, query);
             var result = PostFilterAndSort(items, query);
 
 

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Default.xml

@@ -26,8 +26,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml

@@ -31,8 +31,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml

@@ -32,8 +32,6 @@
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
   <RequiresPlainFolders>true</RequiresPlainFolders>
   <RequiresPlainFolders>true</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml

@@ -33,8 +33,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml

@@ -32,8 +32,6 @@
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml

@@ -30,8 +30,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml

@@ -32,8 +32,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml

@@ -33,8 +33,6 @@
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:pv" value="http://www.pv.com/pvns/" />
     <XmlAttribute name="xmlns:pv" value="http://www.pv.com/pvns/" />

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml

@@ -26,8 +26,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml

@@ -32,8 +32,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:sec" value="http://www.sec.co.kr/" />
     <XmlAttribute name="xmlns:sec" value="http://www.sec.co.kr/" />

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml

@@ -32,8 +32,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml

@@ -34,8 +34,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml

@@ -34,8 +34,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml

@@ -34,8 +34,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml

@@ -34,8 +34,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml

@@ -34,8 +34,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes>
   <XmlRootAttributes>
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
     <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml

@@ -34,8 +34,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml

@@ -33,8 +33,6 @@
   <TimelineOffsetSeconds>5</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>5</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml

@@ -33,8 +33,6 @@
   <TimelineOffsetSeconds>40</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>40</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
   <RequiresPlainFolders>true</RequiresPlainFolders>
   <RequiresPlainFolders>true</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>true</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>true</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml

@@ -33,8 +33,6 @@
   <TimelineOffsetSeconds>40</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>40</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 0 - 2
MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml

@@ -32,8 +32,6 @@
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
   <RequiresPlainFolders>false</RequiresPlainFolders>
   <RequiresPlainFolders>false</RequiresPlainFolders>
-  <SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
-  <SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
   <XmlRootAttributes />
   <XmlRootAttributes />
   <DirectPlayProfiles>
   <DirectPlayProfiles>

+ 20 - 11
MediaBrowser.Model/ApiClient/IApiClient.cs

@@ -41,7 +41,7 @@ namespace MediaBrowser.Model.ApiClient
         /// Occurs when [authenticated].
         /// Occurs when [authenticated].
         /// </summary>
         /// </summary>
         event EventHandler<GenericEventArgs<AuthenticationResult>> Authenticated;
         event EventHandler<GenericEventArgs<AuthenticationResult>> Authenticated;
-        
+
         /// <summary>
         /// <summary>
         /// Gets the API URL.
         /// Gets the API URL.
         /// </summary>
         /// </summary>
@@ -201,7 +201,7 @@ namespace MediaBrowser.Model.ApiClient
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task&lt;HttpResponse&gt;.</returns>
         /// <returns>Task&lt;HttpResponse&gt;.</returns>
         Task<HttpResponse> GetResponse(string url, CancellationToken cancellationToken = default(CancellationToken));
         Task<HttpResponse> GetResponse(string url, CancellationToken cancellationToken = default(CancellationToken));
-        
+
         /// <summary>
         /// <summary>
         /// Updates the user configuration.
         /// Updates the user configuration.
         /// </summary>
         /// </summary>
@@ -225,7 +225,7 @@ namespace MediaBrowser.Model.ApiClient
         /// <param name="query">The query.</param>
         /// <param name="query">The query.</param>
         /// <returns>Task&lt;QueryResult&lt;BaseItemDto&gt;&gt;.</returns>
         /// <returns>Task&lt;QueryResult&lt;BaseItemDto&gt;&gt;.</returns>
         Task<BaseItemDto[]> GetLatestItems(LatestItemsQuery query);
         Task<BaseItemDto[]> GetLatestItems(LatestItemsQuery query);
-        
+
         /// <summary>
         /// <summary>
         /// Gets the intros async.
         /// Gets the intros async.
         /// </summary>
         /// </summary>
@@ -324,7 +324,7 @@ namespace MediaBrowser.Model.ApiClient
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task&lt;ItemsResult&gt;.</returns>
         /// <returns>Task&lt;ItemsResult&gt;.</returns>
         Task<ItemsResult> GetUserViews(string userId, CancellationToken cancellationToken = default(CancellationToken));
         Task<ItemsResult> GetUserViews(string userId, CancellationToken cancellationToken = default(CancellationToken));
-        
+
         /// <summary>
         /// <summary>
         /// Gets the instant mix from song async.
         /// Gets the instant mix from song async.
         /// </summary>
         /// </summary>
@@ -563,7 +563,7 @@ namespace MediaBrowser.Model.ApiClient
         /// <param name="id">The identifier.</param>
         /// <param name="id">The identifier.</param>
         /// <returns>Task&lt;UserDto&gt;.</returns>
         /// <returns>Task&lt;UserDto&gt;.</returns>
         Task<UserDto> GetOfflineUserAsync(string id);
         Task<UserDto> GetOfflineUserAsync(string id);
-        
+
         /// <summary>
         /// <summary>
         /// Gets the parental ratings async.
         /// Gets the parental ratings async.
         /// </summary>
         /// </summary>
@@ -761,7 +761,7 @@ namespace MediaBrowser.Model.ApiClient
         /// <param name="password">The password.</param>
         /// <param name="password">The password.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
         /// <exception cref="ArgumentNullException">userId</exception>
         /// <exception cref="ArgumentNullException">userId</exception>
-        Task<AuthenticationResult> AuthenticateUserAsync(string username, 
+        Task<AuthenticationResult> AuthenticateUserAsync(string username,
             string password);
             string password);
 
 
         /// <summary>
         /// <summary>
@@ -874,7 +874,7 @@ namespace MediaBrowser.Model.ApiClient
         /// <param name="accessToken">The access token.</param>
         /// <param name="accessToken">The access token.</param>
         /// <param name="userId">The user identifier.</param>
         /// <param name="userId">The user identifier.</param>
         void SetAuthenticationInfo(string accessToken, string userId);
         void SetAuthenticationInfo(string accessToken, string userId);
-        
+
         /// <summary>
         /// <summary>
         /// Sets the authentication information.
         /// Sets the authentication information.
         /// </summary>
         /// </summary>
@@ -921,7 +921,7 @@ namespace MediaBrowser.Model.ApiClient
         /// </summary>
         /// </summary>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
         Task StopReceivingSyncJobsUpdates();
         Task StopReceivingSyncJobsUpdates();
-        
+
         /// <summary>
         /// <summary>
         /// Starts the receiving session updates.
         /// Starts the receiving session updates.
         /// </summary>
         /// </summary>
@@ -934,7 +934,7 @@ namespace MediaBrowser.Model.ApiClient
         /// </summary>
         /// </summary>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
         Task StopReceivingSessionUpdates();
         Task StopReceivingSessionUpdates();
-        
+
         /// <summary>
         /// <summary>
         /// Gets the image URL.
         /// Gets the image URL.
         /// </summary>
         /// </summary>
@@ -1378,7 +1378,7 @@ namespace MediaBrowser.Model.ApiClient
         /// <param name="file">The file.</param>
         /// <param name="file">The file.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
-        Task UploadFile(Stream stream, 
+        Task UploadFile(Stream stream,
             LocalFileInfo file,
             LocalFileInfo file,
             CancellationToken cancellationToken);
             CancellationToken cancellationToken);
 
 
@@ -1439,7 +1439,7 @@ namespace MediaBrowser.Model.ApiClient
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task&lt;Stream&gt;.</returns>
         /// <returns>Task&lt;Stream&gt;.</returns>
         Task<Stream> GetSyncJobItemAdditionalFile(string id, string name, CancellationToken cancellationToken);
         Task<Stream> GetSyncJobItemAdditionalFile(string id, string name, CancellationToken cancellationToken);
-        
+
         /// <summary>
         /// <summary>
         /// Opens the web socket.
         /// Opens the web socket.
         /// </summary>
         /// </summary>
@@ -1503,5 +1503,14 @@ namespace MediaBrowser.Model.ApiClient
         /// <param name="id">The identifier.</param>
         /// <param name="id">The identifier.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
         Task EnableCancelledSyncJobItem(string id);
         Task EnableCancelledSyncJobItem(string id);
+        /// <summary>
+        /// Gets the synchronize options.
+        /// </summary>
+        /// <param name="userId">The user identifier.</param>
+        /// <param name="itemIds">The item ids.</param>
+        /// <param name="parentId">The parent identifier.</param>
+        /// <param name="category">The category.</param>
+        /// <returns>Task&lt;SyncOptions&gt;.</returns>
+        Task<SyncOptions> GetSyncOptions(IEnumerable<string> itemIds, string userId, string parentId = null, SyncCategory? category = null);
     }
     }
 }
 }

+ 11 - 0
MediaBrowser.Model/Dlna/AudioOptions.cs

@@ -47,6 +47,17 @@ namespace MediaBrowser.Model.Dlna
         /// <value>The audio transcoding bitrate.</value>
         /// <value>The audio transcoding bitrate.</value>
         public int? AudioTranscodingBitrate { get; set; }
         public int? AudioTranscodingBitrate { get; set; }
 
 
+        /// <summary>
+        /// Gets or sets a value indicating whether [supports direct remote content].
+        /// </summary>
+        /// <value><c>true</c> if [supports direct remote content]; otherwise, <c>false</c>.</value>
+        public bool SupportsDirectRemoteContent { get; set; }
+        /// <summary>
+        /// Gets or sets a value indicating whether [supports custom HTTP headers].
+        /// </summary>
+        /// <value><c>true</c> if [supports custom HTTP headers]; otherwise, <c>false</c>.</value>
+        public bool SupportsCustomHttpHeaders { get; set; }
+        
         /// <summary>
         /// <summary>
         /// Gets the maximum bitrate.
         /// Gets the maximum bitrate.
         /// </summary>
         /// </summary>

+ 0 - 2
MediaBrowser.Model/Dlna/DeviceProfile.cs

@@ -76,8 +76,6 @@ namespace MediaBrowser.Model.Dlna
         public bool RequiresPlainVideoItems { get; set; }
         public bool RequiresPlainVideoItems { get; set; }
         public bool RequiresPlainFolders { get; set; }
         public bool RequiresPlainFolders { get; set; }
 
 
-        public bool SupportsDirectRemoteContent { get; set; }
-        public bool SupportsCustomHttpHeaders { get; set; }
         public bool EnableMSMediaReceiverRegistrar { get; set; }
         public bool EnableMSMediaReceiverRegistrar { get; set; }
 
 
         public XmlAttribute[] XmlRootAttributes { get; set; }
         public XmlAttribute[] XmlRootAttributes { get; set; }

+ 5 - 4
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -258,7 +258,7 @@ namespace MediaBrowser.Model.Dlna
             if (IsEligibleForDirectPlay(item, maxBitrateSetting, subtitleStream, options))
             if (IsEligibleForDirectPlay(item, maxBitrateSetting, subtitleStream, options))
             {
             {
                 // See if it can be direct played
                 // See if it can be direct played
-                var directPlay = GetVideoDirectPlayProfile(options.Profile, item, videoStream, audioStream);
+                var directPlay = GetVideoDirectPlayProfile(options, options.Profile, item, videoStream, audioStream);
 
 
                 if (directPlay != null)
                 if (directPlay != null)
                 {
                 {
@@ -380,7 +380,8 @@ namespace MediaBrowser.Model.Dlna
             return 128000;
             return 128000;
         }
         }
 
 
-        private PlayMethod? GetVideoDirectPlayProfile(DeviceProfile profile,
+        private PlayMethod? GetVideoDirectPlayProfile(VideoOptions options,
+            DeviceProfile profile,
             MediaSourceInfo mediaSource,
             MediaSourceInfo mediaSource,
             MediaStream videoStream,
             MediaStream videoStream,
             MediaStream audioStream)
             MediaStream audioStream)
@@ -504,12 +505,12 @@ namespace MediaBrowser.Model.Dlna
 
 
             if (mediaSource.Protocol == MediaProtocol.Http)
             if (mediaSource.Protocol == MediaProtocol.Http)
             {
             {
-                if (!profile.SupportsDirectRemoteContent)
+                if (!options.SupportsDirectRemoteContent)
                 {
                 {
                     return null;
                     return null;
                 }
                 }
 
 
-                if (mediaSource.RequiredHttpHeaders.Count > 0 && !profile.SupportsCustomHttpHeaders)
+                if (mediaSource.RequiredHttpHeaders.Count > 0 && !options.SupportsCustomHttpHeaders)
                 {
                 {
                     return null;
                     return null;
                 }
                 }

+ 9 - 2
MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs

@@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
                 ValidateUserAccess(user, request, authAttribtues, auth);
                 ValidateUserAccess(user, request, authAttribtues, auth);
             }
             }
 
 
-            var info = (AuthenticationInfo)request.Items["OriginalAuthenticationInfo"];
+            var info = GetTokenInfo(request);
 
 
             if (!IsExemptFromRoles(auth, authAttribtues, info))
             if (!IsExemptFromRoles(auth, authAttribtues, info))
             {
             {
@@ -199,6 +199,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
             }
             }
         }
         }
 
 
+        private AuthenticationInfo GetTokenInfo(IServiceRequest request)
+        {
+            object info;
+            request.Items.TryGetValue("OriginalAuthenticationInfo", out info);
+            return info as AuthenticationInfo;
+        }
+
         private bool IsValidConnectKey(string token)
         private bool IsValidConnectKey(string token)
         {
         {
             if (string.IsNullOrEmpty(token))
             if (string.IsNullOrEmpty(token))
@@ -216,7 +223,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
                 throw new SecurityException("Access token is invalid or expired.");
                 throw new SecurityException("Access token is invalid or expired.");
             }
             }
 
 
-            var info = (AuthenticationInfo)request.Items["OriginalAuthenticationInfo"];
+            var info = GetTokenInfo(request);
 
 
             if (info == null)
             if (info == null)
             {
             {

+ 30 - 0
MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs

@@ -203,6 +203,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
+            CheckDisposed();
+            
             await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
             await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
 
 
             IDbTransaction transaction = null;
             IDbTransaction transaction = null;
@@ -271,6 +273,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 throw new ArgumentNullException("id");
                 throw new ArgumentNullException("id");
             }
             }
 
 
+            CheckDisposed();
+            
             using (var cmd = _connection.CreateCommand())
             using (var cmd = _connection.CreateCommand())
             {
             {
                 cmd.CommandText = "select type,data from TypedBaseItems where guid = @guid";
                 cmd.CommandText = "select type,data from TypedBaseItems where guid = @guid";
@@ -355,6 +359,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
         /// <exception cref="System.ArgumentNullException">id</exception>
         /// <exception cref="System.ArgumentNullException">id</exception>
         public IEnumerable<ChapterInfo> GetChapters(Guid id)
         public IEnumerable<ChapterInfo> GetChapters(Guid id)
         {
         {
+            CheckDisposed();
             return _chapterRepository.GetChapters(id);
             return _chapterRepository.GetChapters(id);
         }
         }
 
 
@@ -367,6 +372,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
         /// <exception cref="System.ArgumentNullException">id</exception>
         /// <exception cref="System.ArgumentNullException">id</exception>
         public ChapterInfo GetChapter(Guid id, int index)
         public ChapterInfo GetChapter(Guid id, int index)
         {
         {
+            CheckDisposed();
             return _chapterRepository.GetChapter(id, index);
             return _chapterRepository.GetChapter(id, index);
         }
         }
 
 
@@ -386,6 +392,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
         /// </exception>
         /// </exception>
         public Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken)
         public Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken)
         {
         {
+            CheckDisposed();
             return _chapterRepository.SaveChapters(id, chapters, cancellationToken);
             return _chapterRepository.SaveChapters(id, chapters, cancellationToken);
         }
         }
 
 
@@ -400,6 +407,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
 
 
         private readonly object _disposeLock = new object();
         private readonly object _disposeLock = new object();
 
 
+        private bool _disposed;
+        private void CheckDisposed()
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException(GetType().Name + " has been disposed and cannot be accessed.");
+            }
+        }
+
         /// <summary>
         /// <summary>
         /// Releases unmanaged and - optionally - managed resources.
         /// Releases unmanaged and - optionally - managed resources.
         /// </summary>
         /// </summary>
@@ -408,6 +424,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
         {
         {
             if (dispose)
             if (dispose)
             {
             {
+                _disposed = true;
+
                 try
                 try
                 {
                 {
                     lock (_disposeLock)
                     lock (_disposeLock)
@@ -456,6 +474,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 throw new ArgumentNullException("parentId");
                 throw new ArgumentNullException("parentId");
             }
             }
 
 
+            CheckDisposed();
+            
             using (var cmd = _connection.CreateCommand())
             using (var cmd = _connection.CreateCommand())
             {
             {
                 cmd.CommandText = "select ItemId from ChildrenIds where ParentId = @ParentId";
                 cmd.CommandText = "select ItemId from ChildrenIds where ParentId = @ParentId";
@@ -479,6 +499,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 throw new ArgumentNullException("parentId");
                 throw new ArgumentNullException("parentId");
             }
             }
 
 
+            CheckDisposed();
+            
             using (var cmd = _connection.CreateCommand())
             using (var cmd = _connection.CreateCommand())
             {
             {
                 cmd.CommandText = "select type,data from TypedBaseItems where guid in (select ItemId from ChildrenIds where ParentId = @ParentId)";
                 cmd.CommandText = "select type,data from TypedBaseItems where guid in (select ItemId from ChildrenIds where ParentId = @ParentId)";
@@ -507,6 +529,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 throw new ArgumentNullException("type");
                 throw new ArgumentNullException("type");
             }
             }
 
 
+            CheckDisposed();
+            
             using (var cmd = _connection.CreateCommand())
             using (var cmd = _connection.CreateCommand())
             {
             {
                 cmd.CommandText = "select type,data from TypedBaseItems where type = @type";
                 cmd.CommandText = "select type,data from TypedBaseItems where type = @type";
@@ -535,6 +559,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 throw new ArgumentNullException("id");
                 throw new ArgumentNullException("id");
             }
             }
 
 
+            CheckDisposed();
+            
             await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
             await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
 
 
             IDbTransaction transaction = null;
             IDbTransaction transaction = null;
@@ -598,6 +624,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 throw new ArgumentNullException("children");
                 throw new ArgumentNullException("children");
             }
             }
 
 
+            CheckDisposed();
+            
             await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
             await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
 
 
             IDbTransaction transaction = null;
             IDbTransaction transaction = null;
@@ -659,11 +687,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
 
 
         public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query)
         public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query)
         {
         {
+            CheckDisposed();
             return _mediaStreamsRepository.GetMediaStreams(query);
             return _mediaStreamsRepository.GetMediaStreams(query);
         }
         }
 
 
         public Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken)
         public Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken)
         {
         {
+            CheckDisposed();
             return _mediaStreamsRepository.SaveMediaStreams(id, streams, cancellationToken);
             return _mediaStreamsRepository.SaveMediaStreams(id, streams, cancellationToken);
         }
         }
     }
     }

+ 23 - 0
MediaBrowser.Server.Implementations/Sync/SyncRepository.cs

@@ -172,6 +172,8 @@ namespace MediaBrowser.Server.Implementations.Sync
                 throw new ArgumentNullException("id");
                 throw new ArgumentNullException("id");
             }
             }
 
 
+            CheckDisposed();
+            
             var guid = new Guid(id);
             var guid = new Guid(id);
 
 
             if (guid == Guid.Empty)
             if (guid == Guid.Empty)
@@ -277,6 +279,8 @@ namespace MediaBrowser.Server.Implementations.Sync
                 throw new ArgumentNullException("job");
                 throw new ArgumentNullException("job");
             }
             }
 
 
+            CheckDisposed();
+            
             await _writeLock.WaitAsync().ConfigureAwait(false);
             await _writeLock.WaitAsync().ConfigureAwait(false);
 
 
             IDbTransaction transaction = null;
             IDbTransaction transaction = null;
@@ -348,6 +352,8 @@ namespace MediaBrowser.Server.Implementations.Sync
                 throw new ArgumentNullException("id");
                 throw new ArgumentNullException("id");
             }
             }
 
 
+            CheckDisposed();
+            
             await _writeLock.WaitAsync().ConfigureAwait(false);
             await _writeLock.WaitAsync().ConfigureAwait(false);
 
 
             IDbTransaction transaction = null;
             IDbTransaction transaction = null;
@@ -407,6 +413,8 @@ namespace MediaBrowser.Server.Implementations.Sync
                 throw new ArgumentNullException("query");
                 throw new ArgumentNullException("query");
             }
             }
 
 
+            CheckDisposed();
+            
             using (var cmd = _connection.CreateCommand())
             using (var cmd = _connection.CreateCommand())
             {
             {
                 cmd.CommandText = BaseJobSelectText;
                 cmd.CommandText = BaseJobSelectText;
@@ -491,6 +499,8 @@ namespace MediaBrowser.Server.Implementations.Sync
                 throw new ArgumentNullException("id");
                 throw new ArgumentNullException("id");
             }
             }
 
 
+            CheckDisposed();
+            
             var guid = new Guid(id);
             var guid = new Guid(id);
 
 
             using (var cmd = _connection.CreateCommand())
             using (var cmd = _connection.CreateCommand())
@@ -618,6 +628,8 @@ namespace MediaBrowser.Server.Implementations.Sync
                 throw new ArgumentNullException("jobItem");
                 throw new ArgumentNullException("jobItem");
             }
             }
 
 
+            CheckDisposed();
+            
             await _writeLock.WaitAsync().ConfigureAwait(false);
             await _writeLock.WaitAsync().ConfigureAwait(false);
 
 
             IDbTransaction transaction = null;
             IDbTransaction transaction = null;
@@ -764,6 +776,15 @@ namespace MediaBrowser.Server.Implementations.Sync
             GC.SuppressFinalize(this);
             GC.SuppressFinalize(this);
         }
         }
 
 
+        private bool _disposed;
+        private void CheckDisposed()
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException(GetType().Name + " has been disposed and cannot be accessed.");
+            }
+        }
+
         private readonly object _disposeLock = new object();
         private readonly object _disposeLock = new object();
 
 
         /// <summary>
         /// <summary>
@@ -774,6 +795,8 @@ namespace MediaBrowser.Server.Implementations.Sync
         {
         {
             if (dispose)
             if (dispose)
             {
             {
+                _disposed = true;
+
                 try
                 try
                 {
                 {
                     lock (_disposeLock)
                     lock (_disposeLock)