1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-21 23:00:06 +02:00

Remove naked malloc (or similar) and free in: export

This commit is contained in:
Paul Licameli 2017-02-25 18:12:04 -05:00
parent 9314fe0cc0
commit 1614db9994
8 changed files with 131 additions and 149 deletions

View File

@ -240,7 +240,7 @@ wxWindow *ExportPlugin::OptionsCreate(wxWindow *parent, int WXUNUSED(format))
std::unique_ptr<Mixer> ExportPlugin::CreateMixer(const WaveTrackConstArray &inputTracks,
const TimeTrack *timeTrack,
double startTime, double stopTime,
unsigned numOutChannels, int outBufferSize, bool outInterleaved,
unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
double outRate, sampleFormat outFormat,
bool highQuality, MixerSpec *mixerSpec)
{

View File

@ -123,7 +123,7 @@ protected:
std::unique_ptr<Mixer> CreateMixer(const WaveTrackConstArray &inputTracks,
const TimeTrack *timeTrack,
double startTime, double stopTime,
unsigned numOutChannels, int outBufferSize, bool outInterleaved,
unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
double outRate, sampleFormat outFormat,
bool highQuality = true, MixerSpec *mixerSpec = NULL);

View File

@ -857,7 +857,7 @@ ProgressResult ExportFFmpeg::Export(AudacityProject *project,
if (!ret)
return ProgressResult::Cancelled;
int pcmBufferSize = 1024;
size_t pcmBufferSize = 1024;
const WaveTrackConstArray waveTracks =
tracks->GetWaveTrackConstArray(selectionOnly, false);
auto mixer = CreateMixer(waveTracks,

View File

@ -173,6 +173,14 @@ static struct
//----------------------------------------------------------------------------
struct FLAC__StreamMetadataDeleter {
void operator () (FLAC__StreamMetadata *p) const
{ if (p) ::FLAC__metadata_object_delete(p); }
};
using FLAC__StreamMetadataHandle = std::unique_ptr<
FLAC__StreamMetadata, FLAC__StreamMetadataDeleter
>;
class ExportFLAC final : public ExportPlugin
{
public:
@ -196,7 +204,7 @@ private:
bool GetMetadata(AudacityProject *project, const Tags *tags);
FLAC__StreamMetadata *mMetadata;
FLAC__StreamMetadataHandle mMetadata;
};
//----------------------------------------------------------------------------
@ -248,7 +256,10 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
}
if (mMetadata) {
encoder.set_metadata(&mMetadata, 1);
// set_metadata expects an array of pointers to metadata and a size.
// The size is 1.
FLAC__StreamMetadata *p = mMetadata.get();
encoder.set_metadata(&p, 1);
}
sampleFormat format;
@ -299,9 +310,7 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
}
#endif
if (mMetadata) {
::FLAC__metadata_object_delete(mMetadata);
}
mMetadata.reset();
const WaveTrackConstArray waveTracks =
tracks->GetWaveTrackConstArray(selectionOnly, false);
@ -367,7 +376,7 @@ bool ExportFLAC::GetMetadata(AudacityProject *project, const Tags *tags)
if (tags == NULL)
tags = project->GetTags();
mMetadata = ::FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
mMetadata.reset(::FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT));
wxString n;
for (const auto &pair : tags->GetRange()) {
@ -378,7 +387,7 @@ bool ExportFLAC::GetMetadata(AudacityProject *project, const Tags *tags)
}
FLAC::Metadata::VorbisComment::Entry entry(n.mb_str(wxConvUTF8),
v.mb_str(wxConvUTF8));
::FLAC__metadata_object_vorbiscomment_append_comment(mMetadata,
::FLAC__metadata_object_vorbiscomment_append_comment(mMetadata.get(),
entry.get_entry(),
true);
}

View File

