public AudioFileResource (final @Nonnull AudioFile audioFile) { this.id = audioFile.getId().stringValue(); this.displayName = audioFile.as(Displayable).getDisplayName(); this.path = audioFile.getPath().toString(); final Metadata metadata = audioFile.getMetadata(); this.fileSize = metadata.get(FILE_SIZE); this.duration = metadata.get(DURATION).map(Duration::toString); final String myUri = resourceUri("audiofile", id); this.content = myUri + "/content"; this.coverArt = metadata.get(ARTWORK).map(x -> myUri + "/coverart"); } }
/******************************************************************************************************************* * ******************************************************************************************************************/ @Nonnull private ResponseEntity<ResourceRegion> audioFileContentResponse (final @Nonnull AudioFile file, final @CheckForNull String rangeHeader) throws IOException { final long length = file.getSize(); final List<Range> ranges = Range.fromHeader(rangeHeader, length); if (ranges.size() > 1) { throw new RuntimeException("Can't support multi-range" + ranges); // FIXME } // E.g. HTML5 <audio> crashes if fed with too many data. final long maxSize = (rangeHeader != null) ? 1024*1024 : length; final Range fullRange = Range.full(length); final Range range = ranges.stream().findFirst().orElse(fullRange).subrange(maxSize); final String displayName = file.as(Displayable).getDisplayName(); // FIXME: getRdfsLabel() final HttpStatus status = range.equals(fullRange) ? OK : PARTIAL_CONTENT; return file.getContent().map(resource -> ResponseEntity.status(status) .contentType(new MediaType("audio", "mpeg")) .header(CONTENT_DISPOSITION, contentDisposition(displayName)) .body(range.getRegion(resource))) .orElseThrow(NotFoundException::new); }
@Nonnull private Res audioResourceOf (final @Nonnull AudioFile audioFile) { final ProtocolInfo protocolInfo = new DLNAProtocolInfo(Protocol.HTTP_GET, "*", "audio/mpeg", "*"); // FIXME: MIME final Metadata audioFileMetadata = audioFile.getMetadata(); final Res resource = new Res(protocolInfo, audioFileMetadata.get(FILE_SIZE).orElse(null), server.absoluteUrl(String.format("rest/audiofile/%s/content", audioFile.getId().stringValue()))); audioFileMetadata.get(DURATION).ifPresent(duration -> resource.setDuration(durationToString(duration))); audioFileMetadata.get(BIT_RATE).ifPresent(bitRate -> resource.setBitrate((long)(int)bitRate)); audioFileMetadata.get(BITS_PER_SAMPLE).ifPresent(bitPerSample -> resource.setBitsPerSample((long)(int)bitPerSample)); audioFileMetadata.get(CHANNELS).ifPresent(channels -> resource.setNrAudioChannels((long)(int)channels)); audioFileMetadata.get(SAMPLE_RATE).ifPresent(sampleRate -> resource.setSampleFrequency((long)(int)sampleRate)); return resource; }
/******************************************************************************************************************* * * @param id the audio file id * @return the binary contents * ******************************************************************************************************************/ @RequestMapping(value = "/audiofile/{id}/coverart") public ResponseEntity<byte[]> getAudioFileCoverArt (final @PathVariable String id) { log.info("getAudioFileCoverArt({})", id); checkStatus(); final Optional<AudioFile> audioFile = catalog.findAudioFiles().withId(new Id(id)).optionalResult(); log.debug(">>>> audioFile: {}", audioFile); return audioFile.flatMap(file -> file.getMetadata().getAll(ARTWORK).stream().findFirst()) .map(bytes -> bytesResponse(bytes, "image", "jpeg", "coverart.jpg")) .orElseThrow(NotFoundException::new); }
final AudioFileFinder allAudioFileFinder = catalog.findAudioFiles(); pw.printf("%n%n%nALL AUDIO FILES (%d):%n%n", allAudioFileFinder.count()); allAudioFileFinder.forEach(audioFile -> pw.printf(" %s%n", audioFile.toDumpString()));
/******************************************************************************************************************* * * Exports the cover art of a record. * * @param id the record id * @return the cover art image * ******************************************************************************************************************/ @RequestMapping(value = "/record/{id}/coverart") public ResponseEntity<byte[]> getRecordCoverArt (final @PathVariable String id) { log.info("getRecordCoverArt({})", id); checkStatus(); return catalog.findTracks().inRecord(new Id(id)) .stream() .flatMap(track -> track.asMany(AudioFileSupplier).stream()) .map(afs -> afs.getAudioFile()) .flatMap(af -> af.getMetadata().getAll(ARTWORK).stream()) .findAny() .map(bytes -> bytesResponse(bytes, "image", "jpeg", "coverart.jpg")) .orElseThrow(NotFoundException::new); }