21#define DESC XO("MP3 files")
62 auto end = it + std::strlen(it);
70 if (result.ec != std::errc {})
73 const auto parsedGenre = tags.
GetGenre(tagValue);
75 if (!parsedGenre.empty())
104#if MPG123_API_VERSION < 46
113 return wxT(
"libmpg123");
136 bool SetupOutputFormat();
138 void ReadTags(
Tags* tags);
148 static ptrdiff_t ReadCallback(
void* handle,
void* buffer,
size_t size);
149 static off_t SeekCallback(
void* handle, off_t offset,
int whence);
160 mpg123_handle* mHandle {
nullptr };
162 bool mFloat64Output {};
170 auto handle = std::make_unique<MP3ImportFileHandle>(Filename);
181 std::make_unique<MP3ImportPlugin>()
191 int errorCode = MPG123_OK;
192 mHandle = mpg123_new(
nullptr, &errorCode);
194 if (errorCode != MPG123_OK)
197 "Failed to create MPG123 handle: %s",
198 mpg123_plain_strerror(errorCode));
205 errorCode = mpg123_replace_reader_handle(
208 if (errorCode != MPG123_OK)
211 "Failed to set reader on the MPG123 handle: %s",
212 mpg123_plain_strerror(errorCode));
219 mpg123_param(
mHandle, MPG123_FLAGS, MPG123_FORCE_FLOAT, 0.0);
221 if (errorCode != MPG123_OK)
224 "Failed to set options on the MPG123 handle",
225 mpg123_plain_strerror(errorCode));
269 auto finalAction =
finally([handle =
mHandle]() { mpg123_close(handle); });
276 long long framesCount = mpg123_framelength(
mHandle);
284 return ProgressResult::Failed;
286 off_t frameIndex { 0 };
287 unsigned char* data {
nullptr };
288 size_t dataSize { 0 };
290 std::vector<float> conversionBuffer;
294 while ((ret = mpg123_decode_frame(
mHandle, &frameIndex, &data, &dataSize)) ==
298 static_cast<long long>(frameIndex), framesCount);
304 const size_t samplesCount = dataSize /
sizeof(float) /
mNumChannels;
312 for (
size_t sampleIndex = 0; sampleIndex < conversionBuffer.size();
315 conversionBuffer[sampleIndex] =
static_cast<float>(
316 reinterpret_cast<const double*
>(data)[sampleIndex]);
319 samples =
reinterpret_cast<constSamplePtr>(conversionBuffer.data());
322 for (
unsigned channel = 0; channel <
mNumChannels; ++channel)
325 samples +
sizeof(
float) * channel,
floatSample, samplesCount,
330 if (ret != MPG123_DONE)
333 "Failed to decode MP3 file: %s", mpg123_plain_strerror(ret));
335 return ProgressResult::Failed;
344 outTracks.push_back(std::move(
mChannels));
355 int encoding = MPG123_ENC_FLOAT_32;
356 mpg123_getformat(
mHandle, &rate, &channels, &encoding);
361 if (encoding != MPG123_ENC_FLOAT_32 && encoding != MPG123_ENC_FLOAT_64)
363 wxLogError(
"MPG123 returned unexpected encoding");
382 meta = mpg123_meta_check(
mHandle);
384 if (meta & MPG123_ID3 && mpg123_id3(
mHandle, &v1, &v2) == MPG123_OK)
386 if (v2 !=
nullptr && v2->title !=
nullptr && v2->title->fill > 0)
388 else if (v1 !=
nullptr && v1->title[0] !=
'\0')
391 if (v2 !=
nullptr && v2->artist !=
nullptr && v2->artist->fill > 0)
393 else if (v1 !=
nullptr && v1->artist[0] !=
'\0')
396 if (v2 !=
nullptr && v2->album !=
nullptr && v2->album->fill > 0)
398 else if (v1 !=
nullptr && v1->album[0] !=
'\0')
401 if (v2 !=
nullptr && v2->year !=
nullptr && v2->year->fill > 0)
403 else if (v1 !=
nullptr && v1->year[0] !=
'\0')
406 if (v2 !=
nullptr && v2->genre !=
nullptr && v2->genre->fill > 0)
408 else if (v1 !=
nullptr)
411 if (v2 !=
nullptr && v2->comment !=
nullptr && v2->comment->fill > 0)
413 else if (v1 !=
nullptr && v1->comment[0] !=
'\0')
418 for (
size_t i = 0; i < v2->comments; ++i)
420 if (v2->comment_list[i].text.fill == 0)
428 for (
size_t i = 0; i < v2->extras; ++i)
430 if (v2->extra[i].text.fill == 0)
439 for (
size_t i = 0; i < v2->texts; ++i)
441 if (memcmp(v2->text[i].id,
"TRCK", 4) == 0)
471 if (
mFile.Seek(0, wxFromStart) == wxInvalidOffset ||
mFile.Error())
478 auto errorCode = mpg123_open_handle(
mHandle,
this);
480 if (errorCode != MPG123_OK)
484 errorCode = mpg123_scan(
mHandle);
486 if (errorCode != MPG123_OK)
490 errorCode = mpg123_decode_frame(
mHandle,
nullptr,
nullptr,
nullptr);
493 if (errorCode != MPG123_NEW_FORMAT)
500 void* handle,
void* buffer,
size_t size)
512 return wxFromCurrent;
524 void* handle, off_t offset,
int whence)
Toolkit-neutral facade for basic user interface services.
Declare functions to perform UTF-8 to std::wstring conversions.
FromCharsResult FromChars(const char *buffer, const char *last, float &value) noexcept
Parse a string into a single precision floating point value, always uses the dot as decimal.
Declare functions to convert numeric types to string representation.
std::vector< std::vector< std::shared_ptr< WaveTrack > > > TrackHolders
The interface that all file import "plugins" (if you want to call them that) must implement....
std::vector< TranslatableString > TranslatableStrings
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
An ImportFileHandle for data.
unsigned long long ByteCount
std::unique_ptr< ProgressDialog > mProgress
std::shared_ptr< WaveTrack > NewWaveTrack(WaveTrackFactory &trackFactory, sampleFormat effectiveFormat, double rate)
Build a wave track with appropriate format, which will not be narrower than the specified one.
Base class for FlacImportPlugin, LOFImportPlugin, MP3ImportPlugin, OggImportPlugin and PCMImportPlugi...
ProgressResult Import(WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags) override
ByteCount GetFileUncompressedBytes() override
MP3ImportFileHandle(const FilePath &filename)
const TranslatableStrings & GetStreamInfo() override
TranslatableString GetFileDescription() override
wxInt32 GetStreamCount() override
ProgressResult mUpdateResult
WaveTrackFactory * mTrackFactory
std::unique_ptr< ImportFileHandle > Open(const FilePath &Filename, AudacityProject *) override
Holds a msgid for the translation catalog; may also bind format arguments.
Used to create or clone a WaveTrack, with appropriate context from the project that will own the trac...
ProgressResult Import(WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags) override
ByteCount GetFileUncompressedBytes() override
const TranslatableStrings & GetStreamInfo() override
static ptrdiff_t ReadCallback(void *handle, void *buffer, size_t size)
WaveTrackFactory * mTrackFactory
static off_t SeekCallback(void *handle, off_t offset, int whence)
ProgressResult mUpdateResult
void ReadTags(Tags *tags)
NewChannelGroup mChannels
TranslatableString GetFileDescription() override
wxInt32 GetStreamCount() override
void SetStreamUsage(wxInt32 StreamID, bool Use) override
TranslatableString GetPluginFormatDescription() override
wxString GetPluginStringID() override
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
wxSeekMode GetWXSeekMode(int whence)
wxString GetId3v2Genre(Tags &tags, const char *genre)
static Importer::RegisteredImportPlugin registered
std::vector< std::shared_ptr< WaveTrack > > NewChannelGroup
wxString ToWXString(const std::string &str)