Audacity 3.2.0
Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle Class Referencefinal
Inheritance diagram for anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle:
[legend]
Collaboration diagram for anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle:
[legend]

Public Member Functions

 MP3ImportFileHandle (const FilePath &filename)
 
 ~MP3ImportFileHandle ()
 
TranslatableString GetFileDescription () override
 
ByteCount GetFileUncompressedBytes () override
 
void Import (ImportProgressListener &progressListener, WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags, std::optional< LibFileFormats::AcidizerTags > &outAcidTags) override
 
bool SetupOutputFormat ()
 
void ReadTags (Tags *tags)
 
wxInt32 GetStreamCount () override
 
const TranslatableStringsGetStreamInfo () override
 
void SetStreamUsage (wxInt32 StreamID, bool Use) override
 
- Public Member Functions inherited from ImportFileHandleEx
 ImportFileHandleEx (const FilePath &filename)
 
FilePath GetFilename () const override
 
void Cancel () override
 
void Stop () override
 
- Public Member Functions inherited from ImportFileHandle
virtual ~ImportFileHandle ()
 
virtual FilePath GetFilename () const =0
 
virtual TranslatableString GetErrorMessage () const
 
virtual TranslatableString GetFileDescription ()=0
 
virtual ByteCount GetFileUncompressedBytes ()=0
 
virtual wxInt32 GetStreamCount ()=0
 
virtual const TranslatableStringsGetStreamInfo ()=0
 
virtual void SetStreamUsage (wxInt32 StreamID, bool Use)=0
 
virtual void Import (ImportProgressListener &progressListener, WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags, std::optional< LibFileFormats::AcidizerTags > &acidTags)=0
 
virtual void Cancel ()=0
 
virtual void Stop ()=0
 

Private Member Functions

bool Open ()
 

Static Private Member Functions

static ptrdiff_t ReadCallback (void *handle, void *buffer, size_t size)
 
static off_t SeekCallback (void *handle, off_t offset, int whence)
 

Private Attributes

wxFile mFile
 
wxFileOffset mFileLen { 0 }
 
WaveTrackFactorymTrackFactory { nullptr }
 
TrackListHolder mTrackList
 
unsigned mNumChannels { 0 }
 
mpg123_handle * mHandle { nullptr }
 
bool mFloat64Output {}
 
friend MP3ImportPlugin
 

Additional Inherited Members

- Public Types inherited from ImportFileHandle
using ByteCount = unsigned long long
 
- Protected Member Functions inherited from ImportFileHandleEx
void BeginImport ()
 
bool IsCancelled () const noexcept
 
bool IsStopped () const noexcept
 

Detailed Description

Definition at line 123 of file ImportMP3_MPG123.cpp.

Constructor & Destructor Documentation

◆ MP3ImportFileHandle()

anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::MP3ImportFileHandle ( const FilePath filename)

Definition at line 186 of file ImportMP3_MPG123.cpp.

