Beispiel #1
0
        public async Task DetectAllTracksAsync(string albumName, CancellationToken cancelToken = default)
        {
            Guard.NotEmpty(albumName, nameof(albumName));

            // Get album info...
            var albumInfo = _albumRegistry.GetAlbumByName(albumName);

            if (albumInfo == null)
            {
                throw new InvalidOperationException(T("Admin.Media.Exception.AlbumNonexistent", albumName));
            }

            if (!albumInfo.HasTrackDetector)
            {
                throw new InvalidOperationException(T("Admin.Media.Exception.AlbumNoTrack", albumName));
            }

            // Load corresponding track detectors for current album...
            var trackDetectors = albumInfo
                                 .TrackDetectorTypes
                                 .Select(x => _trackDetectorFactory[x])
                                 .ToArray();

            var isInstallation = !EngineContext.Current.Application.IsInstalled;

            if (!isInstallation)
            {
                // First delete all tracks for current album...
                await DeleteAllTracksAsync(albumName);
            }

            IAsyncEnumerable <MediaTrack> allTracks = null;

            for (int i = 0; i < trackDetectors.Length; i++)
            {
                // >>>>> DO detection (potentially a long process)...
                var tracks = trackDetectors[i].DetectAllTracksAsync(albumName, cancelToken);

                if (i == 0)
                {
                    allTracks = tracks;
                }
                else if (allTracks != null)
                {
                    // Must be this way to prevent namespace collision with EF.
                    allTracks = Dasync.Collections.IAsyncEnumerableExtensions.Concat(allTracks, tracks);
                }
            }

            // (perf) Batch result data...
            await foreach (var batch in allTracks.SliceAsync(500))
            {
                cancelToken.ThrowIfCancellationRequested();
                // process the batch
                await TrackManyCoreAsync(batch, albumName);
            }
        }
