diff options
author | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2009-06-08 12:12:17 (GMT) |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2009-06-08 12:12:17 (GMT) |
commit | 21fef75cd50b00609a803f123cc27ad0ee9ba509 (patch) | |
tree | ca96462e89b9c4828c7792e62def95e77d69d277 /src/3rdparty/phonon/qt7 | |
parent | 11303c676166cda3aae33e7e97939e9d2942271f (diff) | |
parent | 61d1dcea0efa6b0809639b781bb49baf252b3aad (diff) | |
download | Qt-21fef75cd50b00609a803f123cc27ad0ee9ba509.zip Qt-21fef75cd50b00609a803f123cc27ad0ee9ba509.tar.gz Qt-21fef75cd50b00609a803f123cc27ad0ee9ba509.tar.bz2 |
Merge commit 'origin/4.5'
Conflicts:
src/3rdparty/phonon/qt7/mediaobject.mm
src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
src/gui/text/qfontengine_win.cpp
tools/linguist/shared/cpp.cpp
Diffstat (limited to 'src/3rdparty/phonon/qt7')
-rw-r--r-- | src/3rdparty/phonon/qt7/mediaobject.h | 18 | ||||
-rw-r--r-- | src/3rdparty/phonon/qt7/mediaobject.mm | 109 | ||||
-rw-r--r-- | src/3rdparty/phonon/qt7/quicktimemetadata.h | 8 | ||||
-rw-r--r-- | src/3rdparty/phonon/qt7/quicktimemetadata.mm | 41 | ||||
-rw-r--r-- | src/3rdparty/phonon/qt7/quicktimevideoplayer.h | 19 | ||||
-rw-r--r-- | src/3rdparty/phonon/qt7/quicktimevideoplayer.mm | 163 |
6 files changed, 294 insertions, 64 deletions
diff --git a/src/3rdparty/phonon/qt7/mediaobject.h b/src/3rdparty/phonon/qt7/mediaobject.h index ae623a9..c93eddc 100644 --- a/src/3rdparty/phonon/qt7/mediaobject.h +++ b/src/3rdparty/phonon/qt7/mediaobject.h @@ -42,7 +42,10 @@ namespace QT7 class MediaObjectAudioNode; class MediaObject : public MediaNode, - public Phonon::MediaObjectInterface, public Phonon::AddonInterface + public Phonon::MediaObjectInterface +#ifndef QT_NO_PHONON_MEDIACONTROLLER + , public Phonon::AddonInterface +#endif { Q_OBJECT Q_INTERFACES(Phonon::MediaObjectInterface Phonon::AddonInterface) @@ -113,6 +116,16 @@ namespace QT7 void metaDataChanged(QMultiMap<QString,QString>); void currentSourceChanged(const MediaSource &newSource); + // Add-on interface: + void availableSubtitlesChanged(); + void availableAudioChannelsChanged(); + void titleChanged(int); + void availableTitlesChanged(int); + void chapterChanged(int); + void availableChaptersChanged(int); + void angleChanged(int); + void availableAnglesChanged(int); + protected: void mediaNodeEvent(const MediaNodeEvent *event); bool event(QEvent *event); @@ -126,7 +139,6 @@ namespace QT7 QuickTimeVideoPlayer *m_nextVideoPlayer; QuickTimeAudioPlayer *m_nextAudioPlayer; MediaObjectAudioNode *m_mediaObjectAudioNode; - QuickTimeMetaData *m_metaData; #if QT_ALLOW_QUICKTIME CVDisplayLinkRef m_displayLink; @@ -150,6 +162,7 @@ namespace QT7 bool m_waitNextSwap; int m_swapTimeLeft; QTime m_swapTime; + bool m_autoplayTitles; void synchAudioVideo(); void updateCurrentTime(); @@ -170,6 +183,7 @@ namespace QT7 void inspectVideoGraphRecursive(MediaNode *node, int &effectCount, int &outputCount); void inspectGraph(); bool isCrossFading(); + void setCurrentTrack(int track); QString m_errorString; Phonon::ErrorType m_errorType; diff --git a/src/3rdparty/phonon/qt7/mediaobject.mm b/src/3rdparty/phonon/qt7/mediaobject.mm index 6886a3c..677640c 100644 --- a/src/3rdparty/phonon/qt7/mediaobject.mm +++ b/src/3rdparty/phonon/qt7/mediaobject.mm @@ -46,7 +46,6 @@ MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource, m_mediaObjectAudioNode = new MediaObjectAudioNode(m_audioPlayer, m_nextAudioPlayer); setAudioNode(m_mediaObjectAudioNode); - m_metaData = new QuickTimeMetaData(); m_audioGraph = new AudioGraph(this); m_tickInterval = 0; @@ -55,6 +54,7 @@ MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource, m_transitionTime = 0; m_percentageLoaded = 0; m_waitNextSwap = false; + m_autoplayTitles = true; m_audioEffectCount = 0; m_audioOutputCount = 0; m_videoEffectCount = 0; @@ -85,7 +85,6 @@ MediaObject::~MediaObject() m_nextAudioPlayer->unsetVideoPlayer(); delete m_videoPlayer; delete m_nextVideoPlayer; - delete m_metaData; checkForError(); } @@ -131,7 +130,7 @@ void MediaObject::inspectGraph() // Inspect the graph to check wether there are any // effects or outputs connected. This will have // influence on the audio system and video system that ends up beeing used: - int prevVideoOutputCount = m_videoOutputCount; + int prevVideoOutputCount = m_videoOutputCount; m_audioEffectCount = 0; m_audioOutputCount = 0; m_videoEffectCount = 0; @@ -143,7 +142,7 @@ void MediaObject::inspectGraph() if (m_videoOutputCount != prevVideoOutputCount){ MediaNodeEvent e1(MediaNodeEvent::VideoOutputCountChanged, &m_videoOutputCount); notify(&e1); - } + } } void MediaObject::setupAudioSystem() @@ -176,14 +175,14 @@ void MediaObject::setupAudioSystem() if (newAudioSystem == m_audioSystem) return; - + // Enable selected audio system: - m_audioSystem = newAudioSystem; + m_audioSystem = newAudioSystem; switch (newAudioSystem){ case AS_Silent: m_audioGraph->stop(); m_videoPlayer->enableAudio(false); - m_nextVideoPlayer->enableAudio(false); + m_nextVideoPlayer->enableAudio(false); m_audioPlayer->enableAudio(false); m_nextAudioPlayer->enableAudio(false); break; @@ -227,6 +226,7 @@ void MediaObject::setSource(const MediaSource &source) // Save current state for event/signal handling below: bool prevHasVideo = m_videoPlayer->hasVideo(); qint64 prevTotalTime = totalTime(); + int prevTrackCount = m_videoPlayer->trackCount(); m_waitNextSwap = false; // Cancel cross-fade if any: @@ -238,11 +238,10 @@ void MediaObject::setSource(const MediaSource &source) m_audioPlayer->unsetVideoPlayer(); m_videoPlayer->setMediaSource(source); m_audioPlayer->setVideoPlayer(m_videoPlayer); - m_metaData->setVideo(m_videoPlayer); m_audioGraph->updateStreamSpecifications(); m_nextAudioPlayer->unsetVideoPlayer(); - m_nextVideoPlayer->unsetVideo(); + m_nextVideoPlayer->unsetCurrentMediaSource(); m_currentTime = 0; // Emit/notify information about the new source: @@ -255,12 +254,14 @@ void MediaObject::setSource(const MediaSource &source) updateVideo(emptyFrame); emit currentSourceChanged(source); - emit metaDataChanged(m_metaData->metaData()); + emit metaDataChanged(m_videoPlayer->metaData()); if (prevHasVideo != m_videoPlayer->hasVideo()) - emit hasVideoChanged(m_videoPlayer->hasVideo()); + emit hasVideoChanged(m_videoPlayer->hasVideo()); if (prevTotalTime != totalTime()) - emit totalTimeChanged(totalTime()); + emit totalTimeChanged(totalTime()); + if (prevTrackCount != m_videoPlayer->trackCount()) + emit availableTitlesChanged(m_videoPlayer->trackCount()); if (checkForError()) return; if (!m_videoPlayer->isDrmAuthorized()) @@ -269,7 +270,7 @@ void MediaObject::setSource(const MediaSource &source) return; if (!m_videoPlayer->canPlayMedia()) SET_ERROR("Cannot play media.", FATAL_ERROR) - + // The state might have changed from LoadingState // as a response to an error state change. So we // need to check it before stopping: @@ -296,12 +297,12 @@ void MediaObject::swapCurrentWithNext(qint32 transitionTime) // Save current state for event/signal handling below: bool prevHasVideo = m_videoPlayer->hasVideo(); qint64 prevTotalTime = totalTime(); + int prevTrackCount = m_videoPlayer->trackCount(); qSwap(m_audioPlayer, m_nextAudioPlayer); qSwap(m_videoPlayer, m_nextVideoPlayer); m_mediaObjectAudioNode->startCrossFade(transitionTime); m_audioGraph->updateStreamSpecifications(); - m_metaData->setVideo(m_videoPlayer); m_waitNextSwap = false; m_currentTime = 0; @@ -312,12 +313,14 @@ void MediaObject::swapCurrentWithNext(qint32 transitionTime) notify(&e1); emit currentSourceChanged(m_videoPlayer->mediaSource()); - emit metaDataChanged(m_metaData->metaData()); + emit metaDataChanged(m_videoPlayer->metaData()); if (prevHasVideo != m_videoPlayer->hasVideo()) emit hasVideoChanged(m_videoPlayer->hasVideo()); if (prevTotalTime != totalTime()) emit totalTimeChanged(totalTime()); + if (prevTrackCount != m_videoPlayer->trackCount()) + emit availableTitlesChanged(m_videoPlayer->trackCount()); if (checkForError()) return; if (!m_videoPlayer->isDrmAuthorized()) @@ -517,7 +520,7 @@ void MediaObject::stop() if (!setState(Phonon::StoppedState)) return; m_waitNextSwap = false; - m_nextVideoPlayer->unsetVideo(); + m_nextVideoPlayer->unsetCurrentMediaSource(); m_nextAudioPlayer->unsetVideoPlayer(); pause_internal(); seek(0); @@ -531,7 +534,7 @@ void MediaObject::seek(qint64 milliseconds) return; // Stop cross-fade if any: - m_nextVideoPlayer->unsetVideo(); + m_nextVideoPlayer->unsetCurrentMediaSource(); m_nextAudioPlayer->unsetVideoPlayer(); m_mediaObjectAudioNode->cancelCrossFade(); @@ -651,7 +654,7 @@ bool MediaObject::isSeekable() const qint64 MediaObject::currentTime() const { IMPLEMENTED_SILENT; - const_cast<MediaObject *>(this)->updateCurrentTime(); + const_cast<MediaObject *>(this)->updateCurrentTime(); return m_currentTime; } @@ -661,19 +664,24 @@ void MediaObject::updateCurrentTime() m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime(); quint64 total = m_videoPlayer->duration(); - // Check if it's time to emit aboutToFinish: - quint32 mark = qMax(quint64(0), qMin(total, total + m_transitionTime - 2000)); - if (lastUpdateTime < mark && mark <= m_currentTime) - emit aboutToFinish(); - - // Check if it's time to emit prefinishMarkReached: - mark = qMax(quint64(0), total - m_prefinishMark); - if (lastUpdateTime < mark && mark <= m_currentTime) - emit prefinishMarkReached(total - m_currentTime); + if (m_videoPlayer->currentTrack() < m_videoPlayer->trackCount() - 1){ + // There are still more tracks to play after the current track. + if (m_autoplayTitles) { + if (lastUpdateTime < m_currentTime && m_currentTime == total) + setCurrentTrack(m_videoPlayer->currentTrack() + 1); + } + } else if (m_nextVideoPlayer->state() == QuickTimeVideoPlayer::NoMedia){ + // There is no more sources or tracks to play after the current source. + // Check if it's time to emit aboutToFinish: + quint32 mark = qMax(quint64(0), qMin(total, total + m_transitionTime - 2000)); + if (lastUpdateTime < mark && mark <= m_currentTime) + emit aboutToFinish(); + + // Check if it's time to emit prefinishMarkReached: + mark = qMax(quint64(0), total - m_prefinishMark); + if (lastUpdateTime < mark && mark <= m_currentTime) + emit prefinishMarkReached(total - m_currentTime); - if (m_nextVideoPlayer->state() == QuickTimeVideoPlayer::NoMedia){ - // There is no next source in que. - // Check if it's time to emit finished: if (lastUpdateTime < m_currentTime && m_currentTime == total){ emit finished(); m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime(); @@ -683,7 +691,7 @@ void MediaObject::updateCurrentTime() } else { // We have a next source. // Check if it's time to swap to next source: - mark = qMax(quint64(0), total + m_transitionTime); + quint32 mark = qMax(quint64(0), total + m_transitionTime); if (m_waitNextSwap && m_state == Phonon::PlayingState && m_transitionTime < m_swapTime.msecsTo(QTime::currentTime())){ swapCurrentWithNext(0); @@ -786,11 +794,11 @@ bool MediaObject::setAudioDeviceOnMovie(int id) void MediaObject::updateCrossFade() { - m_mediaObjectAudioNode->updateCrossFade(m_currentTime); + m_mediaObjectAudioNode->updateCrossFade(m_currentTime); // Clean-up previous movie if done fading: if (m_mediaObjectAudioNode->m_fadeDuration == 0){ if (m_nextVideoPlayer->isPlaying() || m_nextAudioPlayer->isPlaying()){ - m_nextVideoPlayer->unsetVideo(); + m_nextVideoPlayer->unsetCurrentMediaSource(); m_nextAudioPlayer->unsetVideoPlayer(); } } @@ -927,13 +935,42 @@ bool MediaObject::event(QEvent *event) return QObject::event(event); } -bool MediaObject::hasInterface(Interface /*interface*/) const +void MediaObject::setCurrentTrack(int track) { - return false; + if (track == m_videoPlayer->currentTrack() || track < 0 || track >= m_videoPlayer->trackCount()) + return; + + m_videoPlayer->setCurrentTrack(track); + emit titleChanged(track); + emit metaDataChanged(m_videoPlayer->metaData()); +} + +bool MediaObject::hasInterface(Interface iface) const +{ + return iface == AddonInterface::TitleInterface; } -QVariant MediaObject::interfaceCall(Interface /*interface*/, int /*command*/, const QList<QVariant> &/*arguments*/) +QVariant MediaObject::interfaceCall(Interface iface, int command, const QList<QVariant> ¶ms) { + switch (iface) { + case TitleInterface: + switch (command) { + case availableTitles: + return m_videoPlayer->trackCount(); + case title: + return m_videoPlayer->currentTrack(); + case setTitle: + setCurrentTrack(params.first().toInt()); + break; + case autoplayTitles: + return m_autoplayTitles; + case setAutoplayTitles: + m_autoplayTitles = params.first().toBool(); + break; + } + default: + break; + } return QVariant(); } diff --git a/src/3rdparty/phonon/qt7/quicktimemetadata.h b/src/3rdparty/phonon/qt7/quicktimemetadata.h index d524183..c589535 100644 --- a/src/3rdparty/phonon/qt7/quicktimemetadata.h +++ b/src/3rdparty/phonon/qt7/quicktimemetadata.h @@ -38,10 +38,8 @@ namespace QT7 class QuickTimeMetaData { public: - QuickTimeMetaData(); - virtual ~QuickTimeMetaData(); - - void setVideo(QuickTimeVideoPlayer *videoPlayer); + QuickTimeMetaData(QuickTimeVideoPlayer *videoPlayer); + void update(); QMultiMap<QString, QString> metaData(); private: @@ -49,6 +47,8 @@ namespace QT7 bool m_movieChanged; QuickTimeVideoPlayer *m_videoPlayer; void readMetaData(); + void guessMetaDataForCD(); + void readMetaDataFromMovie(); #ifdef QUICKTIME_C_API_AVAILABLE QString stripCopyRightSymbol(const QString &key); diff --git a/src/3rdparty/phonon/qt7/quicktimemetadata.mm b/src/3rdparty/phonon/qt7/quicktimemetadata.mm index 851e707..2dcc152 100644 --- a/src/3rdparty/phonon/qt7/quicktimemetadata.mm +++ b/src/3rdparty/phonon/qt7/quicktimemetadata.mm @@ -15,6 +15,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. */ +#include <QtCore/QFileInfo> #include "quicktimemetadata.h" #include "quicktimevideoplayer.h" @@ -25,19 +26,14 @@ namespace Phonon namespace QT7 { -QuickTimeMetaData::QuickTimeMetaData() +QuickTimeMetaData::QuickTimeMetaData(QuickTimeVideoPlayer *videoPlayer) { - m_videoPlayer = 0; + m_videoPlayer = videoPlayer; m_movieChanged = false; } -QuickTimeMetaData::~QuickTimeMetaData() +void QuickTimeMetaData::update() { -} - -void QuickTimeMetaData::setVideo(QuickTimeVideoPlayer *videoPlayer) -{ - m_videoPlayer = videoPlayer; m_movieChanged = true; m_metaData.clear(); } @@ -145,14 +141,22 @@ void QuickTimeMetaData::readFormattedData(QTMetaDataRef metaDataRef, OSType form #endif // QUICKTIME_C_API_AVAILABLE -void QuickTimeMetaData::readMetaData() +void QuickTimeMetaData::guessMetaDataForCD() +{ + QString album = QFileInfo(m_videoPlayer->movieCompactDiscPath()).fileName(); + QString title = QFileInfo(m_videoPlayer->currentTrackPath()).fileName(); + title = title.left(title.lastIndexOf('.')); + m_metaData.insert(QLatin1String("ALBUM"), album); + m_metaData.insert(QLatin1String("TITLE"), title); + m_metaData.insert(QLatin1String("TRACKNUMBER"), QString::number(m_videoPlayer->currentTrack())); +} + +void QuickTimeMetaData::readMetaDataFromMovie() { - if (!m_videoPlayer) - return; QMultiMap<QString, QString> metaMap; - + #ifdef QUICKTIME_C_API_AVAILABLE - QTMetaDataRef metaDataRef; + QTMetaDataRef metaDataRef; OSStatus err = QTCopyMovieMetaData([m_videoPlayer->qtMovie() quickTimeMovie], &metaDataRef); BACKEND_ASSERT2(err == noErr, "Could not read QuickTime meta data", NORMAL_ERROR) @@ -173,6 +177,17 @@ void QuickTimeMetaData::readMetaData() m_metaData.insert(QLatin1String("DESCRIPTION"), metaMap.value(QLatin1String("des"))); } +void QuickTimeMetaData::readMetaData() +{ + if (!m_videoPlayer) + return; + + if (m_videoPlayer->mediaSource().type() == Phonon::MediaSource::Disc) + guessMetaDataForCD(); + else + readMetaDataFromMovie(); +} + QMultiMap<QString, QString> QuickTimeMetaData::metaData() { if (m_videoPlayer && m_videoPlayer->hasMovie() && m_movieChanged) diff --git a/src/3rdparty/phonon/qt7/quicktimevideoplayer.h b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h index bf4f216..98eacb5 100644 --- a/src/3rdparty/phonon/qt7/quicktimevideoplayer.h +++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h @@ -39,6 +39,7 @@ namespace Phonon namespace QT7 { class QuickTimeStreamReader; + class QuickTimeMetaData; class VideoRenderWidgetQTMovieView; class QuickTimeVideoPlayer : QObject @@ -56,7 +57,7 @@ namespace QT7 void setMediaSource(const MediaSource &source); MediaSource mediaSource() const; - void unsetVideo(); + void unsetCurrentMediaSource(); void play(); void pause(); @@ -86,6 +87,7 @@ namespace QT7 bool setAudioDevice(int id); void setPlaybackRate(float rate); QTMovie *qtMovie() const; + QMultiMap<QString, QString> metaData(); float playbackRate() const; float prefferedPlaybackRate() const; @@ -105,6 +107,12 @@ namespace QT7 float percentageLoaded(); quint64 timeLoaded(); + int trackCount() const; + int currentTrack() const; + void setCurrentTrack(int track); + QString movieCompactDiscPath() const; + QString currentTrackPath() const; + static QString timeToString(quint64 ms); // Help functions when drawing to more that one widget in cocoa 64: @@ -118,6 +126,7 @@ namespace QT7 QTMovie *m_QTMovie; State m_state; QGLPixelBuffer *m_QImagePixelBuffer; + QuickTimeMetaData *m_metaData; CVOpenGLTextureRef m_cachedCVTextureRef; QImage m_cachedQImage; @@ -140,6 +149,9 @@ namespace QT7 qreal m_contrast; qreal m_hue; qreal m_saturation; + NSArray *m_folderTracks; + int m_currentTrack; + QString m_movieCompactDiscPath; #ifdef QUICKTIME_C_API_AVAILABLE QTVisualContextRef m_visualContext; @@ -147,16 +159,21 @@ namespace QT7 VideoFrame m_currentFrame; QuickTimeStreamReader *m_streamReader; + void prepareCurrentMovieForPlayback(); void createVisualContext(); void openMovieFromCurrentMediaSource(); void openMovieFromDataRef(QTDataReference *dataRef); void openMovieFromFile(); void openMovieFromUrl(); void openMovieFromStream(); + void openMovieFromCompactDisc(); void openMovieFromData(QByteArray *data, char *fileType); void openMovieFromDataGuessType(QByteArray *data); QString mediaSourcePath(); bool codecExistsAccordingToSuffix(const QString &fileName); + NSString* pathToCompactDisc(); + bool isCompactDisc(NSString *path); + NSArray* scanFolder(NSString *path); void setError(NSError *error); bool errorOccured(); diff --git a/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm index de7c6ed..9a3c811 100644 --- a/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm +++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm @@ -20,6 +20,7 @@ #include "videowidget.h" #include "audiodevice.h" #include "quicktimestreamreader.h" +#include "quicktimemetadata.h" #include <QtCore/QCoreApplication> #include <QtCore/QEventLoop> @@ -52,6 +53,7 @@ QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0) { m_state = NoMedia; m_mediaSource = MediaSource(); + m_metaData = new QuickTimeMetaData(this); m_QTMovie = 0; m_streamReader = 0; m_playbackRate = 1.0f; @@ -69,6 +71,8 @@ QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0) m_primaryRenderingCIImage = 0; m_QImagePixelBuffer = 0; m_cachedCVTextureRef = 0; + m_folderTracks = 0; + m_currentTrack = 0; #ifdef QUICKTIME_C_API_AVAILABLE OSStatus err = EnterMovies(); @@ -80,7 +84,8 @@ QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0) QuickTimeVideoPlayer::~QuickTimeVideoPlayer() { PhononAutoReleasePool pool; - unsetVideo(); + unsetCurrentMediaSource(); + delete m_metaData; [(NSObject*)m_primaryRenderingTarget release]; m_primaryRenderingTarget = 0; #ifdef QUICKTIME_C_API_AVAILABLE @@ -420,7 +425,7 @@ QRect QuickTimeVideoPlayer::videoRect() const return QRect(0, 0, size.width, size.height); } -void QuickTimeVideoPlayer::unsetVideo() +void QuickTimeVideoPlayer::unsetCurrentMediaSource() { if (!m_QTMovie) return; @@ -436,11 +441,14 @@ void QuickTimeVideoPlayer::unsetVideo() m_hasVideo = false; m_staticFps = 0; m_mediaSource = MediaSource(); + m_movieCompactDiscPath.clear(); [(CIImage *)m_primaryRenderingCIImage release]; m_primaryRenderingCIImage = 0; delete m_QImagePixelBuffer; m_QImagePixelBuffer = 0; releaseImageCache(); + [m_folderTracks release]; + m_folderTracks = 0; } QuickTimeVideoPlayer::State QuickTimeVideoPlayer::state() const @@ -550,18 +558,25 @@ bool QuickTimeVideoPlayer::codecExistsAccordingToSuffix(const QString &fileName) void QuickTimeVideoPlayer::setMediaSource(const MediaSource &mediaSource) { PhononAutoReleasePool pool; - unsetVideo(); + unsetCurrentMediaSource(); + m_mediaSource = mediaSource; if (mediaSource.type() == MediaSource::Empty || mediaSource.type() == MediaSource::Invalid){ m_state = NoMedia; return; } + openMovieFromCurrentMediaSource(); if (errorOccured()){ - unsetVideo(); + unsetCurrentMediaSource(); return; } + prepareCurrentMovieForPlayback(); +} + +void QuickTimeVideoPlayer::prepareCurrentMovieForPlayback() +{ #ifdef QUICKTIME_C_API_AVAILABLE if (m_visualContext) SetMovieVisualContext([m_QTMovie quickTimeMovie], m_visualContext); @@ -569,14 +584,14 @@ void QuickTimeVideoPlayer::setMediaSource(const MediaSource &mediaSource) waitStatePlayable(); if (errorOccured()){ - unsetVideo(); + unsetCurrentMediaSource(); return; } readProtection(); preRollMovie(); if (errorOccured()){ - unsetVideo(); + unsetCurrentMediaSource(); return; } @@ -587,6 +602,7 @@ void QuickTimeVideoPlayer::setMediaSource(const MediaSource &mediaSource) enableAudio(m_audioEnabled); setMute(m_mute); setVolume(m_masterVolume, m_relativeVolume); + m_metaData->update(); pause(); } @@ -600,7 +616,7 @@ void QuickTimeVideoPlayer::openMovieFromCurrentMediaSource() openMovieFromUrl(); break; case MediaSource::Disc: - CASE_UNSUPPORTED("Could not open media source.", FATAL_ERROR) + openMovieFromCompactDisc(); break; case MediaSource::Stream: openMovieFromStream(); @@ -662,7 +678,7 @@ void QuickTimeVideoPlayer::openMovieFromDataGuessType(QByteArray *data) // than using e.g [QTMovie movieFileTypes:QTIncludeCommonTypes]. Some // codecs *think* they can decode the stream, and crash... #define TryOpenMovieWithCodec(type) gClearError(); \ - openMovieFromData(data, "."type); \ + openMovieFromData(data, (char *)"."type); \ if (m_QTMovie) return; TryOpenMovieWithCodec("avi"); @@ -702,6 +718,50 @@ void QuickTimeVideoPlayer::openMovieFromStream() openMovieFromDataGuessType(m_streamReader->pointerToData()); } +typedef void (*qt_sighandler_t)(int); +static void sigtest(int) { + qApp->exit(0); +} + +void QuickTimeVideoPlayer::openMovieFromCompactDisc() +{ + // Interrupting the application while the device is open + // causes the application to hang. So we need to handle + // this in a more graceful way: + qt_sighandler_t hndl = signal(SIGINT, sigtest); + if (hndl) + signal(SIGINT, hndl); + + PhononAutoReleasePool pool; + NSString *cd = 0; + QString devName = m_mediaSource.deviceName(); + if (devName.isEmpty()) { + cd = pathToCompactDisc(); + if (!cd) { + SET_ERROR("Could not open media source.", NORMAL_ERROR) + return; + } + m_movieCompactDiscPath = PhononCFString::toQString(reinterpret_cast<CFStringRef>(cd)); + } else { + if (!QFileInfo(devName).isAbsolute()) + devName = QLatin1String("/Volumes/") + devName; + cd = [reinterpret_cast<const NSString *>(PhononCFString::toCFStringRef(devName)) autorelease]; + if (!isCompactDisc(cd)) { + SET_ERROR("Could not open media source.", NORMAL_ERROR) + return; + } + m_movieCompactDiscPath = devName; + } + + m_folderTracks = [scanFolder(cd) retain]; + setCurrentTrack(0); +} + +QString QuickTimeVideoPlayer::movieCompactDiscPath() const +{ + return m_movieCompactDiscPath; +} + MediaSource QuickTimeVideoPlayer::mediaSource() const { return m_mediaSource; @@ -1015,6 +1075,93 @@ void QuickTimeVideoPlayer::readProtection() } } +QMultiMap<QString, QString> QuickTimeVideoPlayer::metaData() +{ + return m_metaData->metaData(); +} + +int QuickTimeVideoPlayer::trackCount() const +{ + if (!m_folderTracks) + return 0; + return [m_folderTracks count]; +} + +int QuickTimeVideoPlayer::currentTrack() const +{ + return m_currentTrack; +} + +QString QuickTimeVideoPlayer::currentTrackPath() const +{ + if (!m_folderTracks) + return QString(); + + PhononAutoReleasePool pool; + NSString *trackPath = [m_folderTracks objectAtIndex:m_currentTrack]; + return PhononCFString::toQString(reinterpret_cast<CFStringRef>(trackPath)); +} + +NSString* QuickTimeVideoPlayer::pathToCompactDisc() +{ + PhononAutoReleasePool pool; + NSArray *devices = [[NSWorkspace sharedWorkspace] mountedRemovableMedia]; + for (NSString *dev in devices) { + if (isCompactDisc(dev)) + return [dev retain]; + } + return 0; +} + +bool QuickTimeVideoPlayer::isCompactDisc(NSString *path) +{ + PhononAutoReleasePool pool; + NSString *type = [NSString string]; + [[NSWorkspace sharedWorkspace] getFileSystemInfoForPath:path + isRemovable:0 + isWritable:0 + isUnmountable:0 + description:0 + type:&type]; + return [type hasPrefix:@"cdd"]; +} + +NSArray* QuickTimeVideoPlayer::scanFolder(NSString *path) +{ + NSMutableArray *tracks = [NSMutableArray arrayWithCapacity:20]; + if (!path) + return tracks; + + NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path]; + while (NSString *track = [enumerator nextObject]) { + if (![track hasPrefix:@"."]) + [tracks addObject:[path stringByAppendingPathComponent:track]]; + } + return tracks; +} + +void QuickTimeVideoPlayer::setCurrentTrack(int track) +{ + PhononAutoReleasePool pool; + [m_QTMovie release]; + m_QTMovie = 0; + m_currentTime = 0; + m_currentTrack = track; + + if (!m_folderTracks) + return; + if (track < 0 || track >= (int)[m_folderTracks count]) + return; + + NSString *trackPath = [m_folderTracks objectAtIndex:track]; + QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToFile:trackPath]; + State currentState = m_state; + openMovieFromDataRef(dataRef); + prepareCurrentMovieForPlayback(); + if (currentState == Playing) + play(); +} + }} QT_END_NAMESPACE |