PageRenderTime 64ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/Code/Source/Teaching.Wpf.MediaBuddy/Library/MediaIndexer.cs

https://bitbucket.org/BernhardGlueck/teaching
C# | 98 lines | 75 code | 19 blank | 4 comment | 8 complexity | 23311eda43f602488fbb34793069cd67 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics.Contracts;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. using Teaching.Wpf.MediaBuddy.Io;
  8. using BufferedStream = Teaching.Wpf.MediaBuddy.Io.BufferedStream;
  9. namespace Teaching.Wpf.MediaBuddy.Library
  10. {
  11. public class MediaIndexer
  12. {
  13. private const int BufferSize = 4096;
  14. private readonly IEnumerable<IContentTypeDetector> contentTypeDetectors;
  15. private readonly IEnumerable<IMediaItemContributor> mediaItemContributors;
  16. public async Task<MediaItem> Index(IFileDescription fileDescription)
  17. {
  18. Contract.Requires<ArgumentNullException>( fileDescription != null,"fileDescription");
  19. using( var fileData = await fileDescription.OpenAsync())
  20. {
  21. var contentType = fileData.ContentType;
  22. foreach( var contentTypeDetector in contentTypeDetectors)
  23. {
  24. // LINQ does not yet have overloads that take async lambdas
  25. var detectedContentType = await contentTypeDetector.DetectContentTypeAsync(fileDescription);
  26. contentType = detectedContentType ?? contentType;
  27. }
  28. var hashStream = new HashStream(fileData.Stream);
  29. var bufferedStream = new BufferedStream(hashStream, 10*1024);
  30. // Perform dummy read
  31. await ReadFile(bufferedStream);
  32. var hashValue = hashStream.FinishHash();
  33. var fileReference = new MediaFileReference()
  34. {
  35. Id = fileDescription.Id,
  36. ContentType = contentType,
  37. Extension = Path.GetExtension(fileDescription.Name),
  38. Hash = hashValue,
  39. Name = fileDescription.Name
  40. };
  41. var mediaItem = new MediaItem() { Name = fileDescription.Name};
  42. mediaItem.Files.Add(fileReference);
  43. foreach( var mediaItemContributor in mediaItemContributors )
  44. {
  45. await mediaItemContributor.Contribute(mediaItem, fileDescription, bufferedStream.Clone);
  46. }
  47. if (contentType != null && WellKnownContentTypes.All.Contains(contentType))
  48. {
  49. return mediaItem;
  50. }
  51. return null;
  52. }
  53. }
  54. private async Task<long> ReadFile(Stream stream)
  55. {
  56. // We do not actually consume the data, but need to walk the file for hash generation and other similar things.
  57. // Common hooks can be used to split of data for further processing.
  58. var buffer = new byte[BufferSize];
  59. var fullBlockCount = stream.Length/BufferSize;
  60. var lastBlockSize = stream.Length%BufferSize;
  61. for( long i = 0L;i < fullBlockCount; ++i )
  62. {
  63. await stream.ReadAsync(buffer, 0, BufferSize);
  64. }
  65. if ( lastBlockSize > 0 )
  66. {
  67. await stream.ReadAsync(buffer, 0, (int)lastBlockSize);
  68. }
  69. return stream.Length;
  70. }
  71. public MediaIndexer(IEnumerable<IContentTypeDetector> contentTypeDetectors,IEnumerable<IMediaItemContributor> mediaItemContributors)
  72. {
  73. Contract.Requires<ArgumentNullException>(contentTypeDetectors != null,"contentTypeDetectors");
  74. Contract.Requires<ArgumentNullException>(mediaItemContributors != null,"mediaItemContributors");
  75. this.contentTypeDetectors = contentTypeDetectors;
  76. this.mediaItemContributors = mediaItemContributors;
  77. }
  78. }
  79. }