mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-21 06:40:08 +02:00
Remove naked malloc (or similar) and free in: export
This commit is contained in:
parent
9314fe0cc0
commit
1614db9994
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -121,7 +121,7 @@ bool ExportOGGOptions::TransferDataFromWindow()
|
||||
// ExportOGG
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define SAMPLES_PER_RUN 8192
|
||||
#define SAMPLES_PER_RUN 8192u
|
||||
|
||||
class ExportOGG final : public ExportPlugin
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user