Browse Source

tags/2021-05-28
jules 18 years ago
parent
commit
1ca5d73733
7 changed files with 706 additions and 651 deletions
  1. +1
    -1
      build/win32/platform_specific_code/juce_win32_SystemStats.cpp
  2. +1
    -1
      juce.h
  3. +6
    -12
      juce_Config.h
  4. +406
    -561
      src/juce_appframework/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp
  5. +1
    -1
      src/juce_appframework/audio/audio_file_formats/juce_QuickTimeAudioFormat.h
  6. +284
    -71
      src/juce_appframework/gui/components/special/juce_QuickTimeMovieComponent.cpp
  7. +7
    -4
      src/juce_appframework/gui/components/special/juce_QuickTimeMovieComponent.h

+ 1
- 1
build/win32/platform_specific_code/juce_win32_SystemStats.cpp View File

@@ -54,7 +54,7 @@
#pragma comment(lib, "GlU32.Lib")
#endif
#if JUCE_QUICKTIME_AUDIOFORMAT
#if JUCE_QUICKTIME
#pragma comment(lib, "QTMLClient.lib")
#endif
#endif


+ 1
- 1
juce.h View File

@@ -177,7 +177,7 @@ END_JUCE_NAMESPACE
#pragma comment(lib, "GlU32.Lib")
#endif
#if JUCE_QUICKTIME_AUDIOFORMAT
#if JUCE_QUICKTIME
#pragma comment (lib, "QTMLClient.lib")
#endif


+ 6
- 12
juce_Config.h View File

@@ -78,24 +78,18 @@
//=============================================================================
/** Comment out this macro if you don't want to enable QuickTime or if you don't
have QuickTime installed. If it's not enabled, the QuickTimeWindow class will
be unavailable.
have the SDK installed.
If this flag is not enabled, the QuickTimeMovieComponent and QuickTimeAudioFormat
classes will be unavailable.
On Windows, if you enable this, you'll need to make sure the Apple Quicktime.dll
file is found on your include path. By default the Quicktime installer will have
put this in the "/Program Files/QuickTime" folder. Only QuickTime version 7 or later
is currently supported.
On Windows, if you enable this, you'll need to have the QuickTime SDK
installed, and its header files will need to be on your include path.
*/
#if ! (defined (JUCE_QUICKTIME) || defined (LINUX) || (defined (_WIN32) && ! defined (_MSC_VER)))
#define JUCE_QUICKTIME 1
#endif
/** This lets you enable the QuickTimeAudioFormat class.
If you're using this on win32, you'll need to have installed the QuickTime SDK.
*/
#if ! (defined (JUCE_QUICKTIME_AUDIOFORMAT) || defined (LINUX) || (defined (_WIN32) && ! defined (_MSC_VER)))
// #define JUCE_QUICKTIME_AUDIOFORMAT 1
#endif
//=============================================================================
/** Comment out this macro if you don't want to enable OpenGL or if you don't


+ 406
- 561
src/juce_appframework/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp View File

@@ -1,561 +1,406 @@
/*
==============================================================================

This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.

------------------------------------------------------------------------------

JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.

JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA

------------------------------------------------------------------------------

If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.

==============================================================================
*/

#include "../../../../juce_Config.h"

#if JUCE_QUICKTIME_AUDIOFORMAT

#if ! defined (_WIN32)
#include <Quicktime/Movies.h>
#include <Quicktime/QTML.h>
#include <Quicktime/QuickTimeComponents.h>
#include <Quicktime/MediaHandlers.h>
#include <Quicktime/ImageCodec.h>
#else
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable : 4100)
#endif

#include <Movies.h>
#include <QTML.h>
#include <QuickTimeComponents.h>
#include <MediaHandlers.h>
#include <ImageCodec.h>

#ifdef _MSC_VER
#pragma warning (pop)
#endif
#endif

#include "../../../juce_core/basics/juce_StandardHeader.h"

BEGIN_JUCE_NAMESPACE

#include "juce_QuickTimeAudioFormat.h"
#include "../../../juce_core/text/juce_LocalisedStrings.h"
#include "../../../juce_core/threads/juce_Thread.h"
#include "../../../juce_core/io/files/juce_FileInputStream.h"
#include "../../../juce_core/io/network/juce_URL.h"

#define qtFormatName TRANS("QuickTime file")
static const tchar* const extensions[] = { T(".mov"), T(".mp3"), 0 };

//==============================================================================
class QTAudioReader : public AudioFormatReader
{
public:
QTAudioReader (InputStream* const input_, const int trackNum_)
: AudioFormatReader (input_, qtFormatName),
ok (false),
movie (0),
trackNum (trackNum_),
extractor (0),
lastSampleRead (0),
lastThreadId (0)
{
bufferList = (AudioBufferList*) juce_calloc (256);

#ifdef WIN32
if (InitializeQTML (0) != noErr)
return;
#endif
if (EnterMovies() != noErr)
return;

#if JUCE_MAC
EnterMoviesOnThread (0);
#endif

if (! openMovie (input_))
return;

{
const int numTracks = GetMovieTrackCount (movie);
int trackCount = 0;

for (int i = 1; i <= numTracks; ++i)
{
track = GetMovieIndTrack (movie, i);
media = GetTrackMedia (track);

OSType mediaType;
GetMediaHandlerDescription (media, &mediaType, 0, 0);

if (mediaType == SoundMediaType
&& trackCount++ == trackNum_)
{
ok = true;
break;
}
}
}

if (! ok)
return;

ok = false;

lengthInSamples = GetMediaDecodeDuration (media);
usesFloatingPointData = false;

samplesPerFrame = (int) (GetMediaDecodeDuration (media) / GetMediaSampleCount (media));

trackUnitsPerFrame = GetMovieTimeScale (movie) * samplesPerFrame
/ GetMediaTimeScale (media);

OSStatus err = MovieAudioExtractionBegin (movie, 0, &extractor);

unsigned long output_layout_size;
err = MovieAudioExtractionGetPropertyInfo (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
0, &output_layout_size, 0);
if (err != noErr)
return;

AudioChannelLayout* const qt_audio_channel_layout
= (AudioChannelLayout*) juce_calloc (output_layout_size);

err = MovieAudioExtractionGetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
output_layout_size, qt_audio_channel_layout, 0);

qt_audio_channel_layout->mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;

err = MovieAudioExtractionSetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
sizeof (qt_audio_channel_layout),
qt_audio_channel_layout);

