src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /*  This file is part of the KDE project.
       
     2 
       
     3     Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 
       
     5     This library is free software: you can redistribute it and/or modify
       
     6     it under the terms of the GNU Lesser General Public License as published by
       
     7     the Free Software Foundation, either version 2.1 or 3 of the License.
       
     8 
       
     9     This library is distributed in the hope that it will be useful,
       
    10     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12     GNU Lesser General Public License for more details.
       
    13 
       
    14     You should have received a copy of the GNU Lesser General Public License
       
    15     along with this library.  If not, see <http://www.gnu.org/licenses/>.
       
    16 */
       
    17 
       
    18 #include "quicktimevideoplayer.h"
       
    19 #include "mediaobject.h"
       
    20 #include "videowidget.h"
       
    21 #include "audiodevice.h"
       
    22 #include "quicktimestreamreader.h"
       
    23 #include "quicktimemetadata.h"
       
    24 
       
    25 #include <QtCore/QCoreApplication>
       
    26 #include <QtCore/QEventLoop>
       
    27 #include <QtCore/QFileInfo>
       
    28 #include <QtCore/QUrl>
       
    29 #include <QtOpenGL/QGLContext>
       
    30 
       
    31 #import <QTKit/QTTrack.h>
       
    32 #import <QTKit/QTMedia.h>
       
    33 #import <QuartzCore/CIContext.h>
       
    34 #import <QuartzCore/CIFilter.h>
       
    35 
       
    36 #ifdef QUICKTIME_C_API_AVAILABLE
       
    37     #include <QuickTime/QuickTime.h>
       
    38     #undef check // avoid name clash;
       
    39     #include <AGL/agl.h>
       
    40 #endif
       
    41 
       
    42 QT_BEGIN_NAMESPACE
       
    43 
       
    44 namespace Phonon
       
    45 {
       
    46 namespace QT7
       
    47 {
       
    48 
       
    49 // Defined in videowidget.cpp:
       
    50 QGLWidget *PhononSharedQGLWidget();
       
    51 
       
    52 QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0)
       
    53 {
       
    54     m_state = NoMedia;
       
    55     m_mediaSource = MediaSource();
       
    56     m_metaData = new QuickTimeMetaData(this);
       
    57     m_QTMovie = 0;
       
    58     m_streamReader = 0;
       
    59     m_playbackRate = 1.0f;
       
    60     m_masterVolume = 1.0f;
       
    61     m_relativeVolume = 1.0f;
       
    62     m_currentTime = 0;
       
    63     m_mute = false;
       
    64     m_audioEnabled = false;
       
    65     m_hasVideo = false;
       
    66     m_staticFps = 0;
       
    67     m_playbackRateSat = false;
       
    68     m_isDrmProtected = false;
       
    69     m_isDrmAuthorized = true;
       
    70 	m_primaryRenderingTarget = 0;
       
    71 	m_primaryRenderingCIImage = 0;
       
    72     m_QImagePixelBuffer = 0;
       
    73     m_cachedCVTextureRef = 0;
       
    74     m_folderTracks = 0;
       
    75     m_currentTrack = 0;
       
    76 
       
    77 #ifdef QUICKTIME_C_API_AVAILABLE
       
    78     OSStatus err = EnterMovies();
       
    79     BACKEND_ASSERT2(err == noErr, "Could not initialize QuickTime", FATAL_ERROR)
       
    80 	createVisualContext();
       
    81 #endif
       
    82 }
       
    83 
       
    84 QuickTimeVideoPlayer::~QuickTimeVideoPlayer()
       
    85 {
       
    86 	PhononAutoReleasePool pool;
       
    87     unsetCurrentMediaSource();
       
    88     delete m_metaData;
       
    89     [(NSObject*)m_primaryRenderingTarget release];
       
    90     m_primaryRenderingTarget = 0;
       
    91 #ifdef QUICKTIME_C_API_AVAILABLE
       
    92     if (m_visualContext)
       
    93         CFRelease(m_visualContext);
       
    94 #endif
       
    95 }
       
    96 
       
    97 void QuickTimeVideoPlayer::releaseImageCache()
       
    98 {
       
    99     if (m_cachedCVTextureRef){
       
   100         CVOpenGLTextureRelease(m_cachedCVTextureRef);
       
   101         m_cachedCVTextureRef = 0;
       
   102     }
       
   103     m_cachedQImage = QImage();
       
   104 }
       
   105 
       
   106 void QuickTimeVideoPlayer::createVisualContext()
       
   107 {
       
   108 #ifdef QUICKTIME_C_API_AVAILABLE
       
   109 	PhononSharedQGLWidget()->makeCurrent();
       
   110 
       
   111 	PhononAutoReleasePool pool;
       
   112     CGLContextObj cglContext = CGLGetCurrentContext();
       
   113 	NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat];
       
   114     CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>([nsglPixelFormat CGLPixelFormatObj]);
       
   115 	BACKEND_ASSERT2(cglContext, "Could not get current CoreVideo GL context (OpenGL)", FATAL_ERROR)
       
   116 	BACKEND_ASSERT2(cglPixelFormat, "Could not get current CoreVideo pixel format (OpenGL)", FATAL_ERROR)
       
   117 
       
   118     CFTypeRef keys[] = { kQTVisualContextWorkingColorSpaceKey };
       
   119     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
       
   120     CFDictionaryRef textureContextAttributes = CFDictionaryCreate(kCFAllocatorDefault,
       
   121         (const void **)keys,
       
   122         (const void **)&colorSpace, 1,
       
   123         &kCFTypeDictionaryKeyCallBacks,
       
   124         &kCFTypeDictionaryValueCallBacks);
       
   125 
       
   126 	OSStatus err = QTOpenGLTextureContextCreate(kCFAllocatorDefault, cglContext,
       
   127         cglPixelFormat, textureContextAttributes, &m_visualContext);
       
   128     CFRelease(textureContextAttributes);
       
   129     BACKEND_ASSERT2(err == noErr, "Could not create visual context (OpenGL)", FATAL_ERROR)
       
   130 #endif // QUICKTIME_C_API_AVAILABLE
       
   131 }
       
   132 
       
   133 bool QuickTimeVideoPlayer::videoFrameChanged()
       
   134 {
       
   135     if (!m_QTMovie || !m_hasVideo)
       
   136         return false;
       
   137 
       
   138 #ifdef QUICKTIME_C_API_AVAILABLE
       
   139 	if (m_primaryRenderingTarget)
       
   140 		return true;
       
   141     if (!m_visualContext)
       
   142 		return false;
       
   143 
       
   144     QTVisualContextTask(m_visualContext);
       
   145     bool changed = QTVisualContextIsNewImageAvailable(m_visualContext, 0);
       
   146     if (changed)
       
   147         releaseImageCache();
       
   148     return changed;
       
   149 
       
   150 #elif defined(QT_MAC_USE_COCOA)
       
   151     return true;
       
   152 
       
   153 #else
       
   154     return false;
       
   155 #endif
       
   156 }
       
   157 
       
   158 CVOpenGLTextureRef QuickTimeVideoPlayer::currentFrameAsCVTexture()
       
   159 {
       
   160 #ifdef QUICKTIME_C_API_AVAILABLE
       
   161     if (!m_visualContext)
       
   162         return 0;
       
   163     if (!m_cachedCVTextureRef){
       
   164         OSStatus err = QTVisualContextCopyImageForTime(m_visualContext, 0, 0, &m_cachedCVTextureRef);
       
   165         BACKEND_ASSERT3(err == noErr, "Could not copy image for time in QuickTime player", FATAL_ERROR, 0)
       
   166     }
       
   167     return m_cachedCVTextureRef;
       
   168 
       
   169 #else
       
   170     return 0;
       
   171 #endif
       
   172 }
       
   173 
       
   174 QImage QuickTimeVideoPlayer::currentFrameAsQImage()
       
   175 {
       
   176     if (!m_cachedQImage.isNull())
       
   177         return m_cachedQImage;
       
   178 
       
   179 #ifdef QUICKTIME_C_API_AVAILABLE
       
   180     QGLContext *prevContext = const_cast<QGLContext *>(QGLContext::currentContext());
       
   181     CVOpenGLTextureRef texture = currentFrameAsCVTexture();
       
   182     GLenum target = CVOpenGLTextureGetTarget(texture);
       
   183     GLfloat lowerLeft[2], lowerRight[2], upperRight[2], upperLeft[2];
       
   184 
       
   185     if (!m_QImagePixelBuffer){
       
   186         m_QImagePixelBuffer = new QGLPixelBuffer(videoRect().size(), QGLFormat::defaultFormat(), PhononSharedQGLWidget());
       
   187         m_QImagePixelBuffer->makeCurrent();
       
   188         glEnable(target);
       
   189         glDisable(GL_BLEND);
       
   190         glDisable(GL_CULL_FACE);
       
   191     } else {
       
   192         m_QImagePixelBuffer->makeCurrent();
       
   193     }
       
   194 
       
   195     CVOpenGLTextureGetCleanTexCoords(texture, upperLeft, upperRight, lowerRight, lowerLeft);
       
   196     glBindTexture(target, CVOpenGLTextureGetName(texture));
       
   197     glBegin(GL_QUADS);
       
   198         glTexCoord2f(lowerLeft[0], lowerLeft[1]);
       
   199         glVertex2i(-1, 1);
       
   200         glTexCoord2f(lowerRight[0], lowerRight[1]);
       
   201         glVertex2i(1, 1);
       
   202         glTexCoord2f(upperRight[0], upperRight[1]);
       
   203         glVertex2i(1, -1);
       
   204         glTexCoord2f(upperLeft[0], upperLeft[1]);
       
   205         glVertex2i(-1, -1);
       
   206     glEnd();
       
   207 
       
   208     m_cachedQImage = m_QImagePixelBuffer->toImage();
       
   209     // Because of QuickTime, m_QImagePixelBuffer->doneCurrent() will fail.
       
   210     // So we store, and restore, the context our selves:
       
   211     prevContext->makeCurrent();
       
   212     return m_cachedQImage;
       
   213 #else
       
   214 	CIImage *img = (CIImage *)currentFrameAsCIImage();
       
   215 	if (!img)
       
   216 		return QImage();
       
   217 
       
   218 	NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
       
   219 	CGRect bounds = [img extent];
       
   220 	QImage qImg([bitmap bitmapData], bounds.size.width, bounds.size.height, QImage::Format_ARGB32);
       
   221 	m_cachedQImage = qImg.rgbSwapped();
       
   222 	[bitmap release];
       
   223 	[img release];
       
   224 	return m_cachedQImage;
       
   225 #endif
       
   226 }
       
   227 
       
   228 void QuickTimeVideoPlayer::setPrimaryRenderingCIImage(void *ciImage)
       
   229 {
       
   230 	[(CIImage *)m_primaryRenderingCIImage release];
       
   231 	m_primaryRenderingCIImage = ciImage;
       
   232 	[(CIImage *)m_primaryRenderingCIImage retain];
       
   233 }
       
   234 
       
   235 void QuickTimeVideoPlayer::setPrimaryRenderingTarget(NSObject *target)
       
   236 {
       
   237 	[(NSObject*)m_primaryRenderingTarget release];
       
   238 	m_primaryRenderingTarget = target;
       
   239 	[(NSObject*)m_primaryRenderingTarget retain];
       
   240 }
       
   241 
       
   242 void *QuickTimeVideoPlayer::primaryRenderingCIImage()
       
   243 {
       
   244 	return m_primaryRenderingCIImage;
       
   245 }
       
   246 
       
   247 void *QuickTimeVideoPlayer::currentFrameAsCIImage()
       
   248 {
       
   249     if (!m_QTMovie)
       
   250         return 0;
       
   251 
       
   252 #if defined(QT_MAC_USE_COCOA)
       
   253 	if (m_primaryRenderingCIImage){
       
   254 		CIImage *img = (CIImage *)m_primaryRenderingCIImage;
       
   255 		if (m_brightness || m_contrast || m_saturation){
       
   256 			CIFilter *colorFilter = [CIFilter filterWithName:@"CIColorControls"];
       
   257 			[colorFilter setValue:[NSNumber numberWithFloat:m_brightness] forKey:@"inputBrightness"];
       
   258 			[colorFilter setValue:[NSNumber numberWithFloat:(m_contrast < 1) ? m_contrast : 1 + ((m_contrast-1)*3)] forKey:@"inputContrast"];
       
   259 			[colorFilter setValue:[NSNumber numberWithFloat:m_saturation] forKey:@"inputSaturation"];
       
   260 			[colorFilter setValue:img forKey:@"inputImage"];
       
   261 			img = [colorFilter valueForKey:@"outputImage"];
       
   262 		}
       
   263 		if (m_hue){
       
   264 			CIFilter *colorFilter = [CIFilter filterWithName:@"CIHueAdjust"];
       
   265 			[colorFilter setValue:[NSNumber numberWithFloat:(m_hue * 3.14)] forKey:@"inputAngle"];
       
   266 			[colorFilter setValue:img forKey:@"inputImage"];
       
   267 			img = [colorFilter valueForKey:@"outputImage"];
       
   268 		}
       
   269 		return [img retain];
       
   270 	}
       
   271 #endif
       
   272 
       
   273 #ifdef QUICKTIME_C_API_AVAILABLE
       
   274 	CVOpenGLTextureRef cvImg = currentFrameAsCVTexture();
       
   275 	CIImage *img = [[CIImage alloc] initWithCVImageBuffer:cvImg];
       
   276 	return img;
       
   277 #else
       
   278 	return 0;
       
   279 #endif
       
   280 }
       
   281 
       
   282 GLuint QuickTimeVideoPlayer::currentFrameAsGLTexture()
       
   283 {
       
   284 	CIImage *img = (CIImage *)currentFrameAsCIImage();
       
   285 	if (!img)
       
   286 		return 0;
       
   287 
       
   288 	NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
       
   289     GLuint texName = 0;
       
   290     glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap pixelsWide]);
       
   291     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
       
   292     glGenTextures(1, &texName);
       
   293     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texName);
       
   294     glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER,  GL_LINEAR);
       
   295 
       
   296     int samplesPerPixel = [bitmap samplesPerPixel];
       
   297     if (![bitmap isPlanar] && (samplesPerPixel == 3 || samplesPerPixel == 4)){
       
   298         glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0,
       
   299             samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
       
   300             [bitmap pixelsWide], [bitmap pixelsHigh],
       
   301             0, samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
       
   302             GL_UNSIGNED_BYTE, [bitmap bitmapData]);
       
   303     } else {
       
   304         // Handle other bitmap formats.
       
   305     }
       
   306 
       
   307     [bitmap release];
       
   308 	[img release];
       
   309     return texName;
       
   310 }
       
   311 
       
   312 void QuickTimeVideoPlayer::setMasterVolume(float volume)
       
   313 {
       
   314     setVolume(volume, m_relativeVolume);
       
   315 }
       
   316 
       
   317 void QuickTimeVideoPlayer::setRelativeVolume(float volume)
       
   318 {
       
   319     setVolume(m_masterVolume, volume);
       
   320 }
       
   321 
       
   322 void QuickTimeVideoPlayer::setVolume(float masterVolume, float relativeVolume)
       
   323 {
       
   324     m_masterVolume = masterVolume;
       
   325     m_relativeVolume = relativeVolume;
       
   326     if (!m_QTMovie || !m_audioEnabled || m_mute)
       
   327         return;
       
   328     [m_QTMovie setVolume:(m_masterVolume * m_relativeVolume)];
       
   329 }
       
   330 
       
   331 void QuickTimeVideoPlayer::setMute(bool mute)
       
   332 {
       
   333     m_mute = mute;
       
   334     if (!m_QTMovie || m_state != Playing || !m_audioEnabled)
       
   335         return;
       
   336 
       
   337     // Work-around bug that happends if you set/unset mute
       
   338     // before movie is playing, and audio is not played
       
   339     // through graph. Then audio is delayed.
       
   340     [m_QTMovie setMuted:mute];
       
   341     [m_QTMovie setVolume:(mute ? 0 : m_masterVolume * m_relativeVolume)];
       
   342 }
       
   343 
       
   344 void QuickTimeVideoPlayer::enableAudio(bool enable)
       
   345 {
       
   346     m_audioEnabled = enable;
       
   347     if (!m_QTMovie || m_state != Playing)
       
   348         return;
       
   349 
       
   350     // Work-around bug that happends if you set/unset mute
       
   351     // before movie is playing, and audio is not played
       
   352     // through graph. Then audio is delayed.
       
   353     [m_QTMovie setMuted:(!enable || m_mute)];
       
   354     [m_QTMovie setVolume:((!enable || m_mute) ? 0 : m_masterVolume * m_relativeVolume)];
       
   355 }
       
   356 
       
   357 bool QuickTimeVideoPlayer::audioEnabled()
       
   358 {
       
   359     return m_audioEnabled;
       
   360 }
       
   361 
       
   362 bool QuickTimeVideoPlayer::setAudioDevice(int id)
       
   363 {
       
   364     if (!m_QTMovie)
       
   365         return false;
       
   366 
       
   367 #ifdef QUICKTIME_C_API_AVAILABLE
       
   368     // The following code will not work for some media codecs that
       
   369     // typically mingle audio/video frames (e.g mpeg).
       
   370     CFStringRef idString = PhononCFString::toCFStringRef(AudioDevice::deviceUID(id));
       
   371     QTAudioContextRef context;
       
   372     QTAudioContextCreateForAudioDevice(kCFAllocatorDefault, idString, 0, &context);
       
   373     OSStatus err = SetMovieAudioContext([m_QTMovie quickTimeMovie], context);
       
   374     CFRelease(context);
       
   375     if (err != noErr)
       
   376         return false;
       
   377     return true;
       
   378 #else
       
   379     Q_UNUSED(id);
       
   380     return false;
       
   381 #endif
       
   382 }
       
   383 
       
   384 void QuickTimeVideoPlayer::setColors(qreal brightness, qreal contrast, qreal hue, qreal saturation)
       
   385 {
       
   386     if (!m_QTMovie)
       
   387         return;
       
   388 
       
   389     // 0 is default value for the colors
       
   390     // in phonon, so adjust scale:
       
   391     contrast += 1;
       
   392     saturation += 1;
       
   393 
       
   394     if (m_brightness == brightness
       
   395         && m_contrast == contrast
       
   396         && m_hue == hue
       
   397         && m_saturation == saturation)
       
   398         return;
       
   399 
       
   400 	m_brightness = brightness;
       
   401 	m_contrast = contrast;
       
   402 	m_hue = hue;
       
   403 	m_saturation = saturation;
       
   404 #ifdef QUICKTIME_C_API_AVAILABLE
       
   405     Float32 value;
       
   406     value = brightness;
       
   407     SetMovieVisualBrightness([m_QTMovie quickTimeMovie], value, 0);
       
   408     value = contrast;
       
   409     SetMovieVisualContrast([m_QTMovie quickTimeMovie], value, 0);
       
   410     value = hue;
       
   411     SetMovieVisualHue([m_QTMovie quickTimeMovie], value, 0);
       
   412     value = saturation;
       
   413     SetMovieVisualSaturation([m_QTMovie quickTimeMovie], value, 0);
       
   414 #endif
       
   415     releaseImageCache();
       
   416 }
       
   417 
       
   418 QRect QuickTimeVideoPlayer::videoRect() const
       
   419 {
       
   420     if (!m_QTMovie)
       
   421         return QRect();
       
   422 
       
   423 	PhononAutoReleasePool pool;
       
   424     NSSize size = [[m_QTMovie attributeForKey:@"QTMovieCurrentSizeAttribute"] sizeValue];
       
   425     return QRect(0, 0, size.width, size.height);
       
   426 }
       
   427 
       
   428 void QuickTimeVideoPlayer::unsetCurrentMediaSource()
       
   429 {
       
   430     if (!m_QTMovie)
       
   431         return;
       
   432 
       
   433     [m_QTMovie release];
       
   434 	m_QTMovie = 0;
       
   435     delete m_streamReader;
       
   436     m_streamReader = 0;
       
   437     m_currentTime = 0;
       
   438     m_state = NoMedia;
       
   439     m_isDrmProtected = false;
       
   440     m_isDrmAuthorized = true;
       
   441     m_hasVideo = false;
       
   442     m_staticFps = 0;
       
   443     m_mediaSource = MediaSource();
       
   444     m_movieCompactDiscPath.clear();
       
   445 	[(CIImage *)m_primaryRenderingCIImage release];
       
   446 	m_primaryRenderingCIImage = 0;
       
   447     delete m_QImagePixelBuffer;
       
   448     m_QImagePixelBuffer = 0;
       
   449     releaseImageCache();
       
   450     [m_folderTracks release];
       
   451     m_folderTracks = 0;
       
   452 }
       
   453 
       
   454 QuickTimeVideoPlayer::State QuickTimeVideoPlayer::state() const
       
   455 {
       
   456     return m_state;
       
   457 }
       
   458 
       
   459 quint64 QuickTimeVideoPlayer::timeLoaded()
       
   460 {
       
   461     if (!m_QTMovie)
       
   462         return 0;
       
   463 #ifdef QUICKTIME_C_API_AVAILABLE
       
   464     TimeValue value;
       
   465     GetMaxLoadedTimeInMovie([m_QTMovie quickTimeMovie], &value);
       
   466     quint64 loaded = static_cast<quint64>(float(value) / float(GetMovieTimeScale([m_QTMovie quickTimeMovie])) * 1000.0f);
       
   467     return (loaded == INT_MAX) ? 0 : loaded;
       
   468 #else
       
   469     return 0;
       
   470 #endif
       
   471 }
       
   472 
       
   473 float QuickTimeVideoPlayer::percentageLoaded()
       
   474 {
       
   475     if (!m_QTMovie || !isSeekable())
       
   476         return 0;
       
   477 #ifdef QUICKTIME_C_API_AVAILABLE
       
   478     TimeValue loaded;
       
   479     GetMaxLoadedTimeInMovie([m_QTMovie quickTimeMovie], &loaded);
       
   480     float duration = GetMovieDuration([m_QTMovie quickTimeMovie]);
       
   481     return duration ? float(loaded) / duration : 0;
       
   482 #else
       
   483     return 0;
       
   484 #endif
       
   485 }
       
   486 
       
   487 void QuickTimeVideoPlayer::waitStatePlayable()
       
   488 {
       
   489 #if defined(QT_MAC_USE_COCOA)
       
   490     long state = [[m_QTMovie attributeForKey:@"QTMovieLoadStateAttribute"] longValue];
       
   491     while (state != QTMovieLoadStateError && state < QTMovieLoadStatePlayable)
       
   492         state = [[m_QTMovie attributeForKey:@"QTMovieLoadStateAttribute"] longValue];
       
   493 #elif defined(QUICKTIME_C_API_AVAILABLE)
       
   494     long state = GetMovieLoadState([m_QTMovie quickTimeMovie]);
       
   495     while (state != kMovieLoadStateError && state < kMovieLoadStatePlayable){
       
   496         MoviesTask(0, 0);
       
   497         state = GetMovieLoadState([m_QTMovie quickTimeMovie]);
       
   498     }
       
   499 #endif
       
   500 }
       
   501 
       
   502 bool QuickTimeVideoPlayer::movieNotLoaded()
       
   503 {
       
   504     if (!m_QTMovie)
       
   505         return true;
       
   506 
       
   507 #if defined(QT_MAC_USE_COCOA)
       
   508     long state = [[m_QTMovie attributeForKey:@"QTMovieLoadStateAttribute"] longValue];
       
   509     return state == QTMovieLoadStateError;
       
   510 #elif defined(QUICKTIME_C_API_AVAILABLE)
       
   511     long state = GetMovieLoadState([m_QTMovie quickTimeMovie]);
       
   512     return state == kMovieLoadStateError;
       
   513 #endif
       
   514 }
       
   515 
       
   516 void QuickTimeVideoPlayer::setError(NSError *error)
       
   517 {
       
   518     if (!error)
       
   519         return;
       
   520     QString desc = QString::fromUtf8([[error localizedDescription] UTF8String]);
       
   521     if (desc == "The file is not a movie file.")
       
   522         desc = QLatin1String("Could not decode media source.");
       
   523     else if (desc == "A necessary data reference could not be resolved."){
       
   524 		if (codecExistsAccordingToSuffix(mediaSourcePath()))
       
   525             desc = QLatin1String("Could not locate media source.");
       
   526 		else
       
   527             desc = QLatin1String("Could not decode media source.");
       
   528     } else if (desc == "You do not have sufficient permissions for this operation.")
       
   529         desc = QLatin1String("Could not open media source.");
       
   530     SET_ERROR(desc, FATAL_ERROR)
       
   531 }
       
   532 
       
   533 bool QuickTimeVideoPlayer::errorOccured()
       
   534 {
       
   535     if (gGetErrorType() != NO_ERROR){
       
   536         return true;
       
   537     } else if (movieNotLoaded()){
       
   538         SET_ERROR("Could not open media source.", FATAL_ERROR)
       
   539         return true;
       
   540     }
       
   541 	return false;
       
   542 }
       
   543 
       
   544 bool QuickTimeVideoPlayer::codecExistsAccordingToSuffix(const QString &fileName)
       
   545 {
       
   546 	PhononAutoReleasePool pool;
       
   547 	NSArray *fileTypes = [QTMovie movieFileTypes:QTIncludeAllTypes];
       
   548 	for (uint i=0; i<[fileTypes count]; ++i){
       
   549 		NSString *type = [fileTypes objectAtIndex:i];
       
   550 		QString formattedType = QString::fromUtf8([type UTF8String]);
       
   551 		formattedType.remove('\'').remove('.');
       
   552 		if (fileName.endsWith(QChar('.') + formattedType, Qt::CaseInsensitive))
       
   553 			return true;
       
   554 	}
       
   555 	return false;
       
   556 }
       
   557 
       
   558 void QuickTimeVideoPlayer::setMediaSource(const MediaSource &mediaSource)
       
   559 {
       
   560     PhononAutoReleasePool pool;
       
   561     unsetCurrentMediaSource();
       
   562 
       
   563     m_mediaSource = mediaSource;
       
   564     if (mediaSource.type() == MediaSource::Empty || mediaSource.type() == MediaSource::Invalid){
       
   565         m_state = NoMedia;
       
   566         return;
       
   567     }
       
   568 
       
   569     openMovieFromCurrentMediaSource();
       
   570     if (errorOccured()){
       
   571         unsetCurrentMediaSource();
       
   572         return;
       
   573     }
       
   574 
       
   575     prepareCurrentMovieForPlayback();
       
   576 }
       
   577 
       
   578 void QuickTimeVideoPlayer::prepareCurrentMovieForPlayback()
       
   579 {
       
   580 #ifdef QUICKTIME_C_API_AVAILABLE
       
   581     if (m_visualContext)
       
   582         SetMovieVisualContext([m_QTMovie quickTimeMovie], m_visualContext);
       
   583 #endif
       
   584 
       
   585     waitStatePlayable();
       
   586     if (errorOccured()){
       
   587         unsetCurrentMediaSource();
       
   588         return;
       
   589     }
       
   590 
       
   591     readProtection();
       
   592     preRollMovie();
       
   593     if (errorOccured()){
       
   594         unsetCurrentMediaSource();
       
   595         return;
       
   596     }
       
   597 
       
   598     if (!m_playbackRateSat)
       
   599         m_playbackRate = prefferedPlaybackRate();
       
   600     checkIfVideoAwailable();
       
   601     calculateStaticFps();
       
   602     enableAudio(m_audioEnabled);
       
   603     setMute(m_mute);
       
   604     setVolume(m_masterVolume, m_relativeVolume);
       
   605     m_metaData->update();
       
   606     pause();
       
   607 }
       
   608 
       
   609 void QuickTimeVideoPlayer::openMovieFromCurrentMediaSource()
       
   610 {
       
   611     switch (m_mediaSource.type()){
       
   612     case MediaSource::LocalFile:
       
   613         openMovieFromFile();
       
   614         break;
       
   615     case MediaSource::Url:
       
   616         openMovieFromUrl();
       
   617         break;
       
   618     case MediaSource::Disc:
       
   619         openMovieFromCompactDisc();
       
   620         break;
       
   621     case MediaSource::Stream:
       
   622         openMovieFromStream();
       
   623         break;
       
   624     case MediaSource::Empty:
       
   625     case MediaSource::Invalid:
       
   626         break;
       
   627     }
       
   628 }
       
   629 
       
   630 QString QuickTimeVideoPlayer::mediaSourcePath()
       
   631 {
       
   632     switch (m_mediaSource.type()){
       
   633     case MediaSource::LocalFile:{
       
   634         QFileInfo fileInfo(m_mediaSource.fileName());
       
   635         return fileInfo.isSymLink() ? fileInfo.symLinkTarget() : fileInfo.canonicalFilePath();
       
   636         break;}
       
   637     case MediaSource::Url:
       
   638 		return m_mediaSource.url().toEncoded();
       
   639         break;
       
   640     default:
       
   641         break;
       
   642     }
       
   643 	return QString();
       
   644 }
       
   645 
       
   646 void QuickTimeVideoPlayer::openMovieFromDataRef(QTDataReference *dataRef)
       
   647 {
       
   648     PhononAutoReleasePool pool;
       
   649     NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys:
       
   650                 dataRef, QTMovieDataReferenceAttribute,
       
   651                 [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute,
       
   652                 [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute,
       
   653                 [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute,
       
   654                 [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute,
       
   655                 nil];
       
   656 
       
   657     NSError *err = 0;
       
   658     m_QTMovie = [[QTMovie movieWithAttributes:attr error:&err] retain];
       
   659     if (err){
       
   660         [m_QTMovie release];
       
   661         m_QTMovie = 0;
       
   662         setError(err);
       
   663     }
       
   664 }
       
   665 
       
   666 void QuickTimeVideoPlayer::openMovieFromData(QByteArray *data, char *fileType)
       
   667 {
       
   668     PhononAutoReleasePool pool;
       
   669     NSString *type = [NSString stringWithUTF8String:fileType];
       
   670     NSData *nsData = [NSData dataWithBytesNoCopy:data->data() length:data->size() freeWhenDone:NO];
       
   671     QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToData:nsData name:type MIMEType:@""];
       
   672     openMovieFromDataRef(dataRef);
       
   673 }
       
   674 
       
   675 void QuickTimeVideoPlayer::openMovieFromDataGuessType(QByteArray *data)
       
   676 {
       
   677     // It turns out to be better to just try the standard file types rather
       
   678     // than using e.g [QTMovie movieFileTypes:QTIncludeCommonTypes]. Some
       
   679     // codecs *think* they can decode the stream, and crash...
       
   680 #define TryOpenMovieWithCodec(type) gClearError(); \
       
   681     openMovieFromData(data, (char *)"."type); \
       
   682     if (m_QTMovie) return;
       
   683 
       
   684     TryOpenMovieWithCodec("avi");
       
   685     TryOpenMovieWithCodec("mp4");
       
   686     TryOpenMovieWithCodec("m4p");
       
   687     TryOpenMovieWithCodec("m1s");
       
   688     TryOpenMovieWithCodec("mp3");
       
   689     TryOpenMovieWithCodec("mpeg");
       
   690     TryOpenMovieWithCodec("mov");
       
   691     TryOpenMovieWithCodec("ogg");
       
   692     TryOpenMovieWithCodec("wav");
       
   693     TryOpenMovieWithCodec("wmv");
       
   694 #undef TryOpenMovieWithCodec(type)
       
   695 }
       
   696 
       
   697 void QuickTimeVideoPlayer::openMovieFromFile()
       
   698 {
       
   699     NSString *nsFilename = (NSString *)PhononCFString::toCFStringRef(mediaSourcePath());
       
   700     QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToFile:nsFilename];
       
   701     openMovieFromDataRef(dataRef);
       
   702 }
       
   703 
       
   704 void QuickTimeVideoPlayer::openMovieFromUrl()
       
   705 {
       
   706     PhononAutoReleasePool pool;
       
   707     NSString *urlString = (NSString *)PhononCFString::toCFStringRef(mediaSourcePath());
       
   708     NSURL *url = [NSURL URLWithString: urlString];
       
   709     QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToURL:url];
       
   710     openMovieFromDataRef(dataRef);
       
   711 }
       
   712 
       
   713 void QuickTimeVideoPlayer::openMovieFromStream()
       
   714 {
       
   715     m_streamReader = new QuickTimeStreamReader(m_mediaSource);
       
   716     if (!m_streamReader->readAllData())
       
   717         return;
       
   718     openMovieFromDataGuessType(m_streamReader->pointerToData());
       
   719 }
       
   720 
       
   721 typedef void (*qt_sighandler_t)(int);
       
   722 static void sigtest(int) {
       
   723     qApp->exit(0);
       
   724 }
       
   725 
       
   726 void QuickTimeVideoPlayer::openMovieFromCompactDisc()
       
   727 {
       
   728     // Interrupting the application while the device is open
       
   729     // causes the application to hang. So we need to handle
       
   730     // this in a more graceful way:
       
   731     qt_sighandler_t hndl = signal(SIGINT, sigtest);
       
   732     if (hndl)
       
   733         signal(SIGINT, hndl);
       
   734 
       
   735     PhononAutoReleasePool pool;
       
   736     NSString *cd = 0;
       
   737     QString devName = m_mediaSource.deviceName();
       
   738     if (devName.isEmpty()) {
       
   739         cd = pathToCompactDisc();
       
   740         if (!cd) {
       
   741             SET_ERROR("Could not open media source.", NORMAL_ERROR)
       
   742             return;
       
   743         }
       
   744         m_movieCompactDiscPath = PhononCFString::toQString(reinterpret_cast<CFStringRef>(cd));
       
   745     } else {
       
   746        if (!QFileInfo(devName).isAbsolute())
       
   747            devName = QLatin1String("/Volumes/") + devName;
       
   748        cd = [reinterpret_cast<const NSString *>(PhononCFString::toCFStringRef(devName)) autorelease];
       
   749        if (!isCompactDisc(cd)) {
       
   750            SET_ERROR("Could not open media source.", NORMAL_ERROR)
       
   751            return;
       
   752        }
       
   753        m_movieCompactDiscPath = devName;
       
   754     }
       
   755 
       
   756     m_folderTracks = [scanFolder(cd) retain];
       
   757     setCurrentTrack(0);
       
   758 }
       
   759 
       
   760 QString QuickTimeVideoPlayer::movieCompactDiscPath() const
       
   761 {
       
   762     return m_movieCompactDiscPath;
       
   763 }
       
   764 
       
   765 MediaSource QuickTimeVideoPlayer::mediaSource() const
       
   766 {
       
   767     return m_mediaSource;
       
   768 }
       
   769 
       
   770 QTMovie *QuickTimeVideoPlayer::qtMovie() const
       
   771 {
       
   772     return m_QTMovie;
       
   773 }
       
   774 
       
   775 void QuickTimeVideoPlayer::setPlaybackRate(float rate)
       
   776 {
       
   777 	PhononAutoReleasePool pool;
       
   778     m_playbackRateSat = true;
       
   779     m_playbackRate = rate;
       
   780     if (m_QTMovie)
       
   781         [m_QTMovie setRate:m_playbackRate];
       
   782 }
       
   783 
       
   784 float QuickTimeVideoPlayer::playbackRate() const
       
   785 {
       
   786     return m_playbackRate;
       
   787 }
       
   788 
       
   789 quint64 QuickTimeVideoPlayer::currentTime() const
       
   790 {
       
   791     if (!m_QTMovie || m_state == Paused)
       
   792         return m_currentTime;
       
   793 
       
   794 	PhononAutoReleasePool pool;
       
   795     QTTime qtTime = [m_QTMovie currentTime];
       
   796     quint64 t = static_cast<quint64>(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f);
       
   797     const_cast<QuickTimeVideoPlayer *>(this)->m_currentTime = t;
       
   798     return m_currentTime;
       
   799 }
       
   800 
       
   801 long QuickTimeVideoPlayer::timeScale() const
       
   802 {
       
   803     if (!m_QTMovie)
       
   804         return 0;
       
   805 
       
   806 	PhononAutoReleasePool pool;
       
   807     return [[m_QTMovie attributeForKey:@"QTMovieTimeScaleAttribute"] longValue];
       
   808 }
       
   809 
       
   810 float QuickTimeVideoPlayer::staticFps()
       
   811 {
       
   812     return m_staticFps;
       
   813 }
       
   814 
       
   815 void QuickTimeVideoPlayer::calculateStaticFps()
       
   816 {
       
   817     if (!m_hasVideo){
       
   818         m_staticFps = 0;
       
   819         return;
       
   820     }
       
   821 
       
   822 #ifdef QT_ALLOW_QUICKTIME
       
   823     Boolean isMpeg = false;
       
   824     Track videoTrack = GetMovieIndTrackType([m_QTMovie quickTimeMovie], 1,
       
   825             FOUR_CHAR_CODE('vfrr'), // 'vfrr' means: has frame rate
       
   826             movieTrackCharacteristic | movieTrackEnabledOnly);
       
   827     Media media = GetTrackMedia(videoTrack);
       
   828     MediaHandler mediaH = GetMediaHandler(media);
       
   829     MediaHasCharacteristic(mediaH, FOUR_CHAR_CODE('mpeg'), &isMpeg);
       
   830 
       
   831     if (isMpeg){
       
   832         MHInfoEncodedFrameRateRecord frameRate;
       
   833         Size frameRateSize = sizeof(frameRate);
       
   834         MediaGetPublicInfo(mediaH, kMHInfoEncodedFrameRate, &frameRate, &frameRateSize);
       
   835         m_staticFps = float(Fix2X(frameRate.encodedFrameRate));
       
   836     } else {
       
   837         Media media = GetTrackMedia(videoTrack);
       
   838         long sampleCount = GetMediaSampleCount(media);
       
   839         TimeValue64 duration = GetMediaDisplayDuration(media);
       
   840         TimeValue64 timeScale = GetMediaTimeScale(media);
       
   841         m_staticFps = float((double)sampleCount * (double)timeScale / (double)duration);
       
   842     }
       
   843 #else
       
   844     m_staticFps = 30.0f;
       
   845 #endif
       
   846 }
       
   847 
       
   848 QString QuickTimeVideoPlayer::timeToString(quint64 ms)
       
   849 {
       
   850     int sec = ms/1000;
       
   851     int min = sec/60;
       
   852     int hour = min/60;
       
   853     return QString(QLatin1String("%1:%2:%3:%4")).arg(hour%60).arg(min%60).arg(sec%60).arg(ms%1000);
       
   854 }
       
   855 
       
   856 QString QuickTimeVideoPlayer::currentTimeString()
       
   857 {
       
   858     return timeToString(currentTime());
       
   859 }
       
   860 
       
   861 quint64 QuickTimeVideoPlayer::duration() const
       
   862 {
       
   863     if (!m_QTMovie)
       
   864         return 0;
       
   865 
       
   866 	PhononAutoReleasePool pool;
       
   867     QTTime qtTime = [m_QTMovie duration];
       
   868     return static_cast<quint64>(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f);
       
   869 }
       
   870 
       
   871 void QuickTimeVideoPlayer::play()
       
   872 {
       
   873     if (!canPlayMedia())
       
   874         return;
       
   875 
       
   876 	PhononAutoReleasePool pool;
       
   877     m_state = Playing;
       
   878     enableAudio(m_audioEnabled);
       
   879     setMute(m_mute);
       
   880     [m_QTMovie setRate:m_playbackRate];
       
   881 }
       
   882 
       
   883 void QuickTimeVideoPlayer::pause()
       
   884 {
       
   885     if (!canPlayMedia())
       
   886         return;
       
   887 
       
   888 	PhononAutoReleasePool pool;
       
   889     currentTime();
       
   890     m_state = Paused;
       
   891 
       
   892     if (isSeekable())
       
   893         [m_QTMovie setRate:0];
       
   894     else // pretend to be paused:
       
   895         [m_QTMovie setMuted:0];
       
   896 }
       
   897 
       
   898 void QuickTimeVideoPlayer::seek(quint64 milliseconds)
       
   899 {
       
   900     if (!canPlayMedia() || !isSeekable() || milliseconds == currentTime())
       
   901         return;
       
   902     if (milliseconds > duration())
       
   903         milliseconds = duration();
       
   904 
       
   905 	PhononAutoReleasePool pool;
       
   906     QTTime newQTTime = [m_QTMovie currentTime];
       
   907     newQTTime.timeValue = (milliseconds / 1000.0f) * newQTTime.timeScale;
       
   908     [m_QTMovie setCurrentTime:newQTTime];
       
   909 
       
   910     // The movie might not have been able to seek
       
   911     // to the exact point we told it to. So set
       
   912     // the current time according to what the movie says:
       
   913     newQTTime = [m_QTMovie currentTime];
       
   914     m_currentTime = static_cast<quint64>
       
   915         (float(newQTTime.timeValue) / float(newQTTime.timeScale) * 1000.0f);
       
   916 
       
   917     if (m_state == Paused){
       
   918         // We need (for reasons unknown) to task
       
   919         // the movie twize to make sure that
       
   920         // a subsequent call to frameAsCvTexture
       
   921         // returns the correct frame:
       
   922 #ifdef QUICKTIME_C_API_AVAILABLE
       
   923         MoviesTask(0, 0);
       
   924         MoviesTask(0, 0);
       
   925 #elif defined(QT_MAC_USE_COCOA)
       
   926         qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
       
   927 #endif
       
   928     }
       
   929 }
       
   930 
       
   931 bool QuickTimeVideoPlayer::canPlayMedia() const
       
   932 {
       
   933     if (!m_QTMovie)
       
   934         return false;
       
   935     return m_isDrmAuthorized;
       
   936 }
       
   937 
       
   938 bool QuickTimeVideoPlayer::isPlaying() const
       
   939 {
       
   940     return m_state == Playing;
       
   941 }
       
   942 
       
   943 bool QuickTimeVideoPlayer::isSeekable() const
       
   944 {
       
   945     return canPlayMedia() && (duration()-1) != INT_MAX;
       
   946 }
       
   947 
       
   948 float QuickTimeVideoPlayer::prefferedPlaybackRate() const
       
   949 {
       
   950     if (!m_QTMovie)
       
   951         return 0;
       
   952 
       
   953 	PhononAutoReleasePool pool;
       
   954     return [[m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue];
       
   955 }
       
   956 
       
   957 #ifdef QUICKTIME_C_API_AVAILABLE
       
   958 void MoviePrePrerollCompleteCallBack(Movie /*theMovie*/, OSErr /*thePrerollErr*/, void * /*userData*/)
       
   959 {
       
   960     // QuickTimeVideoPlayer *player = static_cast<QuickTimeVideoPlayer *>(userData);
       
   961 }
       
   962 #endif
       
   963 
       
   964 bool QuickTimeVideoPlayer::preRollMovie(qint64 startTime)
       
   965 {
       
   966     if (!canPlayMedia())
       
   967         return false;
       
   968 
       
   969 #ifdef QUICKTIME_C_API_AVAILABLE
       
   970     if (PrePrerollMovie([m_QTMovie quickTimeMovie], startTime, FloatToFixed(m_playbackRate),
       
   971         0 /*MoviePrePrerollCompleteCallBack*/, this) != noErr) // No callback means wait (synch)
       
   972         return false;
       
   973 
       
   974     if (PrerollMovie([m_QTMovie quickTimeMovie], startTime, FloatToFixed(m_playbackRate)) != noErr)
       
   975         return false;
       
   976 
       
   977     return true;
       
   978 #else
       
   979     Q_UNUSED(startTime);
       
   980     return false;
       
   981 #endif
       
   982 }
       
   983 
       
   984 bool QuickTimeVideoPlayer::hasAudio() const
       
   985 {
       
   986     if (!m_QTMovie)
       
   987         return false;
       
   988 
       
   989 	PhononAutoReleasePool pool;
       
   990     return [[m_QTMovie attributeForKey:@"QTMovieHasAudioAttribute"] boolValue] == YES;
       
   991 }
       
   992 
       
   993 bool QuickTimeVideoPlayer::hasVideo() const
       
   994 {
       
   995     return m_hasVideo;
       
   996 }
       
   997 
       
   998 bool QuickTimeVideoPlayer::hasMovie() const
       
   999 {
       
  1000     return m_QTMovie != 0;
       
  1001 }
       
  1002 
       
  1003 void QuickTimeVideoPlayer::checkIfVideoAwailable()
       
  1004 {
       
  1005 	PhononAutoReleasePool pool;
       
  1006     m_hasVideo = [[m_QTMovie attributeForKey:@"QTMovieHasVideoAttribute"] boolValue] == YES;
       
  1007 }
       
  1008 
       
  1009 bool QuickTimeVideoPlayer::isDrmProtected() const
       
  1010 {
       
  1011     return m_isDrmProtected;
       
  1012 }
       
  1013 
       
  1014 bool QuickTimeVideoPlayer::isDrmAuthorized() const
       
  1015 {
       
  1016     return m_isDrmAuthorized;
       
  1017 }
       
  1018 /*
       
  1019 void QuickTimeVideoPlayer::movieCodecIsMPEG()
       
  1020 {
       
  1021     NSArray *tracks = [m_QTMovie tracks];
       
  1022     for (QTTrack *track in tracks)
       
  1023         if ([[track media] hasCharacteristic:QTMediaTypeMPEG])
       
  1024             return true;
       
  1025     return false;
       
  1026 }
       
  1027 */
       
  1028 
       
  1029 static void QtGetTrackProtection(QTTrack *track, bool &isDrmProtected, bool &isDrmAuthorized)
       
  1030 {
       
  1031     isDrmProtected = false;
       
  1032     isDrmAuthorized = true;
       
  1033 
       
  1034 #ifdef QUICKTIME_C_API_AVAILABLE
       
  1035     QTMedia *media = [track media];
       
  1036     MediaHandler mediaHandler = GetMediaHandler([media quickTimeMedia]);
       
  1037     if (mediaHandler){
       
  1038         // Regardless, skip message boxes pointing to iTunes regarding DRM:
       
  1039         Boolean boolFalse = false;
       
  1040         QTSetComponentProperty(mediaHandler,
       
  1041             kQTPropertyClass_DRM, kQTDRMPropertyID_InteractWithUser,
       
  1042             sizeof(boolFalse), &boolFalse);
       
  1043 
       
  1044         // Check track:
       
  1045         Boolean value;
       
  1046         OSStatus err = QTGetComponentProperty(mediaHandler,
       
  1047             kQTPropertyClass_DRM, kQTDRMPropertyID_IsProtected,
       
  1048             sizeof(value), &value, 0);
       
  1049         isDrmProtected = (err == noErr) ? bool(value) : false;
       
  1050         err = QTGetComponentProperty(mediaHandler,
       
  1051             kQTPropertyClass_DRM, kQTDRMPropertyID_IsAuthorized,
       
  1052             sizeof(value), &value, 0);
       
  1053         isDrmAuthorized = (err == noErr) ? bool(value) : true;
       
  1054     }
       
  1055 #else
       
  1056     Q_UNUSED(track);
       
  1057 #endif // QUICKTIME_C_API_AVAILABLE
       
  1058 }
       
  1059 
       
  1060 void QuickTimeVideoPlayer::readProtection()
       
  1061 {
       
  1062     m_isDrmProtected = false;
       
  1063     m_isDrmAuthorized = true;
       
  1064 
       
  1065     NSArray *tracks = [m_QTMovie tracks];
       
  1066 	for (uint i=0; i<[tracks count]; ++i){
       
  1067 		QTTrack *track = [tracks objectAtIndex:i];
       
  1068         bool isDrmProtected = false;
       
  1069         bool isDrmAuthorized = true;
       
  1070         QtGetTrackProtection(track, isDrmProtected, isDrmAuthorized);
       
  1071         if (isDrmProtected)
       
  1072             m_isDrmProtected = true;
       
  1073         if (!isDrmAuthorized)
       
  1074             m_isDrmAuthorized = false;
       
  1075     }
       
  1076 }
       
  1077 
       
  1078 QMultiMap<QString, QString> QuickTimeVideoPlayer::metaData()
       
  1079 {
       
  1080     return m_metaData->metaData();
       
  1081 }
       
  1082 
       
  1083 int QuickTimeVideoPlayer::trackCount() const
       
  1084 {
       
  1085     if (!m_folderTracks)
       
  1086         return 0;
       
  1087     return [m_folderTracks count];
       
  1088 }
       
  1089 
       
  1090 int QuickTimeVideoPlayer::currentTrack() const
       
  1091 {
       
  1092     return m_currentTrack;
       
  1093 }
       
  1094 
       
  1095 QString QuickTimeVideoPlayer::currentTrackPath() const
       
  1096 {
       
  1097     if (!m_folderTracks)
       
  1098         return QString();
       
  1099 
       
  1100     PhononAutoReleasePool pool;
       
  1101     NSString *trackPath = [m_folderTracks objectAtIndex:m_currentTrack];
       
  1102     return PhononCFString::toQString(reinterpret_cast<CFStringRef>(trackPath));
       
  1103 }
       
  1104 
       
  1105 NSString* QuickTimeVideoPlayer::pathToCompactDisc()
       
  1106 {
       
  1107     PhononAutoReleasePool pool;
       
  1108     NSArray *devices = [[NSWorkspace sharedWorkspace] mountedRemovableMedia];
       
  1109     for (unsigned int i=0; i<[devices count]; ++i) {
       
  1110         NSString *dev = [devices objectAtIndex:i];
       
  1111         if (isCompactDisc(dev))
       
  1112             return [dev retain];
       
  1113     }
       
  1114     return 0;
       
  1115 }
       
  1116 
       
  1117 bool QuickTimeVideoPlayer::isCompactDisc(NSString *path)
       
  1118 {
       
  1119     PhononAutoReleasePool pool;
       
  1120     NSString *type = [NSString string];
       
  1121     [[NSWorkspace sharedWorkspace] getFileSystemInfoForPath:path
       
  1122         isRemovable:0
       
  1123         isWritable:0
       
  1124         isUnmountable:0
       
  1125         description:0
       
  1126         type:&type];
       
  1127     return [type hasPrefix:@"cdd"];
       
  1128 }
       
  1129 
       
  1130 NSArray* QuickTimeVideoPlayer::scanFolder(NSString *path)
       
  1131 {
       
  1132     NSMutableArray *tracks = [NSMutableArray arrayWithCapacity:20];
       
  1133     if (!path)
       
  1134         return tracks;
       
  1135 
       
  1136     NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path];
       
  1137     while (NSString *track = [enumerator nextObject]) {
       
  1138         if (![track hasPrefix:@"."])
       
  1139             [tracks addObject:[path stringByAppendingPathComponent:track]];
       
  1140     }
       
  1141     return tracks;
       
  1142 }
       
  1143 
       
  1144 void QuickTimeVideoPlayer::setCurrentTrack(int track)
       
  1145 {
       
  1146     PhononAutoReleasePool pool;
       
  1147     [m_QTMovie release];
       
  1148 	m_QTMovie = 0;
       
  1149     m_currentTime = 0;
       
  1150     m_currentTrack = track;
       
  1151 
       
  1152     if (!m_folderTracks)
       
  1153         return;
       
  1154     if (track < 0 || track >= (int)[m_folderTracks count])
       
  1155         return;
       
  1156 
       
  1157     NSString *trackPath = [m_folderTracks objectAtIndex:track];
       
  1158     QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToFile:trackPath];
       
  1159     State currentState = m_state;
       
  1160     openMovieFromDataRef(dataRef);
       
  1161     prepareCurrentMovieForPlayback();
       
  1162     if (currentState == Playing)
       
  1163         play();
       
  1164 }
       
  1165 
       
  1166 }}
       
  1167 
       
  1168 QT_END_NAMESPACE