16#include "../Audacity.h"
20#include "../widgets/AudacityMessageBox.h"
21#include "../widgets/ProgressDialog.h"
23#define DESC XO("QuickTime files")
60 #include <Carbon/Carbon.h>
61 #include <QuickTime/QuickTime.h>
63 #include <wx/osx/core/private.h>
66 #include <ConditionalMacros.h>
68 #include <QuickTimeComponents.h>
71 #include <ToolUtils.h>
73 #include <Navigation.h>
80#include "../WaveTrack.h"
82#define kQTAudioPropertyID_MaxAudioSampleSize 'mssz'
94 err = ::InitializeQTML(0);
98 err = ::EnterMovies();
103#if defined(__WXMSW__)
114#if defined(__WXMSW__)
119 mInitialized =
false;
125 std::unique_ptr<ImportFileHandle>
Open(
135 QTImportFileHandle(
const wxString &
name, Movie movie)
141 virtual ~QTImportFileHandle()
144 DisposeMovie(mMovie);
169 Tags *tags)
override;
172 void AddMetadata(
Tags *tags);
182std::unique_ptr<ImportFileHandle> QTImportPlugin::Open(
187 Movie theMovie = NULL;
188 Handle dataRef = NULL;
189 OSType dataRefType = 0;
192#if defined(__WXMAC__)
193 err = wxMacPathToFSRef(Filename, &inRef);
197 err = FSPathMakeRef((UInt8 *)
OSFILENAME(Filename), &inRef, NULL);
204 err = QTNewDataReferenceFromFSRef(&inRef, 0, &dataRef, &dataRefType);
210 err = NewMovieFromDataRef(&theMovie,
211 newMovieActive | newMovieDontAskUnresolvedDataRefs,
215 DisposeHandle(dataRef);
220 return std::make_unique<QTImportFileHandle>(Filename, theMovie);
224 std::make_unique< QTImportPlugin >()
233auto QTImportFileHandle::GetFileUncompressedBytes() -> ByteCount
238ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
245 MovieAudioExtractionRef maer = NULL;
249 decltype(totSamples) numSamples = 0;
250 Boolean discrete =
true;
251 UInt32 quality = kQTAudioRenderQuality_Max;
252 AudioStreamBasicDescription
desc;
253 UInt32 maxSampleSize;
256 auto cleanup =
finally( [&] {
258 MovieAudioExtractionEnd(maer);
266 err = MovieAudioExtractionBegin(mMovie, 0, &maer);
272 err = MovieAudioExtractionSetProperty(maer,
273 kQTPropertyClass_MovieAudioExtraction_Audio,
274 kQTMovieAudioExtractionAudioPropertyID_RenderQuality,
282 err = MovieAudioExtractionSetProperty(maer,
283 kQTPropertyClass_MovieAudioExtraction_Movie,
284 kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete,
289"Unable to set QuickTime discrete channels property") );
293 err = MovieAudioExtractionGetProperty(maer,
294 kQTPropertyClass_MovieAudioExtraction_Audio,
295 kQTAudioPropertyID_MaxAudioSampleSize,
296 sizeof(maxSampleSize),
301"Unable to get QuickTime sample size property") );
305 err = MovieAudioExtractionGetProperty(maer,
306 kQTPropertyClass_MovieAudioExtraction_Audio,
307 kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
316 auto numchan =
desc.mChannelsPerFrame;
317 const size_t bufsize = 5 *
desc.mSampleRate;
321 switch (maxSampleSize)
339 static_cast< AudioBufferList *
>(
340 calloc( 1, offsetof( AudioBufferList, mBuffers ) +
341 (
sizeof(AudioBuffer) * numchan))) };
342 abl->mNumberBuffers = numchan;
346 const auto size =
sizeof(float) * bufsize;
348 for (
size_t c = 0; c < numchan; c++) {
349 auto &buffer = abl->mBuffers[c];
350 auto &holder = holders[c];
351 auto &channel = channels[c];
353 buffer.mNumberChannels = 1;
354 buffer.mDataByteSize =
size;
356 buffer.mData = holder.get();
358 channel = trackFactory->NewWaveTrack(
format );
359 channel->SetRate(
desc.mSampleRate );
364 UInt32 numFrames = bufsize;
366 err = MovieAudioExtractionFillBuffer(maer,
375 for (
size_t c = 0; c < numchan; c++) {
376 channels[c]->Append((
char *) abl->mBuffers[c].mData,
floatSample, numFrames);
379 numSamples += numFrames;
381 updateResult = mProgress->Update(
382 numSamples.as_long_long(),
383 totSamples.as_long_long() );
385 if (numFrames == 0 || flags & kQTMovieAudioExtractionComplete) {
393 for (
auto &channel: channels)
395 if (!channels.empty())
396 outTracks.push_back(std::move(channels));
419 { kQTMetaDataCommonKeyAuthor,
wxT(
"Author") },
422 { kQTMetaDataCommonKeyDirector,
wxT(
"Director") },
423 { kQTMetaDataCommonKeyDisplayName,
wxT(
"Full Name") },
424 { kQTMetaDataCommonKeyInformation,
wxT(
"Information") },
425 { kQTMetaDataCommonKeyKeywords,
wxT(
"Keywords") },
426 { kQTMetaDataCommonKeyProducer,
wxT(
"Producer") },
427 { kQTMetaDataCommonKeyAlbum,
TAG_ALBUM },
429 { kQTMetaDataCommonKeyChapterName,
wxT(
"Chapter") },
430 { kQTMetaDataCommonKeyComposer,
wxT(
"Composer") },
431 { kQTMetaDataCommonKeyDescription,
wxT(
"Description") },
432 { kQTMetaDataCommonKeyGenre,
TAG_GENRE },
433 { kQTMetaDataCommonKeyOriginalFormat,
wxT(
"Original Format") },
434 { kQTMetaDataCommonKeyOriginalSource,
wxT(
"Original Source") },
435 { kQTMetaDataCommonKeyPerformers,
wxT(
"Performers") },
437 { kQTMetaDataCommonKeyWriter,
wxT(
"Writer") },
440void QTImportFileHandle::AddMetadata(
Tags *tags)
442 QTMetaDataRef metaDataRef = NULL;
443 auto cleanup =
finally( [&] {
446 QTMetaDataRelease(metaDataRef);
451 err = QTCopyMovieMetaData(mMovie, &metaDataRef);
456 for (
int i = 0; i < WXSIZEOF(
names); i++) {
457 QTMetaDataItem item = kQTMetaDataItemUninitialized;
460 err = QTMetaDataGetNextItem(metaDataRef,
461 kQTMetaDataStorageFormatWildcard,
462 kQTMetaDataItemUninitialized,
463 kQTMetaDataKeyFormatCommon,
471 if (item == kQTMetaDataItemUninitialized) {
475 QTPropertyValueType outPropType;
476 ::ByteCount outPropValueSize;
477 ::ByteCount outPropValueSizeUsed = 0;
482 err = QTMetaDataGetItemProperty(metaDataRef,
484 kPropertyClass_MetaDataItem,
485 kQTMetaDataItemPropertyID_DataType,
488 &outPropValueSizeUsed);
494 err = QTMetaDataGetItemPropertyInfo(metaDataRef,
496 kPropertyClass_MetaDataItem,
497 kQTMetaDataItemPropertyID_Value,
509 err = QTMetaDataGetItemProperty(metaDataRef,
511 kPropertyClass_MetaDataItem,
512 kQTMetaDataItemPropertyID_Value,
515 &outPropValueSizeUsed);
523 case kQTMetaDataTypeUTF8:
524 v = wxString(outVals.get(), wxConvUTF8);
526 case kQTMetaDataTypeUTF16BE:
528 wxMBConvUTF16BE conv;
529 v = wxString(outVals.get(), conv);
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
static const AudacityProject::AttachedObjects::RegisteredFactory key
const TranslatableString name
const TranslatableString desc
std::vector< std::shared_ptr< WaveTrack > > NewChannelGroup
std::vector< std::vector< std::shared_ptr< WaveTrack > > > TrackHolders
static Importer::RegisteredImportPlugin registered
The interface that all file import "plugins" (if you want to call them that) must implement....
std::unique_ptr< T, freer > MallocPtr
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.
virtual ByteCount GetFileUncompressedBytes()=0
virtual TranslatableString GetFileDescription()=0
virtual wxInt32 GetStreamCount()=0
virtual ProgressResult Import(WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags)=0
virtual const TranslatableStrings & GetStreamInfo()=0
virtual void SetStreamUsage(wxInt32 StreamID, bool Use)=0
Base class for FlacImportPlugin, LOFImportPlugin, MP3ImportPlugin, OggImportPlugin and PCMImportPlugi...
virtual TranslatableString GetPluginFormatDescription()=0
virtual wxString GetPluginStringID()=0
virtual std::unique_ptr< ImportFileHandle > Open(const FilePath &Filename, AudacityProject *)=0
Holds a msgid for the translation catalog; may also bind format arguments.
Positions or offsets within audio files need a wide type.
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.