juce_free (qt_audio_channel_layout);

err = MovieAudioExtractionGetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
sizeof (inputStreamDesc),
&inputStreamDesc, 0);
if (err != noErr)
return;

inputStreamDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger
| kAudioFormatFlagIsPacked
| kAudioFormatFlagsNativeEndian;
inputStreamDesc.mBitsPerChannel = sizeof (SInt16) * 8;
inputStreamDesc.mChannelsPerFrame = jmin (2, inputStreamDesc.mChannelsPerFrame);
inputStreamDesc.mBytesPerFrame = sizeof (SInt16) * inputStreamDesc.mChannelsPerFrame;
inputStreamDesc.mBytesPerPacket = inputStreamDesc.mBytesPerFrame;

err = MovieAudioExtractionSetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
sizeof (inputStreamDesc),
&inputStreamDesc);
if (err != noErr)
return;

Boolean allChannelsDiscrete = false;
err = MovieAudioExtractionSetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Movie,
kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete,
sizeof (allChannelsDiscrete),
&allChannelsDiscrete);

if (err != noErr)
return;

bufferList->mNumberBuffers = 1;
bufferList->mBuffers[0].mNumberChannels = inputStreamDesc.mChannelsPerFrame;
bufferList->mBuffers[0].mDataByteSize = (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16;
bufferList->mBuffers[0].mData = malloc (bufferList->mBuffers[0].mDataByteSize);

sampleRate = inputStreamDesc.mSampleRate;
bitsPerSample = 16;
numChannels = inputStreamDesc.mChannelsPerFrame;

detachThread();
ok = true;
}

~QTAudioReader()
{
if (extractor != 0)
{
MovieAudioExtractionEnd (extractor);
extractor = 0;
}

checkThreadIsAttached();
DisposeMovie (movie);

juce_free (bufferList->mBuffers[0].mData);
juce_free (bufferList);
}

bool read (int** destSamples,
int64 startSample,
int numSamples)
{
checkThreadIsAttached();
int done = 0;

while (numSamples > 0)
{
if (! loadFrame ((int) startSample))
return false;

const int numToDo = jmin (numSamples, samplesPerFrame);

for (unsigned int j = 0; j < inputStreamDesc.mChannelsPerFrame; ++j)
{
if (destSamples[j] != 0)
{
const short* const src = ((const short*) bufferList->mBuffers[0].mData) + j;

for (int i = 0; i < numToDo; ++i)
destSamples[j][done + i] = src [i << 1] << 16;
}
}

done += numToDo;
startSample += numToDo;
numSamples -= numToDo;
}

detachThread();
return true;
}

bool loadFrame (const int sampleNum)
{
if (lastSampleRead != sampleNum)
{
TimeRecord time;
time.scale = (TimeScale) inputStreamDesc.mSampleRate;
time.base = 0;
time.value.hi = 0;
time.value.lo = (UInt32) sampleNum;

OSStatus err = MovieAudioExtractionSetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Movie,
kQTMovieAudioExtractionMoviePropertyID_CurrentTime,
sizeof (time), &time);

if (err != noErr)
return false;
}

bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * samplesPerFrame;

UInt32 outFlags = 0;
UInt32 actualNumSamples = samplesPerFrame;
OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumSamples,
bufferList, &outFlags);

lastSampleRead = sampleNum + samplesPerFrame;

return err == noErr;
}

juce_UseDebuggingNewOperator

bool ok;

private:
Movie movie;
Media media;
Track track;
const int trackNum;
double trackUnitsPerFrame;
int samplesPerFrame;
int lastSampleRead, lastThreadId;
MovieAudioExtractionRef extractor;
AudioStreamBasicDescription inputStreamDesc;
AudioBufferList* bufferList;

/*OSErr readMovieStream (long offset, long size, void* dataPtr)
{
input->setPosition (offset);
input->read (dataPtr, size);
return noErr;
}

static OSErr readMovieStreamProc (long offset, long size, void* dataPtr, void* userRef)
{
return ((QTAudioReader*) userRef)->readMovieStream (offset, size, dataPtr);
}*/

static Handle createHandleDataRef (Handle dataHandle, const char* fileName)
{
Handle dataRef = 0;
OSStatus err = PtrToHand (&dataHandle, &dataRef, sizeof (Handle));
if (err == noErr)
{
Str255 suffix;
#if JUCE_WIN32
strcpy_s ((char*) suffix, 128, fileName);
#else
strcpy ((char*) suffix, fileName);
#endif
StringPtr name = suffix;
err = PtrAndHand (name, dataRef, name[0]+1);

if (err == noErr)
{
long atoms[3];
atoms[0] = EndianU32_NtoB (3 * sizeof (long));
atoms[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
atoms[2] = EndianU32_NtoB (MovieFileType);

err = PtrAndHand (atoms, dataRef, 3 * sizeof (long));

if (err == noErr)
return dataRef;
}

DisposeHandle (dataRef);
}

return 0;
}

static CFStringRef juceStringToCFString (const String& s)
{
const int len = s.length();
const juce_wchar* const t = (const juce_wchar*) s;

UniChar* temp = (UniChar*) juce_malloc (sizeof (UniChar) * len + 4);

for (int i = 0; i <= len; ++i)
temp[i] = t[i];

CFStringRef result = CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len);
juce_free (temp);

return result;
}