187 : ImportFileHandleEx(filename)
188{
189 int errorCode = MPG123_OK;
190 mHandle = mpg123_new(nullptr, &errorCode);
191
192 if (errorCode != MPG123_OK)
193 {
194 wxLogError(
195 "Failed to create MPG123 handle: %s",
196 mpg123_plain_strerror(errorCode));
197
198 mHandle = nullptr;
199
200 return;
201 }
202
203 errorCode = mpg123_replace_reader_handle(
205
206 if (errorCode != MPG123_OK)
207 {
208 wxLogError(
209 "Failed to set reader on the MPG123 handle: %s",
210 mpg123_plain_strerror(errorCode));
211
212 mpg123_delete(mHandle);
213 mHandle = nullptr;
214 }
215
216 // We force mpg123 to decode into floats
217 mpg123_param(mHandle, MPG123_FLAGS, MPG123_GAPLESS | MPG123_FORCE_FLOAT, 0.0);
218
219 if (errorCode != MPG123_OK)
220 {
221 wxLogError(
222 "Failed to set options on the MPG123 handle",
223 mpg123_plain_strerror(errorCode));
224
225 mpg123_delete(mHandle);
226 mHandle = nullptr;
227 }
228}
ImportFileHandleEx(const FilePath &filename)
static off_t SeekCallback(void *handle, off_t offset, int whence)
static ptrdiff_t ReadCallback(void *handle, void *buffer, size_t size)

References mHandle, ReadCallback(), and SeekCallback().

Here is the call graph for this function:

◆ ~MP3ImportFileHandle()

anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::~MP3ImportFileHandle ( )

Definition at line 230 of file ImportMP3_MPG123.cpp.

231{
232 // nullptr is a valid input for the mpg123_delete
233 mpg123_delete(mHandle);
234}

References mHandle.

Member Function Documentation

◆ GetFileDescription()

TranslatableString anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::GetFileDescription ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 236 of file ImportMP3_MPG123.cpp.

237{
238 return DESC;
239}
#define DESC

References DESC.

◆ GetFileUncompressedBytes()

auto anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::GetFileUncompressedBytes ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 241 of file ImportMP3_MPG123.cpp.

242{
243 // We have to parse the file first using mpg123_scan,
244 // we do not want to do that before the import starts.
245 return 0;
246}

◆ GetStreamCount()

wxInt32 anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::GetStreamCount ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 248 of file ImportMP3_MPG123.cpp.

249{
250 return 1;
251}

◆ GetStreamInfo()

const TranslatableStrings & anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::GetStreamInfo ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 253 of file ImportMP3_MPG123.cpp.

254{
255 static TranslatableStrings empty;
256 return empty;
257}
std::vector< TranslatableString > TranslatableStrings

◆ Import()

void anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::Import ( ImportProgressListener progressListener,
WaveTrackFactory trackFactory,
TrackHolders outTracks,
Tags tags,
std::optional< LibFileFormats::AcidizerTags > &  outAcidTags 
)
overridevirtual

Implements ImportFileHandle.

Definition at line 263 of file ImportMP3_MPG123.cpp.

267{
268 BeginImport();
269
270 auto finalAction = finally([handle = mHandle]() { mpg123_close(handle); });
271
272 outTracks.clear();
273 mTrackFactory = trackFactory;
274
275 long long framesCount = mpg123_framelength(mHandle);
276
277 if (!SetupOutputFormat())
278 {
280 return;
281 }
282
283 off_t frameIndex { 0 };
284 unsigned char* data { nullptr };
285 size_t dataSize { 0 };
286
287 std::vector<float> conversionBuffer;
288
289 int ret = MPG123_OK;
290
291 while ((ret = mpg123_decode_frame(mHandle, &frameIndex, &data, &dataSize)) ==
292 MPG123_OK)
293 {
294 if(framesCount > 0)
295 progressListener.OnImportProgress(static_cast<double>(frameIndex) / static_cast<double>(framesCount));
296
297 if(IsCancelled())
298 {
300 return;
301 }
302 //VS: doesn't implement Stop behavior...
303
304 constSamplePtr samples = reinterpret_cast<constSamplePtr>(data);
305 const size_t samplesCount = dataSize / sizeof(float) / mNumChannels;
306
307 // libmpg123 picks up the format based on some "internal" precision.
308 // This case is not expected to happen
309 if (mFloat64Output)
310 {
311 conversionBuffer.resize(samplesCount * mNumChannels);
312
313 for (size_t sampleIndex = 0; sampleIndex < conversionBuffer.size();
314 ++sampleIndex)
315 {
316 conversionBuffer[sampleIndex] = static_cast<float>(
317 reinterpret_cast<const double*>(data)[sampleIndex]);
318 }
319
320 samples = reinterpret_cast<constSamplePtr>(conversionBuffer.data());
321 }
322 // Just copy the interleaved data to the channels
323 unsigned chn = 0;
324 ImportUtils::ForEachChannel(*mTrackList, [&](auto& channel)
325 {
326 channel.AppendBuffer(
327 samples + sizeof(float) * chn,
328 floatSample, samplesCount,
330 floatSample);
331 ++chn;
332 });
333 }
334
335 if (ret != MPG123_DONE)
336 {
337 wxLogError(
338 "Failed to decode MP3 file: %s", mpg123_plain_strerror(ret));
339
341 return;
342 }
343
345
346 ReadTags(tags);
347
349}
const char * constSamplePtr
Definition: SampleFormat.h:58
bool IsCancelled() const noexcept
virtual void OnImportResult(ImportResult result)=0
Used to report on import result for file handle passed as argument to OnImportFileOpened.
virtual void OnImportProgress(double progress)=0
static void ForEachChannel(TrackList &trackList, const std::function< void(WaveChannel &)> &op)
Iterates over channels in each wave track from the list.
Definition: ImportUtils.cpp:66
static void FinalizeImport(TrackHolders &outTracks, const std::vector< TrackListHolder > &importedStreams)
Flushes the given channels and moves them to outTracks.
Definition: ImportUtils.cpp:49

References ImportFileHandleEx::BeginImport(), ImportProgressListener::Cancelled, ImportProgressListener::Error, ImportUtils::FinalizeImport(), floatSample, ImportUtils::ForEachChannel(), ImportFileHandleEx::IsCancelled(), mFloat64Output, mHandle, mNumChannels, mTrackFactory, mTrackList, ImportProgressListener::OnImportProgress(), ImportProgressListener::OnImportResult(), ReadTags(), SetupOutputFormat(), and ImportProgressListener::Success.

Here is the call graph for this function:

◆ Open()

bool anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::Open ( )
private

Definition at line 453 of file ImportMP3_MPG123.cpp.

454{
455 if (mHandle == nullptr)
456 return false;
457
458 // Open the file
459 if (!mFile.Open(GetFilename()))
460 {
461 return false;
462 }
463
464 // Get the length of the file
465 mFileLen = mFile.Seek(0, wxFromEnd);
466
467 if (mFileLen == wxInvalidOffset || mFile.Error())
468 {
469 mFile.Close();
470 return false;
471 }
472
473 if (mFile.Seek(0, wxFromStart) == wxInvalidOffset || mFile.Error())
474 {
475 mFile.Close();
476 return false;
477 }
478
479 // Check if file is an MP3
480 auto errorCode = mpg123_open_handle(mHandle, this);
481
482 if (errorCode != MPG123_OK)
483 return false;
484
485 // Scan the file
486 errorCode = mpg123_scan(mHandle);
487
488 if (errorCode != MPG123_OK)
489 return false;
490
491 // Read the output format
492 errorCode = mpg123_decode_frame(mHandle, nullptr, nullptr, nullptr);
493
494 // First decode should read the format
495 if (errorCode != MPG123_NEW_FORMAT)
496 return false;
497
498 return true;
499}
FilePath GetFilename() const override

References ImportFileHandleEx::GetFilename(), mFile, mFileLen, and mHandle.

Here is the call graph for this function:

◆ ReadCallback()

ptrdiff_t anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::ReadCallback ( void *  handle,
void *  buffer,
size_t  size 
)
staticprivate

Definition at line 501 of file ImportMP3_MPG123.cpp.

503{
504 return static_cast<MP3ImportFileHandle*>(handle)->mFile.Read(buffer, size);
505}

References mFile, and size.

Referenced by MP3ImportFileHandle().

Here is the caller graph for this function:

◆ ReadTags()

void anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::ReadTags ( Tags tags)

Definition at line 378 of file ImportMP3_MPG123.cpp.

379{
380 mpg123_id3v1* v1;
381 mpg123_id3v2* v2;
382 int meta;
383
384 meta = mpg123_meta_check(mHandle);
385
386 if (meta & MPG123_ID3 && mpg123_id3(mHandle, &v1, &v2) == MPG123_OK)
387 {
388 if (v2 != nullptr && v2->title != nullptr && v2->title->fill > 0)
389 tags->SetTag(TAG_TITLE, audacity::ToWXString(v2->title->p));
390 else if (v1 != nullptr && v1->title[0] != '\0')
391 tags->SetTag(TAG_TITLE, audacity::ToWXString(v1->title));
392
393 if (v2 != nullptr && v2->artist != nullptr && v2->artist->fill > 0)
394 tags->SetTag(TAG_ARTIST, audacity::ToWXString(v2->artist->p));
395 else if (v1 != nullptr && v1->artist[0] != '\0')
396 tags->SetTag(TAG_ARTIST, audacity::ToWXString(v1->artist));
397
398 if (v2 != nullptr && v2->album != nullptr && v2->album->fill > 0)
399 tags->SetTag(TAG_ALBUM, audacity::ToWXString(v2->album->p));
400 else if (v1 != nullptr && v1->album[0] != '\0')
401 tags->SetTag(TAG_ALBUM, audacity::ToWXString(v1->album));
402
403 if (v2 != nullptr && v2->year != nullptr && v2->year->fill > 0)
404 tags->SetTag(TAG_YEAR, audacity::ToWXString(v2->year->p));
405 else if (v1 != nullptr && v1->year[0] != '\0')
406 tags->SetTag(TAG_YEAR, audacity::ToWXString(std::string(v1->year, 4)));
407
408 if (v2 != nullptr && v2->genre != nullptr && v2->genre->fill > 0)
409 tags->SetTag(TAG_GENRE, GetId3v2Genre(*tags, v2->genre->p));
410 else if (v1 != nullptr)
411 tags->SetTag(TAG_GENRE, tags->GetGenre(v1->genre));
412
413 if (v2 != nullptr && v2->comment != nullptr && v2->comment->fill > 0)
414 tags->SetTag(TAG_COMMENTS, audacity::ToWXString(v2->comment->p));
415 else if (v1 != nullptr && v1->comment[0] != '\0')
416 tags->SetTag(TAG_COMMENTS, audacity::ToWXString(v1->comment));
417
418 if (v2 != nullptr)
419 {
420 for (size_t i = 0; i < v2->comments; ++i)
421 {
422 if (v2->comment_list[i].text.fill == 0)
423 continue;
424
425 tags->SetTag(
426 audacity::ToWXString(std::string(v2->comment_list[i].id, 4)),
427 audacity::ToWXString(v2->comment_list[i].text.p));
428 }
429
430 for (size_t i = 0; i < v2->extras; ++i)
431 {
432 if (v2->extra[i].text.fill == 0)
433 continue;
434
435 tags->SetTag(
436 audacity::ToWXString(std::string(v2->extra[i].id, 4)),
437 audacity::ToWXString(v2->extra[i].text.p));
438 }
439
440 // libmpg123 does not parse TRCK tag, we have to do it ourselves
441 for (size_t i = 0; i < v2->texts; ++i)
442 {
443 if (memcmp(v2->text[i].id, "TRCK", 4) == 0)
444 {
445 tags->SetTag(
446 TAG_TRACK, audacity::ToWXString(v2->text[i].text.p));
447 }
448 }
449 }
450 }
451}
#define TAG_TRACK
Definition: Tags.h:61
#define TAG_COMMENTS
Definition: Tags.h:64
#define TAG_GENRE
Definition: Tags.h:63
#define TAG_ALBUM
Definition: Tags.h:60
#define TAG_YEAR
Definition: Tags.h:62
#define TAG_TITLE
Definition: Tags.h:58
#define TAG_ARTIST
Definition: Tags.h:59
wxString GetGenre(int value)
Definition: Tags.cpp:373
void SetTag(const wxString &name, const wxString &value, const bool bSpecialTag=false)
Definition: Tags.cpp:431
wxString GetId3v2Genre(Tags &tags, const char *genre)
wxString ToWXString(const std::string &str)

References Tags::GetGenre(), anonymous_namespace{ImportMP3_MPG123.cpp}::GetId3v2Genre(), mHandle, Tags::SetTag(), TAG_ALBUM, TAG_ARTIST, TAG_COMMENTS, TAG_GENRE, TAG_TITLE, TAG_TRACK, TAG_YEAR, and audacity::ToWXString().

Referenced by Import().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SeekCallback()

off_t anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::SeekCallback ( void *  handle,
off_t  offset,
int  whence 
)
staticprivate

Definition at line 525 of file ImportMP3_MPG123.cpp.

527{
528 return static_cast<MP3ImportFileHandle*>(handle)->mFile.Seek(
529 offset, GetWXSeekMode(whence));
530}

References anonymous_namespace{ImportMP3_MPG123.cpp}::GetWXSeekMode(), and mFile.

Referenced by MP3ImportFileHandle().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetStreamUsage()

void anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::SetStreamUsage ( wxInt32  StreamID,
bool  Use 
)
overridevirtual

Implements ImportFileHandle.

Definition at line 259 of file ImportMP3_MPG123.cpp.

260{
261}

◆ SetupOutputFormat()

bool anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::SetupOutputFormat ( )

Definition at line 351 of file ImportMP3_MPG123.cpp.

352{
353 long rate;
354 int channels;
355 int encoding = MPG123_ENC_FLOAT_32;
356 mpg123_getformat(mHandle, &rate, &channels, &encoding);
357
358 mNumChannels = channels == MPG123_MONO ? 1 : 2;
359
360 if (encoding != MPG123_ENC_FLOAT_32 && encoding != MPG123_ENC_FLOAT_64)
361 {
362 wxLogError("MPG123 returned unexpected encoding");
363
364 return false;
365 }
366
367 mFloat64Output = encoding == MPG123_ENC_FLOAT_64;
368
372 floatSample,
373 rate);
374
375 return true;
376}
static TrackListHolder NewWaveTrack(WaveTrackFactory &trackFactory, unsigned nChannels, sampleFormat effectiveFormat, double rate)
Definition: ImportUtils.cpp:35

