예제 #1
0
        public void shouldNotBeEmptyAfterUpdate()
        {
            var target = new LocalLibrary(@"C:\Temp\Library");

            target.updateLibrary();
            Assert.AreNotEqual(0, target.getBookCount(), "Why there aren't any books?");
        }
예제 #2
0
 public void RemoveFolder(LocalLibraryModel model)
 {
     StorageApplicationPermissions.FutureAccessList.Remove(model.Token);
     LocalLibraryDb.Instance.RemoveLocalLibrary(model);
     LocalLibrary.Remove(model);
     LocalGallery.Where(it => it.LibraryId == model.Id).ToList().ForEach(it => LocalGallery.Remove(it));
 }
    private async Task <Unit> MovePath(TvContext dbContext, Parameters parameters)
    {
        LibraryPath  path       = parameters.LibraryPath;
        LocalLibrary newLibrary = parameters.Library;

        path.LibraryId = newLibrary.Id;
        if (await dbContext.SaveChangesAsync() > 0)
        {
            List <int> ids = await dbContext.Connection.QueryAsync <int>(
                @"SELECT MediaItem.Id FROM MediaItem WHERE LibraryPathId = @LibraryPathId",
                new { LibraryPathId = path.Id })
                             .Map(result => result.ToList());

            foreach (int id in ids)
            {
                Option <MediaItem> maybeMediaItem = await _searchRepository.GetItemToIndex(id);

                foreach (MediaItem mediaItem in maybeMediaItem)
                {
                    _logger.LogInformation("Moving item at {Path}", await GetPath(dbContext, mediaItem));
                    await _searchIndex.UpdateItems(_searchRepository, new List <MediaItem> {
                        mediaItem
                    });
                }
            }
        }

        return(Unit.Default);
    }
예제 #4
0
    /// <summary>
    /// The start function
    /// </summary>
    void Start()
    {
        //Initialise NFC
        AndroidNFCReader.enableBackgroundScan();
        AndroidNFCReader.ScanNFC("GameController", "OnMove");
        //Set the mapmid active so the map can be filled
        MapMid.SetActive(true);
        // Create the locallibrary
        local = new LocalLibrary();
        //Set the mapmid inactive
        MapMid.SetActive(false);

        //Set the energy sprite so it shows correctly
        GameObject newImageObject = GameObject.Find("Energy" + PlayerState.energy);
        Image      newImage       = newImageObject.GetComponent <Image>();

        placeholderImage.sprite = newImage.sprite;

        //Set the correct Jeep Image
        Image jeep = GameObject.Find("JeepImage").GetComponent <Image>();

        jeep.sprite = GameObject.Find("Jeep" + PlayerState.vehicle).GetComponent <Image>().sprite;
        //Set the correct Hat Image
        Image hat = GameObject.Find("HatImage").GetComponent <Image>();

        hat.sprite = GameObject.Find("Hat" + PlayerState.hat).GetComponent <Image>().sprite;
    }
예제 #5
0
 private Task DeleteLocalItem(MusicItem item)
 {
     return(TryFileDeletion(async() => {
         await LocalLibrary.Delete(item);
         // Updates the UI. Apparently, MusicFolder.MusicItems.Remove(item); does not update the UI.
         await RefreshCurrentFolder();
     }));
 }
예제 #6
0
        private async Task DownloadIfNecessary(MusicItem track)
        {
            var maybeLocalUri = await LocalLibrary.LocalUriIfExists(track);

            if (maybeLocalUri == null)
            {
                await BackgroundDownloader.DownloadAsync(track);
            }
        }
예제 #7
0
        protected override async Task EnsureHasDuration(MusicItem track)
        {
            var uri = await LocalLibrary.LocalUriIfExists(track);

            if (uri != null)
            {
                track.Duration = await StoreBeamPlayer.MediaElement.UriDuration(uri);
            }
        }