//==============================================================================
bool openMovie (InputStream* const input)
{
bool ok = false;

QTNewMoviePropertyElement props[5];
zeromem (props, sizeof (props));
int prop = 0;

DataReferenceRecord dr;
props[prop].propClass = kQTPropertyClass_DataLocation;
props[prop].propID = kQTDataLocationPropertyID_DataReference;
props[prop].propValueSize = sizeof (dr);
props[prop].propValueAddress = (void*) &dr;
++prop;

FileInputStream* const fin = dynamic_cast <FileInputStream*> (input);

if (fin != 0)
{
CFStringRef filePath = juceStringToCFString (fin->getFile().getFullPathName());

QTNewDataReferenceFromFullPathCFString (filePath, (QTPathStyle) kQTNativeDefaultPathStyle, 0,
&dr.dataRef, &dr.dataRefType);


ok = openMovie (props, prop);

DisposeHandle (dr.dataRef);
CFRelease (filePath);
}
else
{
// sanity-check because this currently needs to load the whole stream into memory..
jassert (input->getTotalLength() < 50 * 1024 * 1024);

Handle dataHandle = NewHandle ((Size) input->getTotalLength());
HLock (dataHandle);
// read the entire stream into memory - this is a pain, but can't get it to work
// properly using a custom callback to supply the data.
input->read (*dataHandle, (int) input->getTotalLength());
HUnlock (dataHandle);

// different types to get QT to try. (We should really be a bit smarter here by
// working out in advance which one the stream contains, rather than just trying
// each one)
const char* const suffixesToTry[] = { "\04.mov", "\04.mp3",
"\04.avi", "\04.m4a" };

for (int i = 0; i < numElementsInArray (suffixesToTry) && ! ok; ++i)
{
dr.dataRef = createHandleDataRef (dataHandle, suffixesToTry [i]);

/* // this fails for some bizarre reason - it can be bodged to work with
// movies, but can't seem to do it for other file types..
QTNewMovieUserProcRecord procInfo;
procInfo.getMovieUserProc = NewGetMovieUPP (readMovieStreamProc);
procInfo.getMovieUserProcRefcon = this;
procInfo.defaultDataRef.dataRef = dataRef;
procInfo.defaultDataRef.dataRefType = HandleDataHandlerSubType;

props[prop].propClass = kQTPropertyClass_DataLocation;
props[prop].propID = kQTDataLocationPropertyID_MovieUserProc;
props[prop].propValueSize = sizeof (procInfo);
props[prop].propValueAddress = (void*) &procInfo;
++prop; */

dr.dataRefType = HandleDataHandlerSubType;
ok = openMovie (props, prop);

DisposeHandle (dr.dataRef);
}

DisposeHandle (dataHandle);
}

return ok;
}

bool openMovie (QTNewMoviePropertyElement* props, int prop)
{
Boolean trueBool = true;
props[prop].propClass = kQTPropertyClass_MovieInstantiation;
props[prop].propID = kQTMovieInstantiationPropertyID_DontResolveDataRefs;
props[prop].propValueSize = sizeof (trueBool);
props[prop].propValueAddress = &trueBool;
++prop;

props[prop].propClass = kQTPropertyClass_MovieInstantiation;
props[prop].propID = kQTMovieInstantiationPropertyID_AsyncOK;
props[prop].propValueSize = sizeof (trueBool);
props[prop].propValueAddress = &trueBool;
++prop;

Boolean isActive = true;
props[prop].propClass = kQTPropertyClass_NewMovieProperty;
props[prop].propID = kQTNewMoviePropertyID_Active;
props[prop].propValueSize = sizeof (isActive);
props[prop].propValueAddress = &isActive;
++prop;

#if JUCE_MAC
SetPort (0);
#else
MacSetPort (0);
#endif

jassert (prop <= 5);
OSStatus err = NewMovieFromProperties (prop, props, 0, 0, &movie);
return err == noErr;
}

//==============================================================================
void checkThreadIsAttached()
{
#if JUCE_MAC
if (Thread::getCurrentThreadId() != lastThreadId)
EnterMoviesOnThread (0);
AttachMovieToCurrentThread (movie);
#endif
}

void detachThread()
{
#if JUCE_MAC
DetachMovieFromCurrentThread (movie);
#endif
}
};


//==============================================================================
QuickTimeAudioFormat::QuickTimeAudioFormat()
: AudioFormat (qtFormatName, (const tchar**) extensions)
{
}

QuickTimeAudioFormat::~QuickTimeAudioFormat()
{
}

const Array <int> QuickTimeAudioFormat::getPossibleSampleRates()
{
return Array<int>();
}

const Array <int> QuickTimeAudioFormat::getPossibleBitDepths()
{
return Array<int>();
}

bool QuickTimeAudioFormat::canDoStereo()
{
return true;
}

bool QuickTimeAudioFormat::canDoMono()
{
return true;
}

//==============================================================================
AudioFormatReader* QuickTimeAudioFormat::createReaderFor (InputStream* sourceStream,
const bool deleteStreamIfOpeningFails)
{
QTAudioReader* r = new QTAudioReader (sourceStream, 0);

if (! r->ok)
{
if (! deleteStreamIfOpeningFails)
r->input = 0;

deleteAndZero (r);
}

return r;
}