@ -185,7 +185,7 @@ public:
private:
int AddTags(AudacityProject *project, char **buffer, bool *endOfFile, const Tags *tags);
int AddTags(AudacityProject *project, ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags);
#ifdef USE_LIBID3TAG
void AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name);
#endif
@ -242,15 +242,15 @@ ProgressResult ExportMP2::Export(AudacityProject *project,
return ProgressResult::Cancelled;
}
char *id3buffer = NULL;
ArrayOf<char> id3buffer;
int id3len;
bool endOfFile;
id3len = AddTags(project, &id3buffer, &endOfFile, metadata);
id3len = AddTags(project, id3buffer, &endOfFile, metadata);
if (id3len && !endOfFile)
outFile.Write(id3buffer, id3len);
outFile.Write(id3buffer.get(), id3len);
// Values taken from the twolame simple encoder sample
const int pcmBufferSize = 9216 / 2; // number of samples
const size_t pcmBufferSize = 9216 / 2; // number of samples
const size_t mp2BufferSize = 16384u; // bytes
// We allocate a buffer which is twice as big as the
@ -307,11 +307,7 @@ ProgressResult ExportMP2::Export(AudacityProject *project,
/* Write ID3 tag if it was supposed to be at the end of the file */
if (id3len && endOfFile)
outFile.Write(id3buffer, id3len);
if (id3buffer) {
free(id3buffer);
}
outFile.Write(id3buffer.get(), id3len);
/* Close file */
@ -326,11 +322,16 @@ wxWindow *ExportMP2::OptionsCreate(wxWindow *parent, int format)
return safenew ExportMP2Options(parent, format);
}
struct id3_tag_deleter {
void operator () (id3_tag *p) const { if (p) id3_tag_delete(p); }
};
using id3_tag_holder = std::unique_ptr<id3_tag, id3_tag_deleter>;
// returns buffer len; caller frees
int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool *endOfFile, const Tags *tags)
int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags)
{
#ifdef USE_LIBID3TAG
struct id3_tag *tp = id3_tag_new();
id3_tag_holder tp { id3_tag_new() };
for (const auto &pair : tags->GetRange()) {
const auto &n = pair.first;
@ -349,7 +350,7 @@ int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool
else if (n.CmpNoCase(TAG_YEAR) == 0) {
// LLL: Some apps do not like the newer frame ID (ID3_FRAME_YEAR),
// so we add old one as well.
AddFrame(tp, n, v, "TYER");
AddFrame(tp.get(), n, v, "TYER");
name = ID3_FRAME_YEAR;
}
else if (n.CmpNoCase(TAG_GENRE) == 0) {
@ -362,7 +363,7 @@ int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool
name = ID3_FRAME_TRACK;
}
AddFrame(tp, n, v, name);
AddFrame(tp.get(), n, v, name);
}
tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression
@ -378,11 +379,10 @@ int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool
id3_length_t len;
len = id3_tag_render(tp, 0);
*buffer = (char *)malloc(len);
len = id3_tag_render(tp, (id3_byte_t *)*buffer);
len = id3_tag_render(tp.get(), 0);
buffer.reinit(len);
len = id3_tag_render(tp.get(), (id3_byte_t *)buffer.get());
id3_tag_delete(tp);
return len;
#else //ifdef USE_LIBID3TAG
@ -402,8 +402,8 @@ void ExportMP2::AddFrame(struct id3_tag *tp, const wxString & n, const wxString
id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1);
}
id3_ucs4_t *ucs4 =
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8));
MallocString<id3_ucs4_t> ucs4 {
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)) };
if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
// A hack to get around iTunes not recognizing the comment. The
@ -413,22 +413,20 @@ void ExportMP2::AddFrame(struct id3_tag *tp, const wxString & n, const wxString
// way of clearing the field, so do it directly.
id3_field *f = id3_frame_field(frame, 1);
memset(f->immediate.value, 0, sizeof(f->immediate.value));
id3_field_setfullstring(id3_frame_field(frame, 3), ucs4);
id3_field_setfullstring(id3_frame_field(frame, 3), ucs4.get());
}
else if (strcmp(name, "TXXX") == 0) {
id3_field_setstring(id3_frame_field(frame, 2), ucs4);
free(ucs4);
id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8));
ucs4.reset(id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)));
id3_field_setstring(id3_frame_field(frame, 1), ucs4);
id3_field_setstring(id3_frame_field(frame, 1), ucs4.get());
}
else {
id3_field_setstrings(id3_frame_field(frame, 1), 1, &ucs4);
auto addr = ucs4.get();
id3_field_setstrings(id3_frame_field(frame, 1), 1, &addr);
}
free(ucs4);
id3_tag_attachframe(tp, frame);
}
#endif