Beispiel #2
0
        public TreeNode <MediaFolderNode> GetRootNode()
        {
            var cacheKey = FolderTreeKey;

            var root = _cache.Get(cacheKey, () =>
            {
                var query = from x in _folderRepo.TableUntracked
                            orderby x.ParentId, x.Name
                select x;

                var unsortedNodes = query.ToList().Select(x =>
                {
                    var item = new MediaFolderNode
                    {
                        Id              = x.Id,
                        Name            = x.Name,
                        ParentId        = x.ParentId,
                        CanDetectTracks = x.CanDetectTracks,
                        FilesCount      = x.FilesCount,
                        Slug            = x.Slug
                    };

                    if (x is MediaAlbum album)
                    {
                        item.IsAlbum     = true;
                        item.AlbumName   = album.Name;
                        item.Path        = album.Name;
                        item.ResKey      = album.ResKey;
                        item.IncludePath = album.IncludePath;
                        item.Order       = album.Order ?? 0;

                        var albumInfo = _albumRegistry.GetAlbumByName(album.Name);
                        if (albumInfo != null)
                        {
                            var displayHint   = albumInfo.DisplayHint;
                            item.Color        = displayHint.Color;
                            item.OverlayColor = displayHint.OverlayColor;
                            item.OverlayIcon  = displayHint.OverlayIcon;
                        }
                    }

                    return(item);
                });

                var nodeMap  = unsortedNodes.ToMultimap(x => x.ParentId ?? 0, x => x);
                var rootNode = new TreeNode <MediaFolderNode>(new MediaFolderNode {
                    Name = "Root", Id = 0
                });

                AddChildTreeNodes(rootNode, 0, nodeMap);

                return(rootNode);
            }, FolderTreeCacheDuration);

            return(root);
Beispiel #3
0
        public virtual MediaFile InsertPicture(
            byte[] pictureBinary,
            string mimeType,
            string fileName,
            int width,
            int height,
            bool isTransient = true,
            string album     = null)
        {
            var mime = mimeType.EmptyNull().Truncate(100);
            var name = NormalizeFileName(fileName, ref mime, out string ext);

            var file = new MediaFile
            {
                MimeType    = mime,
                Extension   = ext,
                Name        = name,
                IsTransient = isTransient
            };

            file.MediaType = _mediaTypeResolver.Resolve(file);

            if (album.HasValue())
            {
                var albumId = _albumRegistry.GetAlbumByName(album)?.Id;
                if (albumId > 0)
                {
                    file.FolderId = albumId;
                }
            }

            var stream = pictureBinary?.ToStream();

            file.RefreshMetadata(stream);
            _pictureRepository.Insert(file);

            // Save to storage.
            _storageProvider.Value.Save(file, stream);

            return(file);
        }
Beispiel #4
0
        public RoxyFileManagerController(
            IMediaService mediaService,
            IFolderService folderService,
            IAlbumRegistry albumRegistry,
            IMediaTypeResolver mediaTypeResolver,
            MediaHelper mediaHelper,
            MediaExceptionFactory exceptionFactory,
            //IMediaFileSystem fileSystem,
            ILocalizationFileResolver locFileResolver)
        {
            _mediaTypeResolver = mediaTypeResolver;
            _mediaHelper       = mediaHelper;
            _locFileResolver   = locFileResolver;

            _album      = albumRegistry.GetAlbumByName(SystemAlbumProvider.Files);
            _fileSystem = new MediaServiceFileSystemAdapter(mediaService, folderService, _mediaHelper, exceptionFactory);
            _fileRoot   = _album.Name;

            //_fileSystem = fileSystem;
            //_fileRoot = "Uploaded";
        }
Beispiel #5
0
        public void DetectAllTracks(string albumName, bool isMigration = false)
        {
            Guard.NotEmpty(albumName, nameof(albumName));

            // Get album info...
            var albumInfo = _albumRegistry.GetAlbumByName(albumName);

            if (albumInfo == null)
            {
                throw new InvalidOperationException(T("Admin.Media.Exception.AlbumNonexistent", albumName));
            }

            // load corresponding detector provider for current album...
            var provider = _albumProviderFactory[albumInfo.ProviderType] as IMediaTrackDetector;

            if (provider == null)
            {
                throw new InvalidOperationException(T("Admin.Media.Exception.AlbumNoTrack", albumName));
            }

            if (!isMigration)
            {
                // first delete all tracks for current album...
                DeleteAllTracks(albumName);
            }

            // >>>>> DO detection (potentially a very long process)...
            var tracks = provider.DetectAllTracks(albumName);

            // (perf) batch result data...
            foreach (var batch in tracks.Slice(500))
            {
                // process the batch
                TrackManyCore(batch, albumName, isMigration);
            }
        }
Beispiel #6
0
        protected virtual void TrackManyCore(IEnumerable <MediaTrackAction> actions, string albumName, bool isMigration)
        {
            Guard.NotNull(actions, nameof(actions));

            if (!actions.Any())
            {
                return;
            }

            var ctx = _dbContext;

            using (var scope = new DbContextScope(ctx,
                                                  validateOnSave: false,
                                                  hooksEnabled: false,
                                                  autoDetectChanges: false))
            {
                // Get the id for an album (necessary later to set FolderId)...
                int?albumId = albumName.HasValue()
                    ? _albumRegistry.GetAlbumByName(albumName)?.Id
                    : null;

                // Get distinct ids of all detected files...
                var mediaFileIds = actions.Select(x => x.MediaFileId).Distinct().ToArray();

                // fetch these files from database...
                var query = ctx.Set <MediaFile>().Include(x => x.Tracks).Where(x => mediaFileIds.Contains(x.Id));
                if (isMigration)
                {
                    query = query.Where(x => x.Version == 1);
                }
                var files = query.ToDictionary(x => x.Id);

                // for each media file relation to an entity...
                foreach (var action in actions)
                {
                    // fetch the file from local dictionary by its id...
                    if (files.TryGetValue(action.MediaFileId, out var file))
                    {
                        if (isMigration)
                        {
                            // set album id as folder id (during initial migration there are no sub-folders)
                            file.FolderId = albumId;

                            // remember that we processed tracks for this file already
                            file.Version = 2;
                        }

                        var track = action.ToTrack();
                        if (albumName.HasValue() && track.Album.IsEmpty())
                        {
                            // Overwrite track album if scope album was passed.
                            track.Album = albumName;
                        }

                        // add or remove the track from file
                        if (action.Operation == MediaTrackOperation.Track)
                        {
                            file.Tracks.Add(track);
                        }
                        else
                        {
                            var dbTrack = file.Tracks.FirstOrDefault(x => x == track);
                            if (dbTrack != null)
                            {
                                file.Tracks.Remove(track);
                                _dbContext.ChangeState(dbTrack, System.Data.Entity.EntityState.Deleted);
                            }
                        }

                        if (file.Tracks.Count > 0)
                        {
                            // A file with tracks can NEVER be transient
                            file.IsTransient = false;
                        }
                        else if (_makeFilesTransientWhenOrphaned)
                        {
                            // But an untracked file can OPTIONALLY be transient
                            file.IsTransient = true;
                        }
                    }
                }

                // Save whole batch to database
                int num = ctx.SaveChanges();

                // Breathe
                ctx.DetachEntities <MediaFile>(deep: true);
            }
        }
 public int GetAlbumIdByName(string albumName)
 {
     Guard.NotEmpty(albumName, nameof(albumName));
     return(_albumRegistry.GetAlbumByName(albumName)?.Id ?? 0);
 }