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:
Martchus 2021-12-20 23:22:57 +01:00
parent def74db180
commit af325db8ab
3 changed files with 96 additions and 78 deletions

View File

@ -174,7 +174,8 @@ set(TEST_SRC_FILES
tests/overallogg.cpp
tests/tagvalue.cpp
tests/testfilecheck.cpp
tests/utils.cpp)
tests/utils.cpp
doc/example.cpp)
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(RES_FILES "${LANGUAGE_HEADER_ISO_639_2}")

View File

@ -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.
## Usage
This example shows how to read and write tag fields in a format-independent way:
```
#include <tagparser/mediafileinfo.h>
#include <tagparser/diagnostics.h>
#include <tagparser/progressfeedback.h>
// 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
* 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
`tagparser` to query the required compiler/linker flags.
* For a code example that shows how to read and write tag fields in a format-independent way, have
a look at [`example.cpp`](doc/example.cpp).
* The most important class is `TagParser::MediaFileInfo` providing access to everything else.
* IO errors are propagated via standard `std::ios_base::failure`.
* Fatal processing errors are propagated by throwing a class derived from `TagParser::Failure`.

88
doc/example.cpp Normal file
View File

@ -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);
}