View File

@ -1617,7 +1617,7 @@ private:
int FindValue(CHOICES *choices, int cnt, int needle, int def);
wxString FindName(CHOICES *choices, int cnt, int needle);
int AskResample(int bitrate, int rate, int lowrate, int highrate);
int AddTags(AudacityProject *project, char **buffer, bool *endOfFile, const Tags *tags);
int AddTags(AudacityProject *project, ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags);
#ifdef USE_LIBID3TAG
void AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name);
#endif
@ -1796,12 +1796,12 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
return ProgressResult::Cancelled;
}
char *id3buffer = NULL;
ArrayOf<char> id3buffer;
int id3len;
bool endOfFile;
id3len = AddTags(project, &id3buffer, &endOfFile, metadata);
id3len = AddTags(project, id3buffer, &endOfFile, metadata);
if (id3len && !endOfFile) {
outFile.Write(id3buffer, id3len);
outFile.Write(id3buffer.get(), id3len);
}
wxFileOffset pos = outFile.Tell();
@ -1890,11 +1890,7 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
// Write ID3 tag if it was supposed to be at the end of the file
if (id3len && endOfFile) {
outFile.Write(id3buffer, id3len);
}
if (id3buffer) {
free(id3buffer);
outFile.Write(id3buffer.get(), id3len);
}
// Always write the info (Xing/Lame) tag. Until we stop supporting Lame
@ -2008,11 +2004,16 @@ int ExportMP3::AskResample(int bitrate, int rate, int lowrate, int highrate)
return wxAtoi(choice->GetStringSelection());
}
struct id3_tag_deleter {
void operator () (id3_tag *p) const { if (p) id3_tag_delete(p); }
};
using id3_tag_holder = std::unique_ptr<id3_tag, id3_tag_deleter>;
// returns buffer len; caller frees
int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), char **buffer, bool *endOfFile, const Tags *tags)
int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags)
{
#ifdef USE_LIBID3TAG
struct id3_tag *tp = id3_tag_new();
id3_tag_holder tp { id3_tag_new() };
for (const auto &pair : tags->GetRange()) {
const auto &n = pair.first;
@ -2031,7 +2032,7 @@ int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), char **buffer, bool *
else if (n.CmpNoCase(TAG_YEAR) == 0) {
// LLL: Some apps do not like the newer frame ID (ID3_FRAME_YEAR),
// so we add old one as well.
AddFrame(tp, n, v, "TYER");
AddFrame(tp.get(), n, v, "TYER");
name = ID3_FRAME_YEAR;
}
else if (n.CmpNoCase(TAG_GENRE) == 0) {
@ -2044,7 +2045,7 @@ int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), char **buffer, bool *
name = ID3_FRAME_TRACK;
}
AddFrame(tp, n, v, name);
AddFrame(tp.get(), n, v, name);
}
tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression
@ -2060,11 +2061,9 @@ int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), char **buffer, bool *
id3_length_t len;
len = id3_tag_render(tp, 0);
*buffer = (char *)malloc(len);
len = id3_tag_render(tp, (id3_byte_t *)*buffer);
id3_tag_delete(tp);
len = id3_tag_render(tp.get(), 0);
buffer.reinit(len);
len = id3_tag_render(tp.get(), (id3_byte_t *)buffer.get());
return len;
#else //ifdef USE_LIBID3TAG
@ -2084,8 +2083,8 @@ void ExportMP3::AddFrame(struct id3_tag *tp, const wxString & n, const wxString
id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1);
}
id3_ucs4_t *ucs4 =
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8));
MallocString<id3_ucs4_t> ucs4{
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)) };
if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
// A hack to get around iTunes not recognizing the comment. The
@ -2094,27 +2093,25 @@ void ExportMP3::AddFrame(struct id3_tag *tp, const wxString & n, const wxString
// (which one???) or just clear it. Unfortunately, there's no supported
// way of clearing the field, so do it directly.
struct id3_frame *frame2 = id3_frame_new(name);
id3_field_setfullstring(id3_frame_field(frame2, 3), ucs4);
id3_field_setfullstring(id3_frame_field(frame2, 3), ucs4.get());
id3_field *f2 = id3_frame_field(frame2, 1);
memset(f2->immediate.value, 0, sizeof(f2->immediate.value));
id3_tag_attachframe(tp, frame2);
// Now install a second frame with the standard default language = "XXX"
id3_field_setfullstring(id3_frame_field(frame, 3), ucs4);
id3_field_setfullstring(id3_frame_field(frame, 3), ucs4.get());
}
else if (strcmp(name, "TXXX") == 0) {
id3_field_setstring(id3_frame_field(frame, 2), ucs4);
free(ucs4);
id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8));
ucs4.reset(id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)));
id3_field_setstring(id3_frame_field(frame, 1), ucs4);
id3_field_setstring(id3_frame_field(frame, 1), ucs4.get());
}
else {
id3_field_setstrings(id3_frame_field(frame, 1), 1, &ucs4);
auto addr = ucs4.get();
id3_field_setstrings(id3_frame_field(frame, 1), 1, &addr);
}
free(ucs4);
id3_tag_attachframe(tp, frame);
}
#endif

