Media browser has a bunch Entities that it deals with, for example: Movies, Episodes and Shows. We scan the file system and figure out what files and folders map to what entities.

This is done using entity resolution.

I have defined a new set of classes that take in a location and spit out a factory that knows how to create an entity. Sounds a bit tricky, but this trickiness gives us tons of flexibility. The beauty of this system is that code now lives in a very logical place. If a user is trying to figure out why a particular file is not being detected as a Movie we know to look at the MovieResolver which contains all the logic for movie resolution. Additionally, this architecture is very plug-in friendly and incredibly testable.

For example, I just fixed up a bug where folders were not being detected as movies properly.

Writing the fix was really easy, first I started with this test case:

[Test]
public void TestRecusiveMovieResolution()
{
    var resolver =  resolver = new ChainedEntityResolver() { 
        new MovieResolver(2, true), // maximum 2 videos per movie, allow for recursive search
        new FolderResolver()
    };
    var movieFolder = MockFolderMediaLocation.CreateMockLocation(@"
|Rushmore
 |part 1
  a.avi
 |part 2
  b.avi
");

    Assert.AreEqual(resolver.ResolveType(movieFolder), typeof(Movie));
}

Some observations:

  • I wrote an awesome little mock filesystem that allows us to test our algorithms without creating files.
  • We do chained resolution, meaning that if a resolver at the top of the chain resolves the type of a location we stop and return.

Next comes the fix in MovieResolver.cs:

  videoCount += childFolders
     .Select(child => ChildVideos(child))
     .SelectMany(x => x)
     .Take((maxVideosPerMovie - videoCount) + 1)
     .Count();
</code></pre>

and

private IEnumerable<IMediaLocation> ChildVideos(IFolderMediaLocation location) {
    foreach (var child in location.Children) {
        if (child.IsVideo()) { 
            yield return child;
        }
        var folder = child as IFolderMediaLocation;
        if (folder != null) {
            foreach (var grandChild in ChildVideos(folder)) {
                yield return grandChild;  
            } 
        }
    }
    
}

Observations:

  • SelectMany is a really useful LINQ method, that allows you to lazily chain your enumerables.

Comments

Stephen over 16 years ago
Stephen

Thanks Sam!

I'd like to contribute once I get my development environment up and running, problem is I'm running Enterprise and that does not include the MC dlls.

Stephen

Jas_Manghera over 16 years ago
Jas_Manghera

If you can get your hands on the MC dlls, it should be relatively straight forward to dump them into enterprise.

Join the discussion

What do you think?

comments powered by Discourse