From 4da9590140c063551f261b883fb275cafe986b60 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 30 Mar 2010 07:19:47 +0200 Subject: Fix use of bitmap fonts on some Linux systems In 30bd59a1dec78 we added a fallback from font config to XLFD in the case where font config could not supply us with the correct pixel size for a given font. Primarily, this was for when you would try to print a bitmap font on a high resolution printer. This caused a problem for applications that set a point size on a bitmap font, since the calculated pixel size would not be available. For UIs you will usually prefer to select the font with the correct family but nearest pixel size here, which is what font config does. We would however choose the fallback and if XLFD failed to load the font in question, you would get a substitution. Since getting the correct font family seems more important than getting the correct pixel size, we disable the fallback in the case where XLFD does not find the correct font. This will fix the bug where UI fonts were frequently created with the wrong family on e.g. Fedora, and it might cause some trouble with printing bitmap fonts, however, it was deemed that bitmap fonts are not ideal fonts to use for printing. In cases where XLFD can load the bitmap fonts, the fallback will still be used. Task-number: QTBUG-4428 Reviewed-by: Trond --- src/gui/text/qfontdatabase_x11.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp index b1ab478..3b2e4e9 100644 --- a/src/gui/text/qfontdatabase_x11.cpp +++ b/src/gui/text/qfontdatabase_x11.cpp @@ -1939,8 +1939,13 @@ void QFontDatabase::load(const QFontPrivate *d, int script) fe = loadFc(d, script, req); if (fe != 0 && fe->fontDef.pixelSize != req.pixelSize) { - delete fe; - fe = loadXlfd(d->screen, script, req); + QFontEngine *xlfdFontEngine = loadXlfd(d->screen, script, req); + if (xlfdFontEngine->fontDef.family == fe->fontDef.family) { + delete fe; + fe = xlfdFontEngine; + } else { + delete xlfdFontEngine; + } } -- cgit v0.12 From 1a4ee517638e1ba3cdc622af70b3d53561d23392 Mon Sep 17 00:00:00 2001 From: Zeno Albisser Date: Thu, 25 Mar 2010 17:39:41 +0100 Subject: Added variable QMAKE_TARGET.arch to qmake to be used with MSVC++ The variable QMAKE_TARGET.arch shall be used to determine cross compiling for x64 on a x32 system. Reviewed-by: Marius Storm-Olsen Task-number: QTBUG-9160 --- qmake/project.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/qmake/project.cpp b/qmake/project.cpp index 01a3843..56707cf 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -3148,6 +3148,21 @@ QStringList &QMakeProject::values(const QString &_var, QMap[%s]", qPrintable(var), qPrintable(place[var].join("::"))); return place[var]; } -- cgit v0.12 From a354e98838e67e9bbd9473d4cd42b89f45d0e3fe Mon Sep 17 00:00:00 2001 From: Johan Hauan Date: Tue, 6 Apr 2010 11:34:57 +0200 Subject: Sunstudio12.1(5.10): Fix compile errors GTK style and other minor compile errors GTK Style A QHashableLatin1Literal was a bit too clever for sunstudio. Added and alternate constructor for sunstudio(ifdef) Should not affect other compilers. Other: Minor compile fixes, extra semicolon after macros etc. Merge-request: 547 Reviewed-by: Benjamin Poulain --- examples/qtconcurrent/map/main.cpp | 2 +- src/gui/styles/qgtkstyle_p.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/qtconcurrent/map/main.cpp b/examples/qtconcurrent/map/main.cpp index 6068d30..6afefca 100644 --- a/examples/qtconcurrent/map/main.cpp +++ b/examples/qtconcurrent/map/main.cpp @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) // Use QtConcurrentBlocking::mapped to apply the scale function to all the // images in the list. - QList thumbnails = QtConcurrent::blockingMapped(images, scale); + QList thumbnails = QtConcurrent::blockingMapped >(images, scale); return 0; } diff --git a/src/gui/styles/qgtkstyle_p.h b/src/gui/styles/qgtkstyle_p.h index 5bb7550..f0aee46 100644 --- a/src/gui/styles/qgtkstyle_p.h +++ b/src/gui/styles/qgtkstyle_p.h @@ -85,9 +85,14 @@ public: int size() const { return m_size; } const char *data() const { return m_data; } +#ifdef __SUNPRO_CC + QHashableLatin1Literal(const char* str) + : m_size(strlen(str)), m_data(str) {} +#else template QHashableLatin1Literal(const char (&str)[N]) : m_size(N - 1), m_data(str) {} +#endif QHashableLatin1Literal(const QHashableLatin1Literal &other) : m_size(other.m_size), m_data(other.m_data) -- cgit v0.12 From 822efb6807d6164304bc454f39c5f739bbe1f8e5 Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Tue, 6 Apr 2010 11:46:19 +0200 Subject: Fix a coding style issue of the GTK style A tab was introduced in 16614121f8eff813efadc999a7db9ce47eae769e --- src/gui/styles/qgtkstyle_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/styles/qgtkstyle_p.h b/src/gui/styles/qgtkstyle_p.h index f0aee46..68a04e9 100644 --- a/src/gui/styles/qgtkstyle_p.h +++ b/src/gui/styles/qgtkstyle_p.h @@ -87,7 +87,7 @@ public: #ifdef __SUNPRO_CC QHashableLatin1Literal(const char* str) - : m_size(strlen(str)), m_data(str) {} + : m_size(strlen(str)), m_data(str) {} #else template QHashableLatin1Literal(const char (&str)[N]) -- cgit v0.12 From 0c442405a9f85f402d508af2be0a668f34f35caf Mon Sep 17 00:00:00 2001 From: Carlos Manuel Duclos Vergara Date: Tue, 6 Apr 2010 13:47:24 +0200 Subject: [Cocoa] QDialogs with WindowStayOnStopHint parent The problem is with beginModalSession which reorders the windows and sends our window back. This patch queries the window level before calling beginModalSession and sets it after beginModalSession. Task-number: QTBUG-9392 Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qeventdispatcher_mac.mm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index 62e1e81..a7f1224 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -831,7 +831,14 @@ NSModalSession QEventDispatcherMacPrivate::currentModalSession() QBoolBlocker block1(blockSendPostedEvents, true); info.nswindow = window; [(NSWindow*) info.nswindow retain]; - info.session = [NSApp beginModalSessionForWindow:window]; + // When creating a modal session cocoa will rearrange the windows. + // In order to avoid windows to be put behind another we need to + // keep the window level. + { + int level = [window level]; + info.session = [NSApp beginModalSessionForWindow:window]; + [window setLevel:level]; + } } currentModalSessionCached = info.session; } -- cgit v0.12 From ce0af99f47c1728a6d8145ea89f41b1c9207104a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 6 Apr 2010 16:08:20 +0200 Subject: Prevented unnecessary copy in QImage::setAlphaChannel(). If the formats don't match the detch is unnecessary as operator= will anyways destroy the detached QImageData and substitute it with the newly created QImageData from convertToFormat. Task-number: QTBUG-9640 Reviewed-by: Trond --- src/gui/image/qimage.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 233c58d..ce1d6d3 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -5704,9 +5704,10 @@ void QImage::setAlphaChannel(const QImage &alphaChannel) return; } - detach(); - - *this = convertToFormat(QImage::Format_ARGB32_Premultiplied); + if (d->format == QImage::Format_ARGB32_Premultiplied) + detach(); + else + *this = convertToFormat(QImage::Format_ARGB32_Premultiplied); // Slight optimization since alphachannels are returned as 8-bit grays. if (alphaChannel.d->depth == 8 && alphaChannel.isGrayscale()) { -- cgit v0.12 From 06e8d0cae3651beaf95de05e89696cbab4978740 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 6 Apr 2010 16:23:34 +0200 Subject: Fix painting artifacts on text The height of the row is not only decided by the maximum height of the set of glyphs currently being added to the glyph cache, but also the height of the glyphs previously added to the current line in the glyph cache. To minimize the space used, we now calculate the maximum height for glyphs per line, and use this as the vertical advancement when positioning the next line in the cache. The change also removes a redundant test ((c_x + c.w > c.h) is caught earlier on and will always be false at this point.) Task-number: QTBUG-9176 Reviewed-by: Trond --- src/gui/painting/qtextureglyphcache.cpp | 14 +++++--------- src/gui/painting/qtextureglyphcache_p.h | 3 ++- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index cf545be..9eda0ef 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -133,10 +133,13 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const while (iter != listItemCoordinates.end()) { Coord c = iter.value(); + m_currentRowHeight = qMax(m_currentRowHeight, c.h + margin * 2); + if (m_cx + c.w > m_w) { // no room on the current line, start new glyph strip m_cx = 0; - m_cy += rowHeight; + m_cy += m_currentRowHeight; + m_currentRowHeight = 0; // New row } if (m_cy + c.h > m_h) { int new_height = m_h*2; @@ -153,14 +156,7 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const fillTexture(c, iter.key()); coords.insert(iter.key(), c); - if (m_cx + c.w > m_w) { - m_cx = 0; - m_cy += rowHeight; - } else { - // for the Mono case, glyph_width is 8-bit aligned, - // and therefore so will m_cx - m_cx += c.w; - } + m_cx += c.w; ++iter; } diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index 803e71b..8c2f5b4 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -77,7 +77,7 @@ class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache public: QTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix) : QFontEngineGlyphCache(matrix, type), m_current_fontengine(0), - m_w(0), m_h(0), m_cx(0), m_cy(0) + m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0) { } virtual ~QTextureGlyphCache() { } @@ -120,6 +120,7 @@ protected: int m_h; // image height int m_cx; // current x int m_cy; // current y + int m_currentRowHeight; // Height of last row }; -- cgit v0.12 From 253b87180e0a6c5db0feaaed7e321139c4ff1643 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 6 Apr 2010 17:04:20 +0200 Subject: Moved item wouldn't follow mouse cursor when ItemIgnoresTransformations is set Since the introduction of transform properties in QGraphicsItem, QGraphicsItem::transform() is no longer enough to get the correct transform of an item. No auto-test as it involves mouse dragging. Reviewed-by: Yoann Task-number: QTBUG-9295 --- src/gui/graphicsview/qgraphicsitem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index f106b3d..d6daf4d 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -7112,7 +7112,8 @@ void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) // Root items that ignore transformations need to // calculate their diff by mapping viewport coordinates // directly to parent coordinates. - QTransform viewToParentTransform = (item->transform().translate(item->d_ptr->pos.x(), item->d_ptr->pos.y())) + // COMBINE + QTransform viewToParentTransform = (item->d_func()->transformData->computedFullTransform().translate(item->d_ptr->pos.x(), item->d_ptr->pos.y())) * (item->sceneTransform() * view->viewportTransform()).inverted(); currentParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->screenPos()))); buttonDownParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton)))); -- cgit v0.12 From 30f4ad046123449e53b8d4cf936300753df126ec Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 6 Apr 2010 18:09:15 +0200 Subject: Doc: Remove QDBusServer from the public documentation. Task-number: QTBUG-5066 --- src/dbus/qdbusserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp index 8f9323a..13b18a6 100644 --- a/src/dbus/qdbusserver.cpp +++ b/src/dbus/qdbusserver.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE /*! \class QDBusServer \inmodule QtDBus - \since 4.2 + \internal \brief The QDBusServer class provides peer-to-peer communication between processes on the same computer. -- cgit v0.12 From d65d3becc292523f0962aac9d2bf7b96d9c47c04 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 6 Apr 2010 18:15:00 +0200 Subject: Doc: update the QDBusPendingCallWatcher example to show where to delete Task-number: QTBUG-8865 --- doc/src/snippets/code/src.qdbus.qdbuspendingcall.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/src/snippets/code/src.qdbus.qdbuspendingcall.cpp b/doc/src/snippets/code/src.qdbus.qdbuspendingcall.cpp index 94a9f68..2867bd5a 100644 --- a/doc/src/snippets/code/src.qdbus.qdbuspendingcall.cpp +++ b/doc/src/snippets/code/src.qdbus.qdbuspendingcall.cpp @@ -61,5 +61,6 @@ void MyClass::callFinishedSlot(QDBusPendingCallWatcher *call) QByteArray data = reply.argumentAt<1>(); showReply(text, data); } + call->deleteLater(); } //! [1] -- cgit v0.12 From e56af88f159ceee5f9613ab57b2358601e79c081 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 6 Apr 2010 16:48:59 +0200 Subject: QTreeView: fix PageUp/PageDown with disabled items. The problem was seen in Qt Creator (in the 'Sources' tab of the debugger). Same logic as in above() and bellow() Reviewed-by: Gabriel --- src/gui/itemviews/qtreeview.cpp | 4 ++++ tests/auto/qtreeview/tst_qtreeview.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index d934683..c3ff2bd 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -3194,12 +3194,16 @@ void QTreeViewPrivate::layout(int i, bool recursiveExpanding, bool afterIsUninit int QTreeViewPrivate::pageUp(int i) const { int index = itemAtCoordinate(coordinateForItem(i) - viewport->height()); + while (isItemHiddenOrDisabled(index)) + index--; return index == -1 ? 0 : index; } int QTreeViewPrivate::pageDown(int i) const { int index = itemAtCoordinate(coordinateForItem(i) + viewport->height()); + while (isItemHiddenOrDisabled(index)) + index++; return index == -1 ? viewItems.count() - 1 : index; } diff --git a/tests/auto/qtreeview/tst_qtreeview.cpp b/tests/auto/qtreeview/tst_qtreeview.cpp index 2de189d..75a4c62 100644 --- a/tests/auto/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/qtreeview/tst_qtreeview.cpp @@ -215,6 +215,7 @@ private slots: void addRowsWhileSectionsAreHidden(); void filterProxyModelCrash(); void styleOptionViewItem(); + void keyboardNavigationWithDisabled(); // task-specific tests: void task174627_moveLeftToRoot(); @@ -3753,5 +3754,36 @@ void tst_QTreeView::taskQTBUG_9216_setSizeAndUniformRowHeightsWrongRepaint() QTRY_VERIFY(view.painted > 0); } +void tst_QTreeView::keyboardNavigationWithDisabled() +{ + QTreeView view; + QStandardItemModel model(90, 0); + for (int i = 0; i < 90; i ++) { + model.setItem(i, new QStandardItem(QString::number(i))); + model.item(i)->setEnabled(i%6 == 0); + } + view.setModel(&model); + + view.resize(200, view.visualRect(model.index(0,0)).height()*10); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_VERIFY(view.isActiveWindow()); + + view.setCurrentIndex(model.index(1, 0)); + QTest::keyClick(view.viewport(), Qt::Key_Up); + QCOMPARE(view.currentIndex(), model.index(0, 0)); + QTest::keyClick(view.viewport(), Qt::Key_Down); + QCOMPARE(view.currentIndex(), model.index(6, 0)); + QTest::keyClick(view.viewport(), Qt::Key_PageDown); + QCOMPARE(view.currentIndex(), model.index(18, 0)); + QTest::keyClick(view.viewport(), Qt::Key_Down); + QCOMPARE(view.currentIndex(), model.index(24, 0)); + QTest::keyClick(view.viewport(), Qt::Key_PageUp); + QCOMPARE(view.currentIndex(), model.index(12, 0)); + QTest::keyClick(view.viewport(), Qt::Key_Up); + QCOMPARE(view.currentIndex(), model.index(6, 0)); +} + QTEST_MAIN(tst_QTreeView) #include "tst_qtreeview.moc" -- cgit v0.12 From 6253ced81bcd60c04803f1a52bc59a239022b9c4 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 7 Apr 2010 13:48:13 +0200 Subject: Revert "Update Phonon ds9 backend to 4.4.0." This reverts commit 19a3fc3bd817628070e5637caf158b0be79eee82. The phonon backend in 4.4.0 is outdated. Qt has the most recent one. Conflicts: src/3rdparty/phonon/ds9/iodevicereader.cpp --- src/3rdparty/phonon/ds9/abstractvideorenderer.cpp | 4 +- src/3rdparty/phonon/ds9/backend.cpp | 14 +- src/3rdparty/phonon/ds9/backend.h | 4 + src/3rdparty/phonon/ds9/backendnode.cpp | 19 ++ src/3rdparty/phonon/ds9/ds9.desktop | 17 +- src/3rdparty/phonon/ds9/effect.cpp | 4 +- src/3rdparty/phonon/ds9/fakesource.cpp | 34 +--- src/3rdparty/phonon/ds9/iodevicereader.cpp | 94 +++------- src/3rdparty/phonon/ds9/iodevicereader.h | 1 - src/3rdparty/phonon/ds9/mediagraph.cpp | 38 ++-- src/3rdparty/phonon/ds9/mediaobject.cpp | 201 +++++++++----------- src/3rdparty/phonon/ds9/mediaobject.h | 8 +- src/3rdparty/phonon/ds9/qasyncreader.cpp | 72 +++----- src/3rdparty/phonon/ds9/qasyncreader.h | 6 +- src/3rdparty/phonon/ds9/qaudiocdreader.cpp | 54 ++---- src/3rdparty/phonon/ds9/qaudiocdreader.h | 2 +- src/3rdparty/phonon/ds9/qbasefilter.cpp | 33 ++-- src/3rdparty/phonon/ds9/qbasefilter.h | 4 +- src/3rdparty/phonon/ds9/qevr9.h | 143 ++++++++++++++ src/3rdparty/phonon/ds9/qmeminputpin.cpp | 113 ++++-------- src/3rdparty/phonon/ds9/qmeminputpin.h | 9 +- src/3rdparty/phonon/ds9/qpin.cpp | 73 +++----- src/3rdparty/phonon/ds9/qpin.h | 7 +- src/3rdparty/phonon/ds9/videorenderer_default.cpp | 153 +++++++++++++++ src/3rdparty/phonon/ds9/videorenderer_default.h | 55 ++++++ src/3rdparty/phonon/ds9/videorenderer_evr.cpp | 215 ++++++++++++++++++++++ src/3rdparty/phonon/ds9/videorenderer_evr.h | 56 ++++++ src/3rdparty/phonon/ds9/videorenderer_soft.cpp | 15 +- src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp | 113 +----------- src/3rdparty/phonon/ds9/videorenderer_vmr9.h | 1 - src/3rdparty/phonon/ds9/videowidget.cpp | 50 ++++- src/3rdparty/phonon/ds9/volumeeffect.cpp | 5 +- src/3rdparty/phonon/ds9/volumeeffect.h | 2 +- src/plugins/phonon/ds9/ds9.pro | 2 + 34 files changed, 1001 insertions(+), 620 deletions(-) create mode 100644 src/3rdparty/phonon/ds9/qevr9.h create mode 100644 src/3rdparty/phonon/ds9/videorenderer_default.cpp create mode 100644 src/3rdparty/phonon/ds9/videorenderer_default.h create mode 100644 src/3rdparty/phonon/ds9/videorenderer_evr.cpp create mode 100644 src/3rdparty/phonon/ds9/videorenderer_evr.h diff --git a/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp b/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp index e932e70..a9d0694 100644 --- a/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp +++ b/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp @@ -99,8 +99,8 @@ namespace Phonon m_dstX = m_dstY = 0; if (ratio > 0) { - if (realWidth / realHeight > ratio && scaleMode == Phonon::VideoWidget::FitInView - || realWidth / realHeight < ratio && scaleMode == Phonon::VideoWidget::ScaleAndCrop) { + if ((realWidth / realHeight > ratio && scaleMode == Phonon::VideoWidget::FitInView) + || (realWidth / realHeight < ratio && scaleMode == Phonon::VideoWidget::ScaleAndCrop)) { //the height is correct, let's change the width m_dstWidth = qRound(realHeight * ratio); m_dstX = qRound((realWidth - realHeight * ratio) / 2.); diff --git a/src/3rdparty/phonon/ds9/backend.cpp b/src/3rdparty/phonon/ds9/backend.cpp index 2c56af7..fbc4bdc 100644 --- a/src/3rdparty/phonon/ds9/backend.cpp +++ b/src/3rdparty/phonon/ds9/backend.cpp @@ -41,6 +41,8 @@ namespace Phonon { namespace DS9 { + QMutex *Backend::directShowMutex = 0; + bool Backend::AudioMoniker::operator==(const AudioMoniker &other) { return other->IsEqual(*this) == S_OK; @@ -50,6 +52,8 @@ namespace Phonon Backend::Backend(QObject *parent, const QVariantList &) : QObject(parent) { + directShowMutex = &m_directShowMutex; + ::CoInitialize(0); //registering meta types @@ -62,6 +66,8 @@ namespace Phonon m_audioOutputs.clear(); m_audioEffects.clear(); ::CoUninitialize(); + + directShowMutex = 0; } QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList &args) @@ -131,6 +137,7 @@ namespace Phonon QList Backend::objectDescriptionIndexes(Phonon::ObjectDescriptionType type) const { + QMutexLocker locker(&m_directShowMutex); QList ret; switch(type) @@ -157,7 +164,7 @@ namespace Phonon while (S_OK == enumMon->Next(1, mon.pparam(), 0)) { LPOLESTR str = 0; mon->GetDisplayName(0,0,&str); - const QString name = QString::fromUtf16((unsigned short*)str); + const QString name = QString::fromWCharArray(str); ComPointer alloc; ::CoGetMalloc(1, alloc.pparam()); alloc->Free(str); @@ -204,6 +211,7 @@ namespace Phonon QHash Backend::objectDescriptionProperties(Phonon::ObjectDescriptionType type, int index) const { + QMutexLocker locker(&m_directShowMutex); QHash ret; switch (type) { @@ -216,7 +224,7 @@ namespace Phonon LPOLESTR str = 0; HRESULT hr = mon->GetDisplayName(0,0, &str); if (SUCCEEDED(hr)) { - QString name = QString::fromUtf16((unsigned short*)str); + QString name = QString::fromWCharArray(str); ComPointer alloc; ::CoGetMalloc(1, alloc.pparam()); alloc->Free(str); @@ -231,7 +239,7 @@ namespace Phonon WCHAR name[80]; // 80 is clearly stated in the MSDN doc HRESULT hr = ::DMOGetName(m_audioEffects[index], name); if (SUCCEEDED(hr)) { - ret["name"] = QString::fromUtf16((unsigned short*)name); + ret["name"] = QString::fromWCharArray(name); } } break; diff --git a/src/3rdparty/phonon/ds9/backend.h b/src/3rdparty/phonon/ds9/backend.h index ad638f2..7c3c109 100644 --- a/src/3rdparty/phonon/ds9/backend.h +++ b/src/3rdparty/phonon/ds9/backend.h @@ -23,6 +23,7 @@ along with this library. If not, see . #include #include +#include #include "compointer.h" #include "backendnode.h" @@ -63,6 +64,8 @@ namespace Phonon Filter getAudioOutputFilter(int index) const; + static QMutex *directShowMutex; + Q_SIGNALS: void objectDescriptionChanged(ObjectDescriptionType); @@ -74,6 +77,7 @@ namespace Phonon }; mutable QVector m_audioOutputs; mutable QVector m_audioEffects; + mutable QMutex m_directShowMutex; }; } } diff --git a/src/3rdparty/phonon/ds9/backendnode.cpp b/src/3rdparty/phonon/ds9/backendnode.cpp index 7e0b3cd..737ab7b 100644 --- a/src/3rdparty/phonon/ds9/backendnode.cpp +++ b/src/3rdparty/phonon/ds9/backendnode.cpp @@ -57,6 +57,25 @@ namespace Phonon BackendNode::~BackendNode() { + //this will remove the filter from the graph + FILTER_INFO info; + for(int i = 0; i < FILTER_COUNT; ++i) { + const Filter &filter = m_filters[i]; + if (!filter) + continue; + filter->QueryFilterInfo(&info); + if (info.pGraph) { + HRESULT hr = info.pGraph->RemoveFilter(filter); + + if (FAILED(hr) && m_mediaObject) { + m_mediaObject->ensureStopped(); + + hr = info.pGraph->RemoveFilter(filter); + } + Q_ASSERT(SUCCEEDED(hr)); + info.pGraph->Release(); + } + } } void BackendNode::setMediaObject(MediaObject *mo) diff --git a/src/3rdparty/phonon/ds9/ds9.desktop b/src/3rdparty/phonon/ds9/ds9.desktop index 1bc3451..764390e 100644 --- a/src/3rdparty/phonon/ds9/ds9.desktop +++ b/src/3rdparty/phonon/ds9/ds9.desktop @@ -5,13 +5,12 @@ MimeType=application/x-annodex;video/quicktime;video/x-quicktime;audio/x-m4a;app X-KDE-Library=phonon_ds9 X-KDE-PhononBackendInfo-InterfaceVersion=1 X-KDE-PhononBackendInfo-Version=0.1 -X-KDE-PhononBackendInfo-Website=http://www.trolltech.com/ +X-KDE-PhononBackendInfo-Website=http://qt.nokia.com/ InitialPreference=15 Name=DirectShow9 Name[bg]=DirectShow9 Name[ca]=DirectShow9 -Name[ca@valencia]=DirectShow9 Name[cs]=DirectShow9 Name[da]=DirectShow9 Name[de]=DirectShow9 @@ -20,14 +19,11 @@ Name[en_GB]=DirectShow9 Name[es]=DirectShow9 Name[et]=DirectShow9 Name[eu]=DirectShow9 -Name[fi]=DirectShow9 Name[fr]=DirectShow9 Name[ga]=DirectShow9 Name[gl]=DirectShow9 -Name[hr]=DirectShow9 Name[hsb]=DirectShow9 Name[hu]=DirectShow9 -Name[id]=DirectShow9 Name[is]=DirectShow9 Name[it]=DirectShow9 Name[ja]=DirectShow9 @@ -35,7 +31,6 @@ Name[ko]=DirectShow9 Name[ku]=DirectShow9 Name[lt]=DirectShow9 Name[lv]=DirectShow9 -Name[nb]=DirectShow9 Name[nds]=DirectShow9 Name[nl]=DirectShow9 Name[nn]=DirectShow9 @@ -43,13 +38,10 @@ Name[pa]=ਡਾਇਰੈਕਸ਼ੋ9 Name[pl]=DirectShow9 Name[pt]=DirectShow9 Name[pt_BR]=DirectShow9 -Name[ru]=DirectShow9 Name[se]=DirectShow9 Name[sk]=DirectShow 9 Name[sl]=DirectShow 9 Name[sr]=Директшоу‑9 -Name[sr@ijekavian]=Директшоу‑9 -Name[sr@ijekavianlatin]=DirectShow‑9 Name[sr@latin]=DirectShow‑9 Name[sv]=Directshow 9 Name[tr]=DirectShow9 @@ -61,7 +53,6 @@ Name[zh_TW]=DirectShow9 Comment=Phonon DirectShow9 backend Comment[bg]=Phonon DirectShow9 Comment[ca]=Dorsal DirectShow9 del Phonon -Comment[ca@valencia]=Dorsal DirectShow9 del Phonon Comment[cs]=Phonon DirectShow9 backend Comment[da]=DirectShow9-backend til Phonon Comment[de]=Phonon-Treiber für DirectShow9 @@ -70,13 +61,11 @@ Comment[en_GB]=Phonon DirectShow9 backend Comment[es]=Motor DirectShow9 para Phonon Comment[et]=Phononi DirectShow9 taustaprogramm Comment[eu]=Phonon DirectShow9 backend -Comment[fi]=Phonon DirectShow9-taustaohjelma Comment[fr]=Système de gestion DirectShow9 pour Phonon Comment[ga]=Inneall DirectShow9 le haghaidh Phonon Comment[gl]=Infraestrutura de DirectShow9 para Phonon Comment[hsb]=Phonon DirectShow9 backend Comment[hu]=Phonon DirectShow9 modul -Comment[id]=Phonon DirectShow9 backend Comment[is]=Phonon DirectShow9 bakendi Comment[it]=Motore DirectShow9 di Phonon Comment[ja]=Phonon DirectShow9 バックエンド @@ -84,7 +73,6 @@ Comment[ko]=Phonon DirectShow9 백엔드 Comment[ku]=Binesaza Phonon DirectShow9 Comment[lt]=Phonon DirectShow9 galinė sąsaja Comment[lv]=Phonon DirectShow9 aizmugure -Comment[nb]=Phonon-motor for DirectShow9 Comment[nds]=Phonon-Hülpprogrmm DirectShow9 Comment[nl]=DirectShow9-backend (Phonon) Comment[nn]=Phonon-motor for DirectShow9 @@ -92,13 +80,10 @@ Comment[pa]=ਫੋਨੋਨ ਡਾਇਰੈਕਟਸ਼ੋ9 ਬੈਕਐਂਡ Comment[pl]=Obsługa DirectShow9 przez Phonon Comment[pt]=Infra-estrutura do DirectShow9 para o Phonon Comment[pt_BR]=Infraestrutura Phonon DirectShow9 -Comment[ru]=Механизм DirectShow9 для Phonon Comment[se]=Phonon DirectShow9 duogášmohtor Comment[sk]=Phonon DirectShow 9 podsystém Comment[sl]=Phononova Hrbtenica DirectShow 9 Comment[sr]=Директшоу‑9 као позадина Фонона -Comment[sr@ijekavian]=Директшоу‑9 као позадина Фонона -Comment[sr@ijekavianlatin]=DirectShow‑9 kao pozadina Phonona Comment[sr@latin]=DirectShow‑9 kao pozadina Phonona Comment[sv]=Phonon Directshow 9-gränssnitt Comment[tr]=Phonon DirectShow9 arka ucu diff --git a/src/3rdparty/phonon/ds9/effect.cpp b/src/3rdparty/phonon/ds9/effect.cpp index 104a3c1..ebe976b 100644 --- a/src/3rdparty/phonon/ds9/effect.cpp +++ b/src/3rdparty/phonon/ds9/effect.cpp @@ -82,7 +82,7 @@ namespace Phonon current += wcslen(current) + 1; //skip the name current += wcslen(current) + 1; //skip the unit for(; *current; current += wcslen(current) + 1) { - values.append( QString::fromUtf16((unsigned short*)current) ); + values.append( QString::fromWCharArray(current) ); } } //FALLTHROUGH @@ -107,7 +107,7 @@ namespace Phonon Phonon::EffectParameter::Hints hint = info.mopCaps == MP_CAPS_CURVE_INVSQUARE ? Phonon::EffectParameter::LogarithmicHint : Phonon::EffectParameter::Hints(0); - const QString n = QString::fromUtf16((unsigned short*)name); + const QString n = QString::fromWCharArray(name); ret.append(Phonon::EffectParameter(i, n, hint, def, min, max, values)); ::CoTaskMemFree(name); //let's free the memory } diff --git a/src/3rdparty/phonon/ds9/fakesource.cpp b/src/3rdparty/phonon/ds9/fakesource.cpp index 9a61a2e..4dce138 100644 --- a/src/3rdparty/phonon/ds9/fakesource.cpp +++ b/src/3rdparty/phonon/ds9/fakesource.cpp @@ -29,8 +29,10 @@ namespace Phonon namespace DS9 { static WAVEFORMATEX g_defaultWaveFormat = {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0}; - static BITMAPINFOHEADER g_defautBitmapHeader = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}; - static VIDEOINFOHEADER2 g_defaultVideoInfo = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + static VIDEOINFOHEADER2 g_defaultVideoInfo = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {sizeof(BITMAPINFOHEADER), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0} }; + + static const AM_MEDIA_TYPE g_fakeAudioType = {MEDIATYPE_Audio, MEDIASUBTYPE_PCM, 0, 0, 2, FORMAT_WaveFormatEx, 0, sizeof(WAVEFORMATEX), reinterpret_cast(&g_defaultWaveFormat)}; + static const AM_MEDIA_TYPE g_fakeVideoType = {MEDIATYPE_Video, MEDIASUBTYPE_RGB32, TRUE, FALSE, 0, FORMAT_VideoInfo2, 0, sizeof(VIDEOINFOHEADER2), reinterpret_cast(&g_defaultVideoInfo)}; class FakePin : public QPin { @@ -128,36 +130,12 @@ namespace Phonon void FakeSource::createFakeAudioPin() { - AM_MEDIA_TYPE mt; - qMemSet(&mt, 0, sizeof(AM_MEDIA_TYPE)); - mt.majortype = MEDIATYPE_Audio; - mt.subtype = MEDIASUBTYPE_PCM; - mt.formattype = FORMAT_WaveFormatEx; - mt.lSampleSize = 2; - - //fake the format (stereo 44.1 khz stereo 16 bits) - mt.cbFormat = sizeof(WAVEFORMATEX); - mt.pbFormat = reinterpret_cast(&g_defaultWaveFormat); - - new FakePin(this, mt); + new FakePin(this, g_fakeAudioType); } void FakeSource::createFakeVideoPin() { - AM_MEDIA_TYPE mt; - qMemSet(&mt, 0, sizeof(AM_MEDIA_TYPE)); - mt.majortype = MEDIATYPE_Video; - mt.subtype = MEDIASUBTYPE_RGB32; - mt.formattype = FORMAT_VideoInfo2; - mt.bFixedSizeSamples = 1; - - g_defaultVideoInfo.bmiHeader = g_defautBitmapHeader; - - //fake the format - mt.cbFormat = sizeof(VIDEOINFOHEADER2); - mt.pbFormat = reinterpret_cast(&g_defaultVideoInfo); - - new FakePin(this, mt); + new FakePin(this, g_fakeVideoType); } } diff --git a/src/3rdparty/phonon/ds9/iodevicereader.cpp b/src/3rdparty/phonon/ds9/iodevicereader.cpp index 9152712..ba4ae5c 100644 --- a/src/3rdparty/phonon/ds9/iodevicereader.cpp +++ b/src/3rdparty/phonon/ds9/iodevicereader.cpp @@ -36,18 +36,20 @@ namespace Phonon //these mediatypes define a stream, its type will be autodetected by DirectShow static QVector getMediaTypes() { - AM_MEDIA_TYPE mt = { MEDIATYPE_Stream, MEDIASUBTYPE_NULL, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0}; + //the order here is important because otherwise, + //directshow might not be able to detect the stream type correctly + + AM_MEDIA_TYPE mt = { MEDIATYPE_Stream, MEDIASUBTYPE_Avi, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0}; QVector ret; - //normal auto-detect stream - mt.subtype = MEDIASUBTYPE_NULL; - ret << mt; //AVI stream - mt.subtype = MEDIASUBTYPE_Avi; ret << mt; //WAVE stream mt.subtype = MEDIASUBTYPE_WAVE; ret << mt; + //normal auto-detect stream (must be at the end!) + mt.subtype = MEDIASUBTYPE_NULL; + ret << mt; return ret; } @@ -64,7 +66,6 @@ namespace Phonon //for Phonon::StreamInterface void writeData(const QByteArray &data) { - QWriteLocker locker(&m_lock); m_pos += data.size(); m_buffer += data; } @@ -75,54 +76,22 @@ namespace Phonon void setStreamSize(qint64 newSize) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_size = newSize; } - qint64 streamSize() const - { - QReadLocker locker(&m_lock); - return m_size; - } - void setStreamSeekable(bool s) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_seekable = s; } - bool streamSeekable() const - { - QReadLocker locker(&m_lock); - return m_seekable; - } - - void setCurrentPos(qint64 pos) - { - QWriteLocker locker(&m_lock); - m_pos = pos; - seekStream(pos); - m_buffer.clear(); - } - - qint64 currentPos() const - { - QReadLocker locker(&m_lock); - return m_pos; - } - - int currentBufferSize() const - { - QReadLocker locker(&m_lock); - return m_buffer.size(); - } - //virtual pure members //implementation from IAsyncReader STDMETHODIMP Length(LONGLONG *total, LONGLONG *available) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (total) { *total = m_size; } @@ -137,37 +106,39 @@ namespace Phonon HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual) { - QMutexLocker locker(&m_mutexRead); + Q_ASSERT(!m_mutex.tryLock()); + if (m_mediaGraph->isStopping()) { + return VFW_E_WRONG_STATE; + } - if(streamSize() != 1 && pos + length > streamSize()) { + if(m_size != 1 && pos + length > m_size) { //it tries to read outside of the boundaries return E_FAIL; } - if (currentPos() - currentBufferSize() != pos) { - if (!streamSeekable()) { + if (m_pos - m_buffer.size() != pos) { + if (!m_seekable) { return S_FALSE; } - setCurrentPos(pos); + m_pos = pos; + seekStream(pos); + m_buffer.clear(); } - int oldSize = currentBufferSize(); - while (currentBufferSize() < int(length)) { + int oldSize = m_buffer.size(); + while (m_buffer.size() < int(length)) { needData(); - if (oldSize == currentBufferSize()) { + if (oldSize == m_buffer.size()) { break; //we didn't get any data } - oldSize = currentBufferSize(); + oldSize = m_buffer.size(); } - DWORD bytesRead = qMin(currentBufferSize(), int(length)); - { - QWriteLocker locker(&m_lock); - qMemCopy(buffer, m_buffer.data(), bytesRead); - //truncate the buffer - m_buffer = m_buffer.mid(bytesRead); - } + int bytesRead = qMin(m_buffer.size(), int(length)); + qMemCopy(buffer, m_buffer.data(), bytesRead); + //truncate the buffer + m_buffer = m_buffer.mid(bytesRead); if (actual) { *actual = bytesRead; //initialization @@ -183,7 +154,6 @@ namespace Phonon qint64 m_pos; qint64 m_size; - QMutex m_mutexRead; const MediaGraph *m_mediaGraph; }; @@ -197,14 +167,6 @@ namespace Phonon IODeviceReader::~IODeviceReader() { } - - STDMETHODIMP IODeviceReader::Stop() - { - HRESULT hr = QBaseFilter::Stop(); - m_streamReader->enoughData(); //this asks to cancel any blocked call to needData - return hr; - } - } } diff --git a/src/3rdparty/phonon/ds9/iodevicereader.h b/src/3rdparty/phonon/ds9/iodevicereader.h index af4b271..c8b91c3 100644 --- a/src/3rdparty/phonon/ds9/iodevicereader.h +++ b/src/3rdparty/phonon/ds9/iodevicereader.h @@ -41,7 +41,6 @@ namespace Phonon public: IODeviceReader(const MediaSource &source, const MediaGraph *); ~IODeviceReader(); - STDMETHODIMP Stop(); private: StreamReader *m_streamReader; diff --git a/src/3rdparty/phonon/ds9/mediagraph.cpp b/src/3rdparty/phonon/ds9/mediagraph.cpp index db0ec84..3e7a68b 100644 --- a/src/3rdparty/phonon/ds9/mediagraph.cpp +++ b/src/3rdparty/phonon/ds9/mediagraph.cpp @@ -68,6 +68,8 @@ namespace Phonon return ret; } + +/* static HRESULT saveToFile(Graph graph, const QString &filepath) { const WCHAR wszStreamName[] = L"ActiveMovieGraph"; @@ -103,7 +105,7 @@ namespace Phonon return hr; } - +*/ MediaGraph::MediaGraph(MediaObject *mo, short index) : m_graph(CLSID_FilterGraph, IID_IGraphBuilder), @@ -377,11 +379,12 @@ namespace Phonon FILTER_INFO info; filter->QueryFilterInfo(&info); #ifdef GRAPH_DEBUG - qDebug() << "removeFilter" << QString::fromUtf16(info.achName); + qDebug() << "removeFilter" << QString((const QChar *)info.achName); #endif if (info.pGraph) { info.pGraph->Release(); - return m_graph->RemoveFilter(filter); + if (info.pGraph == m_graph) + return m_graph->RemoveFilter(filter); } //already removed @@ -537,11 +540,11 @@ namespace Phonon const QList outputs = BackendNode::pins(filter, PINDIR_OUTPUT); for(int i = 0; i < outputs.count(); ++i) { const OutputPin &pin = outputs.at(i); - if (VFW_E_NOT_CONNECTED == pin->ConnectedTo(inPin.pparam())) { + if (HRESULT(VFW_E_NOT_CONNECTED) == pin->ConnectedTo(inPin.pparam())) { return SUCCEEDED(pin->Connect(newIn, 0)); } } - //we should never go here + //we shoud never go here return false; } else { QAMMediaType type; @@ -679,7 +682,6 @@ namespace Phonon #ifndef QT_NO_PHONON_MEDIACONTROLLER } else if (source.discType() == Phonon::Cd) { m_realSource = Filter(new QAudioCDPlayer); - m_result = m_graph->AddFilter(m_realSource, 0); #endif //QT_NO_PHONON_MEDIACONTROLLER } else { @@ -809,7 +811,7 @@ namespace Phonon for (int i = 0; i < outputs.count(); ++i) { const OutputPin &out = outputs.at(i); InputPin pin; - if (out->ConnectedTo(pin.pparam()) == VFW_E_NOT_CONNECTED) { + if (out->ConnectedTo(pin.pparam()) == HRESULT(VFW_E_NOT_CONNECTED)) { m_decoderPins += out; //unconnected outputs can be decoded outputs } } @@ -820,7 +822,7 @@ namespace Phonon //let's reestablish the connections for (int i = 0; i < connections.count(); ++i) { const GraphConnection &connection = connections.at(i); - //check if we should transfer the sink node + //check if we shoud transfer the sink node grabFilter(connection.input); grabFilter(connection.output); @@ -873,7 +875,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName); + qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -919,7 +921,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << "found a decoder filter" << QString::fromUtf16(info.achName); + qDebug() << "found a decoder filter" << QString((const QChar *)info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -935,7 +937,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName); + qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -954,7 +956,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName); + qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -988,7 +990,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << "found a demuxer filter" << QString::fromUtf16(info.achName); + qDebug() << "found a demuxer filter" << QString((const QChar *)info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -1006,27 +1008,27 @@ namespace Phonon BSTR str; HRESULT hr = mediaContent->get_AuthorName(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("ARTIST"), QString::fromUtf16((const unsigned short*)str)); + ret.insert(QLatin1String("ARTIST"), QString::fromWCharArray(str)); SysFreeString(str); } hr = mediaContent->get_Title(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("TITLE"), QString::fromUtf16((const unsigned short*)str)); + ret.insert(QLatin1String("TITLE"), QString::fromWCharArray(str)); SysFreeString(str); } hr = mediaContent->get_Description(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("DESCRIPTION"), QString::fromUtf16((const unsigned short*)str)); + ret.insert(QLatin1String("DESCRIPTION"), QString::fromWCharArray(str)); SysFreeString(str); } hr = mediaContent->get_Copyright(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("COPYRIGHT"), QString::fromUtf16((const unsigned short*)str)); + ret.insert(QLatin1String("COPYRIGHT"), QString::fromWCharArray(str)); SysFreeString(str); } hr = mediaContent->get_MoreInfoText(&str); if (SUCCEEDED(hr)) { - ret.insert(QLatin1String("MOREINFO"), QString::fromUtf16((const unsigned short*)str)); + ret.insert(QLatin1String("MOREINFO"), QString::fromWCharArray(str)); SysFreeString(str); } } diff --git a/src/3rdparty/phonon/ds9/mediaobject.cpp b/src/3rdparty/phonon/ds9/mediaobject.cpp index d1e15c0..34f92c2 100644 --- a/src/3rdparty/phonon/ds9/mediaobject.cpp +++ b/src/3rdparty/phonon/ds9/mediaobject.cpp @@ -23,11 +23,10 @@ along with this library. If not, see . #ifndef Q_CC_MSVC #include -#endif //Q_CC_MSVC +#endif #include #include #include -#include #include #include "mediaobject.h" @@ -50,7 +49,7 @@ namespace Phonon //first the definition of the WorkerThread class WorkerThread::WorkerThread() - : QThread(), m_currentRenderId(0), m_finished(false), m_currentWorkId(1) + : QThread(), m_finished(false), m_currentWorkId(1) { } @@ -58,24 +57,6 @@ namespace Phonon { } - WorkerThread::Work WorkerThread::dequeueWork() - { - QMutexLocker locker(&m_mutex); - if (m_finished) { - return Work(); - } - Work ret = m_queue.dequeue(); - - //we ensure to have the wait condition in the right state - if (m_queue.isEmpty()) { - m_waitCondition.reset(); - } else { - m_waitCondition.set(); - } - - return ret; - } - void WorkerThread::run() { while (m_finished == false) { @@ -89,11 +70,6 @@ namespace Phonon } DWORD result = ::WaitForMultipleObjects(count, handles, FALSE, INFINITE); if (result == WAIT_OBJECT_0) { - if (m_finished) { - //that's the end of the thread execution - return; - } - handleTask(); } else { //this is the event management @@ -181,6 +157,7 @@ namespace Phonon //we create a new graph w.graph = Graph(CLSID_FilterGraph, IID_IGraphBuilder); w.filter = filter; + w.graph->AddFilter(filter, 0); w.id = m_currentWorkId++; m_queue.enqueue(w); m_waitCondition.set(); @@ -200,23 +177,29 @@ namespace Phonon void WorkerThread::handleTask() { - const Work w = dequeueWork(); + QMutexLocker locker(Backend::directShowMutex); + { + QMutexLocker locker(&m_mutex); + if (m_finished || m_queue.isEmpty()) { + return; + } - if (m_finished) { - return; + m_currentWork = m_queue.dequeue(); + + //we ensure to have the wait condition in the right state + if (m_queue.isEmpty()) { + m_waitCondition.reset(); + } else { + m_waitCondition.set(); + } } HRESULT hr = S_OK; - m_currentRender = w.graph; - m_currentRenderId = w.id; - if (w.task == ReplaceGraph) { - QMutexLocker locker(&m_mutex); - HANDLE h; - + if (m_currentWork.task == ReplaceGraph) { int index = -1; for(int i = 0; i < FILTER_COUNT; ++i) { - if (m_graphHandle[i].graph == w.oldGraph) { + if (m_graphHandle[i].graph == m_currentWork.oldGraph) { m_graphHandle[i].graph = Graph(); index = i; break; @@ -229,51 +212,40 @@ namespace Phonon Q_ASSERT(index != -1); //add the new graph - if (SUCCEEDED(ComPointer(w.graph, IID_IMediaEvent) + HANDLE h; + if (SUCCEEDED(ComPointer(m_currentWork.graph, IID_IMediaEvent) ->GetEventHandle(reinterpret_cast(&h)))) { - m_graphHandle[index].graph = w.graph; + m_graphHandle[index].graph = m_currentWork.graph; m_graphHandle[index].handle = h; } - } else if (w.task == Render) { - if (w.filter) { + } else if (m_currentWork.task == Render) { + if (m_currentWork.filter) { //let's render pins - w.graph->AddFilter(w.filter, 0); - const QList outputs = BackendNode::pins(w.filter, PINDIR_OUTPUT); - for (int i = 0; i < outputs.count(); ++i) { - //blocking call - hr = w.graph->Render(outputs.at(i)); - if (FAILED(hr)) { - break; - } + const QList outputs = BackendNode::pins(m_currentWork.filter, PINDIR_OUTPUT); + for (int i = 0; SUCCEEDED(hr) && i < outputs.count(); ++i) { + hr = m_currentWork.graph->Render(outputs.at(i)); } - } else if (!w.url.isEmpty()) { + } else if (!m_currentWork.url.isEmpty()) { //let's render a url (blocking call) - hr = w.graph->RenderFile(reinterpret_cast(w.url.utf16()), 0); + hr = m_currentWork.graph->RenderFile(reinterpret_cast(m_currentWork.url.utf16()), 0); } if (hr != E_ABORT) { - emit asyncRenderFinished(w.id, hr, w.graph); + emit asyncRenderFinished(m_currentWork.id, hr, m_currentWork.graph); } - } else if (w.task == Seek) { + } else if (m_currentWork.task == Seek) { //that's a seekrequest - ComPointer mediaSeeking(w.graph, IID_IMediaSeeking); - qint64 newtime = w.time * 10000; + ComPointer mediaSeeking(m_currentWork.graph, IID_IMediaSeeking); + qint64 newtime = m_currentWork.time * 10000; hr = mediaSeeking->SetPositions(&newtime, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); - qint64 currentTime = -1; - if (SUCCEEDED(hr)) { - hr = mediaSeeking->GetCurrentPosition(¤tTime); - if (SUCCEEDED(hr)) { - currentTime /= 10000; //convert to ms - } - } - emit asyncSeekingFinished(w.id, currentTime); + emit asyncSeekingFinished(m_currentWork.id, newtime / 10000); hr = E_ABORT; //to avoid emitting asyncRenderFinished - } else if (w.task == ChangeState) { + } else if (m_currentWork.task == ChangeState) { //remove useless decoders QList unused; - for (int i = 0; i < w.decoders.count(); ++i) { - const Filter &filter = w.decoders.at(i); + for (int i = 0; i < m_currentWork.decoders.count(); ++i) { + const Filter &filter = m_currentWork.decoders.at(i); bool used = false; const QList pins = BackendNode::pins(filter, PINDIR_OUTPUT); for( int i = 0; i < pins.count(); ++i) { @@ -290,15 +262,15 @@ namespace Phonon //we can get the state for (int i = 0; i < unused.count(); ++i) { //we should remove this filter from the graph - w.graph->RemoveFilter(unused.at(i)); + m_currentWork.graph->RemoveFilter(unused.at(i)); } //we can get the state - ComPointer mc(w.graph, IID_IMediaControl); + ComPointer mc(m_currentWork.graph, IID_IMediaControl); //we change the state here - switch(w.state) + switch(m_currentWork.state) { case State_Stopped: mc->Stop(); @@ -316,36 +288,38 @@ namespace Phonon if (SUCCEEDED(hr)) { if (s == State_Stopped) { - emit stateReady(w.graph, Phonon::StoppedState); + emit stateReady(m_currentWork.graph, Phonon::StoppedState); } else if (s == State_Paused) { - emit stateReady(w.graph, Phonon::PausedState); + emit stateReady(m_currentWork.graph, Phonon::PausedState); } else /*if (s == State_Running)*/ { - emit stateReady(w.graph, Phonon::PlayingState); + emit stateReady(m_currentWork.graph, Phonon::PlayingState); } } } - m_currentRender = Graph(); - m_currentRenderId = 0; - + { + QMutexLocker locker(&m_mutex); + m_currentWork = Work(); //reinitialize + } } - void WorkerThread::abortCurrentRender(qint16 renderId) - { + void WorkerThread::abortCurrentRender(qint16 renderId) + { QMutexLocker locker(&m_mutex); + if (m_currentWork.id == renderId) { + m_currentWork.graph->Abort(); + } bool found = false; - //we try to see if there is already an attempt to seek and we remove it for(int i = 0; !found && i < m_queue.size(); ++i) { const Work &w = m_queue.at(i); if (w.id == renderId) { found = true; m_queue.removeAt(i); + if (m_queue.isEmpty()) { + m_waitCondition.reset(); + } } } - - if (m_currentRender && m_currentRenderId == renderId) { - m_currentRender->Abort(); - } } //tells the thread to stop processing @@ -353,9 +327,9 @@ namespace Phonon { QMutexLocker locker(&m_mutex); m_queue.clear(); - if (m_currentRender) { + if (m_currentWork.graph) { //in case we're currently rendering something - m_currentRender->Abort(); + m_currentWork.graph->Abort(); } @@ -387,17 +361,17 @@ namespace Phonon m_graphs[i] = new MediaGraph(this, i); } - connect(&m_thread, SIGNAL(stateReady(Graph, Phonon::State)), - SLOT(slotStateReady(Graph, Phonon::State))); + connect(&m_thread, SIGNAL(stateReady(Graph,Phonon::State)), + SLOT(slotStateReady(Graph,Phonon::State))); - connect(&m_thread, SIGNAL(eventReady(Graph, long, long)), - SLOT(handleEvents(Graph, long, long))); + connect(&m_thread, SIGNAL(eventReady(Graph,long,long)), + SLOT(handleEvents(Graph,long,long))); - connect(&m_thread, SIGNAL(asyncRenderFinished(quint16, HRESULT, Graph)), - SLOT(finishLoading(quint16, HRESULT, Graph))); + connect(&m_thread, SIGNAL(asyncRenderFinished(quint16,HRESULT,Graph)), + SLOT(finishLoading(quint16,HRESULT,Graph))); - connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16, qint64)), - SLOT(finishSeeking(quint16, qint64))); + connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16,qint64)), + SLOT(finishSeeking(quint16,qint64))); //really special case m_mediaObject = this; m_thread.start(); @@ -520,6 +494,18 @@ namespace Phonon qSwap(m_graphs[0], m_graphs[1]); //swap the graphs + if (m_transitionTime >= 0) + m_graphs[1]->stop(); //make sure we stop the previous graph + + if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid && + catchComError(currentGraph()->renderResult())) { + setState(Phonon::ErrorState); + return; + } + + //we need to play the next media + play(); + //we tell the video widgets to switch now to the new source #ifndef QT_NO_PHONON_VIDEO for (int i = 0; i < m_videoWidgets.count(); ++i) { @@ -528,15 +514,6 @@ namespace Phonon #endif //QT_NO_PHONON_VIDEO emit currentSourceChanged(currentGraph()->mediaSource()); - - if (currentGraph()->isLoading()) { - //will simply tell that when loading is finished - //it should start the playback - play(); - } - - - emit metaDataChanged(currentGraph()->metadata()); if (nextGraph()->hasVideo() != currentGraph()->hasVideo()) { @@ -549,15 +526,6 @@ namespace Phonon #ifndef QT_NO_PHONON_MEDIACONTROLLER setTitles(currentGraph()->titles()); #endif //QT_NO_PHONON_MEDIACONTROLLER - - //this manages only gapless transitions - if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid) { - if (catchComError(currentGraph()->renderResult())) { - setState(Phonon::ErrorState); - } else { - play(); - } - } } Phonon::State MediaObject::state() const @@ -792,15 +760,16 @@ namespace Phonon case Phonon::PausedState: pause(); break; - case Phonon::StoppedState: - stop(); - break; case Phonon::PlayingState: play(); break; case Phonon::ErrorState: setState(Phonon::ErrorState); break; + case Phonon::StoppedState: + default: + stop(); + break; } } } @@ -848,11 +817,11 @@ namespace Phonon #endif LPAMGETERRORTEXT getErrorText = (LPAMGETERRORTEXT)QLibrary::resolve(QLatin1String("quartz"), "AMGetErrorTextW"); - ushort buffer[MAX_ERROR_TEXT_LEN]; - if (getErrorText && getErrorText(hr, (WCHAR*)buffer, MAX_ERROR_TEXT_LEN)) { - m_errorString = QString::fromUtf16(buffer); + WCHAR buffer[MAX_ERROR_TEXT_LEN]; + if (getErrorText && getErrorText(hr, buffer, MAX_ERROR_TEXT_LEN)) { + m_errorString = QString::fromWCharArray(buffer); } else { - m_errorString = QString::fromUtf16((ushort*)_com_error(hr).ErrorMessage()); + m_errorString = QString::fromLatin1("Unknown error"); } const QString comError = QString::number(uint(hr), 16); if (!m_errorString.toLower().contains(comError.toLower())) { diff --git a/src/3rdparty/phonon/ds9/mediaobject.h b/src/3rdparty/phonon/ds9/mediaobject.h index 2c34ffc..34aa666 100644 --- a/src/3rdparty/phonon/ds9/mediaobject.h +++ b/src/3rdparty/phonon/ds9/mediaobject.h @@ -114,6 +114,7 @@ namespace Phonon enum Task { + None, Render, Seek, ChangeState, @@ -122,6 +123,7 @@ namespace Phonon struct Work { + Work() : task(None), id(0), time(0) { } Task task; quint16 id; Graph graph; @@ -135,16 +137,14 @@ namespace Phonon }; QList decoders; //for the state change requests }; - Work dequeueWork(); void handleTask(); - Graph m_currentRender; - qint16 m_currentRenderId; + Work m_currentWork; QQueue m_queue; bool m_finished; quint16 m_currentWorkId; QWinWaitCondition m_waitCondition; - QMutex m_mutex; + QMutex m_mutex; // mutex for the m_queue, m_finished and m_currentWorkId //this is for WaitForMultipleObjects struct diff --git a/src/3rdparty/phonon/ds9/qasyncreader.cpp b/src/3rdparty/phonon/ds9/qasyncreader.cpp index 68ec1f8..a3f9cda 100644 --- a/src/3rdparty/phonon/ds9/qasyncreader.cpp +++ b/src/3rdparty/phonon/ds9/qasyncreader.cpp @@ -15,8 +15,6 @@ You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ -#include - #include "qasyncreader.h" #include "qbasefilter.h" @@ -80,8 +78,7 @@ namespace Phonon STDMETHODIMP QAsyncReader::Request(IMediaSample *sample,DWORD_PTR user) { - QMutexLocker mutexLocker(&m_mutexWait); - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (m_flushing) { return VFW_E_WRONG_STATE; } @@ -93,33 +90,28 @@ namespace Phonon STDMETHODIMP QAsyncReader::WaitForNext(DWORD timeout, IMediaSample **sample, DWORD_PTR *user) { - QMutexLocker locker(&m_mutexWait); + QMutexLocker locker(&m_mutex); if (!sample ||!user) { return E_POINTER; } + //msdn says to return immediately if we're flushing but that doesn't seem to be true + //since it triggers a dead-lock somewhere inside directshow (see task 258830) + *sample = 0; *user = 0; - AsyncRequest r = getNextRequest(); - - if (r.sample == 0) { - //there is no request in the queue - if (isFlushing()) { + if (m_requestQueue.isEmpty()) { + if (m_requestWait.wait(&m_mutex, timeout) == false) { + return VFW_E_TIMEOUT; + } + if (m_requestQueue.isEmpty()) { return VFW_E_WRONG_STATE; - } else { - //First we need to lock the mutex - if (m_requestWait.wait(&m_mutexWait, timeout) == false) { - return VFW_E_TIMEOUT; - } - if (isFlushing()) { - return VFW_E_WRONG_STATE; - } - - r = getNextRequest(); } } + AsyncRequest r = m_requestQueue.dequeue(); + //at this point we're sure to have a request to proceed if (r.sample == 0) { return E_FAIL; @@ -127,14 +119,12 @@ namespace Phonon *sample = r.sample; *user = r.user; - - return SyncReadAligned(r.sample); + return syncReadAlignedUnlocked(r.sample); } STDMETHODIMP QAsyncReader::BeginFlush() { - QMutexLocker mutexLocker(&m_mutexWait); - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_flushing = true; m_requestWait.wakeOne(); return S_OK; @@ -142,13 +132,28 @@ namespace Phonon STDMETHODIMP QAsyncReader::EndFlush() { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_flushing = false; return S_OK; } STDMETHODIMP QAsyncReader::SyncReadAligned(IMediaSample *sample) { + QMutexLocker locker(&m_mutex); + return syncReadAlignedUnlocked(sample); + } + + STDMETHODIMP QAsyncReader::SyncRead(LONGLONG pos, LONG length, BYTE *buffer) + { + QMutexLocker locker(&m_mutex); + return read(pos, length, buffer, 0); + } + + + STDMETHODIMP QAsyncReader::syncReadAlignedUnlocked(IMediaSample *sample) + { + Q_ASSERT(!m_mutex.tryLock()); + if (!sample) { return E_POINTER; } @@ -175,23 +180,6 @@ namespace Phonon return sample->SetActualDataLength(actual); } - STDMETHODIMP QAsyncReader::SyncRead(LONGLONG pos, LONG length, BYTE *buffer) - { - return read(pos, length, buffer, 0); - } - - - //addition - QAsyncReader::AsyncRequest QAsyncReader::getNextRequest() - { - QWriteLocker locker(&m_lock); - AsyncRequest ret; - if (!m_requestQueue.isEmpty()) { - ret = m_requestQueue.dequeue(); - } - - return ret; - } } } diff --git a/src/3rdparty/phonon/ds9/qasyncreader.h b/src/3rdparty/phonon/ds9/qasyncreader.h index cb789ee..95872f9 100644 --- a/src/3rdparty/phonon/ds9/qasyncreader.h +++ b/src/3rdparty/phonon/ds9/qasyncreader.h @@ -48,11 +48,12 @@ namespace Phonon STDMETHODIMP WaitForNext(DWORD,IMediaSample **,DWORD_PTR *); STDMETHODIMP SyncReadAligned(IMediaSample *); STDMETHODIMP SyncRead(LONGLONG,LONG,BYTE *); - virtual STDMETHODIMP Length(LONGLONG *,LONGLONG *) = 0; + STDMETHODIMP Length(LONGLONG *,LONGLONG *) = 0; STDMETHODIMP BeginFlush(); STDMETHODIMP EndFlush(); protected: + STDMETHODIMP syncReadAlignedUnlocked(IMediaSample *); virtual HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual) = 0; private: @@ -62,9 +63,6 @@ namespace Phonon IMediaSample *sample; DWORD_PTR user; }; - AsyncRequest getNextRequest(); - - QMutex m_mutexWait; QQueue m_requestQueue; QWaitCondition m_requestWait; diff --git a/src/3rdparty/phonon/ds9/qaudiocdreader.cpp b/src/3rdparty/phonon/ds9/qaudiocdreader.cpp index b9f9fd6..6d0f335 100644 --- a/src/3rdparty/phonon/ds9/qaudiocdreader.cpp +++ b/src/3rdparty/phonon/ds9/qaudiocdreader.cpp @@ -103,8 +103,8 @@ namespace Phonon private: HANDLE m_cddrive; - CDROM_TOC *m_toc; - WaveStructure *m_waveHeader; + CDROM_TOC m_toc; + WaveStructure m_waveHeader; qint64 m_trackAddress; }; @@ -112,19 +112,8 @@ namespace Phonon #define SECTOR_SIZE 2352 #define NB_SECTORS_READ 20 - static AM_MEDIA_TYPE getAudioCDMediaType() - { - AM_MEDIA_TYPE mt; - qMemSet(&mt, 0, sizeof(AM_MEDIA_TYPE)); - mt.majortype = MEDIATYPE_Stream; - mt.subtype = MEDIASUBTYPE_WAVE; - mt.bFixedSizeSamples = TRUE; - mt.bTemporalCompression = FALSE; - mt.lSampleSize = 1; - mt.formattype = GUID_NULL; - return mt; - } - + static const AM_MEDIA_TYPE audioCDMediaType = { MEDIATYPE_Stream, MEDIASUBTYPE_WAVE, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0}; + int addressToSectors(UCHAR address[4]) { return ((address[0] * 60 + address[1]) * 60 + address[2]) * 75 + address[3] - 150; @@ -141,11 +130,8 @@ namespace Phonon } - QAudioCDReader::QAudioCDReader(QBaseFilter *parent, QChar drive) : QAsyncReader(parent, QVector() << getAudioCDMediaType()) + QAudioCDReader::QAudioCDReader(QBaseFilter *parent, QChar drive) : QAsyncReader(parent, QVector() << audioCDMediaType) { - m_toc = new CDROM_TOC; - m_waveHeader = new WaveStructure; - //now open the cd-drive QString path; if (drive.isNull()) { @@ -154,36 +140,30 @@ namespace Phonon path = QString::fromLatin1("\\\\.\\%1:").arg(drive); } - m_cddrive = QT_WA_INLINE ( - ::CreateFile( (TCHAR*)path.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ), - ::CreateFileA( path.toLocal8Bit().constData(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ) - ); + m_cddrive = ::CreateFile((const wchar_t *)path.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - qMemSet(m_toc, 0, sizeof(CDROM_TOC)); + qMemSet(&m_toc, 0, sizeof(CDROM_TOC)); //read the TOC DWORD bytesRead = 0; - bool tocRead = ::DeviceIoControl(m_cddrive, IOCTL_CDROM_READ_TOC, 0, 0, m_toc, sizeof(CDROM_TOC), &bytesRead, 0); + bool tocRead = ::DeviceIoControl(m_cddrive, IOCTL_CDROM_READ_TOC, 0, 0, &m_toc, sizeof(CDROM_TOC), &bytesRead, 0); if (!tocRead) { qWarning("unable to load the TOC from the CD"); return; } - m_trackAddress = addressToSectors(m_toc->TrackData[0].Address); - const qint32 nbSectorsToRead = (addressToSectors(m_toc->TrackData[m_toc->LastTrack + 1 - m_toc->FirstTrack].Address) + m_trackAddress = addressToSectors(m_toc.TrackData[0].Address); + const qint32 nbSectorsToRead = (addressToSectors(m_toc.TrackData[m_toc.LastTrack + 1 - m_toc.FirstTrack].Address) - m_trackAddress); const qint32 dataLength = nbSectorsToRead * SECTOR_SIZE; - m_waveHeader->chunksize = 4 + (8 + m_waveHeader->chunksize2) + (8 + dataLength); - m_waveHeader->dataLength = dataLength; + m_waveHeader.chunksize = 4 + (8 + m_waveHeader.chunksize2) + (8 + dataLength); + m_waveHeader.dataLength = dataLength; } QAudioCDReader::~QAudioCDReader() { ::CloseHandle(m_cddrive); - delete m_toc; - delete m_waveHeader; - } STDMETHODIMP_(ULONG) QAudioCDReader::AddRef() @@ -199,7 +179,7 @@ namespace Phonon STDMETHODIMP QAudioCDReader::Length(LONGLONG *total,LONGLONG *available) { - const LONGLONG length = sizeof(WaveStructure) + m_waveHeader->dataLength; + const LONGLONG length = sizeof(WaveStructure) + m_waveHeader.dataLength; if (total) { *total = length; } @@ -238,11 +218,11 @@ namespace Phonon if (pos < sizeof(WaveStructure)) { //we first copy the content of the structure nbRead = qMin(LONG(sizeof(WaveStructure) - pos), length); - qMemCopy(buffer, reinterpret_cast(m_waveHeader) + pos, nbRead); + qMemCopy(buffer, reinterpret_cast(&m_waveHeader) + pos, nbRead); } const LONGLONG posInTrack = pos - sizeof(WaveStructure) + nbRead; - const int bytesLeft = qMin(m_waveHeader->dataLength - posInTrack, LONGLONG(length - nbRead)); + const int bytesLeft = qMin(m_waveHeader.dataLength - posInTrack, LONGLONG(length - nbRead)); if (bytesLeft > 0) { @@ -297,8 +277,8 @@ namespace Phonon { QList ret; ret << 0; - for(int i = m_toc->FirstTrack; i <= m_toc->LastTrack ; ++i) { - const uchar *address = m_toc->TrackData[i].Address; + for(int i = m_toc.FirstTrack; i <= m_toc.LastTrack ; ++i) { + const uchar *address = m_toc.TrackData[i].Address; ret << ((address[0] * 60 + address[1]) * 60 + address[2]) * 1000 + address[3]*1000/75 - 2000; } diff --git a/src/3rdparty/phonon/ds9/qaudiocdreader.h b/src/3rdparty/phonon/ds9/qaudiocdreader.h index 9049b66..eff845d 100644 --- a/src/3rdparty/phonon/ds9/qaudiocdreader.h +++ b/src/3rdparty/phonon/ds9/qaudiocdreader.h @@ -31,7 +31,7 @@ namespace Phonon { struct CDROM_TOC; struct WaveStructure; - extern const IID IID_ITitleInterface; + EXTERN_C const IID IID_ITitleInterface; //interface for the Titles struct ITitleInterface : public IUnknown diff --git a/src/3rdparty/phonon/ds9/qbasefilter.cpp b/src/3rdparty/phonon/ds9/qbasefilter.cpp index 95cab92..78b8b8f 100644 --- a/src/3rdparty/phonon/ds9/qbasefilter.cpp +++ b/src/3rdparty/phonon/ds9/qbasefilter.cpp @@ -92,8 +92,8 @@ namespace Phonon return E_POINTER; } - int nbfetched = 0; - while (nbfetched < int(count) && m_index < m_pins.count()) { + uint nbfetched = 0; + while (nbfetched < count && m_index < m_pins.count()) { IPin *current = m_pins[m_index]; current->AddRef(); ret[nbfetched] = current; @@ -166,19 +166,19 @@ namespace Phonon const QList QBaseFilter::pins() const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); return m_pins; } void QBaseFilter::addPin(QPin *pin) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_pins.append(pin); } void QBaseFilter::removePin(QPin *pin) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_pins.removeAll(pin); } @@ -211,7 +211,8 @@ namespace Phonon } else if (iid == IID_IMediaPosition || iid == IID_IMediaSeeking) { if (inputPins().isEmpty()) { - if (*out = getUpStreamInterface(iid)) { + *out = getUpStreamInterface(iid); + if (*out) { return S_OK; //we return here to avoid adding a reference } else { hr = E_NOINTERFACE; @@ -250,35 +251,35 @@ namespace Phonon STDMETHODIMP QBaseFilter::GetClassID(CLSID *clsid) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); *clsid = m_clsid; return S_OK; } STDMETHODIMP QBaseFilter::Stop() { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_state = State_Stopped; return S_OK; } STDMETHODIMP QBaseFilter::Pause() { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_state = State_Paused; return S_OK; } STDMETHODIMP QBaseFilter::Run(REFERENCE_TIME) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_state = State_Running; return S_OK; } STDMETHODIMP QBaseFilter::GetState(DWORD, FILTER_STATE *state) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (!state) { return E_POINTER; } @@ -289,7 +290,7 @@ namespace Phonon STDMETHODIMP QBaseFilter::SetSyncSource(IReferenceClock *clock) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (clock) { clock->AddRef(); } @@ -302,7 +303,7 @@ namespace Phonon STDMETHODIMP QBaseFilter::GetSyncSource(IReferenceClock **clock) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (!clock) { return E_POINTER; } @@ -341,7 +342,7 @@ namespace Phonon STDMETHODIMP QBaseFilter::QueryFilterInfo(FILTER_INFO *info ) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (!info) { return E_POINTER; } @@ -355,9 +356,9 @@ namespace Phonon STDMETHODIMP QBaseFilter::JoinFilterGraph(IFilterGraph *graph, LPCWSTR name) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_graph = graph; - m_name = QString::fromUtf16((const unsigned short*)name); + m_name = QString::fromWCharArray(name); return S_OK; } diff --git a/src/3rdparty/phonon/ds9/qbasefilter.h b/src/3rdparty/phonon/ds9/qbasefilter.h index 85f1431..a72d6fe 100644 --- a/src/3rdparty/phonon/ds9/qbasefilter.h +++ b/src/3rdparty/phonon/ds9/qbasefilter.h @@ -22,7 +22,7 @@ along with this library. If not, see . #include #include -#include +#include #include @@ -127,7 +127,7 @@ namespace Phonon IFilterGraph *m_graph; FILTER_STATE m_state; QList m_pins; - mutable QReadWriteLock m_lock; + mutable QMutex m_mutex; }; } } diff --git a/src/3rdparty/phonon/ds9/qevr9.h b/src/3rdparty/phonon/ds9/qevr9.h new file mode 100644 index 0000000..8599fce --- /dev/null +++ b/src/3rdparty/phonon/ds9/qevr9.h @@ -0,0 +1,143 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see . +*/ + +#include + +#define DXVA2_ProcAmp_Brightness 1 +#define DXVA2_ProcAmp_Contrast 2 +#define DXVA2_ProcAmp_Hue 4 +#define DXVA2_ProcAmp_Saturation 8 + +typedef enum { + MFVideoARMode_None = 0x00000000, + MFVideoARMode_PreservePicture = 0x00000001, + MFVideoARMode_PreservePixel = 0x00000002, + MFVideoARMode_NonLinearStretch = 0x00000004, + MFVideoARMode_Mask = 0x00000007 +} MFVideoAspectRatioMode; + +typedef struct { + float left; + float top; + float right; + float bottom; +} MFVideoNormalizedRect; + +typedef struct { + UINT DeviceCaps; + D3DPOOL InputPool; + UINT NumForwardRefSamples; + UINT NumBackwardRefSamples; + UINT Reserved; + UINT DeinterlaceTechnology; + UINT ProcAmpControlCaps; + UINT VideoProcessorOperations; + UINT NoiseFilterTechnology; + UINT DetailFilterTechnology; +} DXVA2_VideoProcessorCaps; + +typedef struct { + union { + struct { + USHORT Fraction; + SHORT Value; + }; + LONG ll; + }; +} DXVA2_Fixed32; + +typedef struct { + DXVA2_Fixed32 MinValue; + DXVA2_Fixed32 MaxValue; + DXVA2_Fixed32 DefaultValue; + DXVA2_Fixed32 StepSize; +} DXVA2_ValueRange; + +typedef struct { + DXVA2_Fixed32 Brightness; + DXVA2_Fixed32 Contrast; + DXVA2_Fixed32 Hue; + DXVA2_Fixed32 Saturation; +} DXVA2_ProcAmpValues; + +DXVA2_Fixed32 DXVA2FloatToFixed(const float _float_) +{ + DXVA2_Fixed32 _fixed_; + _fixed_.Fraction = LOWORD(_float_ * 0x10000); + _fixed_.Value = HIWORD(_float_ * 0x10000); + return _fixed_; +} + +float DXVA2FixedToFloat(const DXVA2_Fixed32 _fixed_) +{ + return (FLOAT)_fixed_.Value + (FLOAT)_fixed_.Fraction / 0x10000; +} + +#undef INTERFACE +#define INTERFACE IMFVideoDisplayControl +DECLARE_INTERFACE_(IMFVideoDisplayControl, IUnknown) +{ + STDMETHOD(GetNativeVideoSize)(THIS_ SIZE* pszVideo, SIZE* pszARVideo) PURE; + STDMETHOD(GetIdealVideoSize)(THIS_ SIZE* pszMin, SIZE* pszMax) PURE; + STDMETHOD(SetVideoPosition)(THIS_ const MFVideoNormalizedRect* pnrcSource, const LPRECT prcDest) PURE; + STDMETHOD(GetVideoPosition)(THIS_ MFVideoNormalizedRect* pnrcSource, LPRECT prcDest) PURE; + STDMETHOD(SetAspectRatioMode)(THIS_ DWORD dwAspectRatioMode) PURE; + STDMETHOD(GetAspectRatioMode)(THIS_ DWORD* pdwAspectRatioMode) PURE; + STDMETHOD(SetVideoWindow)(THIS_ HWND hwndVideo) PURE; + STDMETHOD(GetVideoWindow)(THIS_ HWND* phwndVideo) PURE; + STDMETHOD(RepaintVideo)(THIS_) PURE; + STDMETHOD(GetCurrentImage)(THIS_ BITMAPINFOHEADER* pBih, BYTE** pDib, DWORD* pcbDib, LONGLONG* pTimeStamp) PURE; + STDMETHOD(SetBorderColor)(THIS_ COLORREF Clr) PURE; + STDMETHOD(GetBorderColor)(THIS_ COLORREF* pClr) PURE; + STDMETHOD(SetRenderingPrefs)(THIS_ DWORD dwRenderFlags) PURE; + STDMETHOD(GetRenderingPrefs)(THIS_ DWORD* pdwRenderFlags) PURE; + STDMETHOD(SetFullScreen)(THIS_ BOOL fFullscreen) PURE; + STDMETHOD(GetFullScreen)(THIS_ BOOL* pfFullscreen) PURE; +}; +#undef INTERFACE +#define INTERFACE IMFVideoMixerControl +DECLARE_INTERFACE_(IMFVideoMixerControl, IUnknown) +{ + STDMETHOD(SetStreamZOrder)(THIS_ DWORD dwStreamID, DWORD dwZ) PURE; + STDMETHOD(GetStreamZOrder)(THIS_ DWORD dwStreamID, DWORD* pdwZ) PURE; + STDMETHOD(SetStreamOutputRect)(THIS_ DWORD dwStreamID, const MFVideoNormalizedRect* pnrcOutput) PURE; + STDMETHOD(GetStreamOutputRect)(THIS_ DWORD dwStreamID, MFVideoNormalizedRect* pnrcOutput) PURE; +}; +#undef INTERFACE +#define INTERFACE IMFVideoProcessor +DECLARE_INTERFACE_(IMFVideoProcessor, IUnknown) +{ + STDMETHOD(GetAvailableVideoProcessorModes)(THIS_ UINT* lpdwNumProcessingModes, GUID** ppVideoProcessingModes) PURE; + STDMETHOD(GetVideoProcessorCaps)(THIS_ LPGUID lpVideoProcessorMode, DXVA2_VideoProcessorCaps* lpVideoProcessorCaps) PURE; + STDMETHOD(GetVideoProcessorMode)(THIS_ LPGUID lpMode) PURE; + STDMETHOD(SetVideoProcessorMode)(THIS_ LPGUID lpMode) PURE; + STDMETHOD(GetProcAmpRange)(THIS_ DWORD dwProperty, DXVA2_ValueRange* pPropRange) PURE; + STDMETHOD(GetProcAmpValues)(THIS_ DWORD dwFlags, DXVA2_ProcAmpValues* Values) PURE; + STDMETHOD(SetProcAmpValues)(THIS_ DWORD dwFlags, DXVA2_ProcAmpValues* pValues) PURE; + STDMETHOD(GetFilteringRange)(THIS_ DWORD dwProperty, DXVA2_ValueRange* pPropRange) PURE; + STDMETHOD(GetFilteringValue)(THIS_ DWORD dwProperty, DXVA2_Fixed32* pValue) PURE; + STDMETHOD(SetFilteringValue)(THIS_ DWORD dwProperty, DXVA2_Fixed32* pValue) PURE; + STDMETHOD(GetBackgroundColor)(THIS_ COLORREF* lpClrBkg) PURE; + STDMETHOD(SetBackgroundColor)(THIS_ COLORREF ClrBkg) PURE; +}; +#undef INTERFACE +#define INTERFACE IMFGetService +DECLARE_INTERFACE_(IMFGetService, IUnknown) +{ + STDMETHOD(GetService)(THIS_ REFGUID guidService, REFIID riid, LPVOID* ppvObject) PURE; +}; +#undef INTERFACE diff --git a/src/3rdparty/phonon/ds9/qmeminputpin.cpp b/src/3rdparty/phonon/ds9/qmeminputpin.cpp index dca99db..a21fbe7 100644 --- a/src/3rdparty/phonon/ds9/qmeminputpin.cpp +++ b/src/3rdparty/phonon/ds9/qmeminputpin.cpp @@ -28,8 +28,8 @@ namespace Phonon namespace DS9 { - QMemInputPin::QMemInputPin(QBaseFilter *parent, const QVector &mt, bool transform) : - QPin(parent, PINDIR_INPUT, mt), m_shouldDuplicateSamples(true), m_transform(transform) + QMemInputPin::QMemInputPin(QBaseFilter *parent, const QVector &mt, bool transform, QPin *output) : + QPin(parent, PINDIR_INPUT, mt), m_shouldDuplicateSamples(true), m_transform(transform), m_output(output) { } @@ -66,11 +66,9 @@ namespace Phonon { //this allows to serialize with Receive calls QMutexLocker locker(&m_mutexReceive); - for(int i = 0; i < m_outputs.count(); ++i) { - IPin *conn = m_outputs.at(i)->connected(); - if (conn) { - conn->EndOfStream(); - } + IPin *conn = m_output ? m_output->connected() : 0; + if (conn) { + conn->EndOfStream(); } return S_OK; } @@ -78,13 +76,11 @@ namespace Phonon STDMETHODIMP QMemInputPin::BeginFlush() { //pass downstream - for(int i = 0; i < m_outputs.count(); ++i) { - IPin *conn = m_outputs.at(i)->connected(); - if (conn) { - conn->BeginFlush(); - } + IPin *conn = m_output ? m_output->connected() : 0; + if (conn) { + conn->BeginFlush(); } - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_flushing = true; return S_OK; } @@ -92,22 +88,19 @@ namespace Phonon STDMETHODIMP QMemInputPin::EndFlush() { //pass downstream - for(int i = 0; i < m_outputs.count(); ++i) { - IPin *conn = m_outputs.at(i)->connected(); - if (conn) { - conn->EndFlush(); - } + IPin *conn = m_output ? m_output->connected() : 0; + if (conn) { + conn->EndFlush(); } - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_flushing = false; return S_OK; } STDMETHODIMP QMemInputPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate) { - for(int i = 0; i < m_outputs.count(); ++i) { - m_outputs.at(i)->NewSegment(start, stop, rate); - } + if (m_output) + m_output->NewSegment(start, stop, rate); return S_OK; } @@ -119,14 +112,9 @@ namespace Phonon if (hr == S_OK && mt->majortype != MEDIATYPE_NULL && mt->subtype != MEDIASUBTYPE_NULL && - mt->formattype != GUID_NULL) { - //we tell the output pins that they should connect with this type - for(int i = 0; i < m_outputs.count(); ++i) { - hr = m_outputs.at(i)->setAcceptedMediaType(connectedType()); - if (FAILED(hr)) { - break; - } - } + mt->formattype != GUID_NULL && m_output) { + //we tell the output pin that it should connect with this type + hr = m_output->setAcceptedMediaType(connectedType()); } return hr; } @@ -137,7 +125,8 @@ namespace Phonon return E_POINTER; } - if (*alloc = memoryAllocator(true)) { + *alloc = memoryAllocator(true); + if (*alloc) { return S_OK; } @@ -151,18 +140,15 @@ namespace Phonon } { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); m_shouldDuplicateSamples = m_transform && readonly; } setMemoryAllocator(alloc); - for(int i = 0; i < m_outputs.count(); ++i) { - IPin *pin = m_outputs.at(i)->connected(); - if (pin) { - ComPointer input(pin, IID_IMemInputPin); - input->NotifyAllocator(alloc, m_shouldDuplicateSamples); - } + if (m_output) { + ComPointer input(m_output, IID_IMemInputPin); + input->NotifyAllocator(alloc, m_shouldDuplicateSamples); } return S_OK; @@ -201,22 +187,18 @@ namespace Phonon } } - for (int i = 0; i < m_outputs.count(); ++i) { - QPin *current = m_outputs.at(i); + if (m_output) { IMediaSample *outSample = m_shouldDuplicateSamples ? - duplicateSampleForOutput(sample, current->memoryAllocator()) + duplicateSampleForOutput(sample, m_output->memoryAllocator()) : sample; if (m_shouldDuplicateSamples) { m_parent->processSample(outSample); } - IPin *pin = current->connected(); - if (pin) { - ComPointer input(pin, IID_IMemInputPin); - if (input) { - input->Receive(outSample); - } + ComPointer input(m_output->connected(), IID_IMemInputPin); + if (input) { + input->Receive(outSample); } if (m_shouldDuplicateSamples) { @@ -247,39 +229,16 @@ namespace Phonon STDMETHODIMP QMemInputPin::ReceiveCanBlock() { - //we test the output to see if they can block - for(int i = 0; i < m_outputs.count(); ++i) { - IPin *input = m_outputs.at(i)->connected(); - if (input) { - ComPointer meminput(input, IID_IMemInputPin); - if (meminput && meminput->ReceiveCanBlock() != S_FALSE) { - return S_OK; - } + //we test the output to see if it can block + if (m_output) { + ComPointer meminput(m_output->connected(), IID_IMemInputPin); + if (meminput && meminput->ReceiveCanBlock() != S_FALSE) { + return S_OK; } } return S_FALSE; } - //addition - //this should be used by the filter to tell its input pins to which output they should route the samples - - void QMemInputPin::addOutput(QPin *output) - { - QWriteLocker locker(&m_lock); - m_outputs += output; - } - - void QMemInputPin::removeOutput(QPin *output) - { - QWriteLocker locker(&m_lock); - m_outputs.removeOne(output); - } - - QList QMemInputPin::outputs() const - { - QReadLocker locker(&m_lock); - return m_outputs; - } ALLOCATOR_PROPERTIES QMemInputPin::getDefaultAllocatorProperties() const { @@ -294,7 +253,7 @@ namespace Phonon LONG length = sample->GetActualDataLength(); HRESULT hr = alloc->Commit(); - if (hr == VFW_E_SIZENOTSET) { + if (hr == HRESULT(VFW_E_SIZENOTSET)) { ALLOCATOR_PROPERTIES prop = getDefaultAllocatorProperties(); prop.cbBuffer = qMax(prop.cbBuffer, length); ALLOCATOR_PROPERTIES actual; @@ -324,7 +283,7 @@ namespace Phonon { LONGLONG start, end; hr = sample->GetMediaTime(&start, &end); - if (hr != VFW_E_MEDIA_TIME_NOT_SET) { + if (hr != HRESULT(VFW_E_MEDIA_TIME_NOT_SET)) { hr = out->SetMediaTime(&start, &end); Q_ASSERT(SUCCEEDED(hr)); } diff --git a/src/3rdparty/phonon/ds9/qmeminputpin.h b/src/3rdparty/phonon/ds9/qmeminputpin.h index c449721..d74c451 100644 --- a/src/3rdparty/phonon/ds9/qmeminputpin.h +++ b/src/3rdparty/phonon/ds9/qmeminputpin.h @@ -37,7 +37,7 @@ namespace Phonon class QMemInputPin : public QPin, public IMemInputPin { public: - QMemInputPin(QBaseFilter *, const QVector &, bool transform); + QMemInputPin(QBaseFilter *, const QVector &, bool transform, QPin *output); ~QMemInputPin(); //reimplementation from IUnknown @@ -60,18 +60,13 @@ namespace Phonon STDMETHODIMP ReceiveMultiple(IMediaSample **,long,long *); STDMETHODIMP ReceiveCanBlock(); - //addition - void addOutput(QPin *output); - void removeOutput(QPin *output); - QList outputs() const; - private: IMediaSample *duplicateSampleForOutput(IMediaSample *, IMemAllocator *); ALLOCATOR_PROPERTIES getDefaultAllocatorProperties() const; bool m_shouldDuplicateSamples; const bool m_transform; //defines if the pin is transforming the samples - QList m_outputs; + QPin* const m_output; QMutex m_mutexReceive; }; } diff --git a/src/3rdparty/phonon/ds9/qpin.cpp b/src/3rdparty/phonon/ds9/qpin.cpp index 37fe48d..b4afd10 100644 --- a/src/3rdparty/phonon/ds9/qpin.cpp +++ b/src/3rdparty/phonon/ds9/qpin.cpp @@ -28,20 +28,7 @@ namespace Phonon namespace DS9 { - static const AM_MEDIA_TYPE defaultMediaType() - { - AM_MEDIA_TYPE ret; - ret.majortype = MEDIATYPE_NULL; - ret.subtype = MEDIASUBTYPE_NULL; - ret.bFixedSizeSamples = TRUE; - ret.bTemporalCompression = FALSE; - ret.lSampleSize = 1; - ret.formattype = GUID_NULL; - ret.pUnk = 0; - ret.cbFormat = 0; - ret.pbFormat = 0; - return ret; - } + static const AM_MEDIA_TYPE defaultMediaType = { MEDIATYPE_NULL, MEDIASUBTYPE_NULL, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0}; class QEnumMediaTypes : public IEnumMediaTypes { @@ -104,8 +91,8 @@ namespace Phonon return E_INVALIDARG; } - int nbFetched = 0; - while (nbFetched < int(count) && m_index < m_pin->mediaTypes().count()) { + uint nbFetched = 0; + while (nbFetched < count && m_index < m_pin->mediaTypes().count()) { //the caller will deallocate the memory *out = static_cast(::CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))); const AM_MEDIA_TYPE original = m_pin->mediaTypes().at(m_index); @@ -158,9 +145,9 @@ namespace Phonon QPin::QPin(QBaseFilter *parent, PIN_DIRECTION dir, const QVector &mt) : - m_memAlloc(0), m_parent(parent), m_refCount(1), m_connected(0), - m_direction(dir), m_mediaTypes(mt), m_connectedType(defaultMediaType()), - m_flushing(false) + m_parent(parent), m_flushing(false), m_refCount(1), m_connected(0), + m_direction(dir), m_mediaTypes(mt), m_connectedType(defaultMediaType), + m_memAlloc(0) { Q_ASSERT(m_parent); m_parent->addPin(this); @@ -273,7 +260,7 @@ namespace Phonon if (FAILED(hr)) { setConnected(0); - setConnectedType(defaultMediaType()); + setConnectedType(defaultMediaType); } else { ComPointer input(pin, IID_IMemInputPin); if (input) { @@ -315,10 +302,8 @@ namespace Phonon } setConnected(0); - setConnectedType(defaultMediaType()); - if (m_direction == PINDIR_INPUT) { - setMemoryAllocator(0); - } + setConnectedType(defaultMediaType); + setMemoryAllocator(0); return S_OK; } @@ -338,7 +323,7 @@ namespace Phonon STDMETHODIMP QPin::ConnectionMediaType(AM_MEDIA_TYPE *type) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (!type) { return E_POINTER; } @@ -353,7 +338,6 @@ namespace Phonon STDMETHODIMP QPin::QueryPinInfo(PIN_INFO *info) { - QReadLocker locker(&m_lock); if (!info) { return E_POINTER; } @@ -361,14 +345,12 @@ namespace Phonon info->dir = m_direction; info->pFilter = m_parent; m_parent->AddRef(); - qMemCopy(info->achName, m_name.utf16(), qMin(MAX_FILTER_NAME, m_name.length()+1) *2); - + info->achName[0] = 0; return S_OK; } STDMETHODIMP QPin::QueryDirection(PIN_DIRECTION *dir) { - QReadLocker locker(&m_lock); if (!dir) { return E_POINTER; } @@ -379,20 +361,18 @@ namespace Phonon STDMETHODIMP QPin::QueryId(LPWSTR *id) { - QReadLocker locker(&m_lock); if (!id) { return E_POINTER; } - int nbBytes = (m_name.length()+1)*2; - *id = static_cast(::CoTaskMemAlloc(nbBytes)); - qMemCopy(*id, m_name.utf16(), nbBytes); + *id = static_cast(::CoTaskMemAlloc(2)); + *id[0] = 0; return S_OK; } STDMETHODIMP QPin::QueryAccept(const AM_MEDIA_TYPE *type) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (!type) { return E_POINTER; } @@ -439,7 +419,7 @@ namespace Phonon STDMETHODIMP QPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate) { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (m_direction == PINDIR_OUTPUT && m_connected) { //we deliver this downstream m_connected->NewSegment(start, stop, rate); @@ -456,8 +436,8 @@ namespace Phonon HRESULT QPin::checkOutputMediaTypesConnection(IPin *pin) { - IEnumMediaTypes *emt = 0; - HRESULT hr = pin->EnumMediaTypes(&emt); + ComPointer emt; + HRESULT hr = pin->EnumMediaTypes(emt.pparam()); if (hr != S_OK) { return hr; } @@ -470,7 +450,7 @@ namespace Phonon freeMediaType(type); return S_OK; } else { - setConnectedType(defaultMediaType()); + setConnectedType(defaultMediaType); freeMediaType(type); } } @@ -520,7 +500,7 @@ namespace Phonon void QPin::setConnectedType(const AM_MEDIA_TYPE &type) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); //1st we free memory freeMediaType(m_connectedType); @@ -530,13 +510,13 @@ namespace Phonon const AM_MEDIA_TYPE &QPin::connectedType() const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); return m_connectedType; } void QPin::setConnected(IPin *pin) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (pin) { pin->AddRef(); } @@ -548,7 +528,7 @@ namespace Phonon IPin *QPin::connected(bool addref) const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (addref && m_connected) { m_connected->AddRef(); } @@ -557,13 +537,12 @@ namespace Phonon bool QPin::isFlushing() const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); return m_flushing; } FILTER_STATE QPin::filterState() const { - QReadLocker locker(&m_lock); FILTER_STATE fstate = State_Stopped; m_parent->GetState(0, &fstate); return fstate; @@ -571,7 +550,7 @@ namespace Phonon QVector QPin::mediaTypes() const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); return m_mediaTypes; } @@ -607,7 +586,7 @@ namespace Phonon void QPin::setMemoryAllocator(IMemAllocator *alloc) { - QWriteLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (alloc) { alloc->AddRef(); } @@ -619,7 +598,7 @@ namespace Phonon IMemAllocator *QPin::memoryAllocator(bool addref) const { - QReadLocker locker(&m_lock); + QMutexLocker locker(&m_mutex); if (addref && m_memAlloc) { m_memAlloc->AddRef(); } diff --git a/src/3rdparty/phonon/ds9/qpin.h b/src/3rdparty/phonon/ds9/qpin.h index a3287c4..280ad61 100644 --- a/src/3rdparty/phonon/ds9/qpin.h +++ b/src/3rdparty/phonon/ds9/qpin.h @@ -22,7 +22,7 @@ along with this library. If not, see . #include #include -#include +#include #include @@ -85,8 +85,8 @@ namespace Phonon protected: //this can be used by sub-classes - mutable QReadWriteLock m_lock; - QBaseFilter *m_parent; + mutable QMutex m_mutex; + QBaseFilter * const m_parent; bool m_flushing; private: @@ -98,7 +98,6 @@ namespace Phonon const PIN_DIRECTION m_direction; QVector m_mediaTypes; //accepted media types AM_MEDIA_TYPE m_connectedType; - QString m_name; IMemAllocator *m_memAlloc; }; diff --git a/src/3rdparty/phonon/ds9/videorenderer_default.cpp b/src/3rdparty/phonon/ds9/videorenderer_default.cpp new file mode 100644 index 0000000..0045a49 --- /dev/null +++ b/src/3rdparty/phonon/ds9/videorenderer_default.cpp @@ -0,0 +1,153 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see . +*/ + + +#include "videorenderer_default.h" + +#ifndef QT_NO_PHONON_VIDEO + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + + +namespace Phonon +{ + namespace DS9 + { + VideoRendererDefault::~VideoRendererDefault() + { + } + + bool VideoRendererDefault::isNative() const + { + return true; + } + + + VideoRendererDefault::VideoRendererDefault(QWidget *target) : m_target(target) + { + m_target->setAttribute(Qt::WA_PaintOnScreen, true); + m_filter = Filter(CLSID_VideoRenderer, IID_IBaseFilter); + } + + QSize VideoRendererDefault::videoSize() const + { + LONG w = 0, + h = 0; + ComPointer basic(m_filter, IID_IBasicVideo); + if (basic) { + basic->GetVideoSize( &w, &h); + } + return QSize(w, h); + } + + void VideoRendererDefault::repaintCurrentFrame(QWidget * /*target*/, const QRect & /*rect*/) + { + //nothing to do here: the renderer paints everything + } + + void VideoRendererDefault::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio, + Phonon::VideoWidget::ScaleMode scaleMode) + { + if (!isActive()) { + ComPointer basic(m_filter, IID_IBasicVideo); + if (basic) { + basic->SetDestinationPosition(0, 0, 0, 0); + } + return; + } + + ComPointer video(m_filter, IID_IVideoWindow); + + OAHWND owner; + HRESULT hr = video->get_Owner(&owner); + if (FAILED(hr)) { + return; + } + + const OAHWND newOwner = reinterpret_cast(m_target->winId()); + if (owner != newOwner) { + video->put_Owner(newOwner); + video->put_MessageDrain(newOwner); + video->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + } + + //make sure the widget takes the whole size of the parent + video->SetWindowPosition(0, 0, size.width(), size.height()); + + const QSize vsize = videoSize(); + internalNotifyResize(size, vsize, aspectRatio, scaleMode); + + ComPointer basic(m_filter, IID_IBasicVideo); + if (basic) { + basic->SetDestinationPosition(m_dstX, m_dstY, m_dstWidth, m_dstHeight); + } + } + + void VideoRendererDefault::applyMixerSettings(qreal /*brightness*/, qreal /*contrast*/, qreal /*m_hue*/, qreal /*saturation*/) + { + //this can't be supported for the default renderer + } + + QImage VideoRendererDefault::snapshot() const + { + ComPointer basic(m_filter, IID_IBasicVideo); + if (basic) { + LONG bufferSize = 0; + //1st we get the buffer size + basic->GetCurrentImage(&bufferSize, 0); + + QByteArray buffer; + buffer.resize(bufferSize); + HRESULT hr = basic->GetCurrentImage(&bufferSize, reinterpret_cast(buffer.data())); + + if (SUCCEEDED(hr)) { + + const BITMAPINFOHEADER *bmi = reinterpret_cast(buffer.constData()); + + const int w = qAbs(bmi->biWidth), + h = qAbs(bmi->biHeight); + + // Create image and copy data into image. + QImage ret(w, h, QImage::Format_RGB32); + + if (!ret.isNull()) { + const char *data = buffer.constData() + bmi->biSize; + const int bytes_per_line = w * sizeof(QRgb); + for (int y = h - 1; y >= 0; --y) { + qMemCopy(ret.scanLine(y), //destination + data, //source + bytes_per_line); + data += bytes_per_line; + } + } + return ret; + } + } + return QImage(); + } + + } +} + +QT_END_NAMESPACE + +#endif //QT_NO_PHONON_VIDEO diff --git a/src/3rdparty/phonon/ds9/videorenderer_default.h b/src/3rdparty/phonon/ds9/videorenderer_default.h new file mode 100644 index 0000000..43768d9 --- /dev/null +++ b/src/3rdparty/phonon/ds9/videorenderer_default.h @@ -0,0 +1,55 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see . +*/ + +#ifndef PHONON_VIDEORENDERER_DEFAULT_H +#define PHONON_VIDEORENDERER_DEFAULT_H + +#include "abstractvideorenderer.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEO + +namespace Phonon +{ + namespace DS9 + { + class VideoRendererDefault : public AbstractVideoRenderer + { + public: + VideoRendererDefault(QWidget *target); + ~VideoRendererDefault(); + + //Implementation from AbstractVideoRenderer + void repaintCurrentFrame(QWidget *target, const QRect &rect); + void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode); + QSize videoSize() const; + QImage snapshot() const; + void applyMixerSettings(qreal brightness, qreal contrast, qreal m_hue, qreal saturation); + bool isNative() const; + private: + QWidget *m_target; + }; + } +} + +#endif //QT_NO_PHONON_VIDEO + +QT_END_NAMESPACE + +#endif + diff --git a/src/3rdparty/phonon/ds9/videorenderer_evr.cpp b/src/3rdparty/phonon/ds9/videorenderer_evr.cpp new file mode 100644 index 0000000..d23d9ce --- /dev/null +++ b/src/3rdparty/phonon/ds9/videorenderer_evr.cpp @@ -0,0 +1,215 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see . +*/ + + +#include "videorenderer_evr.h" +#include "qevr9.h" + +#ifndef QT_NO_PHONON_VIDEO + +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + namespace DS9 + { + //we have to define them here because not all compilers/sdk have them + static const GUID MR_VIDEO_RENDER_SERVICE = {0x1092a86c, 0xab1a, 0x459a, {0xa3, 0x36, 0x83, 0x1f, 0xbc, 0x4d, 0x11, 0xff} }; + static const GUID MR_VIDEO_MIXER_SERVICE = { 0x73cd2fc, 0x6cf4, 0x40b7, {0x88, 0x59, 0xe8, 0x95, 0x52, 0xc8, 0x41, 0xf8} }; + static const IID IID_IMFVideoDisplayControl = {0xa490b1e4, 0xab84, 0x4d31, {0xa1, 0xb2, 0x18, 0x1e, 0x03, 0xb1, 0x07, 0x7a} }; + static const IID IID_IMFVideoMixerControl = {0xA5C6C53F, 0xC202, 0x4aa5, {0x96, 0x95, 0x17, 0x5B, 0xA8, 0xC5, 0x08, 0xA5} }; + static const IID IID_IMFVideoProcessor = {0x6AB0000C, 0xFECE, 0x4d1f, {0xA2, 0xAC, 0xA9, 0x57, 0x35, 0x30, 0x65, 0x6E} }; + static const IID IID_IMFGetService = {0xFA993888, 0x4383, 0x415A, {0xA9, 0x30, 0xDD, 0x47, 0x2A, 0x8C, 0xF6, 0xF7} }; + static const GUID CLSID_EnhancedVideoRenderer = {0xfa10746c, 0x9b63, 0x4b6c, {0xbc, 0x49, 0xfc, 0x30, 0xe, 0xa5, 0xf2, 0x56} }; + + template ComPointer getService(const Filter &filter, REFGUID guidService, REFIID riid) + { + //normally we should use IID_IMFGetService but this introduces another dependency + //so here we simply define our own IId with the same value + ComPointer getService(filter, IID_IMFGetService); + Q_ASSERT(getService); + T *ptr = 0; + HRESULT hr = getService->GetService(guidService, riid, reinterpret_cast(&ptr)); + if (!SUCCEEDED(hr) || ptr == 0) + Q_ASSERT(!SUCCEEDED(hr) && ptr != 0); + ComPointer service(ptr); + return service; + } + + VideoRendererEVR::~VideoRendererEVR() + { + } + + bool VideoRendererEVR::isNative() const + { + return true; + } + + VideoRendererEVR::VideoRendererEVR(QWidget *target) : m_target(target) + { + m_filter = Filter(CLSID_EnhancedVideoRenderer, IID_IBaseFilter); + if (!m_filter) { + return; + } + + ComPointer filterControl = getService(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); + + filterControl->SetVideoWindow(reinterpret_cast(target->winId())); + filterControl->SetAspectRatioMode(MFVideoARMode_None); // We're in control of the size + } + + QImage VideoRendererEVR::snapshot() const + { + // This will always capture black areas where no video is drawn, if any are present. + // Due to the hack in notifyResize() + ComPointer filterControl = getService(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); + if (filterControl) { + BITMAPINFOHEADER bmi; + BYTE *buffer = 0; + DWORD bufferSize; + LONGLONG timeStamp; + + bmi.biSize = sizeof(BITMAPINFOHEADER); + + HRESULT hr = filterControl->GetCurrentImage(&bmi, &buffer, &bufferSize, &timeStamp); + if (SUCCEEDED(hr)) { + + const int w = qAbs(bmi.biWidth), + h = qAbs(bmi.biHeight); + + // Create image and copy data into image. + QImage ret(w, h, QImage::Format_RGB32); + + if (!ret.isNull()) { + uchar *data = buffer; + const int bytes_per_line = w * sizeof(QRgb); + for (int y = h - 1; y >= 0; --y) { + qMemCopy(ret.scanLine(y), //destination + data, //source + bytes_per_line); + data += bytes_per_line; + } + } + ::CoTaskMemFree(buffer); + return ret; + } + } + return QImage(); + } + + QSize VideoRendererEVR::videoSize() const + { + SIZE nativeSize; + SIZE aspectRatioSize; + + ComPointer filterControl = getService(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); + + filterControl->GetNativeVideoSize(&nativeSize, &aspectRatioSize); + + return QSize(nativeSize.cx, nativeSize.cy); + } + + void VideoRendererEVR::repaintCurrentFrame(QWidget *target, const QRect &rect) + { + // repaint the video + ComPointer filterControl = getService(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); + // All failed results can be safely ignored + filterControl->RepaintVideo(); + } + + void VideoRendererEVR::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio, + Phonon::VideoWidget::ScaleMode scaleMode) + { + if (!isActive()) { + RECT dummyRect = { 0, 0, 0, 0}; + ComPointer filterControl = getService(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); + filterControl->SetVideoPosition(0, &dummyRect); + return; + } + + const QSize vsize = videoSize(); + internalNotifyResize(size, vsize, aspectRatio, scaleMode); + + RECT dstRectWin = { 0, 0, size.width(), size.height()}; + + // Resize the Stream output rect instead of the destination rect. + // Hacky workaround for flicker in the areas outside of the destination rect + // This way these areas don't exist + MFVideoNormalizedRect streamOutputRect = { float(m_dstX) / float(size.width()), float(m_dstY) / float(size.height()), + float(m_dstWidth + m_dstX) / float(size.width()), float(m_dstHeight + m_dstY) / float(size.height())}; + + ComPointer filterMixer = getService(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoMixerControl); + ComPointer filterControl = getService(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl); + + filterMixer->SetStreamOutputRect(0, &streamOutputRect); + filterControl->SetVideoPosition(0, &dstRectWin); + } + + void VideoRendererEVR::applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation) + { + InputPin sink = BackendNode::pins(m_filter, PINDIR_INPUT).first(); + OutputPin source; + if (FAILED(sink->ConnectedTo(source.pparam()))) { + return; //it must be connected to work + } + + // Get the "Video Processor" (used for brightness/contrast/saturation/hue) + ComPointer processor = getService(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoProcessor); + Q_ASSERT(processor); + + DXVA2_ValueRange contrastRange; + DXVA2_ValueRange brightnessRange; + DXVA2_ValueRange saturationRange; + DXVA2_ValueRange hueRange; + + if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Contrast, &contrastRange))) + return; + if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Brightness, &brightnessRange))) + return; + if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Saturation, &saturationRange))) + return; + if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Hue, &hueRange))) + return; + + DXVA2_ProcAmpValues values; + + values.Contrast = DXVA2FloatToFixed(((contrast < 0 + ? DXVA2FixedToFloat(contrastRange.MinValue) : DXVA2FixedToFloat(contrastRange.MaxValue)) + - DXVA2FixedToFloat(contrastRange.DefaultValue)) * qAbs(contrast) + DXVA2FixedToFloat(contrastRange.DefaultValue)); + values.Brightness = DXVA2FloatToFixed(((brightness < 0 + ? DXVA2FixedToFloat(brightnessRange.MinValue) : DXVA2FixedToFloat(brightnessRange.MaxValue)) + - DXVA2FixedToFloat(brightnessRange.DefaultValue)) * qAbs(brightness) + DXVA2FixedToFloat(brightnessRange.DefaultValue)); + values.Saturation = DXVA2FloatToFixed(((saturation < 0 + ? DXVA2FixedToFloat(saturationRange.MinValue) : DXVA2FixedToFloat(saturationRange.MaxValue)) + - DXVA2FixedToFloat(saturationRange.DefaultValue)) * qAbs(saturation) + DXVA2FixedToFloat(saturationRange.DefaultValue)); + values.Hue = DXVA2FloatToFixed(((hue < 0 + ? DXVA2FixedToFloat(hueRange.MinValue) : DXVA2FixedToFloat(hueRange.MaxValue)) + - DXVA2FixedToFloat(hueRange.DefaultValue)) * qAbs(hue) + DXVA2FixedToFloat(hueRange.DefaultValue)); + + //finally set the settings + processor->SetProcAmpValues(DXVA2_ProcAmp_Contrast | DXVA2_ProcAmp_Brightness | DXVA2_ProcAmp_Saturation | DXVA2_ProcAmp_Hue, &values); + + } + } +} + +QT_END_NAMESPACE + +#endif //QT_NO_PHONON_VIDEO diff --git a/src/3rdparty/phonon/ds9/videorenderer_evr.h b/src/3rdparty/phonon/ds9/videorenderer_evr.h new file mode 100644 index 0000000..229c36d --- /dev/null +++ b/src/3rdparty/phonon/ds9/videorenderer_evr.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + +This library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 or 3 of the License. + +This library 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library. If not, see . +*/ + +#ifndef PHONON_VIDEORENDERER_EVR_H +#define PHONON_VIDEORENDERER_EVR_H + +#include "abstractvideorenderer.h" +#include "compointer.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEO + +namespace Phonon +{ + namespace DS9 + { + class VideoRendererEVR : public AbstractVideoRenderer + { + public: + VideoRendererEVR(QWidget *target); + ~VideoRendererEVR(); + + //Implementation from AbstractVideoRenderer + void repaintCurrentFrame(QWidget *target, const QRect &rect); + void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode); + QSize videoSize() const; + QImage snapshot() const; + void applyMixerSettings(qreal brightness, qreal contrast, qreal m_hue, qreal saturation); + bool isNative() const; + private: + QWidget *m_target; + }; + } +} + +#endif //QT_NO_PHONON_VIDEO + +QT_END_NAMESPACE + +#endif + diff --git a/src/3rdparty/phonon/ds9/videorenderer_soft.cpp b/src/3rdparty/phonon/ds9/videorenderer_soft.cpp index 491d1bd..9c7993c 100644 --- a/src/3rdparty/phonon/ds9/videorenderer_soft.cpp +++ b/src/3rdparty/phonon/ds9/videorenderer_soft.cpp @@ -194,8 +194,8 @@ namespace Phonon m_sampleBuffer = ComPointer(); #ifndef QT_NO_OPENGL freeGLResources(); -#endif // QT_NO_OPENGL m_textureUploaded = false; +#endif // QT_NO_OPENGL } void endOfStream() @@ -314,7 +314,6 @@ namespace Phonon REFERENCE_TIME m_start; HANDLE m_renderEvent, m_receiveCanWait; // Signals sample to render QSize m_size; - bool m_textureUploaded; //mixer settings qreal m_brightness, @@ -356,6 +355,7 @@ namespace Phonon bool m_checkedPrograms; bool m_usingOpenGL; + bool m_textureUploaded; GLuint m_program[2]; GLuint m_texture[3]; #endif @@ -365,7 +365,7 @@ namespace Phonon { public: VideoRendererSoftPin(VideoRendererSoftFilter *parent) : - QMemInputPin(parent, videoMediaTypes(), false /*no transformation of the samples*/), + QMemInputPin(parent, videoMediaTypes(), false /*no transformation of the samples*/, 0), m_renderer(parent) { } @@ -436,7 +436,7 @@ namespace Phonon QBaseFilter(CLSID_NULL), m_inputPin(new VideoRendererSoftPin(this)), m_renderer(renderer), m_start(0) #ifndef QT_NO_OPENGL - ,m_usingOpenGL(false), m_checkedPrograms(false), m_textureUploaded(false) + , m_checkedPrograms(false), m_usingOpenGL(false), m_textureUploaded(false) #endif { m_renderEvent = ::CreateEvent(0, 0, 0, 0); @@ -661,7 +661,10 @@ namespace Phonon #ifndef QT_NO_OPENGL - if (painter.paintEngine() && painter.paintEngine()->type() == QPaintEngine::OpenGL && checkGLPrograms()) { + if (painter.paintEngine() && + (painter.paintEngine()->type() == QPaintEngine::OpenGL || painter.paintEngine()->type() == QPaintEngine::OpenGL2) + && checkGLPrograms()) { + //for now we only support YUV (both YV12 and YUY2) updateTexture(); @@ -673,6 +676,7 @@ namespace Phonon } //let's draw the texture + painter.beginNativePainting(); //Let's pass the other arguments const Program prog = (m_inputPin->connectedType().subtype == MEDIASUBTYPE_YV12) ? YV12toRGB : YUY2toRGB; @@ -722,6 +726,7 @@ namespace Phonon glDisableClientState(GL_VERTEX_ARRAY); glDisable(GL_FRAGMENT_PROGRAM_ARB); + painter.endNativePainting(); return; } else #endif diff --git a/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp b/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp index 298e9fa..545b31e 100644 --- a/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp +++ b/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp @@ -22,14 +22,9 @@ along with this library. If not, see . #include #include -#include -#ifndef Q_OS_WINCE #include #include -#else -#include -#endif QT_BEGIN_NAMESPACE @@ -48,116 +43,10 @@ namespace Phonon } -#ifdef Q_OS_WINCE - VideoRendererVMR9::VideoRendererVMR9(QWidget *target) : m_target(target) - { - m_target->setAttribute(Qt::WA_PaintOnScreen, true); - m_filter = Filter(CLSID_VideoRenderer, IID_IBaseFilter); - } - - QSize VideoRendererVMR9::videoSize() const - { - LONG w = 0, - h = 0; - ComPointer basic(m_filter, IID_IBasicVideo); - if (basic) { - basic->GetVideoSize( &w, &h); - } - return QSize(w, h); - } - - void VideoRendererVMR9::repaintCurrentFrame(QWidget * /*target*/, const QRect & /*rect*/) - { - //nothing to do here: the renderer paints everything - } - - void VideoRendererVMR9::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio, - Phonon::VideoWidget::ScaleMode scaleMode) - { - if (!isActive()) { - ComPointer basic(m_filter, IID_IBasicVideo); - if (basic) { - basic->SetDestinationPosition(0, 0, 0, 0); - } - return; - } - - ComPointer video(m_filter, IID_IVideoWindow); - - OAHWND owner; - HRESULT hr = video->get_Owner(&owner); - if (FAILED(hr)) { - return; - } - - const OAHWND newOwner = reinterpret_cast(m_target->winId()); - if (owner != newOwner) { - video->put_Owner(newOwner); - video->put_MessageDrain(newOwner); - video->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - } - - //make sure the widget takes the whole size of the parent - video->SetWindowPosition(0, 0, size.width(), size.height()); - - const QSize vsize = videoSize(); - internalNotifyResize(size, vsize, aspectRatio, scaleMode); - - ComPointer basic(m_filter, IID_IBasicVideo); - if (basic) { - basic->SetDestinationPosition(m_dstX, m_dstY, m_dstWidth, m_dstHeight); - } - } - - void VideoRendererVMR9::applyMixerSettings(qreal /*brightness*/, qreal /*contrast*/, qreal /*m_hue*/, qreal /*saturation*/) - { - //this can't be supported for WinCE - } - - QImage VideoRendererVMR9::snapshot() const - { - ComPointer basic(m_filter, IID_IBasicVideo); - if (basic) { - LONG bufferSize = 0; - //1st we get the buffer size - basic->GetCurrentImage(&bufferSize, 0); - - QByteArray buffer; - buffer.resize(bufferSize); - HRESULT hr = basic->GetCurrentImage(&bufferSize, reinterpret_cast(buffer.data())); - - if (SUCCEEDED(hr)) { - - const BITMAPINFOHEADER *bmi = reinterpret_cast(buffer.constData()); - - const int w = qAbs(bmi->biWidth), - h = qAbs(bmi->biHeight); - - // Create image and copy data into image. - QImage ret(w, h, QImage::Format_RGB32); - - if (!ret.isNull()) { - const char *data = buffer.constData() + bmi->biSize; - const int bytes_per_line = w * sizeof(QRgb); - for (int y = h - 1; y >= 0; --y) { - qMemCopy(ret.scanLine(y), //destination - data, //source - bytes_per_line); - data += bytes_per_line; - } - } - return ret; - } - } - return QImage(); - } - -#else VideoRendererVMR9::VideoRendererVMR9(QWidget *target) : m_target(target) { m_filter = Filter(CLSID_VideoMixingRenderer9, IID_IBaseFilter); if (!m_filter) { - qWarning("the video widget could not be initialized correctly"); return; } @@ -169,6 +58,7 @@ namespace Phonon Q_ASSERT(SUCCEEDED(hr)); ComPointer windowlessControl(m_filter, IID_IVMRWindowlessControl9); windowlessControl->SetVideoClippingWindow(reinterpret_cast(target->winId())); + windowlessControl->SetAspectRatioMode(VMR9ARMode_None); //we're in control of the size } QImage VideoRendererVMR9::snapshot() const @@ -324,7 +214,6 @@ namespace Phonon //finally set the settings mixer->SetProcAmpControl(0, &ctrl); } -#endif } } diff --git a/src/3rdparty/phonon/ds9/videorenderer_vmr9.h b/src/3rdparty/phonon/ds9/videorenderer_vmr9.h index 4eb237e..516d79d 100644 --- a/src/3rdparty/phonon/ds9/videorenderer_vmr9.h +++ b/src/3rdparty/phonon/ds9/videorenderer_vmr9.h @@ -19,7 +19,6 @@ along with this library. If not, see . #define PHONON_VIDEORENDERER_VMR9_H #include "abstractvideorenderer.h" -#include "compointer.h" QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/phonon/ds9/videowidget.cpp b/src/3rdparty/phonon/ds9/videowidget.cpp index de7ce5f..09d42a4 100644 --- a/src/3rdparty/phonon/ds9/videowidget.cpp +++ b/src/3rdparty/phonon/ds9/videowidget.cpp @@ -24,7 +24,12 @@ along with this library. If not, see . #include "mediaobject.h" +#ifndef Q_OS_WINCE +#include "videorenderer_evr.h" #include "videorenderer_vmr9.h" +#else +#include "videorenderer_default.h" +#endif #include "videorenderer_soft.h" QT_BEGIN_NAMESPACE @@ -84,7 +89,19 @@ namespace Phonon void setCurrentRenderer(AbstractVideoRenderer *renderer) { m_currentRenderer = renderer; - update(); + //we disallow repaint on that widget for just a fraction of second + //this allows better transition between videos + setUpdatesEnabled(false); + m_flickerFreeTimer.start(20, this); + } + + void timerEvent(QTimerEvent *e) + { + if (e->timerId() == m_flickerFreeTimer.timerId()) { + m_flickerFreeTimer.stop(); + setUpdatesEnabled(true); + } + QWidget::timerEvent(e); } QSize sizeHint() const @@ -106,6 +123,8 @@ namespace Phonon void paintEvent(QPaintEvent *e) { + if (!updatesEnabled()) + return; //this avoids repaint from native events checkCurrentRenderingMode(); m_currentRenderer->repaintCurrentFrame(this, e->rect()); } @@ -153,13 +172,14 @@ namespace Phonon } } else if (!isEmbedded()) { m_currentRenderer = m_node->switchRendering(m_currentRenderer); - setAttribute(Qt::WA_PaintOnScreen, true); + setAttribute(Qt::WA_PaintOnScreen, false); } } VideoWidget *m_node; AbstractVideoRenderer *m_currentRenderer; QVariant m_restoreScreenSaverActive; + QBasicTimer m_flickerFreeTimer; }; VideoWidget::VideoWidget(QWidget *parent) @@ -203,6 +223,9 @@ namespace Phonon if (toNative && m_noNativeRendererSupported) return current; //no switch here + if (!mediaObject()) + return current; + //firt we delete the renderer //initialization of the widgets for(int i = 0; i < FILTER_COUNT; ++i) { @@ -261,6 +284,7 @@ namespace Phonon { m_aspectRatio = aspectRatio; updateVideoSize(); + m_widget->update(); } Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const @@ -279,6 +303,7 @@ namespace Phonon { m_scaleMode = scaleMode; updateVideoSize(); + m_widget->update(); } void VideoWidget::setBrightness(qreal b) @@ -332,14 +357,29 @@ namespace Phonon int index = graphIndex * 2 + type; if (m_renderers[index] == 0 && autoCreate) { AbstractVideoRenderer *renderer = 0; - if (type == Native) { - renderer = new VideoRendererVMR9(m_widget); + if (type == Native) { +#ifndef Q_OS_WINCE + renderer = new VideoRendererEVR(m_widget); + if (renderer->getFilter() == 0) { + delete renderer; + //EVR not present, let's try VMR + renderer = new VideoRendererVMR9(m_widget); + if (renderer->getFilter() == 0) { + //instanciating the renderer might fail + m_noNativeRendererSupported = true; + delete renderer; + renderer = 0; + } + } +#else + renderer = new VideoRendererDefault(m_widget); if (renderer->getFilter() == 0) { - //instanciating the renderer might fail with error VFW_E_DDRAW_CAPS_NOT_SUITABLE (0x80040273) + //instanciating the renderer might fail m_noNativeRendererSupported = true; delete renderer; renderer = 0; } +#endif } if (renderer == 0) { diff --git a/src/3rdparty/phonon/ds9/volumeeffect.cpp b/src/3rdparty/phonon/ds9/volumeeffect.cpp index b9a5fce..a93b074 100644 --- a/src/3rdparty/phonon/ds9/volumeeffect.cpp +++ b/src/3rdparty/phonon/ds9/volumeeffect.cpp @@ -76,7 +76,7 @@ namespace Phonon class VolumeMemInputPin : public QMemInputPin { public: - VolumeMemInputPin(QBaseFilter *parent, const QVector &mt) : QMemInputPin(parent, mt, true /*transform*/) + VolumeMemInputPin(QBaseFilter *parent, const QVector &mt, QPin *output) : QMemInputPin(parent, mt, true /*transform*/, output) { } @@ -139,8 +139,7 @@ namespace Phonon //then creating the input mt << audioMediaType(); - m_input = new VolumeMemInputPin(this, mt); - m_input->addOutput(m_output); //make the connection here + m_input = new VolumeMemInputPin(this, mt, m_output); } void VolumeEffectFilter::treatOneSamplePerChannel(BYTE **buffer, int sampleSize, int channelCount, int frequency) diff --git a/src/3rdparty/phonon/ds9/volumeeffect.h b/src/3rdparty/phonon/ds9/volumeeffect.h index 39b20d0..d1b0186 100644 --- a/src/3rdparty/phonon/ds9/volumeeffect.h +++ b/src/3rdparty/phonon/ds9/volumeeffect.h @@ -47,7 +47,7 @@ namespace Phonon private: float m_volume; - //parameters used to fade + //paramaters used to fade Phonon::VolumeFaderEffect::FadeCurve m_fadeCurve; bool m_fading; //determines if we should be fading. diff --git a/src/plugins/phonon/ds9/ds9.pro b/src/plugins/phonon/ds9/ds9.pro index f40c561..dab5116 100644 --- a/src/plugins/phonon/ds9/ds9.pro +++ b/src/plugins/phonon/ds9/ds9.pro @@ -23,6 +23,7 @@ HEADERS += \ $$PHONON_DS9_DIR/videowidget.h \ $$PHONON_DS9_DIR/videorenderer_soft.h \ $$PHONON_DS9_DIR/videorenderer_vmr9.h \ + $$PHONON_DS9_DIR/videorenderer_evr.h \ $$PHONON_DS9_DIR/volumeeffect.h \ $$PHONON_DS9_DIR/qbasefilter.h \ $$PHONON_DS9_DIR/qpin.h \ @@ -46,6 +47,7 @@ SOURCES += \ $$PHONON_DS9_DIR/videowidget.cpp \ $$PHONON_DS9_DIR/videorenderer_soft.cpp \ $$PHONON_DS9_DIR/videorenderer_vmr9.cpp \ + $$PHONON_DS9_DIR/videorenderer_evr.cpp \ $$PHONON_DS9_DIR/volumeeffect.cpp \ $$PHONON_DS9_DIR/qbasefilter.cpp \ $$PHONON_DS9_DIR/qpin.cpp \ -- cgit v0.12 From a7177ea6be1a7617f82edf062164083bbc2eb47a Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 7 Apr 2010 13:56:39 +0200 Subject: Revert "Remove references to evr based renderer from .pro." This reverts commit 04d3b7ada83042c587a9ba199395b639c5f83623. Why would anyone want to remove evr renderer... --- src/plugins/phonon/ds9/ds9.pro | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/plugins/phonon/ds9/ds9.pro b/src/plugins/phonon/ds9/ds9.pro index dab5116..301808e 100644 --- a/src/plugins/phonon/ds9/ds9.pro +++ b/src/plugins/phonon/ds9/ds9.pro @@ -22,8 +22,6 @@ HEADERS += \ $$PHONON_DS9_DIR/mediaobject.h \ $$PHONON_DS9_DIR/videowidget.h \ $$PHONON_DS9_DIR/videorenderer_soft.h \ - $$PHONON_DS9_DIR/videorenderer_vmr9.h \ - $$PHONON_DS9_DIR/videorenderer_evr.h \ $$PHONON_DS9_DIR/volumeeffect.h \ $$PHONON_DS9_DIR/qbasefilter.h \ $$PHONON_DS9_DIR/qpin.h \ @@ -46,8 +44,6 @@ SOURCES += \ $$PHONON_DS9_DIR/mediaobject.cpp \ $$PHONON_DS9_DIR/videowidget.cpp \ $$PHONON_DS9_DIR/videorenderer_soft.cpp \ - $$PHONON_DS9_DIR/videorenderer_vmr9.cpp \ - $$PHONON_DS9_DIR/videorenderer_evr.cpp \ $$PHONON_DS9_DIR/volumeeffect.cpp \ $$PHONON_DS9_DIR/qbasefilter.cpp \ $$PHONON_DS9_DIR/qpin.cpp \ @@ -55,6 +51,15 @@ SOURCES += \ $$PHONON_DS9_DIR/qaudiocdreader.cpp \ $$PHONON_DS9_DIR/qmeminputpin.cpp +#the EVR renderer (only available on desktop) +!wince*:SOURCES += $$PHONON_DS9_DIR/videorenderer_evr.cpp \ + $$PHONON_DS9_DIR/videorenderer_vmr9.cpp +!wince*:HEADERS += $$PHONON_DS9_DIR/qevr9.h \ + $$PHONON_DS9_DIR/videorenderer_evr.h \ + $$PHONON_DS9_DIR/videorenderer_vmr9.h +wince*:SOURCES += $$PHONON_DS9_DIR/videorenderer_default.cpp +wince*:HEADERS += $$PHONON_DS9_DIR/videorenderer_default.h + target.path = $$[QT_INSTALL_PLUGINS]/phonon_backend INSTALLS += target -- cgit v0.12 From 2df78bfc92bdf6da1de87ae684b4c59b70767f90 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 7 Apr 2010 16:38:37 +0200 Subject: Disable EGLImage usage It's broken. It will be fixed properly. --- src/opengl/qgl_x11egl.cpp | 48 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index af0100b..456e111 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -435,30 +435,30 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, cons // If the pixmap doesn't already have a valid surface, try binding it via EGLImage // first, as going through EGLImage should be faster and better supported: - if (!textureIsBound && haveEglImageTFP) { - Q_ASSERT(eglCreateImageKHR); - - EGLImageKHR eglImage; - - EGLint attribs[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, - EGL_NONE - }; - eglImage = eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, - (EGLClientBuffer)QEgl::nativePixmap(pixmap), attribs); - - QGLContext* ctx = q; - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage); - - GLint err = glGetError(); - if (err == GL_NO_ERROR) - textureIsBound = true; - - // Once the egl image is bound, the texture becomes a new sibling image and we can safely - // destroy the EGLImage we created for the pixmap: - if (eglImage != EGL_NO_IMAGE_KHR) - eglDestroyImageKHR(QEgl::display(), eglImage); - } +// if (!textureIsBound && haveEglImageTFP) { +// Q_ASSERT(eglCreateImageKHR); +// +// EGLImageKHR eglImage; +// +// EGLint attribs[] = { +// EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, +// EGL_NONE +// }; +// eglImage = eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, +// (EGLClientBuffer)QEgl::nativePixmap(pixmap), attribs); +// +// QGLContext* ctx = q; +// glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage); +// +// GLint err = glGetError(); +// if (err == GL_NO_ERROR) +// textureIsBound = true; +// +// // Once the egl image is bound, the texture becomes a new sibling image and we can safely +// // destroy the EGLImage we created for the pixmap: +// if (eglImage != EGL_NO_IMAGE_KHR) +// eglDestroyImageKHR(QEgl::display(), eglImage); +// } if (!textureIsBound && haveTFP) { // Check to see if the surface is still valid -- cgit v0.12 From 864ace14e12cedd8e8f78841249e5309eb0a0795 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 7 Apr 2010 16:44:59 +0200 Subject: Fixed the action geometry of menu bar in RTL It could happen (with MDI widgets) that the first actions would not be visible. Task-number: QTBUG-9560 Reviewed-by: gabi --- src/gui/widgets/qmenubar.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index e368d3d..a13a2fa 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -268,19 +268,15 @@ void QMenuBarPrivate::updateGeometries() QRect QMenuBarPrivate::actionRect(QAction *act) const { - Q_Q(const QMenuBar); const int index = actions.indexOf(act); - if (index == -1) - return QRect(); //makes sure the geometries are up-to-date const_cast(this)->updateGeometries(); - if (index >= actionRects.count()) + if (index < 0 || index >= actionRects.count()) return QRect(); // that can happen in case of native menubar - QRect ret = actionRects.at(index); - return QStyle::visualRect(q->layoutDirection(), q->rect(), ret); + return actionRects.at(index); } void QMenuBarPrivate::focusFirstAction() @@ -505,6 +501,9 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start) const //keep moving along.. x += rect.width() + itemSpacing; + + //make sure we follow the layout direction + rect = QStyle::visualRect(q->layoutDirection(), q->rect(), rect); } } -- cgit v0.12 From 99c17c0efb1331f5d11260b08614c9dff9bbf2e1 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 7 Apr 2010 17:18:04 +0200 Subject: Fix EGLImage & re-enable its use in QtOpenGL Make sure we set the EGL_KHR_image_base define when we define the reset of the extension defines. This also makes eglCreateImageKHR get defined when previously it wasn't. Reviewed-By: TrustMe --- src/gui/egl/qegl_p.h | 9 ++++++--- src/opengl/qgl_x11egl.cpp | 48 +++++++++++++++++++++++------------------------ 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index 540cd3d..f81add6 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -139,6 +139,12 @@ QT_BEGIN_NAMESPACE typedef void *EGLImageKHR; #define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) #define EGL_IMAGE_PRESERVED_KHR 0x30D2 +#define EGL_KHR_image_base +#endif + +#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_pixmap) +#define EGL_NATIVE_PIXMAP_KHR 0x30B0 +#define EGL_KHR_image_pixmap #endif // It is possible that something has included eglext.h (like Symbian 10.1's broken egl.h), in @@ -154,9 +160,6 @@ extern Q_GUI_EXPORT _eglCreateImageKHR eglCreateImageKHR; extern Q_GUI_EXPORT _eglDestroyImageKHR eglDestroyImageKHR; #endif // (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES) -#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_pixmap) -#define EGL_NATIVE_PIXMAP_KHR 0x30B0 -#endif class QEglProperties; diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 456e111..af0100b 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -435,30 +435,30 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, cons // If the pixmap doesn't already have a valid surface, try binding it via EGLImage // first, as going through EGLImage should be faster and better supported: -// if (!textureIsBound && haveEglImageTFP) { -// Q_ASSERT(eglCreateImageKHR); -// -// EGLImageKHR eglImage; -// -// EGLint attribs[] = { -// EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, -// EGL_NONE -// }; -// eglImage = eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, -// (EGLClientBuffer)QEgl::nativePixmap(pixmap), attribs); -// -// QGLContext* ctx = q; -// glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage); -// -// GLint err = glGetError(); -// if (err == GL_NO_ERROR) -// textureIsBound = true; -// -// // Once the egl image is bound, the texture becomes a new sibling image and we can safely -// // destroy the EGLImage we created for the pixmap: -// if (eglImage != EGL_NO_IMAGE_KHR) -// eglDestroyImageKHR(QEgl::display(), eglImage); -// } + if (!textureIsBound && haveEglImageTFP) { + Q_ASSERT(eglCreateImageKHR); + + EGLImageKHR eglImage; + + EGLint attribs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE + }; + eglImage = eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, + (EGLClientBuffer)QEgl::nativePixmap(pixmap), attribs); + + QGLContext* ctx = q; + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage); + + GLint err = glGetError(); + if (err == GL_NO_ERROR) + textureIsBound = true; + + // Once the egl image is bound, the texture becomes a new sibling image and we can safely + // destroy the EGLImage we created for the pixmap: + if (eglImage != EGL_NO_IMAGE_KHR) + eglDestroyImageKHR(QEgl::display(), eglImage); + } if (!textureIsBound && haveTFP) { // Check to see if the surface is still valid -- cgit v0.12 From e1e728daad07600fca7bc1811c92fb05065884c6 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 7 Apr 2010 16:55:01 +0200 Subject: O(n^2) to O(n) optimization in QTreeWidget::selectedItems() As we need to ensure that there will be no duplicates in the list returned by QTreeWidget::selectedItems() (see commit ea75d434e40100a9abf56195b646a8efdf3c1288), we now use a QSet to ensure unicity while keeping the same order as before. Reviewed-by: Olivier Task-number: QTBUG-9485 --- src/gui/itemviews/qtreewidget.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/itemviews/qtreewidget.cpp b/src/gui/itemviews/qtreewidget.cpp index 19ed10b..4c80325 100644 --- a/src/gui/itemviews/qtreewidget.cpp +++ b/src/gui/itemviews/qtreewidget.cpp @@ -3039,10 +3039,14 @@ QList QTreeWidget::selectedItems() const Q_D(const QTreeWidget); QModelIndexList indexes = selectionModel()->selectedIndexes(); QList items; + items.reserve(indexes.count()); + QSet seen; + seen.reserve(indexes.count()); for (int i = 0; i < indexes.count(); ++i) { QTreeWidgetItem *item = d->item(indexes.at(i)); - if (isItemHidden(item) || items.contains(item)) // ### slow, optimize later + if (isItemHidden(item) || seen.contains(item)) continue; + seen.insert(item); items.append(item); } return items; -- cgit v0.12 From 75b338aaa8e3c5138718019e95271d8eed5f0c39 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Thu, 18 Mar 2010 22:24:13 +0900 Subject: Fix compile error with QT_NO_ANIMATION Task-number: QTBUG-7414 Author: Tasuku Suzuki --- src/gui/animation/qguivariantanimation.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp index 52303f5..28cde3e 100644 --- a/src/gui/animation/qguivariantanimation.cpp +++ b/src/gui/animation/qguivariantanimation.cpp @@ -38,12 +38,11 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - -#ifndef QT_NO_ANIMATION - #include #include +#ifndef QT_NO_ANIMATION + #include #include #include -- cgit v0.12 From bf195e57ff96c326fa26c6b3a4f64e26d18fd9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 8 Apr 2010 13:50:46 +0200 Subject: Fixed bug in QPainterPath::intersected(). When we compute the angle delta we can't use qFuzzyCompare as it will cause slightly negative deltas to be snapped to 0, causing the winged edge builder to put path edges in the wrong order. Task-number: QTBUG-3778 Reviewed-by: Trond --- src/gui/painting/qpathclipper.cpp | 7 +++---- tests/auto/qpathclipper/tst_qpathclipper.cpp | 29 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp index 949a820..00e74ba 100644 --- a/src/gui/painting/qpathclipper.cpp +++ b/src/gui/painting/qpathclipper.cpp @@ -935,10 +935,9 @@ qreal QWingedEdge::delta(int vertex, int a, int b) const qreal result = b_angle - a_angle; - if (qFuzzyIsNull(result) || qFuzzyCompare(result, 128)) - return 0; - - if (result < 0) + if (result >= 128.) + return result - 128.; + else if (result < 0) return result + 128.; else return result; diff --git a/tests/auto/qpathclipper/tst_qpathclipper.cpp b/tests/auto/qpathclipper/tst_qpathclipper.cpp index 38d253a..db5a13e 100644 --- a/tests/auto/qpathclipper/tst_qpathclipper.cpp +++ b/tests/auto/qpathclipper/tst_qpathclipper.cpp @@ -95,6 +95,8 @@ private slots: void task209056(); void task251909(); + + void qtbug3778(); }; Q_DECLARE_METATYPE(QPainterPath) @@ -1346,6 +1348,33 @@ void tst_QPathClipper::task251909() QVERIFY(result.elementCount() <= 5); } +void tst_QPathClipper::qtbug3778() +{ + QPainterPath path1; + path1.moveTo(200, 3.22409e-5); + // e-5 and higher leads to a bug + // Using 3.22409e-4 starts to work correctly + path1.lineTo(0, 0); + path1.lineTo(1.07025e-13, 1450); + path1.lineTo(750, 950); + path1.lineTo(950, 750); + path1.lineTo(200, 3.22409e-13); + + QPainterPath path2; + path2.moveTo(0, 0); + path2.lineTo(200, 800); + path2.lineTo(600, 1500); + path2.lineTo(1500, 1400); + path2.lineTo(1900, 1200); + path2.lineTo(2000, 1000); + path2.lineTo(1400, 0); + path2.lineTo(0, 0); + + QPainterPath p12 = path1.intersected(path2); + + QVERIFY(p12.contains(QPointF(100, 100))); +} + QTEST_APPLESS_MAIN(tst_QPathClipper) -- cgit v0.12