References floatSample, mFloat64Output, mHandle, mNumChannels, mTrackFactory, mTrackList, and ImportUtils::NewWaveTrack().

Referenced by Import().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mFile

wxFile anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::mFile
private

Definition at line 151 of file ImportMP3_MPG123.cpp.

Referenced by Open(), ReadCallback(), and SeekCallback().

◆ mFileLen

wxFileOffset anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::mFileLen { 0 }
private

Definition at line 152 of file ImportMP3_MPG123.cpp.

Referenced by Open().

◆ mFloat64Output

bool anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::mFloat64Output {}
private

Definition at line 160 of file ImportMP3_MPG123.cpp.

Referenced by Import(), and SetupOutputFormat().

◆ mHandle

mpg123_handle* anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::mHandle { nullptr }
private

◆ mNumChannels

unsigned anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::mNumChannels { 0 }
private

Definition at line 156 of file ImportMP3_MPG123.cpp.

Referenced by Import(), and SetupOutputFormat().

◆ MP3ImportPlugin

friend anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::MP3ImportPlugin
private

Definition at line 162 of file ImportMP3_MPG123.cpp.

◆ mTrackFactory

WaveTrackFactory* anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::mTrackFactory { nullptr }
private

Definition at line 154 of file ImportMP3_MPG123.cpp.

Referenced by Import(), and SetupOutputFormat().

◆ mTrackList

TrackListHolder anonymous_namespace{ImportMP3_MPG123.cpp}::MP3ImportFileHandle::mTrackList
private

Definition at line 155 of file ImportMP3_MPG123.cpp.

Referenced by Import(), and SetupOutputFormat().


The documentation for this class was generated from the following file: