C bindings - properties i/f (#1091)

Support properties in C bindings

---------

Co-authored-by: whatdoineed2do/Ray <whatdoineed2do@nospam.gmail.com>
Co-authored-by: Urs Fleisch <ufleisch@users.sourceforge.net>
This commit is contained in:
whatdoineed2do 2023-07-09 18:48:27 +01:00 committed by GitHub
parent ceb142c9bd
commit e20a53afbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 170 additions and 2 deletions

View File

@ -39,6 +39,7 @@
#include <tag.h>
#include <string.h>
#include <id3v2framefactory.h>
#include <tpropertymap.h>
#include "tag_c.h"
@ -313,3 +314,104 @@ void taglib_id3v2_set_default_text_encoding(TagLib_ID3v2_Encoding encoding)
ID3v2::FrameFactory::instance()->setDefaultTextEncoding(type);
}
/******************************************************************************
* Properties API
******************************************************************************/
namespace {
void _taglib_property_set(TagLib_File *file, const char* prop, const char* value, bool append)
{
if(file == NULL || prop == NULL)
return;
File *tfile = reinterpret_cast<File *>(file);
PropertyMap map = tfile->tag()->properties();
if(value) {
TagLib::PropertyMap::Iterator property = map.find(prop);
if(property == map.end()) {
map.insert(prop, StringList(value));
}
else {
if(append) {
property->second.append(value);
}
else {
property->second = StringList(value);
}
}
}
else {
map.erase(prop);
}
tfile->setProperties(map);
}
} // namespace
void taglib_property_set(TagLib_File *f, const char *prop, const char *value)
{
_taglib_property_set(f, prop, value, false);
}
void taglib_property_set_append(TagLib_File *f, const char *prop, const char *value)
{
_taglib_property_set(f, prop, value, true);
}
char** taglib_property_keys(TagLib_File *file)
{
if(file == NULL)
return NULL;
const PropertyMap map = reinterpret_cast<const File *>(file)->properties();
if(map.isEmpty())
return NULL;
char **props = static_cast<char **>(malloc(sizeof(char *) * (map.size() + 1)));
char **pp = props;
for(const auto &i : map) {
*pp++ = stringToCharArray(i.first);
}
*pp = NULL;
return props;
}
char **taglib_property_get(TagLib_File *file, const char *prop)
{
if(file == NULL || prop == NULL)
return NULL;
const PropertyMap map = reinterpret_cast<const File *>(file)->properties();
TagLib::PropertyMap::ConstIterator property = map.find(prop);
if(property == map.end())
return NULL;
char **props = static_cast<char **>(malloc(sizeof(char *) * (property->second.size() + 1)));
char **pp = props;
for(const auto &i : property->second) {
*pp++ = stringToCharArray(i);
}
*pp = NULL;
return props;
}
void taglib_property_free(char **props)
{
if(props == NULL)
return;
char **p = props;
while(*p) {
free(*p++);
}
free(props);
}

View File

@ -292,6 +292,43 @@ typedef enum {
TAGLIB_C_EXPORT void taglib_id3v2_set_default_text_encoding(TagLib_ID3v2_Encoding encoding);
/******************************************************************************
* Properties API
******************************************************************************/
/*!
* Sets the property \a prop with \a value. Use \a value = NULL to remove
* the property, otherwise it will be replaced.
*/
TAGLIB_C_EXPORT void taglib_property_set(TagLib_File *file, const char *prop, const char *value);
/*!
* Appends \a value to the property \a prop (sets it if non-existing).
* Use \a value = NULL to remove all values associated with the property.
*/
TAGLIB_C_EXPORT void taglib_property_set_append(TagLib_File *file, const char *prop, const char *value);
/*!
* Get the keys of the property map.
*
* \return NULL terminated array of C-strings (char *), only NULL if empty.
* It must be freed by the client using taglib_property_free().
*/
TAGLIB_C_EXPORT char** taglib_property_keys(TagLib_File *file);
/*!
* Get value(s) of property \a prop.
*
* \return NULL terminated array of C-strings (char *), only NULL if empty.
It must be freed by the client using taglib_property_free().
*/
TAGLIB_C_EXPORT char** taglib_property_get(TagLib_File *file, const char *prop);
/*!
* Frees the NULL terminated array \a props and the C-strings it contains.
*/
TAGLIB_C_EXPORT void taglib_property_free(char **props);
#ifdef __cplusplus
}
#endif

View File

@ -23,6 +23,7 @@
*/
#include <stdio.h>
#include <string.h>
#include <tag_c.h>
#ifndef FALSE
@ -37,8 +38,9 @@ int main(int argc, char *argv[])
TagLib_File *file;
TagLib_Tag *tag;
const TagLib_AudioProperties *properties;
char **propertiesMap;
taglib_set_strings_unicode(FALSE);
taglib_set_strings_unicode(1);
for(i = 1; i < argc; i++) {
printf("******************** \"%s\" ********************\n", argv[i]);
@ -50,9 +52,10 @@ int main(int argc, char *argv[])
tag = taglib_file_tag(file);
properties = taglib_file_audioproperties(file);
propertiesMap = taglib_property_keys(file);
if(tag != NULL) {
printf("-- TAG --\n");
printf("-- TAG (basic) --\n");
printf("title - \"%s\"\n", taglib_tag_title(tag));
printf("artist - \"%s\"\n", taglib_tag_artist(tag));
printf("album - \"%s\"\n", taglib_tag_album(tag));
@ -62,6 +65,31 @@ int main(int argc, char *argv[])
printf("genre - \"%s\"\n", taglib_tag_genre(tag));
}
if(propertiesMap != NULL) {
char **keyPtr = propertiesMap;
int longest = 0;
while(*keyPtr) {
int len = (int)strlen(*keyPtr++);
if(len > longest) {
longest = len;
}
}
keyPtr = propertiesMap;
printf("-- TAG (properties) --\n");
while(*keyPtr) {
char **valPtr;
char **propertyValues = valPtr = taglib_property_get(file, *keyPtr);
while(valPtr && *valPtr)
{
printf("%-*s - \"%s\"\n", longest, *keyPtr, *valPtr++);
}
taglib_property_free(propertyValues);
++keyPtr;
}
}
if(properties != NULL) {
seconds = taglib_audioproperties_length(properties) % 60;
minutes = (taglib_audioproperties_length(properties) - seconds) / 60;
@ -73,6 +101,7 @@ int main(int argc, char *argv[])
printf("length - %i:%02i\n", minutes, seconds);
}
taglib_property_free(propertiesMap);
taglib_tag_free_strings();
taglib_file_free(file);
}