import java.io.IOException;
import java.io.InputStream;
-import net.pterodactylus.sonitus.data.Format;
+import net.pterodactylus.sonitus.data.ContentMetadata;
+import net.pterodactylus.sonitus.data.FormatMetadata;
+import net.pterodactylus.sonitus.data.Metadata;
+import com.google.common.base.Optional;
import com.jcraft.jogg.Packet;
import com.jcraft.jogg.Page;
import com.jcraft.jogg.StreamState;
import com.jcraft.jorbis.Info;
/**
- * Identifies Ogg Vorbis files.
+ * Identifies Ogg Vorbis files. <p> All knowledge used in this class has been
+ * taken from <a href="http://www.jcraft.com/jorbis/tutorial/Tutorial.html">jcraft.com/jorbis/tutorial/Tutorial.html</a>.
+ * </p>
*
* @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
*/
/**
* Tries to parse the given stream as Ogg Vorbis file and returns a {@link
- * Format} describing the stream.
+ * Metadata} describing the stream.
*
* @param inputStream
- * @return
+ * The input stream to identify as Ogg Vorbis
+ * @return The identified metadata, or {@link Optional#absent()} if the stream
+ * could not be identified
* @throws IOException
+ * if an I/O error occurs
*/
- public static Format identify(InputStream inputStream) throws IOException {
+ public static Optional<Metadata> identify(InputStream inputStream) throws IOException {
/* stuff needed to decode Ogg. */
Packet packet = new Packet();
syncState.wrote(read);
switch (syncState.pageout(page)) {
case -1:
- throw new IOException("Hole in Ogg data!");
+ return Optional.absent();
case 1:
if (!streamStateInitialized) {
/* init stream state. */
streamStateInitialized = true;
}
if (streamState.pagein(page) == -1) {
- throw new IOException("Error parsing Ogg data!");
+ return Optional.absent();
}
switch (streamState.packetout(packet)) {
case -1:
- throw new IOException("Error parsing Ogg data!");
+ return Optional.absent();
case 1:
info.synthesis_headerin(comment, packet);
packetsRead++;
buffer = syncState.data;
}
- return new Format(info.channels, info.rate, "Vorbis");
+ FormatMetadata formatMetadata = new FormatMetadata(info.channels, info.rate, "Vorbis");
+ ContentMetadata contentMetadata = new ContentMetadata("");
+ for (int c = 0; c < comment.comments; ++c) {
+ String field = comment.getComment(c);
+ Optional<String> extractedField = extractField(field, "ARTIST");
+ if (extractedField.isPresent()) {
+ contentMetadata = contentMetadata.artist(extractedField.get());
+ continue;
+ }
+ extractedField = extractField(field, "TITLE");
+ if (extractedField.isPresent()) {
+ contentMetadata = contentMetadata.name(extractedField.get());
+ continue;
+ }
+ }
+ return Optional.of(new Metadata(formatMetadata, contentMetadata));
+ }
+
+ /**
+ * Extracts the content of the field from the comment if the comment contains
+ * the given field.
+ *
+ * @param comment
+ * The comment to extract the value from
+ * @param fieldName
+ * The name of the field to extract
+ * @return The extracted field, or {@link Optional#absent()} if the comment
+ * does not contain the given field
+ */
+ private static Optional<String> extractField(String comment, String fieldName) {
+ if (comment.startsWith(fieldName + "=")) {
+ return Optional.of(comment.substring(fieldName.length() + 1));
+ }
+ return Optional.absent();
}
}