View File

@ -121,7 +121,7 @@ bool ExportOGGOptions::TransferDataFromWindow()
// ExportOGG
//----------------------------------------------------------------------------
#define SAMPLES_PER_RUN 8192
#define SAMPLES_PER_RUN 8192u
class ExportOGG final : public ExportPlugin
{

View File

@ -28,6 +28,7 @@
#include "../FileFormats.h"
#include "../Internat.h"
#include "../MemoryX.h"
#include "../Mix.h"
#include "../Prefs.h"
#include "../Project.h"
@ -328,7 +329,7 @@ public:
private:
char *AdjustString(const wxString & wxStr, int sf_format);
ArrayOf<char> AdjustString(const wxString & wxStr, int sf_format);
bool AddStrings(AudacityProject *project, SNDFILE *sf, const Tags *tags, int sf_format);
void AddID3Chunk(wxString fName, const Tags *tags, int sf_format);
@ -472,7 +473,7 @@ ProgressResult ExportPCM::Export(AudacityProject *project,
else
format = int16Sample;
int maxBlockLen = 44100 * 5;
size_t maxBlockLen = 44100 * 5;
const WaveTrackConstArray waveTracks =
tracks->GetWaveTrackConstArray(selectionOnly, false);
@ -538,7 +539,7 @@ ProgressResult ExportPCM::Export(AudacityProject *project,
return updateResult;
}
char *ExportPCM::AdjustString(const wxString & wxStr, int sf_format)
ArrayOf<char> ExportPCM::AdjustString(const wxString & wxStr, int sf_format)
{
bool b_aiff = false;
if ((sf_format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF)
@ -547,34 +548,26 @@ char *ExportPCM::AdjustString(const wxString & wxStr, int sf_format)
// We must convert the string to 7 bit ASCII
size_t sz = wxStr.length();
if(sz == 0)
return NULL;
// Size for secure malloc in case of local wide char usage
return {};
// Size for secure allocation in case of local wide char usage
size_t sr = (sz+4) * 2;
char *pDest = (char *)malloc(sr);
ArrayOf<char> pDest{ sr, true };
if (!pDest)
return NULL;
char *pSrc = (char *)malloc(sr);
return {};
ArrayOf<char> pSrc{ sr, true };
if (!pSrc)
{
free(pDest);
return NULL;
}
memset(pDest, 0, sr);
memset(pSrc, 0, sr);
return {};
if(wxStr.mb_str(wxConvISO8859_1))
strncpy(pSrc, wxStr.mb_str(wxConvISO8859_1), sz);
strncpy(pSrc.get(), wxStr.mb_str(wxConvISO8859_1), sz);
else if(wxStr.mb_str())
strncpy(pSrc, wxStr.mb_str(), sz);
else {
free(pDest);
free(pSrc);
return NULL;
}
strncpy(pSrc.get(), wxStr.mb_str(), sz);
else
return {};
char *pD = pDest;
char *pS = pSrc;
char *pD = pDest.get();
char *pS = pSrc.get();
unsigned char c;
// ISO Latin to 7 bit ascii conversion table (best approximation)
@ -622,13 +615,11 @@ char *ExportPCM::AdjustString(const wxString & wxStr, int sf_format)
}
*pD = '\0';
free(pSrc);
if(b_aiff) {
int len = (int)strlen(pDest);
int len = (int)strlen(pDest.get());
if((len % 2) != 0) {
// In case of an odd length string, add a space char
strcat(pDest, " ");
strcat(pDest.get(), " ");
}
}
@ -638,84 +629,80 @@ char *ExportPCM::AdjustString(const wxString & wxStr, int sf_format)
bool ExportPCM::AddStrings(AudacityProject * WXUNUSED(project), SNDFILE *sf, const Tags *tags, int sf_format)
{
if (tags->HasTag(TAG_TITLE)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_TITLE), sf_format);
auto ascii7Str = AdjustString(tags->GetTag(TAG_TITLE), sf_format);
if (ascii7Str) {
sf_set_string(sf, SF_STR_TITLE, ascii7Str);
free(ascii7Str);
sf_set_string(sf, SF_STR_TITLE, ascii7Str.get());
}
}
if (tags->HasTag(TAG_ALBUM)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_ALBUM), sf_format);
auto ascii7Str = AdjustString(tags->GetTag(TAG_ALBUM), sf_format);
if (ascii7Str) {
sf_set_string(sf, SF_STR_ALBUM, ascii7Str);
free(ascii7Str);
sf_set_string(sf, SF_STR_ALBUM, ascii7Str.get());
}
}
if (tags->HasTag(TAG_ARTIST)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_ARTIST), sf_format);
auto ascii7Str = AdjustString(tags->GetTag(TAG_ARTIST), sf_format);
if (ascii7Str) {
sf_set_string(sf, SF_STR_ARTIST, ascii7Str);
free(ascii7Str);
sf_set_string(sf, SF_STR_ARTIST, ascii7Str.get());
}
}
if (tags->HasTag(TAG_COMMENTS)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_COMMENTS), sf_format);
auto ascii7Str = AdjustString(tags->GetTag(TAG_COMMENTS), sf_format);
if (ascii7Str) {
sf_set_string(sf, SF_STR_COMMENT, ascii7Str);
free(ascii7Str);
sf_set_string(sf, SF_STR_COMMENT, ascii7Str.get());
}
}
if (tags->HasTag(TAG_YEAR)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_YEAR), sf_format);
auto ascii7Str = AdjustString(tags->GetTag(TAG_YEAR), sf_format);
if (ascii7Str) {
sf_set_string(sf, SF_STR_DATE, ascii7Str);
free(ascii7Str);
sf_set_string(sf, SF_STR_DATE, ascii7Str.get());
}
}
if (tags->HasTag(TAG_GENRE)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_GENRE), sf_format);
auto ascii7Str = AdjustString(tags->GetTag(TAG_GENRE), sf_format);
if (ascii7Str) {
sf_set_string(sf, SF_STR_GENRE, ascii7Str);
free(ascii7Str);
sf_set_string(sf, SF_STR_GENRE, ascii7Str.get());
}
}
if (tags->HasTag(TAG_COPYRIGHT)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_COPYRIGHT), sf_format);
auto ascii7Str = AdjustString(tags->GetTag(TAG_COPYRIGHT), sf_format);
if (ascii7Str) {
sf_set_string(sf, SF_STR_COPYRIGHT, ascii7Str);
free(ascii7Str);
sf_set_string(sf, SF_STR_COPYRIGHT, ascii7Str.get());
}
}
if (tags->HasTag(TAG_SOFTWARE)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_SOFTWARE), sf_format);
auto ascii7Str = AdjustString(tags->GetTag(TAG_SOFTWARE), sf_format);
if (ascii7Str) {
sf_set_string(sf, SF_STR_SOFTWARE, ascii7Str);
free(ascii7Str);
sf_set_string(sf, SF_STR_SOFTWARE, ascii7Str.get());
}
}
if (tags->HasTag(TAG_TRACK)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_TRACK), sf_format);
auto ascii7Str = AdjustString(tags->GetTag(TAG_TRACK), sf_format);
if (ascii7Str) {
sf_set_string(sf, SF_STR_TRACKNUMBER, ascii7Str);
free(ascii7Str);
sf_set_string(sf, SF_STR_TRACKNUMBER, ascii7Str.get());
}
}
return true;
}
struct id3_tag_deleter {
void operator () (id3_tag *p) const { if (p) id3_tag_delete(p); }
};
using id3_tag_holder = std::unique_ptr<id3_tag, id3_tag_deleter>;
void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
{
#ifdef USE_LIBID3TAG
struct id3_tag *tp = id3_tag_new();
id3_tag_holder tp { id3_tag_new() };
for (const auto &pair : tags->GetRange()) {
const auto &n = pair.first;
@ -756,8 +743,8 @@ void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1);
}
id3_ucs4_t *ucs4 =
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8));
MallocString<id3_ucs4_t> ucs4{
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)) };
if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
// A hack to get around iTunes not recognizing the comment. The
@ -767,23 +754,21 @@ void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
// way of clearing the field, so do it directly.
id3_field *f = id3_frame_field(frame, 1);
memset(f->immediate.value, 0, sizeof(f->immediate.value));
id3_field_setfullstring(id3_frame_field(frame, 3), ucs4);
id3_field_setfullstring(id3_frame_field(frame, 3), ucs4.get());
}
else if (strcmp(name, "TXXX") == 0) {
id3_field_setstring(id3_frame_field(frame, 2), ucs4);
free(ucs4);
id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8));
ucs4.reset(id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)));
id3_field_setstring(id3_frame_field(frame, 1), ucs4);
id3_field_setstring(id3_frame_field(frame, 1), ucs4.get());
}
else {
id3_field_setstrings(id3_frame_field(frame, 1), 1, &ucs4);
auto addr = ucs4.get();
id3_field_setstrings(id3_frame_field(frame, 1), 1, &addr);
}
free(ucs4);
id3_tag_attachframe(tp, frame);
id3_tag_attachframe(tp.get(), frame);
}
tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression
@ -797,24 +782,19 @@ void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
id3_length_t len;
len = id3_tag_render(tp, 0);
if (len == 0) {
id3_tag_delete(tp);
len = id3_tag_render(tp.get(), 0);
if (len == 0)
return;
}
if ((len % 2) != 0) len++; // Length must be even.
id3_byte_t *buffer = (id3_byte_t *)malloc(len);
if (buffer == NULL) {
id3_tag_delete(tp);
ArrayOf<id3_byte_t> buffer { len, true };
if (buffer == NULL)
return;
}
// Zero all locations, for ending odd UTF16 content
// correctly, i.e., two '\0's at the end.
memset(buffer, 0, len);
id3_tag_render(tp, buffer);
id3_tag_delete(tp);
id3_tag_render(tp.get(), buffer.get());
wxFFile f(fName, wxT("r+b"));
// FIXME: TRAP_ERR wxFFILE ops in Export PCM ID3 could fail.
@ -831,7 +811,7 @@ void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
}
f.Write(&sz, 4);
f.Write(buffer, len);
f.Write(buffer.get(), len);
sz = (wxUint32) f.Tell() - 8;
if ((sf_format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF)
@ -842,8 +822,6 @@ void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
f.Close();
}
free(buffer);
#endif
return;
}