Improve "Usage" documentation
* Move example code to a different file and build it as part of the tests to make sure it actually compiles * Add notes about the CMake find module and pkg-config module
This commit is contained in:
parent
def74db180
commit
af325db8ab
|
@ -174,7 +174,8 @@ set(TEST_SRC_FILES
|
||||||
tests/overallogg.cpp
|
tests/overallogg.cpp
|
||||||
tests/tagvalue.cpp
|
tests/tagvalue.cpp
|
||||||
tests/testfilecheck.cpp
|
tests/testfilecheck.cpp
|
||||||
tests/utils.cpp)
|
tests/utils.cpp
|
||||||
|
doc/example.cpp)
|
||||||
set(DOC_FILES README.md doc/adding-new-fields.md)
|
set(DOC_FILES README.md doc/adding-new-fields.md)
|
||||||
set(LANGUAGE_HEADER_ISO_639_2 "${CMAKE_CURRENT_BINARY_DIR}/resources/iso_language_codes.h")
|
set(LANGUAGE_HEADER_ISO_639_2 "${CMAKE_CURRENT_BINARY_DIR}/resources/iso_language_codes.h")
|
||||||
set(RES_FILES "${LANGUAGE_HEADER_ISO_639_2}")
|
set(RES_FILES "${LANGUAGE_HEADER_ISO_639_2}")
|
||||||
|
|
83
README.md
83
README.md
|
@ -40,83 +40,12 @@ It also allows to inspect and validate the element structure of MP4 and Matroska
|
||||||
The library is aware of different text encodings and can convert between different encodings using iconv.
|
The library is aware of different text encodings and can convert between different encodings using iconv.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
This example shows how to read and write tag fields in a format-independent way:
|
* For building/installing the library, checkout the build instructions below.
|
||||||
|
* To use the library with CMake, use its find module (e.g. `find_package(tagparser 10.1.0 REQUIRED)`) which
|
||||||
```
|
provides the imported target `tagparser` you can link against. Otherwise, use the `pkg-config` module
|
||||||
#include <tagparser/mediafileinfo.h>
|
`tagparser` to query the required compiler/linker flags.
|
||||||
#include <tagparser/diagnostics.h>
|
* For a code example that shows how to read and write tag fields in a format-independent way, have
|
||||||
#include <tagparser/progressfeedback.h>
|
a look at [`example.cpp`](doc/example.cpp).
|
||||||
|
|
||||||
// create a MediaFileInfo for high-level access to overall functionality of the library
|
|
||||||
auto fileInfo = MediaFileInfo();
|
|
||||||
|
|
||||||
// create container for errors, warnings, etc.
|
|
||||||
auto diag = Diagnostics();
|
|
||||||
|
|
||||||
// create handle to abort gracefully and get feedback during during long operations
|
|
||||||
auto progress = AbortableProgressFeedback([callback for status update], [callback for percentage-only updates]);
|
|
||||||
|
|
||||||
// open file (might throw ios_base::failure)
|
|
||||||
fileInfo.setPath("/path/to/some/file");
|
|
||||||
fileInfo.open();
|
|
||||||
|
|
||||||
// parse container format, tags, attachments and/or chapters as needed
|
|
||||||
// notes:
|
|
||||||
// - These functions might throw exceptions derived from ios_base::failure for IO errors and
|
|
||||||
// populate diag with possibly critical parsing messages you definitely want to check in production
|
|
||||||
// code.
|
|
||||||
// - Parsing a file can be expensive if the file is big or the disk IO is slow. You might want to
|
|
||||||
// run it in a separate thread.
|
|
||||||
// - At this point the parser does not make much use of the progress object.
|
|
||||||
fileInfo.parseContainerFormat(diag, progress);
|
|
||||||
fileInfo.parseTags(diag, progress);
|
|
||||||
fileInfo.parseAttachments(diag, progress);
|
|
||||||
fileInfo.parseChapters(diag, progress);
|
|
||||||
fileInfo.parseEverything(diag, progress); // just use that one if you want all over the above
|
|
||||||
|
|
||||||
// get tag as an object derived from the Tag class
|
|
||||||
// notes:
|
|
||||||
// - In real code you might want to check how many tags are assigned or use
|
|
||||||
// fileInfo.createAppropriateTags(…) to create tags as needed.
|
|
||||||
auto tag = fileInfo.tags().at(0);
|
|
||||||
|
|
||||||
// extract a field value and convert it to UTF-8 std::string (toString() might throw ConversionException)
|
|
||||||
#include <tagparser/tag.h>
|
|
||||||
#include <tagparser/tagvalue.h>
|
|
||||||
auto title = tag->value(TagParser::KnownField::Title).toString(TagParser::TagTextEncoding::Utf8);
|
|
||||||
|
|
||||||
// change a field value using an encoding suitable for the tag format
|
|
||||||
tag->setValue(KnownField::Album, TagValue("some UTF-8 string", TagTextEncoding::Utf8, tag->proposedTextEncoding()));
|
|
||||||
|
|
||||||
// get/remove/create attachments
|
|
||||||
#include <tagparser/abstractattachment.h>
|
|
||||||
if (auto *const container = fileInfo.container()) {
|
|
||||||
for (auto i = 0, count = container->attachmentCount(); i != count; ++i) {
|
|
||||||
auto attachment = container->attachment(i);
|
|
||||||
if (attachment->mimeType() == "image/jpeg") {
|
|
||||||
attachment->setIgnored(true); // remove existing attachment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// create new attachment
|
|
||||||
auto attachment = container->createAttachment();
|
|
||||||
attachment->setName("cover.jpg");
|
|
||||||
attachment->setFile(cover, diag);
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply changes to the file on disk
|
|
||||||
// notes:
|
|
||||||
// - Might throw exception derived from TagParser::Failure for fatal processing error or ios_base::failure
|
|
||||||
// for IO errors.
|
|
||||||
// - Applying changes can be expensive if the file is big or the disk IO is slow. You might want to
|
|
||||||
// run it in a separate thread.
|
|
||||||
// - Use progress.tryToAbort() from another thread or an interrupt handler to abort gracefully without leaving
|
|
||||||
// the file in an inconsistent state.
|
|
||||||
// - Be sure everything has been parsed before as the library needs to be aware of the whole file structure.
|
|
||||||
fileInfo.parseEverything(diag, progress);
|
|
||||||
fileInfo.applyChanges(diag, progress);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Summary
|
|
||||||
* The most important class is `TagParser::MediaFileInfo` providing access to everything else.
|
* The most important class is `TagParser::MediaFileInfo` providing access to everything else.
|
||||||
* IO errors are propagated via standard `std::ios_base::failure`.
|
* IO errors are propagated via standard `std::ios_base::failure`.
|
||||||
* Fatal processing errors are propagated by throwing a class derived from `TagParser::Failure`.
|
* Fatal processing errors are propagated by throwing a class derived from `TagParser::Failure`.
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
#include <tagparser/abstractattachment.h>
|
||||||
|
#include <tagparser/diagnostics.h>
|
||||||
|
#include <tagparser/mediafileinfo.h>
|
||||||
|
#include <tagparser/progressfeedback.h>
|
||||||
|
#include <tagparser/tag.h>
|
||||||
|
#include <tagparser/tagvalue.h>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief An example for reading and writing tags in a format-independent way.
|
||||||
|
* \sa Checkout the README's "Usage" section for further explanations.
|
||||||
|
*/
|
||||||
|
void example()
|
||||||
|
{
|
||||||
|
using namespace std::literals;
|
||||||
|
using namespace TagParser;
|
||||||
|
|
||||||
|
// create a MediaFileInfo for high-level access to overall functionality of the library
|
||||||
|
auto fileInfo = MediaFileInfo();
|
||||||
|
|
||||||
|
// create container for errors, warnings, etc.
|
||||||
|
auto diag = Diagnostics();
|
||||||
|
|
||||||
|
// create handle to abort gracefully and get feedback during during long operations
|
||||||
|
auto progress = AbortableProgressFeedback([] (AbortableProgressFeedback &feedback) {
|
||||||
|
// callback for status update
|
||||||
|
std::clog << "At step: " << feedback.step() << '\n';
|
||||||
|
}, [] (AbortableProgressFeedback &feedback) {
|
||||||
|
// callback for percentage-only updates
|
||||||
|
std::clog << "Step percentage: " << feedback.stepPercentage() << '\n';
|
||||||
|
});
|
||||||
|
|
||||||
|
// open file (might throw ios_base::failure)
|
||||||
|
fileInfo.setPath("/path/to/some/file"sv);
|
||||||
|
fileInfo.open();
|
||||||
|
|
||||||
|
// parse container format, tags, attachments and/or chapters as needed
|
||||||
|
// notes:
|
||||||
|
// - These functions might throw exceptions derived from ios_base::failure for IO errors and
|
||||||
|
// populate diag with possibly critical parsing messages you definitely want to check in production
|
||||||
|
// code.
|
||||||
|
// - Parsing a file can be expensive if the file is big or the disk IO is slow. You might want to
|
||||||
|
// run it in a separate thread.
|
||||||
|
// - At this point the parser does not make much use of the progress object.
|
||||||
|
fileInfo.parseContainerFormat(diag, progress);
|
||||||
|
fileInfo.parseTags(diag, progress);
|
||||||
|
fileInfo.parseAttachments(diag, progress);
|
||||||
|
fileInfo.parseChapters(diag, progress);
|
||||||
|
fileInfo.parseEverything(diag, progress); // just use that one if you want all over the above
|
||||||
|
|
||||||
|
// get tag as an object derived from the Tag class
|
||||||
|
// notes:
|
||||||
|
// - In real code you might want to check how many tags are assigned or use
|
||||||
|
// fileInfo.createAppropriateTags(…) to create tags as needed.
|
||||||
|
auto tag = fileInfo.tags().at(0);
|
||||||
|
|
||||||
|
// extract a field value and convert it to UTF-8 std::string (toString() might throw ConversionException)
|
||||||
|
auto title = tag->value(TagParser::KnownField::Title).toString(TagParser::TagTextEncoding::Utf8);
|
||||||
|
|
||||||
|
// change a field value using an encoding suitable for the tag format
|
||||||
|
tag->setValue(KnownField::Album, TagValue("some UTF-8 string", TagTextEncoding::Utf8, tag->proposedTextEncoding()));
|
||||||
|
|
||||||
|
// get/remove/create attachments
|
||||||
|
if (auto *const container = fileInfo.container()) {
|
||||||
|
for (std::size_t i = 0, count = container->attachmentCount(); i != count; ++i) {
|
||||||
|
auto attachment = container->attachment(i);
|
||||||
|
if (attachment->mimeType() == "image/jpeg") {
|
||||||
|
attachment->setIgnored(true); // remove existing attachment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// create new attachment
|
||||||
|
auto attachment = container->createAttachment();
|
||||||
|
attachment->setName("The cover");
|
||||||
|
attachment->setFile("cover.jpg", diag, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply changes to the file on disk
|
||||||
|
// notes:
|
||||||
|
// - Might throw exception derived from TagParser::Failure for fatal processing error or ios_base::failure
|
||||||
|
// for IO errors.
|
||||||
|
// - Applying changes can be expensive if the file is big or the disk IO is slow. You might want to
|
||||||
|
// run it in a separate thread.
|
||||||
|
// - Use progress.tryToAbort() from another thread or an interrupt handler to abort gracefully without leaving
|
||||||
|
// the file in an inconsistent state.
|
||||||
|
// - Be sure everything has been parsed before as the library needs to be aware of the whole file structure.
|
||||||
|
fileInfo.parseEverything(diag, progress);
|
||||||
|
fileInfo.applyChanges(diag, progress);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue