|
| 1 | +#include <cstdio> |
| 2 | +#include "matroskafile.h" |
| 3 | +#include "matroskatag.h" |
| 4 | +#include "matroskasimpletag.h" |
| 5 | +#include "matroskaattachments.h" |
| 6 | +#include "matroskaattachedfile.h" |
| 7 | +#include "matroskachapters.h" |
| 8 | +#include "matroskachapteredition.h" |
| 9 | +#include "tstring.h" |
| 10 | +#include "tutils.h" |
| 11 | +#include "tbytevector.h" |
| 12 | +#define GREEN_TEXT(s) "[1;32m" s "[0m" |
| 13 | +#define PRINT_PRETTY(label, value) printf(" " GREEN_TEXT(label) ": %s\n", value) |
| 14 | + |
| 15 | +int main(int argc, char *argv[]) |
| 16 | +{ |
| 17 | + if(argc != 2) { |
| 18 | + printf("Usage: matroskareader FILE\n"); |
| 19 | + return 1; |
| 20 | + } |
| 21 | + TagLib::Matroska::File file(argv[1]); |
| 22 | + if(!file.isValid()) { |
| 23 | + printf("File is not valid\n"); |
| 24 | + return 1; |
| 25 | + } |
| 26 | + auto tag = dynamic_cast<TagLib::Matroska::Tag*>(file.tag()); |
| 27 | + if(!tag) { |
| 28 | + printf("File has no tag\n"); |
| 29 | + return 0; |
| 30 | + } |
| 31 | + |
| 32 | + const TagLib::Matroska::SimpleTagsList &list = tag->simpleTagsList(); |
| 33 | + printf("Found %u tag(s):\n", list.size()); |
| 34 | + |
| 35 | + for(const TagLib::Matroska::SimpleTag &t : list) { |
| 36 | + PRINT_PRETTY("Tag Name", t.name().toCString(true)); |
| 37 | + |
| 38 | + if(t.type() == TagLib::Matroska::SimpleTag::StringType) |
| 39 | + PRINT_PRETTY("Tag Value", t.toString().toCString(true)); |
| 40 | + else if(t.type() == TagLib::Matroska::SimpleTag::BinaryType) |
| 41 | + PRINT_PRETTY("Tag Value", |
| 42 | + TagLib::Utils::formatString("Binary with size %i", t.toByteVector().size()).toCString(false) |
| 43 | + ); |
| 44 | + |
| 45 | + auto targetTypeValue = static_cast<unsigned int>(t.targetTypeValue()); |
| 46 | + PRINT_PRETTY("Target Type Value", |
| 47 | + targetTypeValue == 0 ? "None" : TagLib::Utils::formatString("%i", targetTypeValue).toCString(false) |
| 48 | + ); |
| 49 | + if(auto trackUid = t.trackUid()) { |
| 50 | + PRINT_PRETTY("Track UID", |
| 51 | + TagLib::Utils::formatString("%llu",trackUid).toCString(false) |
| 52 | + ); |
| 53 | + } |
| 54 | + const TagLib::String &language = t.language(); |
| 55 | + PRINT_PRETTY("Language", !language.isEmpty() ? language.toCString(false) : "Not set"); |
| 56 | + |
| 57 | + printf("\n"); |
| 58 | + } |
| 59 | + |
| 60 | + TagLib::Matroska::Attachments *attachments = file.attachments(); |
| 61 | + if(attachments) { |
| 62 | + const TagLib::Matroska::Attachments::AttachedFileList &list = attachments->attachedFileList(); |
| 63 | + printf("Found %u attachment(s)\n", list.size()); |
| 64 | + for(const auto &attachedFile : list) { |
| 65 | + PRINT_PRETTY("Filename", attachedFile.fileName().toCString(true)); |
| 66 | + const TagLib::String &description = attachedFile.description(); |
| 67 | + PRINT_PRETTY("Description", !description.isEmpty() ? description.toCString(true) : "None"); |
| 68 | + const TagLib::String &mediaType = attachedFile.mediaType(); |
| 69 | + PRINT_PRETTY("Media Type", !mediaType.isEmpty() ? mediaType.toCString(false) : "None"); |
| 70 | + PRINT_PRETTY("Data Size", |
| 71 | + TagLib::Utils::formatString("%u byte(s)", attachedFile.data().size()).toCString(false) |
| 72 | + ); |
| 73 | + PRINT_PRETTY("UID", |
| 74 | + TagLib::Utils::formatString("%llu", attachedFile.uid()).toCString(false) |
| 75 | + ); |
| 76 | + } |
| 77 | + } |
| 78 | + else |
| 79 | + printf("File has no attachments\n"); |
| 80 | + |
| 81 | + TagLib::Matroska::Chapters *chapters = file.chapters(); |
| 82 | + if(chapters) { |
| 83 | + printf("Chapters:\n"); |
| 84 | + const TagLib::Matroska::Chapters::ChapterEditionList &editions = chapters->chapterEditionList(); |
| 85 | + for(const auto &edition : editions) { |
| 86 | + if(edition.uid()) { |
| 87 | + PRINT_PRETTY("Edition UID", TagLib::Utils::formatString("%llu", edition.uid()) |
| 88 | + .toCString(false)); |
| 89 | + } |
| 90 | + PRINT_PRETTY("Edition Flags", TagLib::Utils::formatString("default=%d, ordered=%d", |
| 91 | + edition.isDefault(), edition.isOrdered()) |
| 92 | + .toCString(false)); |
| 93 | + printf("\n"); |
| 94 | + for(const auto &chapter : edition.chapterList()) { |
| 95 | + PRINT_PRETTY("Chapter UID", TagLib::Utils::formatString("%llu", chapter.uid()) |
| 96 | + .toCString(false)); |
| 97 | + PRINT_PRETTY("Chapter flags", TagLib::Utils::formatString("hidden=%d", chapter.isHidden()) |
| 98 | + .toCString(false)); |
| 99 | + PRINT_PRETTY("Start-End", TagLib::Utils::formatString("%llu-%llu", |
| 100 | + chapter.timeStart(), chapter.timeEnd()).toCString(false)); |
| 101 | + for(const auto &display : chapter.displayList()) { |
| 102 | + PRINT_PRETTY("Display", display.string().toCString(false)); |
| 103 | + PRINT_PRETTY("Language", !display.language().isEmpty() |
| 104 | + ? display.language().toCString(false) : "Not set"); |
| 105 | + } |
| 106 | + printf("\n"); |
| 107 | + } |
| 108 | + } |
| 109 | + } |
| 110 | + else |
| 111 | + printf("File has no chapters\n"); |
| 112 | + |
| 113 | + if(auto properties = dynamic_cast<const TagLib::Matroska::Properties *>(file.audioProperties())) { |
| 114 | + printf("Properties:\n"); |
| 115 | + PRINT_PRETTY("Doc Type", properties->docType().toCString(false)); |
| 116 | + PRINT_PRETTY("Doc Type Version", TagLib::String::number(properties->docTypeVersion()).toCString(false)); |
| 117 | + PRINT_PRETTY("Codec Name", properties->codecName().toCString(true)); |
| 118 | + PRINT_PRETTY("Bitrate", TagLib::String::number(properties->bitrate()).toCString(false)); |
| 119 | + PRINT_PRETTY("Sample Rate", TagLib::String::number(properties->sampleRate()).toCString(false)); |
| 120 | + PRINT_PRETTY("Channels", TagLib::String::number(properties->channels()).toCString(false)); |
| 121 | + PRINT_PRETTY("Length [ms]", TagLib::String::number(properties->lengthInMilliseconds()).toCString(false)); |
| 122 | + } |
| 123 | + return 0; |
| 124 | +} |
0 commit comments