AudioFormatWriter* QuickTimeAudioFormat::createWriterFor (OutputStream* /*streamToWriteTo*/,
double /*sampleRateToUse*/,
unsigned int /*numberOfChannels*/,
int /*bitsPerSample*/,
const StringPairArray& /*metadataValues*/,
int /*qualityOptionIndex*/)
{
jassertfalse // not yet implemented!
return 0;
}


END_JUCE_NAMESPACE

#endif
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../../juce_Config.h"
#if JUCE_QUICKTIME
#if ! defined (_WIN32)
#include <Quicktime/Movies.h>
#include <Quicktime/QTML.h>
#include <Quicktime/QuickTimeComponents.h>
#include <Quicktime/MediaHandlers.h>
#include <Quicktime/ImageCodec.h>
#else
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable : 4100)
#endif
#include <Movies.h>
#include <QTML.h>
#include <QuickTimeComponents.h>
#include <MediaHandlers.h>
#include <ImageCodec.h>
#ifdef _MSC_VER
#pragma warning (pop)
#endif
#endif
#include "../../../juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_QuickTimeAudioFormat.h"
#include "../../../juce_core/text/juce_LocalisedStrings.h"
#include "../../../juce_core/threads/juce_Thread.h"
#include "../../../juce_core/io/network/juce_URL.h"
bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle);
#define qtFormatName TRANS("QuickTime file")
static const tchar* const extensions[] = { T(".mov"), T(".mp3"), 0 };
//==============================================================================
class QTAudioReader : public AudioFormatReader
{
public:
QTAudioReader (InputStream* const input_, const int trackNum_)
: AudioFormatReader (input_, qtFormatName),
ok (false),
movie (0),
trackNum (trackNum_),
extractor (0),
lastSampleRead (0),
lastThreadId (0),
dataHandle (0)
{
bufferList = (AudioBufferList*) juce_calloc (256);
#ifdef WIN32
if (InitializeQTML (0) != noErr)
return;
#endif
if (EnterMovies() != noErr)
return;
#if JUCE_MAC
EnterMoviesOnThread (0);
#endif
bool opened = juce_OpenQuickTimeMovieFromStream (input_, movie, dataHandle);
if (! opened)
return;
{
const int numTracks = GetMovieTrackCount (movie);
int trackCount = 0;
for (int i = 1; i <= numTracks; ++i)
{
track = GetMovieIndTrack (movie, i);
media = GetTrackMedia (track);
OSType mediaType;
GetMediaHandlerDescription (media, &mediaType, 0, 0);
if (mediaType == SoundMediaType
&& trackCount++ == trackNum_)
{
ok = true;
break;
}
}
}
if (! ok)
return;
ok = false;
lengthInSamples = GetMediaDecodeDuration (media);
usesFloatingPointData = false;
samplesPerFrame = (int) (GetMediaDecodeDuration (media) / GetMediaSampleCount (media));
trackUnitsPerFrame = GetMovieTimeScale (movie) * samplesPerFrame
/ GetMediaTimeScale (media);
OSStatus err = MovieAudioExtractionBegin (movie, 0, &extractor);
unsigned long output_layout_size;
err = MovieAudioExtractionGetPropertyInfo (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
0, &output_layout_size, 0);
if (err != noErr)
return;
AudioChannelLayout* const qt_audio_channel_layout
= (AudioChannelLayout*) juce_calloc (output_layout_size);
err = MovieAudioExtractionGetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
output_layout_size, qt_audio_channel_layout, 0);
qt_audio_channel_layout->mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
err = MovieAudioExtractionSetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
sizeof (qt_audio_channel_layout),
qt_audio_channel_layout);
juce_free (qt_audio_channel_layout);
err = MovieAudioExtractionGetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
sizeof (inputStreamDesc),
&inputStreamDesc, 0);
if (err != noErr)
return;
inputStreamDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger
| kAudioFormatFlagIsPacked
| kAudioFormatFlagsNativeEndian;
inputStreamDesc.mBitsPerChannel = sizeof (SInt16) * 8;
inputStreamDesc.mChannelsPerFrame = jmin (2, inputStreamDesc.mChannelsPerFrame);
inputStreamDesc.mBytesPerFrame = sizeof (SInt16) * inputStreamDesc.mChannelsPerFrame;
inputStreamDesc.mBytesPerPacket = inputStreamDesc.mBytesPerFrame;
err = MovieAudioExtractionSetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
sizeof (inputStreamDesc),
&inputStreamDesc);
if (err != noErr)
return;
Boolean allChannelsDiscrete = false;
err = MovieAudioExtractionSetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Movie,
kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete,
sizeof (allChannelsDiscrete),
&allChannelsDiscrete);
if (err != noErr)
return;
bufferList->mNumberBuffers = 1;
bufferList->mBuffers[0].mNumberChannels = inputStreamDesc.mChannelsPerFrame;
bufferList->mBuffers[0].mDataByteSize = (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16;
bufferList->mBuffers[0].mData = malloc (bufferList->mBuffers[0].mDataByteSize);
sampleRate = inputStreamDesc.mSampleRate;
bitsPerSample = 16;
numChannels = inputStreamDesc.mChannelsPerFrame;
detachThread();
ok = true;
}
~QTAudioReader()
{
if (dataHandle != 0)
DisposeHandle (dataHandle);
if (extractor != 0)
{
MovieAudioExtractionEnd (extractor);
extractor = 0;
}
checkThreadIsAttached();
DisposeMovie (movie);
juce_free (bufferList->mBuffers[0].mData);
juce_free (bufferList);
}
bool read (int** destSamples,
int64 startSample,
int numSamples)
{
checkThreadIsAttached();
int done = 0;
while (numSamples > 0)
{
if (! loadFrame ((int) startSample))
return false;
const int numToDo = jmin (numSamples, samplesPerFrame);
for (unsigned int j = 0; j < inputStreamDesc.mChannelsPerFrame; ++j)
{
if (destSamples[j] != 0)
{
const short* const src = ((const short*) bufferList->mBuffers[0].mData) + j;
for (int i = 0; i < numToDo; ++i)
destSamples[j][done + i] = src [i << 1] << 16;
}
}
done += numToDo;
startSample += numToDo;
numSamples -= numToDo;
}
detachThread();
return true;
}
bool loadFrame (const int sampleNum)
{
if (lastSampleRead != sampleNum)
{
TimeRecord time;
time.scale = (TimeScale) inputStreamDesc.mSampleRate;
time.base = 0;
time.value.hi = 0;
time.value.lo = (UInt32) sampleNum;
OSStatus err = MovieAudioExtractionSetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Movie,
kQTMovieAudioExtractionMoviePropertyID_CurrentTime,
sizeof (time), &time);
if (err != noErr)
return false;
}
bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * samplesPerFrame;
UInt32 outFlags = 0;
UInt32 actualNumSamples = samplesPerFrame;
OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumSamples,
bufferList, &outFlags);
lastSampleRead = sampleNum + samplesPerFrame;
return err == noErr;
}
juce_UseDebuggingNewOperator
bool ok;
private:
Movie movie;
Media media;
Track track;
const int trackNum;
double trackUnitsPerFrame;
int samplesPerFrame;
int lastSampleRead, lastThreadId;
MovieAudioExtractionRef extractor;
AudioStreamBasicDescription inputStreamDesc;
AudioBufferList* bufferList;
Handle dataHandle;
/*OSErr readMovieStream (long offset, long size, void* dataPtr)
{
input->setPosition (offset);
input->read (dataPtr, size);
return noErr;
}
static OSErr readMovieStreamProc (long offset, long size, void* dataPtr, void* userRef)
{
return ((QTAudioReader*) userRef)->readMovieStream (offset, size, dataPtr);
}*/
//==============================================================================
void checkThreadIsAttached()
{
#if JUCE_MAC
if (Thread::getCurrentThreadId() != lastThreadId)
EnterMoviesOnThread (0);
AttachMovieToCurrentThread (movie);
#endif
}
void detachThread()
{
#if JUCE_MAC
DetachMovieFromCurrentThread (movie);
#endif
}
};
//==============================================================================
QuickTimeAudioFormat::QuickTimeAudioFormat()
: AudioFormat (qtFormatName, (const tchar**) extensions)
{
}
QuickTimeAudioFormat::~QuickTimeAudioFormat()
{
}
const Array <int> QuickTimeAudioFormat::getPossibleSampleRates()
{
return Array<int>();
}
const Array <int> QuickTimeAudioFormat::getPossibleBitDepths()
{
return Array<int>();
}
bool QuickTimeAudioFormat::canDoStereo()
{
return true;
}
bool QuickTimeAudioFormat::canDoMono()
{
return true;
}
//==============================================================================
AudioFormatReader* QuickTimeAudioFormat::createReaderFor (InputStream* sourceStream,
const bool deleteStreamIfOpeningFails)
{
QTAudioReader* r = new QTAudioReader (sourceStream, 0);
if (! r->ok)
{
if (! deleteStreamIfOpeningFails)
r->input = 0;
deleteAndZero (r);
}
return r;
}
AudioFormatWriter* QuickTimeAudioFormat::createWriterFor (OutputStream* /*streamToWriteTo*/,
double /*sampleRateToUse*/,
unsigned int /*numberOfChannels*/,
int /*bitsPerSample*/,
const StringPairArray& /*metadataValues*/,
int /*qualityOptionIndex*/)
{
jassertfalse // not yet implemented!
return 0;
}
END_JUCE_NAMESPACE
#endif