예제 #8
0
        public async Task AddFolder(params IFolderItem[] paths)
        {
            foreach (var path in paths)
            {
                var gallery = await ScanForGalleryAsync(path);

                var result = LocalLibraryDb.Instance.AddLocalLibrary(path, gallery);
                LocalLibrary.Add(result);
                gallery.ForEach(it => LocalGallery.Add(it));
            }
        }
예제 #9
0
 public List <Book> GetBooksInLibrary(Book book, LocalLibrary library)
 {
     using (var context = new AuthContext())
     {
         return(context.Books
                .Include(_book => _book.Author)
                .Include(_book => _book.LocalLibrary)
                .Where(_book => _book.Name == book.Name && _book.Author.Name == book.Author.Name /* && book.LocalLibrary.Id == library.Id*/)
                .ToList());
     }
 }
예제 #10
0
        /// <summary>
        /// Downloads the song if it is not already available offline.
        /// </summary>
        /// <param name="track"></param>
        /// <returns>the local uri of the downloaded track</returns>
        public async Task <Uri> DownloadAsync(MusicItem track)
        {
            await BeforeDownload(track);

            var maybeLocalUri = await PhoneLocalLibrary.Instance.LocalUriIfExists(track);

            if (maybeLocalUri != null)
            {
                return(maybeLocalUri);
            }
            return(await AddTransferAsync(track.Source, LocalLibrary.AbsolutePathTo(track)));
        }
예제 #11
0
 protected void Delete(MusicItem song)
 {
     try {
         var shouldRemove = song.IsSourceLocal;
         LocalLibrary.Delete(song.Path);
         // refreshes the items in the current view
         if (shouldRemove)
         {
             MusicFolder.MusicItems.Remove(song);
         }
     } catch (Exception e) {
         Send("Unable to delete. Perhaps the file is in use. " + e.Message);
     }
 }
    private async Task <LocalLibraryViewModel> PersistLocalLibrary(
        TvContext dbContext,
        LocalLibrary localLibrary)
    {
        await dbContext.LocalLibraries.AddAsync(localLibrary);

        await dbContext.SaveChangesAsync();

        if (_entityLocker.LockLibrary(localLibrary.Id))
        {
            await _workerChannel.WriteAsync(new ForceScanLocalLibrary(localLibrary.Id));
        }

        return(ProjectToViewModel(localLibrary));
    }
예제 #13
0
    protected static async Task <Validation <BaseError, LocalLibrary> > PathsMustBeValid(
        TvContext dbContext,
        LocalLibrary localLibrary,
        int?existingLibraryId = null)
    {
        List <string> allPaths = await dbContext.LocalLibraries
                                 .Include(ll => ll.Paths)
                                 .Filter(ll => existingLibraryId == null || ll.Id != existingLibraryId)
                                 .ToListAsync()
                                 .Map(list => list.SelectMany(ll => ll.Paths).Map(lp => lp.Path).ToList());

        return(Optional(localLibrary.Paths.Count(folder => allPaths.Any(f => AreSubPaths(f, folder.Path))))
               .Where(length => length == 0)
               .Map(_ => localLibrary)
               .ToValidation <BaseError>("Path must not belong to another library path"));
    }
