34#define FLAC_HEADER "fLaC"
36#define DESC XO("FLAC files")
46#include "FLAC++/decoder.h"
58#if !defined FLACPP_API_VERSION_CURRENT || FLACPP_API_VERSION_CURRENT < 6
73 set_metadata_ignore_all();
74 set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT);
75 set_metadata_respond(FLAC__METADATA_TYPE_STREAMINFO);
91 FLAC__StreamDecoderWriteStatus
write_callback(
const FLAC__Frame *frame,
92 const FLAC__int32 *
const buffer[])
override;
94 void error_callback(FLAC__StreamDecoderErrorStatus status)
override;
110 std::unique_ptr<ImportFileHandle>
Open(
129 std::optional<LibFileFormats::AcidizerTags>& outAcidTags)
override;
158 switch (metadata->type)
160 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
161 for (FLAC__uint32 i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
162 mComments.push_back(
UTF8CTOWX((
char *)metadata->data.vorbis_comment.comments[i].entry));
166 case FLAC__METADATA_TYPE_STREAMINFO:
183 case FLAC__METADATA_TYPE_PADDING:
184 case FLAC__METADATA_TYPE_APPLICATION:
185 case FLAC__METADATA_TYPE_SEEKTABLE:
186 case FLAC__METADATA_TYPE_CUESHEET:
187 case FLAC__METADATA_TYPE_PICTURE:
188 case FLAC__METADATA_TYPE_UNDEFINED:
220 const FLAC__int32 *
const buffer[])
223 return GuardedCall< FLAC__StreamDecoderWriteStatus > ( [&] {
229 if (frame->header.bits_per_sample <= 16) {
230 if (frame->header.bits_per_sample == 8) {
231 for (unsigned int s = 0; s < frame->header.blocksize; s++) {
232 tmp[s] = buffer[chn][s] << 8;
235 for (unsigned int s = 0; s < frame->header.blocksize; s++) {
236 tmp[s] = buffer[chn][s];
240 channel.AppendBuffer((samplePtr)tmp.get(),
242 frame->header.blocksize, 1,
246 channel.AppendBuffer((samplePtr)buffer[chn],
248 frame->header.blocksize, 1,
262 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
265 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
282 if (!binaryFile.Open(filename)) {
290 id3_byte_t query[ID3_TAG_QUERYSIZE];
291 cnt = binaryFile.Read(query,
sizeof(query));
292 cnt = id3_tag_query(query, cnt);
293 binaryFile.Seek(cnt);
297 cnt = binaryFile.Read(buf, 4);
300 if (cnt == wxInvalidOffset || strncmp(buf,
FLAC_HEADER, 4) != 0) {
306 auto handle = std::make_unique<FLACImportFileHandle>(filename);
308 bool success = handle->Init();
314 return std::move(handle);
318 std::make_unique< FLACImportPlugin >()
324 mStreamInfoDone(false)
328 mFile = std::make_unique<MyFLACFile>(
this);
338 mFile->set_metadata_respond(FLAC__METADATA_TYPE_STREAMINFO);
339 mFile->set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT);
340 FLAC::Decoder::File::State state =
mFile->init();
341 if (state != FLAC__FILE_DECODER_OK) {
358 if (result != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
362 mFile->process_until_end_of_metadata();
365 state =
mFile->get_state();
366 if (state != FLAC__FILE_DECODER_OK) {
371 if (
mFile->get_state() > FLAC__STREAM_DECODER_READ_FRAME) {
376 if (!
mFile->is_valid() ||
mFile->get_was_error()) {
398 std::optional<LibFileFormats::AcidizerTags>&)
404 auto cleanup =
finally([&]{
mFile->mImportProgressListener =
nullptr; });
410 mFile->mImportProgressListener = &progressListener;
415 bool res = (
mFile->process_until_end_of_file() != 0);
417 bool res = (
mFile->process_until_end_of_stream() != 0);
429 wxString description;
431 size_t cnt =
mFile->mComments.size();
434 for (
size_t c = 0; c < cnt; c++) {
435 wxString
name =
mFile->mComments[c].BeforeFirst(
wxT(
'='));
436 wxString value =
mFile->mComments[c].AfterFirst(
wxT(
'='));
437 wxString upper =
name.Upper();
440 if (value.length() == 4 && value.ToLong(&val)) {
444 else if (upper ==
wxT(
"COMMENT") || upper ==
wxT(
"COMMENTS")) {
448 else if (upper ==
wxT(
"DESCRIPTION")) {
455 if (comment.empty()) {
456 comment = description;
458 if (!comment.empty()) {
SimpleGuard< R > MakeSimpleGuard(R value) noexcept(noexcept(SimpleGuard< R >{ value }))
Convert a value to a handler function returning that value, suitable for GuardedCall<R>
static Importer::RegisteredImportPlugin registered
The interface that all file import "plugins" (if you want to call them that) must implement....
std::vector< std::shared_ptr< Track > > TrackHolders
std::vector< TranslatableString > TranslatableStrings
This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better t...
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
An ImportFileHandle for FLAC data.
void Import(ImportProgressListener &progressListener, WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags, std::optional< LibFileFormats::AcidizerTags > &outAcidTags) override
FLACImportFileHandle(const FilePath &name)
void SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override
FLAC__uint64 mSamplesDone
std::unique_ptr< MyFLACFile > mFile
const TranslatableStrings & GetStreamInfo() override
TranslatableString GetFileDescription() override
ByteCount GetFileUncompressedBytes() override
unsigned long mBitsPerSample
unsigned long mNumChannels
unsigned long mSampleRate
wxInt32 GetStreamCount() override
An ImportPlugin for FLAC data.
wxString GetPluginStringID() override
std::unique_ptr< ImportFileHandle > Open(const FilePath &Filename, AudacityProject *) override
TranslatableString GetPluginFormatDescription() override
bool IsStopped() const noexcept
FilePath GetFilename() const override
bool IsCancelled() const noexcept
unsigned long long ByteCount
Base class for FlacImportPlugin, LOFImportPlugin, MP3ImportPlugin, OggImportPlugin and PCMImportPlugi...
Interface used to report on import state and progress.
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 std::shared_ptr< WaveTrack > NewWaveTrack(WaveTrackFactory &trackFactory, unsigned nChannels, sampleFormat effectiveFormat, double rate)
static void ForEachChannel(TrackList &trackList, const std::function< void(WaveChannel &)> &op)
Iterates over channels in each wave track from the list.
static void FinalizeImport(TrackHolders &outTracks, const std::vector< std::shared_ptr< WaveTrack > > &importedStreams)
Flushes the given channels and moves them to outTracks.
void error_callback(FLAC__StreamDecoderErrorStatus status) override
MyFLACFile(FLACImportFileHandle *handle)
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__Frame *frame, const FLAC__int32 *const buffer[]) override
bool get_was_error() const
FLACImportFileHandle * mFile
ImportProgressListener * mImportProgressListener
void metadata_callback(const FLAC__StreamMetadata *metadata) 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...
std::shared_ptr< WaveTrack > Holder
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
const char * end(const char *str) noexcept
const char * begin(const char *str) noexcept