+ 1
- 1
src/juce_appframework/audio/audio_file_formats/juce_QuickTimeAudioFormat.h View File

@@ -33,7 +33,7 @@
#define __JUCE_QUICKTIMEAUDIOFORMAT_JUCEHEADER__
#include "juce_AudioFormat.h"
#if JUCE_QUICKTIME_AUDIOFORMAT
#if JUCE_QUICKTIME
//==============================================================================


+ 284
- 71
src/juce_appframework/gui/components/special/juce_QuickTimeMovieComponent.cpp View File

@@ -40,6 +40,21 @@
#ifdef _WIN32
#include <windows.h>

#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable : 4100)
#endif

#include <Movies.h>
#include <QTML.h>
#include <QuickTimeComponents.h>
#include <MediaHandlers.h>
#include <ImageCodec.h>

#ifdef _MSC_VER
#pragma warning (pop)
#endif

// If you've got QuickTime 7 installed, then these COM objects should be found in
// the "\Program Files\Quicktime" directory. You'll need to add this directory to
// your include search path to make these import statements work.
@@ -51,6 +66,8 @@
#else
#include <Carbon/Carbon.h>
#include <QuickTime/Movies.h>
#include <QuickTime/QuickTimeComponents.h>
#include <QuickTime/MediaHandlers.h>
#endif

#include "../../../../juce_core/basics/juce_StandardHeader.h"
@@ -58,17 +75,50 @@
BEGIN_JUCE_NAMESPACE

#include "juce_QuickTimeMovieComponent.h"
#include "../../../../juce_core/io/files/juce_FileInputStream.h"

bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle);

//==============================================================================
#if JUCE_WIN32

//==============================================================================
struct QTMovieCompInternal
{
QTMovieCompInternal()
: dataHandle (0)
{
#if JUCE_MAC
movie = 0;
controller = 0;
#endif
}

~QTMovieCompInternal()
{
clearHandle();
}

#if JUCE_MAC
Movie movie;
MovieController controller;
#else
IQTControlPtr qtControlInternal;
IQTMoviePtr qtMovieInternal;
#endif

Handle dataHandle;

void clearHandle()
{
if (dataHandle != 0)
{
DisposeHandle (dataHandle);
dataHandle = 0;
}
}
};

#if JUCE_WIN32

#define qtControl (((QTMovieCompInternal*) internal)->qtControlInternal)
#define qtMovie (((QTMovieCompInternal*) internal)->qtMovieInternal)

@@ -122,10 +172,10 @@ bool QuickTimeMovieComponent::isControlCreated() const
return isControlOpen();
}

bool QuickTimeMovieComponent::loadMovie (const File& movieFile_,
bool QuickTimeMovieComponent::loadMovie (InputStream* movieStream,
const bool isControllerVisible)
{
movieFile = movieFile_;
movieFile = File::nonexistent;
movieLoaded = false;
qtMovie = 0;
controllerVisible = isControllerVisible;
@@ -135,24 +185,36 @@ bool QuickTimeMovieComponent::loadMovie (const File& movieFile_,
{
if (qtControl != 0)
{
qtControl->PutURL ((const WCHAR*) movieFile_.getFullPathName());
qtMovie = qtControl->GetMovie();
qtControl->Put_MovieHandle (0);
((QTMovieCompInternal*) internal)->clearHandle();

Movie movie;
if (juce_OpenQuickTimeMovieFromStream (movieStream, movie, ((QTMovieCompInternal*) internal)->dataHandle))
{
qtControl->Put_MovieHandle ((long) (pointer_sized_int) movie);

qtMovie = qtControl->GetMovie();

if (qtMovie != 0)
qtMovie->PutMovieControllerType (isControllerVisible ? qtMovieControllerTypeStandard
: qtMovieControllerTypeNone);
if (qtMovie != 0)
qtMovie->PutMovieControllerType (isControllerVisible ? qtMovieControllerTypeStandard
: qtMovieControllerTypeNone);
}

if (movie == 0)
((QTMovieCompInternal*) internal)->clearHandle();
}

movieLoaded = (qtMovie != 0);
return movieLoaded;
}
else
{
// You're trying to open a movie when the control hasn't yet been created, probably because
// you've not yet added this component to a Window and made the whole component hierarchy visible.
jassertfalse
return false;
}

delete movieStream;
return movieLoaded;
}

void QuickTimeMovieComponent::closeMovie()
@@ -163,7 +225,10 @@ void QuickTimeMovieComponent::closeMovie()
qtMovie = 0;

if (qtControl != 0)
qtControl->PutURL (L"");
qtControl->Put_MovieHandle (0);
//qtControl->PutURL (L"");

((QTMovieCompInternal*) internal)->clearHandle();
}

const File QuickTimeMovieComponent::getCurrentMovieFile() const
@@ -327,25 +392,14 @@ void OfferMouseClickToQuickTime (WindowRef window,
}
}

//==============================================================================
struct InternalData
{
Movie movie;
MovieController controller;
};

//==============================================================================
QuickTimeMovieComponent::QuickTimeMovieComponent()
: internal (new InternalData()),
: internal (new QTMovieCompInternal()),
associatedWindow (0),
controllerVisible (false),
controllerAssignedToWindow (false),
reentrant (false)
{
InternalData* const id = (InternalData*) internal;
id->movie = 0;
id->controller = 0;

if (! hasLoadedQT)
{
hasLoadedQT = true;
@@ -364,7 +418,7 @@ QuickTimeMovieComponent::~QuickTimeMovieComponent()

activeQTWindows.removeValue ((void*) this);

InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;
delete id;

if (activeQTWindows.size() == 0 && isQTAvailable)
@@ -376,13 +430,14 @@ QuickTimeMovieComponent::~QuickTimeMovieComponent()
}
}