예제 #14
0
        /// <summary>
        /// Downloads the song in the background if it's not already available offline.
        /// </summary>
        /// <param name="track"></param>
        public async Task SubmitDownload(MusicItem track)
        {
            await BeforeDownload(track);

            try {
                var maybeLocalUri = await PhoneLocalLibrary.Instance.LocalUriIfExists(track);

                if (maybeLocalUri == null)
                {
                    // For Subsonic, the response may be transcoded audio, in which case the
                    // path to the track, which has the original file extension as stored on
                    // the server, may be incorrect (example: response is transcoded to .mp3,
                    // path is .flac).

                    // TODO: Ensure that the file is stored locally with the correct extension,
                    // that is, find out whether the response is transcoded.
                    var destination = LocalLibrary.AbsolutePathTo(track);
                    var downloadUri = MusicProvider.DownloadUriFor(track);
                    // Only downloads tracks that are stored as MP3s, because this app does not support other local file formats.
                    if (destination.EndsWith("mp3"))
                    {
                        var downloadable = new Downloadable(downloadUri, destination);
                        if (LoadTransfersCount() < 3)
                        {
                            AddTransfer(downloadUri, destination);
                        }
                        else
                        {
                            // add the download to persistent storage from which it will be taken
                            // later when there are fewer concurrent downloads
                            DownloadDataContext.Add(downloadable);
                        }
                    }
                }
            } catch (PathTooLongException) {
                // Thrown if track.Path is about over 190 characters long, but I'm not sure what
                // the limit is and I don't want to be too defensive with this so I catch and
                // suppress the exception when it occurs.

                // The exception says "The specified path, file name, or both are too long.
                // The fully qualified file name must be less than 260 characters, and the
                // directory name must be less than 248 characters.", however, I don't know
                // the length of the fully qualified path name, so 190 chars is an estimate.
                AddMessage("Download of " + track.Name + " failed. The path is too long: " + track.Path);
            }
        }
    private async Task <Unit> DoDeletion(TvContext dbContext, LocalLibrary localLibrary)
    {
        List <int> ids = await dbContext.Connection.QueryAsync <int>(
            @"SELECT MediaItem.Id FROM MediaItem
                      INNER JOIN LibraryPath LP on MediaItem.LibraryPathId = LP.Id
                      WHERE LP.LibraryId = @LibraryId",
            new { LibraryId = localLibrary.Id })
                         .Map(result => result.ToList());

        await _searchIndex.RemoveItems(ids);

        _searchIndex.Commit();

        dbContext.LocalLibraries.Remove(localLibrary);
        await dbContext.SaveChangesAsync();

        return(Unit.Default);
    }
예제 #16
0
    private static Task <Validation <BaseError, Parameters> > LocalLibraryMustExist(
        TvContext dbContext,
        UpdateLocalLibrary request) =>
    dbContext.LocalLibraries
    .Include(ll => ll.Paths)
    .SelectOneAsync(ll => ll.Id, ll => ll.Id == request.Id)
    .MapT(
        existing =>
    {
        var incoming = new LocalLibrary
        {
            Name  = request.Name,
            Paths = request.Paths.Map(p => new LibraryPath {
                Id = p.Id, Path = p.Path
            }).ToList(),
            MediaSourceId = existing.Id
        };

        return(new Parameters(existing, incoming));
    })
    .Map(o => o.ToValidation <BaseError>("LocalLibrary does not exist."));
예제 #17
0
        //private async Task<Uri> DownloadIfNotExists(MusicItem track, Func<Task<Uri>> performDownload) {
        //    var maybeLocalUri = await LocalLibrary.LocalUriIfExists(track);
        //    if(maybeLocalUri != null) {
        //        return maybeLocalUri;
        //    }
        //    return await performDownload();
        //}
        /// <summary>
        /// Prepares a download. A return value of null indicates that the download shall
        /// not proceed. This may be the case if the track already exists locally, or some
        /// IO error prevents the download, for example if the intended destination path
        /// is too long.
        /// </summary>
        /// <param name="track"></param>
        /// <returns>download parameters, or null if the track shall not be downloaded</returns>
        private async Task <DownloadParameters> GetDownloadInfo(MusicItem track)
        {
            var maybeLocalUri = await LocalLibrary.LocalUriIfExists(track);

            if (maybeLocalUri == null)
            {
                try {
                    var source   = RemoveCredentialsFromQueryParams(track.Source);
                    var destFile = await Utils.FileTo(PathTo(track));

                    return(new DownloadParameters(source, destFile));
                } catch (IOException) {
                    // may have thrown PathTooLongException
                    // does not proceed with the download
                    return(null);
                }
            }
            else
            {
                return(null);
            }
        }
예제 #18
0
        public async Task <string> Upload(MusicItem song, string resource)
        {
            await DownloadIfNecessary(song);
            await EnsureHasDuration(song);

            // TODO refactor to HttpClient extension method or some such
            using (var content = new MultipartFormDataContent()) {
                // the trickery with quotes is due to bugs in the recipient of the uploaded content, Play Framework 2
                // see http://stackoverflow.com/questions/17900934/httpclient-uploading-multipartformdata-to-play-2-framework
                foreach (var param in content.Headers.ContentType.Parameters.Where(param => param.Name.Equals("boundary")))
                {
                    param.Value = param.Value.Replace("\"", String.Empty);
                }
                return(await LocalLibrary.WithStream <string>(song, async stream => {
                    var fileName = ProviderService.Instance.PathHelper.FileNameOf(song.Path);
                    content.Add(new StreamContent(stream), "\"file\"", "\"" + fileName + "\"");
                    content.Headers.Add(TrackHeader, JsonConvert.SerializeObject(new PimpTrack(song)));
                    using (var httpResponse = await LongTimeoutClient.PostAsync(resource, content)) {
                        return await httpResponse.Content.ReadAsStringAsync();
                    }
                }));
            }
        }
예제 #19
0
        public async Task CalculateConsumedGb()
        {
            var bytes = await LocalLibrary.ConsumedDiskSpaceBytes();

            ConsumedGb = 1.0D * bytes / 1024 / 1024 / 1024;
        }
예제 #20
0
 private record RequestParameters(
     LocalLibrary LocalLibrary,
     string FFprobePath,
     string FFmpegPath,
     bool ForceScan,
     int LibraryRefreshInterval);
예제 #21
0
        public void shouldBeEmptyUponCreation()
        {
            var target = new LocalLibrary();

            Assert.AreEqual(0, target.getBookCount(), "Why are there any books?");
        }
예제 #22
0
        public void shouldBeAvailable()
        {
            var target = new LocalLibrary(@"C:\Temp\Library");

            Assert.IsTrue(target.isAvailable());
        }
예제 #23
0
 private record Parameters(LocalLibrary Existing, LocalLibrary Incoming);
예제 #24
0
 protected static Task <Validation <BaseError, LocalLibrary> > NameMustBeValid(
     ILocalLibraryRequest request,
     LocalLibrary localLibrary) =>
 request.NotEmpty(c => c.Name)
 .Bind(_ => request.NotLongerThan(50)(c => c.Name))
 .Map(_ => localLibrary).AsTask();
예제 #25
0
        public async Task SubmitDownloads(IEnumerable <MusicItem> tracks)
        {
            await BeforeDownload(tracks);

            try {
                var remoteTracks = await tracks.FilterAsync(async track => await PhoneLocalLibrary.Instance.LocalUriIfExists(track) == null);

                var downloadables = remoteTracks
                                    .Select(track => new Downloadable(MusicProvider.DownloadUriFor(track), LocalLibrary.AbsolutePathTo(track)))
                                    .Where(d => d.Destination.EndsWith("mp3"))
                                    .ToList();
                var transfers  = LoadTransfersCount();
                var queueables = (transfers < 3 ? downloadables.Skip(3) : downloadables).ToList();
                if (transfers < 3)
                {
                    foreach (var dl in downloadables.Take(3).ToList())
                    {
                        AddTransfer(dl.Source, dl.Destination);
                    }
                }
                if (queueables.Count > 0)
                {
                    // add the download to persistent storage from which it will be taken
                    // later when there are fewer concurrent downloads
                    DownloadDataContext.AddAll(queueables);
                }
            } catch (PathTooLongException) {
                // Thrown if track.Path is about over 190 characters long, but I'm not sure what
                // the limit is and I don't want to be too defensive with this so I catch and
                // suppress the exception when it occurs.

                // The exception says "The specified path, file name, or both are too long.
                // The fully qualified file name must be less than 260 characters, and the
                // directory name must be less than 248 characters.", however, I don't know
                // the length of the fully qualified path name, so 190 chars is an estimate.
                AddMessage("Unable to submit all tracks for download. A file path was too long.");
            }
        }