1
0
mirror of https://git.FreeBSD.org/ports.git synced 2024-11-18 00:10:04 +00:00

converters/gbsdconv: Fix build with Taglib 2.x

PR:		276677
This commit is contained in:
Jason E. Hale 2024-06-06 18:23:06 -04:00
parent 332610a716
commit 13b6ffc52c
4 changed files with 1332 additions and 1 deletions

View File

@ -1,6 +1,6 @@
PORTNAME= gbsdconv
PORTVERSION= 11.3
PORTREVISION= 3
PORTREVISION= 4
CATEGORIES= converters python
MAINTAINER= buganini@gmail.com

View File

@ -0,0 +1,30 @@
--- gbsdconv.orig 2024-06-06 19:33:30 UTC
+++ gbsdconv
@@ -38,10 +38,10 @@ taglib.taglib_mpeg_file.restype=c_void_p
taglib.taglib_mpeg_file.argtypes=[c_void_p]
taglib.taglib_mpeg_file.restype=c_void_p
-taglib.taglib_mpeg_file_save3.argtypes=[c_void_p, c_int, c_bool, c_int]
+taglib.taglib_mpeg_file_save3.argtypes=[c_void_p, c_int, c_bool, c_int, c_bool]
taglib.taglib_mpeg_file_save3.restype=c_bool
-taglib.taglib_mpeg_file_strip.argtypes=[c_void_p, c_int]
+taglib.taglib_mpeg_file_strip.argtypes=[c_void_p, c_int, c_bool]
taglib.taglib_mpeg_file_strip.restype=c_bool
taglib.taglib_file_tag.argtypes=[c_void_p]
@@ -1281,12 +1281,12 @@ class gBsdConv(object):
mpeg=taglib.taglib_mpeg_file(mfile)
if mpeg and builder.get_object('chk_use_id3v2_3').get_active():
- taglib.taglib_mpeg_file_save3(mpeg, 0xffff, False, 3)
+ taglib.taglib_mpeg_file_save3(mpeg, 0xffff, False, 3, True)
else:
taglib.taglib_file_save(mfile)
if mpeg and builder.get_object('chk_remove_id3v1').get_active():
- taglib.taglib_mpeg_file_strip(mpeg, 0x0001)
+ taglib.taglib_mpeg_file_strip(mpeg, 0x0001, True)
taglib.taglib_tag_free_strings()
taglib.taglib_file_free(mfile)

View File

@ -0,0 +1,873 @@
--- taglib/tag_c.cpp.orig 2014-02-15 21:45:54 UTC
+++ taglib/tag_c.cpp
@@ -19,43 +19,82 @@
* USA *
***************************************************************************/
+#include "tag_c.h"
+
+#include <cstdlib>
+#include <cstring>
+#include <sstream>
+#include <utility>
+
#ifdef HAVE_CONFIG_H
-#include "config.h"
+# include "config.h"
#endif
+#include "tstringlist.h"
+#include "tbytevectorstream.h"
+#include "tiostream.h"
+#include "tfile.h"
+#include "tpropertymap.h"
+#include "fileref.h"
+#include "asffile.h"
+#include "vorbisfile.h"
+#include "mpegfile.h"
+#include "flacfile.h"
+#include "oggflacfile.h"
+#include "mpcfile.h"
+#include "wavpackfile.h"
+#include "speexfile.h"
+#include "trueaudiofile.h"
+#include "mp4file.h"
+#include "aifffile.h"
+#include "wavfile.h"
+#include "apefile.h"
+#include "itfile.h"
+#include "modfile.h"
+#include "s3mfile.h"
+#include "xmfile.h"
+#include "opusfile.h"
+#include "dsffile.h"
+#include "dsdifffile.h"
+#include "tag.h"
+#include "id3v2framefactory.h"
-#include <stdlib.h>
-#include <fileref.h>
-#include <tfile.h>
-#include <asffile.h>
-#include <vorbisfile.h>
-#include <mpegfile.h>
-#include <flacfile.h>
-#include <oggflacfile.h>
-#include <mpcfile.h>
-#include <wavpackfile.h>
-#include <speexfile.h>
-#include <trueaudiofile.h>
-#include <mp4file.h>
-#include <tag.h>
-#include <string.h>
-#include <id3v2framefactory.h>
+using namespace TagLib;
-#include "tag_c.h"
+namespace
+{
+ List<char *> strings;
+ bool unicodeStrings = true;
+ bool stringManagementEnabled = true;
-using namespace TagLib;
+ char *stringToCharArray(const String &s)
+ {
+ const std::string str = s.to8Bit(unicodeStrings);
-static List<char *> strings;
-static bool unicodeStrings = true;
-static bool stringManagementEnabled = true;
+#ifdef HAVE_ISO_STRDUP
+ return ::_strdup(str.c_str());
+
+#else
+
+ return ::strdup(str.c_str());
+
+#endif
+ }
+
+ String charArrayToString(const char *s)
+ {
+ return String(s, unicodeStrings ? String::UTF8 : String::Latin1);
+ }
+} // namespace
+
void taglib_set_strings_unicode(BOOL unicode)
{
- unicodeStrings = bool(unicode);
+ unicodeStrings = (unicode != 0);
}
void taglib_set_string_management_enabled(BOOL management)
{
- stringManagementEnabled = bool(management);
+ stringManagementEnabled = (management != 0);
}
void taglib_free(void* pointer)
@@ -64,69 +103,130 @@ void taglib_free(void* pointer)
}
////////////////////////////////////////////////////////////////////////////////
-// TagLib::File wrapper
+// TagLib::IOStream wrapper
////////////////////////////////////////////////////////////////////////////////
+TagLib_IOStream *taglib_memory_iostream_new(const char *data, unsigned int size)
+{
+ return reinterpret_cast<TagLib_IOStream *>(
+ new ByteVectorStream(ByteVector(data, size)));
+}
+
+void taglib_iostream_free(TagLib_IOStream *stream)
+{
+ delete reinterpret_cast<IOStream *>(stream);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TagLib::FileRef wrapper
+////////////////////////////////////////////////////////////////////////////////
+
TagLib_File *taglib_file_new(const char *filename)
{
- return reinterpret_cast<TagLib_File *>(FileRef::create(filename));
+ return reinterpret_cast<TagLib_File *>(new FileRef(filename));
}
TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type)
{
+ File *file = NULL;
switch(type) {
case TagLib_File_MPEG:
- return reinterpret_cast<TagLib_File *>(new MPEG::File(filename));
+ file = new MPEG::File(filename);
+ break;
case TagLib_File_OggVorbis:
- return reinterpret_cast<TagLib_File *>(new Ogg::Vorbis::File(filename));
+ file = new Ogg::Vorbis::File(filename);
+ break;
case TagLib_File_FLAC:
- return reinterpret_cast<TagLib_File *>(new FLAC::File(filename));
+ file = new FLAC::File(filename);
+ break;
case TagLib_File_MPC:
- return reinterpret_cast<TagLib_File *>(new MPC::File(filename));
+ file = new MPC::File(filename);
+ break;
case TagLib_File_OggFlac:
- return reinterpret_cast<TagLib_File *>(new Ogg::FLAC::File(filename));
+ file = new Ogg::FLAC::File(filename);
+ break;
case TagLib_File_WavPack:
- return reinterpret_cast<TagLib_File *>(new WavPack::File(filename));
+ file = new WavPack::File(filename);
+ break;
case TagLib_File_Speex:
- return reinterpret_cast<TagLib_File *>(new Ogg::Speex::File(filename));
+ file = new Ogg::Speex::File(filename);
+ break;
case TagLib_File_TrueAudio:
- return reinterpret_cast<TagLib_File *>(new TrueAudio::File(filename));
+ file = new TrueAudio::File(filename);
+ break;
case TagLib_File_MP4:
- return reinterpret_cast<TagLib_File *>(new MP4::File(filename));
+ file = new MP4::File(filename);
+ break;
case TagLib_File_ASF:
- return reinterpret_cast<TagLib_File *>(new ASF::File(filename));
+ file = new ASF::File(filename);
+ break;
+ case TagLib_File_AIFF:
+ file = new RIFF::AIFF::File(filename);
+ break;
+ case TagLib_File_WAV:
+ file = new RIFF::WAV::File(filename);
+ break;
+ case TagLib_File_APE:
+ file = new APE::File(filename);
+ break;
+ case TagLib_File_IT:
+ file = new IT::File(filename);
+ break;
+ case TagLib_File_Mod:
+ file = new Mod::File(filename);
+ break;
+ case TagLib_File_S3M:
+ file = new S3M::File(filename);
+ break;
+ case TagLib_File_XM:
+ file = new XM::File(filename);
+ break;
+ case TagLib_File_Opus:
+ file = new Ogg::Opus::File(filename);
+ break;
+ case TagLib_File_DSF:
+ file = new DSF::File(filename);
+ break;
+ case TagLib_File_DSDIFF:
+ file = new DSDIFF::File(filename);
+ break;
default:
- return 0;
+ break;
}
+ return file ? reinterpret_cast<TagLib_File *>(new FileRef(file)) : NULL;
+}
- return 0;
+TagLib_File *taglib_file_new_iostream(TagLib_IOStream *stream)
+{
+ return reinterpret_cast<TagLib_File *>(
+ new FileRef(reinterpret_cast<IOStream *>(stream)));
}
void taglib_file_free(TagLib_File *file)
{
- delete reinterpret_cast<File *>(file);
+ delete reinterpret_cast<FileRef *>(file);
}
BOOL taglib_file_is_valid(const TagLib_File *file)
{
- return reinterpret_cast<const File *>(file)->isValid();
+ return !reinterpret_cast<const FileRef *>(file)->isNull();
}
TagLib_Tag *taglib_file_tag(const TagLib_File *file)
{
- const File *f = reinterpret_cast<const File *>(file);
+ auto f = reinterpret_cast<const FileRef *>(file);
return reinterpret_cast<TagLib_Tag *>(f->tag());
}
const TagLib_AudioProperties *taglib_file_audioproperties(const TagLib_File *file)
{
- const File *f = reinterpret_cast<const File *>(file);
+ auto f = reinterpret_cast<const FileRef *>(file);
return reinterpret_cast<const TagLib_AudioProperties *>(f->audioProperties());
}
BOOL taglib_file_save(TagLib_File *file)
{
- return reinterpret_cast<File *>(file)->save();
+ return reinterpret_cast<FileRef *>(file)->save();
}
////////////////////////////////////////////////////////////////////////////////
@@ -135,8 +235,8 @@ char *taglib_tag_title(const TagLib_Tag *tag)
char *taglib_tag_title(const TagLib_Tag *tag)
{
- const Tag *t = reinterpret_cast<const Tag *>(tag);
- char *s = ::strdup(t->title().toCString(unicodeStrings));
+ auto t = reinterpret_cast<const Tag *>(tag);
+ char *s = stringToCharArray(t->title());
if(stringManagementEnabled)
strings.append(s);
return s;
@@ -144,8 +244,8 @@ char *taglib_tag_artist(const TagLib_Tag *tag)
char *taglib_tag_artist(const TagLib_Tag *tag)
{
- const Tag *t = reinterpret_cast<const Tag *>(tag);
- char *s = ::strdup(t->artist().toCString(unicodeStrings));
+ auto t = reinterpret_cast<const Tag *>(tag);
+ char *s = stringToCharArray(t->artist());
if(stringManagementEnabled)
strings.append(s);
return s;
@@ -153,8 +253,8 @@ char *taglib_tag_album(const TagLib_Tag *tag)
char *taglib_tag_album(const TagLib_Tag *tag)
{
- const Tag *t = reinterpret_cast<const Tag *>(tag);
- char *s = ::strdup(t->album().toCString(unicodeStrings));
+ auto t = reinterpret_cast<const Tag *>(tag);
+ char *s = stringToCharArray(t->album());
if(stringManagementEnabled)
strings.append(s);
return s;
@@ -162,8 +262,8 @@ char *taglib_tag_comment(const TagLib_Tag *tag)
char *taglib_tag_comment(const TagLib_Tag *tag)
{
- const Tag *t = reinterpret_cast<const Tag *>(tag);
- char *s = ::strdup(t->comment().toCString(unicodeStrings));
+ auto t = reinterpret_cast<const Tag *>(tag);
+ char *s = stringToCharArray(t->comment());
if(stringManagementEnabled)
strings.append(s);
return s;
@@ -171,8 +271,8 @@ char *taglib_tag_genre(const TagLib_Tag *tag)
char *taglib_tag_genre(const TagLib_Tag *tag)
{
- const Tag *t = reinterpret_cast<const Tag *>(tag);
- char *s = ::strdup(t->genre().toCString(unicodeStrings));
+ auto t = reinterpret_cast<const Tag *>(tag);
+ char *s = stringToCharArray(t->genre());
if(stringManagementEnabled)
strings.append(s);
return s;
@@ -180,55 +280,55 @@ unsigned int taglib_tag_year(const TagLib_Tag *tag)
unsigned int taglib_tag_year(const TagLib_Tag *tag)
{
- const Tag *t = reinterpret_cast<const Tag *>(tag);
+ auto t = reinterpret_cast<const Tag *>(tag);
return t->year();
}
unsigned int taglib_tag_track(const TagLib_Tag *tag)
{
- const Tag *t = reinterpret_cast<const Tag *>(tag);
+ auto t = reinterpret_cast<const Tag *>(tag);
return t->track();
}
void taglib_tag_set_title(TagLib_Tag *tag, const char *title)
{
- Tag *t = reinterpret_cast<Tag *>(tag);
- t->setTitle(String(title, unicodeStrings ? String::UTF8 : String::Latin1));
+ auto t = reinterpret_cast<Tag *>(tag);
+ t->setTitle(charArrayToString(title));
}
void taglib_tag_set_artist(TagLib_Tag *tag, const char *artist)
{
- Tag *t = reinterpret_cast<Tag *>(tag);
- t->setArtist(String(artist, unicodeStrings ? String::UTF8 : String::Latin1));
+ auto t = reinterpret_cast<Tag *>(tag);
+ t->setArtist(charArrayToString(artist));
}
void taglib_tag_set_album(TagLib_Tag *tag, const char *album)
{
- Tag *t = reinterpret_cast<Tag *>(tag);
- t->setAlbum(String(album, unicodeStrings ? String::UTF8 : String::Latin1));
+ auto t = reinterpret_cast<Tag *>(tag);
+ t->setAlbum(charArrayToString(album));
}
void taglib_tag_set_comment(TagLib_Tag *tag, const char *comment)
{
- Tag *t = reinterpret_cast<Tag *>(tag);
- t->setComment(String(comment, unicodeStrings ? String::UTF8 : String::Latin1));
+ auto t = reinterpret_cast<Tag *>(tag);
+ t->setComment(charArrayToString(comment));
}
void taglib_tag_set_genre(TagLib_Tag *tag, const char *genre)
{
- Tag *t = reinterpret_cast<Tag *>(tag);
- t->setGenre(String(genre, unicodeStrings ? String::UTF8 : String::Latin1));
+ auto t = reinterpret_cast<Tag *>(tag);
+ t->setGenre(charArrayToString(genre));
}
void taglib_tag_set_year(TagLib_Tag *tag, unsigned int year)
{
- Tag *t = reinterpret_cast<Tag *>(tag);
+ auto t = reinterpret_cast<Tag *>(tag);
t->setYear(year);
}
void taglib_tag_set_track(TagLib_Tag *tag, unsigned int track)
{
- Tag *t = reinterpret_cast<Tag *>(tag);
+ auto t = reinterpret_cast<Tag *>(tag);
t->setTrack(track);
}
@@ -237,8 +337,8 @@ void taglib_tag_free_strings()
if(!stringManagementEnabled)
return;
- for(List<char *>::Iterator it = strings.begin(); it != strings.end(); ++it)
- free(*it);
+ for(auto &string : std::as_const(strings))
+ free(string);
strings.clear();
}
@@ -248,25 +348,25 @@ int taglib_audioproperties_length(const TagLib_AudioPr
int taglib_audioproperties_length(const TagLib_AudioProperties *audioProperties)
{
- const AudioProperties *p = reinterpret_cast<const AudioProperties *>(audioProperties);
- return p->length();
+ auto p = reinterpret_cast<const AudioProperties *>(audioProperties);
+ return p->lengthInSeconds();
}
int taglib_audioproperties_bitrate(const TagLib_AudioProperties *audioProperties)
{
- const AudioProperties *p = reinterpret_cast<const AudioProperties *>(audioProperties);
+ auto p = reinterpret_cast<const AudioProperties *>(audioProperties);
return p->bitrate();
}
int taglib_audioproperties_samplerate(const TagLib_AudioProperties *audioProperties)
{
- const AudioProperties *p = reinterpret_cast<const AudioProperties *>(audioProperties);
+ auto p = reinterpret_cast<const AudioProperties *>(audioProperties);
return p->sampleRate();
}
int taglib_audioproperties_channels(const TagLib_AudioProperties *audioProperties)
{
- const AudioProperties *p = reinterpret_cast<const AudioProperties *>(audioProperties);
+ auto p = reinterpret_cast<const AudioProperties *>(audioProperties);
return p->channels();
}
@@ -293,6 +393,423 @@ void taglib_id3v2_set_default_text_encoding(TagLib_ID3
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;
+
+ auto tfile = reinterpret_cast<FileRef *>(file);
+ PropertyMap map = tfile->tag()->properties();
+
+ if(value) {
+ auto property = map.find(prop);
+ if(property == map.end()) {
+ map.insert(prop, StringList(charArrayToString(value)));
+ }
+ else {
+ if(append) {
+ property->second.append(charArrayToString(value));
+ }
+ else {
+ property->second = StringList(charArrayToString(value));
+ }
+ }
+ }
+ else {
+ map.erase(prop);
+ }
+
+ tfile->setProperties(map);
+}
+
+} // namespace
+
+void taglib_property_set(TagLib_File *file, const char *prop, const char *value)
+{
+ _taglib_property_set(file, prop, value, false);
+}
+
+void taglib_property_set_append(TagLib_File *file, const char *prop, const char *value)
+{
+ _taglib_property_set(file, prop, value, true);
+}
+
+char** taglib_property_keys(const TagLib_File *file)
+{
+ if(file == NULL)
+ return NULL;
+
+ const PropertyMap map = reinterpret_cast<const FileRef *>(file)->properties();
+ if(map.isEmpty())
+ return NULL;
+
+ auto 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(const TagLib_File *file, const char *prop)
+{
+ if(file == NULL || prop == NULL)
+ return NULL;
+
+ const PropertyMap map = reinterpret_cast<const FileRef *>(file)->properties();
+
+ auto property = map.find(prop);
+ if(property == map.end())
+ return NULL;
+
+ auto 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);
+}
+
+
+/******************************************************************************
+ * Complex Properties API
+ ******************************************************************************/
+
+namespace {
+
+bool _taglib_complex_property_set(
+ TagLib_File *file, const char *key,
+ const TagLib_Complex_Property_Attribute **value, bool append)
+{
+ if(file == NULL || key == NULL)
+ return false;
+
+ auto tfile = reinterpret_cast<FileRef *>(file);
+
+ if(value == NULL) {
+ return tfile->setComplexProperties(key, {});
+ }
+
+ VariantMap map;
+ const TagLib_Complex_Property_Attribute** attrPtr = value;
+ while(*attrPtr) {
+ const TagLib_Complex_Property_Attribute *attr = *attrPtr;
+ String attrKey(attr->key);
+ switch(attr->value.type) {
+ case TagLib_Variant_Void:
+ map.insert(attrKey, Variant());
+ break;
+ case TagLib_Variant_Bool:
+ map.insert(attrKey, attr->value.value.boolValue != 0);
+ break;
+ case TagLib_Variant_Int:
+ map.insert(attrKey, attr->value.value.intValue);
+ break;
+ case TagLib_Variant_UInt:
+ map.insert(attrKey, attr->value.value.uIntValue);
+ break;
+ case TagLib_Variant_LongLong:
+ map.insert(attrKey, attr->value.value.longLongValue);
+ break;
+ case TagLib_Variant_ULongLong:
+ map.insert(attrKey, attr->value.value.uLongLongValue);
+ break;
+ case TagLib_Variant_Double:
+ map.insert(attrKey, attr->value.value.doubleValue);
+ break;
+ case TagLib_Variant_String:
+ map.insert(attrKey, charArrayToString(attr->value.value.stringValue));
+ break;
+ case TagLib_Variant_StringList: {
+ StringList strs;
+ if(attr->value.value.stringListValue) {
+ char **s = attr->value.value.stringListValue;;
+ while(*s) {
+ strs.append(charArrayToString(*s++));
+ }
+ }
+ map.insert(attrKey, strs);
+ break;
+ }
+ case TagLib_Variant_ByteVector:
+ map.insert(attrKey, ByteVector(attr->value.value.byteVectorValue,
+ attr->value.size));
+ break;
+ }
+ ++attrPtr;
+ }
+
+ return append ? tfile->setComplexProperties(key, tfile->complexProperties(key).append(map))
+ : tfile->setComplexProperties(key, {map});
+}
+
+} // namespace
+
+BOOL taglib_complex_property_set(
+ TagLib_File *file, const char *key,
+ const TagLib_Complex_Property_Attribute **value)
+{
+ return _taglib_complex_property_set(file, key, value, false);
+}
+
+BOOL taglib_complex_property_set_append(
+ TagLib_File *file, const char *key,
+ const TagLib_Complex_Property_Attribute **value)
+{
+ return _taglib_complex_property_set(file, key, value, true);
+}
+
+char** taglib_complex_property_keys(const TagLib_File *file)
+{
+ if(file == NULL) {
+ return NULL;
+ }
+
+ const StringList strs = reinterpret_cast<const FileRef *>(file)->complexPropertyKeys();
+ if(strs.isEmpty()) {
+ return NULL;
+ }
+
+ auto keys = static_cast<char **>(malloc(sizeof(char *) * (strs.size() + 1)));
+ char **keyPtr = keys;
+
+ for(const auto &str : strs) {
+ *keyPtr++ = stringToCharArray(str);
+ }
+ *keyPtr = NULL;
+
+ return keys;
+}
+
+TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
+ const TagLib_File *file, const char *key)
+{
+ if(file == NULL || key == NULL) {
+ return NULL;
+ }
+
+ const auto variantMaps = reinterpret_cast<const FileRef *>(file)->complexProperties(key);
+ if(variantMaps.isEmpty()) {
+ return NULL;
+ }
+
+ auto props = static_cast<TagLib_Complex_Property_Attribute ***>(
+ malloc(sizeof(TagLib_Complex_Property_Attribute **) * (variantMaps.size() + 1)));
+ TagLib_Complex_Property_Attribute ***propPtr = props;
+
+ for(const auto &variantMap : variantMaps) {
+ if(!variantMap.isEmpty()) {
+ auto attrs = static_cast<TagLib_Complex_Property_Attribute **>(
+ malloc(sizeof(TagLib_Complex_Property_Attribute *) * (variantMap.size() + 1)));
+ auto attr = static_cast<TagLib_Complex_Property_Attribute *>(
+ malloc(sizeof(TagLib_Complex_Property_Attribute) * variantMap.size()));
+ TagLib_Complex_Property_Attribute **attrPtr = attrs;
+ // The next assignment is redundant to silence the clang analyzer,
+ // it is done at the end of the loop, which must be entered because
+ // variantMap is not empty.
+ *attrPtr = attr;
+ for(const auto &[k, v] : variantMap) {
+ attr->key = stringToCharArray(k);
+ attr->value.size = 0;
+ switch(v.type()) {
+ case Variant::Void:
+ attr->value.type = TagLib_Variant_Void;
+ attr->value.value.stringValue = NULL;
+ break;
+ case Variant::Bool:
+ attr->value.type = TagLib_Variant_Bool;
+ attr->value.value.boolValue = v.value<bool>();
+ break;
+ case Variant::Int:
+ attr->value.type = TagLib_Variant_Int;
+ attr->value.value.intValue = v.value<int>();
+ break;
+ case Variant::UInt:
+ attr->value.type = TagLib_Variant_UInt;
+ attr->value.value.uIntValue = v.value<unsigned int>();
+ break;
+ case Variant::LongLong:
+ attr->value.type = TagLib_Variant_LongLong;
+ attr->value.value.longLongValue = v.value<long long>();
+ break;
+ case Variant::ULongLong:
+ attr->value.type = TagLib_Variant_ULongLong;
+ attr->value.value.uLongLongValue = v.value<unsigned long long>();
+ break;
+ case Variant::Double:
+ attr->value.type = TagLib_Variant_Double;
+ attr->value.value.doubleValue = v.value<double>();
+ break;
+ case Variant::String: {
+ attr->value.type = TagLib_Variant_String;
+ auto str = v.value<String>();
+ attr->value.value.stringValue = stringToCharArray(str);
+ attr->value.size = str.size();
+ break;
+ }
+ case Variant::StringList: {
+ attr->value.type = TagLib_Variant_StringList;
+ auto strs = v.value<StringList>();
+ auto strPtr = static_cast<char **>(malloc(sizeof(char *) * (strs.size() + 1)));
+ attr->value.value.stringListValue = strPtr;
+ attr->value.size = strs.size();
+ for(const auto &str : strs) {
+ *strPtr++ = stringToCharArray(str);
+ }
+ *strPtr = NULL;
+ break;
+ }
+ case Variant::ByteVector: {
+ attr->value.type = TagLib_Variant_ByteVector;
+ const ByteVector data = v.value<ByteVector>();
+ auto bytePtr = static_cast<char *>(malloc(data.size()));
+ attr->value.value.byteVectorValue = bytePtr;
+ attr->value.size = data.size();
+ ::memcpy(bytePtr, data.data(), data.size());
+ break;
+ }
+ case Variant::ByteVectorList:
+ case Variant::VariantList:
+ case Variant::VariantMap: {
+ attr->value.type = TagLib_Variant_String;
+ std::stringstream ss;
+ ss << v;
+ attr->value.value.stringValue = stringToCharArray(ss.str());
+ break;
+ }
+ }
+ *attrPtr++ = attr++;
+ }
+ *attrPtr = NULL;
+ *propPtr++ = attrs;
+ }
+ }
+ *propPtr = NULL;
+ return props;
+}
+
+void taglib_picture_from_complex_property(
+ TagLib_Complex_Property_Attribute*** properties,
+ TagLib_Complex_Property_Picture_Data *picture)
+{
+ if(!properties || !picture) {
+ return;
+ }
+ std::memset(picture, 0, sizeof(*picture));
+ TagLib_Complex_Property_Attribute*** propPtr = properties;
+ while(!picture->data && *propPtr) {
+ TagLib_Complex_Property_Attribute** attrPtr = *propPtr;
+ while(*attrPtr) {
+ TagLib_Complex_Property_Attribute *attr = *attrPtr;
+ switch(attr->value.type) {
+ case TagLib_Variant_String:
+ if(strcmp("mimeType", attr->key) == 0) {
+ picture->mimeType = attr->value.value.stringValue;
+ }
+ else if(strcmp("description", attr->key) == 0) {
+ picture->description = attr->value.value.stringValue;
+ }
+ else if(strcmp("pictureType", attr->key) == 0) {
+ picture->pictureType = attr->value.value.stringValue;
+ }
+ break;
+ case TagLib_Variant_ByteVector:
+ if(strcmp("data", attr->key) == 0) {
+ picture->data = attr->value.value.byteVectorValue;
+ picture->size = attr->value.size;
+ }
+ break;
+ default:
+ break;
+ }
+ ++attrPtr;
+ }
+ ++propPtr;
+ }
+}
+
+void taglib_complex_property_free_keys(char **keys)
+{
+ if(keys == NULL) {
+ return;
+ }
+
+ char **k = keys;
+ while(*k) {
+ free(*k++);
+ }
+ free(keys);
+}
+
+void taglib_complex_property_free(
+ TagLib_Complex_Property_Attribute ***props)
+{
+ if(props == NULL) {
+ return;
+ }
+ TagLib_Complex_Property_Attribute*** propPtr = props;
+ while(*propPtr) {
+ TagLib_Complex_Property_Attribute** attrPtr = *propPtr;
+ while(*attrPtr) {
+ TagLib_Complex_Property_Attribute *attr = *attrPtr;
+ switch(attr->value.type) {
+ case TagLib_Variant_String:
+ free(attr->value.value.stringValue);
+ break;
+ case TagLib_Variant_StringList:
+ if(attr->value.value.stringListValue) {
+ char **s = attr->value.value.stringListValue;
+ while(*s) {
+ free(*s++);
+ }
+ free(attr->value.value.stringListValue);
+ }
+ break;
+ case TagLib_Variant_ByteVector:
+ free(attr->value.value.byteVectorValue);
+ break;
+ case TagLib_Variant_Void:
+ case TagLib_Variant_Bool:
+ case TagLib_Variant_Int:
+ case TagLib_Variant_UInt:
+ case TagLib_Variant_LongLong:
+ case TagLib_Variant_ULongLong:
+ case TagLib_Variant_Double:
+ break;
+ }
+ free(attr->key);
+ ++attrPtr;
+ }
+ free(**propPtr);
+ free(*propPtr++);
+ }
+ free(props);
+}
+
////////////////////////////////////////////////////////////////////////////////
// TagLib::MPEG::File wrapper
////////////////////////////////////////////////////////////////////////////////
@@ -302,15 +819,18 @@ TagLib_Mpeg_File *taglib_mpeg_file(TagLib_File *file)
return reinterpret_cast<TagLib_Mpeg_File *>(dynamic_cast<MPEG::File *>(reinterpret_cast<File *>(file)));
}
-BOOL taglib_mpeg_file_save3(TagLib_Mpeg_File *file, int tags, BOOL stripOthers, int id3v2Version)
+BOOL taglib_mpeg_file_save3(TagLib_Mpeg_File *file, int tags, BOOL stripOthers, int id3v2Version, BOOL duplicateTags)
{
MPEG::File *f=reinterpret_cast<MPEG::File *>(file);
- return f->save(tags, (bool)stripOthers, id3v2Version);
+ return f->save(tags,
+ stripOthers ? File::StripOthers : File::StripNone,
+ id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4,
+ duplicateTags ? File::Duplicate : File::DoNotDuplicate);
}
-BOOL taglib_mpeg_file_strip(TagLib_Mpeg_File *file, int tags)
+BOOL taglib_mpeg_file_strip(TagLib_Mpeg_File *file, int tags, BOOL freeMemory)
{
MPEG::File *f=reinterpret_cast<MPEG::File *>(file);
- return f->strip(tags);
+ return f->strip(tags, freeMemory);
}

View File

@ -0,0 +1,428 @@
--- taglib/tag_c.h.orig 2014-02-15 21:45:54 UTC
+++ taglib/tag_c.h
@@ -29,7 +29,9 @@ extern "C" {
extern "C" {
#endif
-#if defined(_WIN32) || defined(_WIN64)
+#if defined(TAGLIB_STATIC)
+#define TAGLIB_C_EXPORT
+#elif defined(_WIN32) || defined(_WIN64)
#ifdef MAKE_TAGLIB_C_LIB
#define TAGLIB_C_EXPORT __declspec(dllexport)
#else
@@ -41,7 +43,10 @@ extern "C" {
#define TAGLIB_C_EXPORT
#endif
-#ifndef BOOL
+#ifdef _MSC_VER
+/* minwindef.h contains typedef int BOOL */
+#include <windows.h>
+#elif !defined BOOL
#define BOOL int
#endif
@@ -55,14 +60,15 @@ extern "C" {
*******************************************************************************/
/*
- * These are used for type provide some type safety to the C API (as opposed to
- * using void *, but pointers to them are simply cast to the corresponding C++
+ * These are used to give the C API some type safety (as opposed to
+ * using void * ), but pointers to them are simply cast to the corresponding C++
* types in the implementation.
*/
typedef struct { int dummy; } TagLib_File;
typedef struct { int dummy; } TagLib_Tag;
typedef struct { int dummy; } TagLib_AudioProperties;
+typedef struct { int dummy; } TagLib_IOStream;
typedef struct { int dummy; } TagLib_Mpeg_File;
/*!
@@ -86,6 +92,22 @@ TAGLIB_C_EXPORT void taglib_free(void* pointer);
TAGLIB_C_EXPORT void taglib_free(void* pointer);
/*******************************************************************************
+ * Stream API
+ ******************************************************************************/
+
+/*!
+ * Creates a byte vector stream from \a size bytes of \a data.
+ * Such a stream can be used with taglib_file_new_iostream() to create a file
+ * from memory.
+ */
+TAGLIB_C_EXPORT TagLib_IOStream *taglib_memory_iostream_new(const char *data, unsigned int size);
+
+/*!
+ * Frees and closes the stream.
+ */
+TAGLIB_C_EXPORT void taglib_iostream_free(TagLib_IOStream *stream);
+
+/*******************************************************************************
* File API
******************************************************************************/
@@ -99,7 +121,17 @@ typedef enum {
TagLib_File_Speex,
TagLib_File_TrueAudio,
TagLib_File_MP4,
- TagLib_File_ASF
+ TagLib_File_ASF,
+ TagLib_File_AIFF,
+ TagLib_File_WAV,
+ TagLib_File_APE,
+ TagLib_File_IT,
+ TagLib_File_Mod,
+ TagLib_File_S3M,
+ TagLib_File_XM,
+ TagLib_File_Opus,
+ TagLib_File_DSF,
+ TagLib_File_DSDIFF
} TagLib_File_Type;
/*!
@@ -118,12 +150,22 @@ TAGLIB_C_EXPORT TagLib_File *taglib_file_new_type(cons
TAGLIB_C_EXPORT TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type);
/*!
+ * Creates a TagLib file from a \a stream.
+ * A byte vector stream can be used to read a file from memory and write to
+ * memory, e.g. when fetching network data.
+ * The stream has to be created using taglib_memory_iostream_new() and shall be
+ * freed using taglib_iostream_free() \e after this file is freed with
+ * taglib_file_free().
+ */
+TAGLIB_C_EXPORT TagLib_File *taglib_file_new_iostream(TagLib_IOStream *stream);
+
+/*!
* Frees and closes the file.
*/
TAGLIB_C_EXPORT void taglib_file_free(TagLib_File *file);
/*!
- * Returns true if the file is open and readble and valid information for
+ * Returns \c true if the file is open and readable and valid information for
* the Tag and / or AudioProperties was found.
*/
@@ -136,7 +178,7 @@ TAGLIB_C_EXPORT TagLib_Tag *taglib_file_tag(const TagL
TAGLIB_C_EXPORT TagLib_Tag *taglib_file_tag(const TagLib_File *file);
/*!
- * Returns a pointer to the the audio properties associated with this file. This
+ * Returns a pointer to the audio properties associated with this file. This
* will be freed automatically when the file is freed.
*/
TAGLIB_C_EXPORT const TagLib_AudioProperties *taglib_file_audioproperties(const TagLib_File *file);
@@ -191,12 +233,12 @@ TAGLIB_C_EXPORT char *taglib_tag_genre(const TagLib_Ta
TAGLIB_C_EXPORT char *taglib_tag_genre(const TagLib_Tag *tag);
/*!
- * Returns the tag's year or 0 if year is not set.
+ * Returns the tag's year or 0 if the year is not set.
*/
TAGLIB_C_EXPORT unsigned int taglib_tag_year(const TagLib_Tag *tag);
/*!
- * Returns the tag's track number or 0 if track number is not set.
+ * Returns the tag's track number or 0 if the track number is not set.
*/
TAGLIB_C_EXPORT unsigned int taglib_tag_track(const TagLib_Tag *tag);
@@ -284,14 +326,14 @@ TAGLIB_C_EXPORT TagLib_Mpeg_File *taglib_mpeg_file(Tag
TAGLIB_C_EXPORT TagLib_Mpeg_File *taglib_mpeg_file(TagLib_File *file);
/*!
- * bool TagLib::MPEG:File::save(int tags, bool stripOthers, int id3v2Version);
+ * bool TagLib::MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, DuplicateTags duplicate);
*/
-TAGLIB_C_EXPORT BOOL taglib_mpeg_file_save3(TagLib_Mpeg_File *file, int tags, BOOL stripOthers, int id3v2Version);
+TAGLIB_C_EXPORT BOOL taglib_mpeg_file_save3(TagLib_Mpeg_File *file, int tags, BOOL stripOthers, int id3v2Version, BOOL duplicateTags);
/*!
- * bool TagLib::MPEG:File::strip(int tags);
+ * bool TagLib::MPEG::File::strip(int tags, bool freeMemory);
*/
-TAGLIB_C_EXPORT BOOL taglib_mpeg_file_strip(TagLib_Mpeg_File *file, int tags);
+TAGLIB_C_EXPORT BOOL taglib_mpeg_file_strip(TagLib_Mpeg_File *file, int tags, BOOL freeMemory);
/*******************************************************************************
* Special convenience ID3v2 functions
@@ -309,6 +351,275 @@ TAGLIB_C_EXPORT void taglib_id3v2_set_default_text_enc
*/
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(const 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(const 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);
+
+/******************************************************************************
+ * Complex Properties API
+ ******************************************************************************/
+
+/*!
+ * Types which can be stored in a TagLib_Variant.
+ *
+ * \related TagLib::Variant::Type
+ * These correspond to TagLib::Variant::Type, but ByteVectorList, VariantList,
+ * VariantMap are not supported and will be returned as their string
+ * representation.
+ */
+typedef enum {
+ TagLib_Variant_Void,
+ TagLib_Variant_Bool,
+ TagLib_Variant_Int,
+ TagLib_Variant_UInt,
+ TagLib_Variant_LongLong,
+ TagLib_Variant_ULongLong,
+ TagLib_Variant_Double,
+ TagLib_Variant_String,
+ TagLib_Variant_StringList,
+ TagLib_Variant_ByteVector
+} TagLib_Variant_Type;
+
+/*!
+ * Discriminated union used in complex property attributes.
+ *
+ * \e type must be set according to the \e value union used.
+ * \e size is only required for TagLib_Variant_ByteVector and must contain
+ * the number of bytes.
+ *
+ * \related TagLib::Variant.
+ */
+typedef struct {
+ TagLib_Variant_Type type;
+ unsigned int size;
+ union {
+ char *stringValue;
+ char *byteVectorValue;
+ char **stringListValue;
+ BOOL boolValue;
+ int intValue;
+ unsigned int uIntValue;
+ long long longLongValue;
+ unsigned long long uLongLongValue;
+ double doubleValue;
+ } value;
+} TagLib_Variant;
+
+/*!
+ * Attribute of a complex property.
+ * Complex properties consist of a NULL-terminated array of pointers to
+ * this structure with \e key and \e value.
+ */
+typedef struct {
+ char *key;
+ TagLib_Variant value;
+} TagLib_Complex_Property_Attribute;
+
+/*!
+ * Picture data extracted from a complex property by the convenience function
+ * taglib_picture_from_complex_property().
+ */
+typedef struct {
+ char *mimeType;
+ char *description;
+ char *pictureType;
+ char *data;
+ unsigned int size;
+} TagLib_Complex_Property_Picture_Data;
+
+/*!
+ * Declare complex property attributes to set a picture.
+ * Can be used to define a variable \a var which can be used with
+ * taglib_complex_property_set() and a "PICTURE" key to set an
+ * embedded picture with the picture data \a dat of size \a siz
+ * and description \a desc, mime type \a mime and picture type
+ * \a typ (size is unsigned int, the other input parameters char *).
+ */
+#define TAGLIB_COMPLEX_PROPERTY_PICTURE(var, dat, siz, desc, mime, typ) \
+const TagLib_Complex_Property_Attribute \
+var##Attrs[] = { \
+ { \
+ (char *)"data", \
+ { \
+ TagLib_Variant_ByteVector, \
+ (siz), \
+ { \
+ (char *)(dat) \
+ } \
+ } \
+ }, \
+ { \
+ (char *)"mimeType", \
+ { \
+ TagLib_Variant_String, \
+ 0U, \
+ { \
+ (char *)(mime) \
+ } \
+ } \
+ }, \
+ { \
+ (char *)"description", \
+ { \
+ TagLib_Variant_String, \
+ 0U, \
+ { \
+ (char *)(desc) \
+ } \
+ } \
+ }, \
+ { \
+ (char *)"pictureType", \
+ { \
+ TagLib_Variant_String, \
+ 0U, \
+ { \
+ (char *)(typ) \
+ } \
+ } \
+ } \
+}; \
+const TagLib_Complex_Property_Attribute *var[] = { \
+ &var##Attrs[0], &var##Attrs[1], &var##Attrs[2], \
+ &var##Attrs[3], NULL \
+}
+
+/*!
+ * Sets the complex property \a key with \a value. Use \a value = NULL to
+ * remove the property, otherwise it will be replaced with the NULL
+ * terminated array of attributes in \a value.
+ *
+ * A picture can be set with the TAGLIB_COMPLEX_PROPERTY_PICTURE macro:
+ *
+ * \code {.c}
+ * TagLib_File *file = taglib_file_new("myfile.mp3");
+ * FILE *fh = fopen("mypicture.jpg", "rb");
+ * if(fh) {
+ * fseek(fh, 0L, SEEK_END);
+ * long size = ftell(fh);
+ * fseek(fh, 0L, SEEK_SET);
+ * char *data = (char *)malloc(size);
+ * fread(data, size, 1, fh);
+ * TAGLIB_COMPLEX_PROPERTY_PICTURE(props, data, size, "Written by TagLib",
+ * "image/jpeg", "Front Cover");
+ * taglib_complex_property_set(file, "PICTURE", props);
+ * taglib_file_save(file);
+ * free(data);
+ * fclose(fh);
+ * }
+ * \endcode
+ */
+TAGLIB_C_EXPORT BOOL taglib_complex_property_set(
+ TagLib_File *file, const char *key,
+ const TagLib_Complex_Property_Attribute **value);
+
+/*!
+ * Appends \a value to the complex property \a key (sets it if non-existing).
+ * Use \a value = NULL to remove all values associated with the \a key.
+ */
+TAGLIB_C_EXPORT BOOL taglib_complex_property_set_append(
+ TagLib_File *file, const char *key,
+ const TagLib_Complex_Property_Attribute **value);
+
+/*!
+ * Get the keys of the complex properties.
+ *
+ * \return NULL terminated array of C-strings (char *), only NULL if empty.
+ * It must be freed by the client using taglib_complex_property_free_keys().
+ */
+TAGLIB_C_EXPORT char** taglib_complex_property_keys(const TagLib_File *file);
+
+/*!
+ * Get value(s) of complex property \a key.
+ *
+ * \return NULL terminated array of property values, which are themselves an
+ * array of property attributes, only NULL if empty.
+ * It must be freed by the client using taglib_complex_property_free().
+ */
+TAGLIB_C_EXPORT TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
+ const TagLib_File *file, const char *key);
+
+/*!
+ * Extract the complex property values of a picture.
+ *
+ * This function can be used to get the data from a "PICTURE" complex property
+ * without having to traverse the whole variant map. A picture can be
+ * retrieved like this:
+ *
+ * \code {.c}
+ * TagLib_File *file = taglib_file_new("myfile.mp3");
+ * TagLib_Complex_Property_Attribute*** properties =
+ * taglib_complex_property_get(file, "PICTURE");
+ * TagLib_Complex_Property_Picture_Data picture;
+ * taglib_picture_from_complex_property(properties, &picture);
+ * // Do something with picture.mimeType, picture.description,
+ * // picture.pictureType, picture.data, picture.size, e.g. extract it.
+ * FILE *fh = fopen("mypicture.jpg", "wb");
+ * if(fh) {
+ * fwrite(picture.data, picture.size, 1, fh);
+ * fclose(fh);
+ * }
+ * taglib_complex_property_free(properties);
+ * \endcode
+ *
+ * Note that the data in \a picture contains pointers to data in \a properties,
+ * i.e. it only lives as long as the properties, until they are freed with
+ * taglib_complex_property_free().
+ * If you want to access multiple pictures or additional properties of FLAC
+ * pictures ("width", "height", "numColors", "colorDepth" int values), you
+ * have to traverse the \a properties yourself.
+ */
+TAGLIB_C_EXPORT void taglib_picture_from_complex_property(
+ TagLib_Complex_Property_Attribute*** properties,
+ TagLib_Complex_Property_Picture_Data *picture);
+
+/*!
+ * Frees the NULL terminated array \a keys (as returned by
+ * taglib_complex_property_keys()) and the C-strings it contains.
+ */
+TAGLIB_C_EXPORT void taglib_complex_property_free_keys(char **keys);
+
+/*!
+ * Frees the NULL terminated array \a props of property attribute arrays
+ * (as returned by taglib_complex_property_get()) and the data such as
+ * C-strings and byte vectors contained in these attributes.
+ */
+TAGLIB_C_EXPORT void taglib_complex_property_free(
+ TagLib_Complex_Property_Attribute ***props);
#ifdef __cplusplus
}