bool QuickTimeMovieComponent::loadMovie (const File& f,
bool QuickTimeMovieComponent::loadMovie (InputStream* movieStream,
const bool controllerVisible_)
{
if (! (isQTAvailable && f.existsAsFile()))
if (! isQTAvailable)
return false;

closeMovie();
movieFile = File::nonexistent;

if (getPeer() == 0)
{
@@ -394,45 +449,30 @@ bool QuickTimeMovieComponent::loadMovie (const File& f,

controllerVisible = controllerVisible_;

InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

GrafPtr savedPort;
GetPort (&savedPort);
bool result = false;

FSSpec fsSpec;

PlatformUtilities::makeFSSpecFromPath (&fsSpec, f.getFullPathName());

short refNum = -1;
OSErr err;

if ((err = OpenMovieFile (&fsSpec, &refNum, fsRdWrPerm)) == noErr
|| (err = OpenMovieFile (&fsSpec, &refNum, fsRdPerm)) == noErr)
if (juce_OpenQuickTimeMovieFromStream (movieStream, id->movie, id->dataHandle))
{
id->controller = 0;

short resID = 0;
void* window = getWindowHandle();

if (NewMovieFromFile (&id->movie, refNum, &resID, 0, newMovieActive, 0) == noErr
&& id->movie != 0)
{
void* window = getWindowHandle();

if (window != associatedWindow && window != 0)
associatedWindow = window;
if (window != associatedWindow && window != 0)
associatedWindow = window;

assignMovieToWindow();
assignMovieToWindow();

SetMovieActive (id->movie, true);
SetMovieProgressProc (id->movie, (MovieProgressUPP) -1, 0);
SetMovieActive (id->movie, true);
SetMovieProgressProc (id->movie, (MovieProgressUPP) -1, 0);

movieFile = f;
startTimer (1000 / 50); // this needs to be quite a high frequency for smooth playback
result = true;
startTimer (1000 / 50); // this needs to be quite a high frequency for smooth playback
result = true;

repaint();
}
repaint();
}

MacSetPort (savedPort);
@@ -444,7 +484,7 @@ void QuickTimeMovieComponent::closeMovie()
{
stop();

InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->controller != 0)
{
@@ -458,13 +498,15 @@ void QuickTimeMovieComponent::closeMovie()
id->movie = 0;
}

id->clearHandle();

stopTimer();
movieFile = File::nonexistent;
}

bool QuickTimeMovieComponent::isMovieOpen() const
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;
return id->movie != 0 && id->controller != 0;
}

@@ -488,7 +530,7 @@ void QuickTimeMovieComponent::assignMovieToWindow()

reentrant = true;

InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;
if (id->controller != 0)
{
DisposeMovieController (id->controller);
@@ -550,7 +592,7 @@ void QuickTimeMovieComponent::assignMovieToWindow()

void QuickTimeMovieComponent::play()
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->movie != 0)
StartMovie (id->movie);
@@ -558,7 +600,7 @@ void QuickTimeMovieComponent::play()

void QuickTimeMovieComponent::stop()
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->movie != 0)
StopMovie (id->movie);
@@ -566,14 +608,14 @@ void QuickTimeMovieComponent::stop()

bool QuickTimeMovieComponent::isPlaying() const
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

return id->movie != 0 && GetMovieRate (id->movie) != 0;
}

void QuickTimeMovieComponent::setPosition (const double seconds)
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->controller != 0)
{
@@ -595,7 +637,7 @@ void QuickTimeMovieComponent::setPosition (const double seconds)

double QuickTimeMovieComponent::getPosition() const
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->movie != 0)
{
@@ -611,7 +653,7 @@ double QuickTimeMovieComponent::getPosition() const

void QuickTimeMovieComponent::setSpeed (const float newSpeed)
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->movie != 0)
SetMovieRate (id->movie, (Fixed) (newSpeed * (Fixed) 0x00010000L));
@@ -619,7 +661,7 @@ void QuickTimeMovieComponent::setSpeed (const float newSpeed)

double QuickTimeMovieComponent::getMovieDuration() const
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->movie != 0)
return GetMovieDuration (id->movie) / (double) GetMovieTimeScale (id->movie);
@@ -629,7 +671,7 @@ double QuickTimeMovieComponent::getMovieDuration() const

void QuickTimeMovieComponent::setLooping (const bool shouldLoop)
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;
looping = shouldLoop;

if (id->controller != 0)
@@ -643,7 +685,7 @@ bool QuickTimeMovieComponent::isLooping() const

void QuickTimeMovieComponent::setMovieVolume (const float newVolume)
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->movie != 0)
SetMovieVolume (id->movie, jlimit ((short) 0, (short) 0x100, (short) (newVolume * 0x0100)));
@@ -651,7 +693,7 @@ void QuickTimeMovieComponent::setMovieVolume (const float newVolume)

float QuickTimeMovieComponent::getMovieVolume() const
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->movie != 0)
return jmax (0.0f, GetMovieVolume (id->movie) / (float) 0x0100);
@@ -664,7 +706,7 @@ void QuickTimeMovieComponent::getMovieNormalSize (int& width, int& height) const
width = 0;
height = 0;

InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->movie != 0)
{
@@ -677,7 +719,7 @@ void QuickTimeMovieComponent::getMovieNormalSize (int& width, int& height) const

void QuickTimeMovieComponent::paint (Graphics& g)
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->movie == 0 || id->controller == 0)
{
@@ -720,7 +762,7 @@ void QuickTimeMovieComponent::moved()

void QuickTimeMovieComponent::resized()
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->controller != 0 && isShowing())
{
@@ -767,7 +809,7 @@ void QuickTimeMovieComponent::visibilityChanged()

void QuickTimeMovieComponent::timerCallback()
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->controller != 0)
{
@@ -800,7 +842,7 @@ void QuickTimeMovieComponent::parentHierarchyChanged()

void QuickTimeMovieComponent::handleMCEvent (void* ev)
{
InternalData* const id = (InternalData*) internal;
QTMovieCompInternal* const id = (QTMovieCompInternal*) internal;

if (id->controller != 0 && isShowing())
{
@@ -833,6 +875,177 @@ void QuickTimeMovieComponent::handleMCEvent (void* ev)
//==============================================================================
// (methods common to both platforms..)

static Handle createHandleDataRef (Handle dataHandle, const char* fileName)
{
Handle dataRef = 0;
OSStatus err = PtrToHand (&dataHandle, &dataRef, sizeof (Handle));
if (err == noErr)
{
Str255 suffix;
#if JUCE_WIN32
strcpy_s ((char*) suffix, 128, fileName);
#else
strcpy ((char*) suffix, fileName);
#endif
StringPtr name = suffix;
err = PtrAndHand (name, dataRef, name[0] + 1);

if (err == noErr)
{
long atoms[3];
atoms[0] = EndianU32_NtoB (3 * sizeof (long));
atoms[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
atoms[2] = EndianU32_NtoB (MovieFileType);

err = PtrAndHand (atoms, dataRef, 3 * sizeof (long));

if (err == noErr)
return dataRef;
}

DisposeHandle (dataRef);
}

return 0;
}

static CFStringRef juceStringToCFString (const String& s)
{
const int len = s.length();
const juce_wchar* const t = (const juce_wchar*) s;

UniChar* temp = (UniChar*) juce_malloc (sizeof (UniChar) * len + 4);

for (int i = 0; i <= len; ++i)
temp[i] = t[i];

CFStringRef result = CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len);
juce_free (temp);

return result;
}

static bool openMovie (QTNewMoviePropertyElement* props, int prop, Movie& movie)
{
Boolean trueBool = true;
props[prop].propClass = kQTPropertyClass_MovieInstantiation;
props[prop].propID = kQTMovieInstantiationPropertyID_DontResolveDataRefs;
props[prop].propValueSize = sizeof (trueBool);
props[prop].propValueAddress = &trueBool;
++prop;

props[prop].propClass = kQTPropertyClass_MovieInstantiation;
props[prop].propID = kQTMovieInstantiationPropertyID_AsyncOK;
props[prop].propValueSize = sizeof (trueBool);
props[prop].propValueAddress = &trueBool;
++prop;

Boolean isActive = true;
props[prop].propClass = kQTPropertyClass_NewMovieProperty;
props[prop].propID = kQTNewMoviePropertyID_Active;
props[prop].propValueSize = sizeof (isActive);
props[prop].propValueAddress = &isActive;
++prop;

#if JUCE_MAC
SetPort (0);
#else
MacSetPort (0);
#endif

jassert (prop <= 5);
OSStatus err = NewMovieFromProperties (prop, props, 0, 0, &movie);
return err == noErr;
}

bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle)
{
if (input == 0)
return false;

dataHandle = 0;
bool ok = false;

QTNewMoviePropertyElement props[5];
zeromem (props, sizeof (props));
int prop = 0;

DataReferenceRecord dr;
props[prop].propClass = kQTPropertyClass_DataLocation;
props[prop].propID = kQTDataLocationPropertyID_DataReference;
props[prop].propValueSize = sizeof (dr);
props[prop].propValueAddress = (void*) &dr;
++prop;

FileInputStream* const fin = dynamic_cast <FileInputStream*> (input);

if (fin != 0)
{
CFStringRef filePath = juceStringToCFString (fin->getFile().getFullPathName());

QTNewDataReferenceFromFullPathCFString (filePath, (QTPathStyle) kQTNativeDefaultPathStyle, 0,
&dr.dataRef, &dr.dataRefType);


ok = openMovie (props, prop, movie);

DisposeHandle (dr.dataRef);
CFRelease (filePath);
}
else
{
// sanity-check because this currently needs to load the whole stream into memory..
jassert (input->getTotalLength() < 50 * 1024 * 1024);

dataHandle = NewHandle ((Size) input->getTotalLength());
HLock (dataHandle);
// read the entire stream into memory - this is a pain, but can't get it to work
// properly using a custom callback to supply the data.
input->read (*dataHandle, (int) input->getTotalLength());
HUnlock (dataHandle);

// different types to get QT to try. (We should really be a bit smarter here by
// working out in advance which one the stream contains, rather than just trying
// each one)
const char* const suffixesToTry[] = { "\04.mov", "\04.mp3",
"\04.avi", "\04.m4a" };

for (int i = 0; i < numElementsInArray (suffixesToTry) && ! ok; ++i)
{
/* // this fails for some bizarre reason - it can be bodged to work with
// movies, but can't seem to do it for other file types..
QTNewMovieUserProcRecord procInfo;
procInfo.getMovieUserProc = NewGetMovieUPP (readMovieStreamProc);
procInfo.getMovieUserProcRefcon = this;
procInfo.defaultDataRef.dataRef = dataRef;
procInfo.defaultDataRef.dataRefType = HandleDataHandlerSubType;

props[prop].propClass = kQTPropertyClass_DataLocation;
props[prop].propID = kQTDataLocationPropertyID_MovieUserProc;
props[prop].propValueSize = sizeof (procInfo);
props[prop].propValueAddress = (void*) &procInfo;
++prop; */

dr.dataRef = createHandleDataRef (dataHandle, suffixesToTry [i]);
dr.dataRefType = HandleDataHandlerSubType;
ok = openMovie (props, prop, movie);

DisposeHandle (dr.dataRef);
}
}

return ok;
}

bool QuickTimeMovieComponent::loadMovie (const File& movieFile_,
const bool isControllerVisible)
{
const bool ok = loadMovie ((InputStream*) movieFile_.createInputStream(), isControllerVisible);
movieFile = movieFile_;
return ok;
}

void QuickTimeMovieComponent::goToStart()
{
setPosition (0.0);


+ 7
- 4
src/juce_appframework/gui/components/special/juce_QuickTimeMovieComponent.h View File

@@ -85,6 +85,9 @@ public:
bool loadMovie (const File& movieFile,
const bool isControllerVisible);
bool loadMovie (InputStream* movieStream,
const bool isControllerVisible);
/** Closes the movie, if one is open. */
void closeMovie();
@@ -137,9 +140,9 @@ public:
/** Returns the current play position of the movie. */
double getPosition() const;
/** Changes the movie playback rate.
A value of 1 is normal speed, greater values play it proportionately faster,
/** Changes the movie playback rate.
A value of 1 is normal speed, greater values play it proportionately faster,
smaller values play it slower.
*/
void setSpeed (const float newSpeed);
@@ -191,7 +194,7 @@ public:
/** @internal */
void resized();
#endif
juce_UseDebuggingNewOperator
private:


Loading…
Cancel
Save