diff options
Diffstat (limited to 'src')
125 files changed, 6123 insertions, 496 deletions
diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index 276ca04..3dfe803 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -55,8 +55,6 @@ CONFIG(standalone_package) { isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$PWD/../JavaScriptCore/generated PRECOMPILED_HEADER = $$PWD/../WebKit/qt/WebKit_pch.h - - symbian: TARGET += $${QT_LIBINFIX} } else { isEmpty(WC_GENERATED_SOURCES_DIR):WC_GENERATED_SOURCES_DIR = generated isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = ../JavaScriptCore/generated @@ -76,6 +74,7 @@ CONFIG(QTDIR_build) { VERSION = $${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} DESTDIR = $$OUTPUT_DIR/lib !static: DEFINES += QT_MAKEDLL + symbian: TARGET +=$${QT_LIBINFIX} } unix { diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebkitversion.h b/src/3rdparty/webkit/WebKit/qt/Api/qwebkitversion.h index f0fbef0..de79dd1 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebkitversion.h +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebkitversion.h @@ -17,7 +17,7 @@ Boston, MA 02110-1301, USA. */ -#include <qstring.h> +#include <QtCore/qstring.h> #ifndef qwebkitversion_h #define qwebkitversion_h diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp index 0fcdf96..44a0a01 100644 --- a/src/corelib/codecs/qiconvcodec.cpp +++ b/src/corelib/codecs/qiconvcodec.cpp @@ -168,7 +168,7 @@ Q_GLOBAL_STATIC(QThreadStorage<QIconvCodec::IconvState *>, toUnicodeState) QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState *convState) const { if (utf16Codec == reinterpret_cast<QTextCodec *>(~0)) - return QString::fromAscii(chars, len); + return QString::fromLatin1(chars, len); int invalidCount = 0; int remainingCount = 0; @@ -207,9 +207,9 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState static int reported = 0; if (!reported++) { fprintf(stderr, - "QIconvCodec::convertToUnicode: using ASCII for conversion, iconv_open failed\n"); + "QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed\n"); } - return QString::fromAscii(chars, len); + return QString::fromLatin1(chars, len); } *pstate = new IconvState(cd); @@ -273,14 +273,14 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState // some other error // note, cannot use qWarning() since we are implementing the codecForLocale :) - perror("QIconvCodec::convertToUnicode: using ASCII for conversion, iconv failed"); + perror("QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv failed"); if (!convState) { // reset state iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft); } - return QString::fromAscii(chars, len); + return QString::fromLatin1(chars, len); } } while (inBytesLeft != 0); @@ -353,12 +353,12 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt state = new IconvState(QIconvCodec::createIconv_t(0, UTF16)); if (state->cd == reinterpret_cast<iconv_t>(-1)) { if (!setByteOrder(state->cd)) { - perror("QIconvCodec::convertFromUnicode: using ASCII for conversion, iconv failed for BOM"); + perror("QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv failed for BOM"); iconv_close(state->cd); state->cd = reinterpret_cast<iconv_t>(-1); - return QString(uc, len).toAscii(); + return QString(uc, len).toLatin1(); } } } @@ -366,9 +366,9 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt static int reported = 0; if (!reported++) { fprintf(stderr, - "QIconvCodec::convertFromUnicode: using ASCII for conversion, iconv_open failed\n"); + "QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed\n"); } - return QString(uc, len).toAscii(); + return QString(uc, len).toLatin1(); } size_t outBytesLeft = len; @@ -425,12 +425,12 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt default: { // note, cannot use qWarning() since we are implementing the codecForLocale :) - perror("QIconvCodec::convertFromUnicode: using ASCII for conversion, iconv failed"); + perror("QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv failed"); // reset to initial state iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft); - return QString(uc, len).toAscii(); + return QString(uc, len).toLatin1(); } } } diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index dfa2c17..373c0b4 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2079,7 +2079,28 @@ static void mac_default_handler(const char *msg) } #endif // Q_CC_MWERKS && Q_OS_MACX - +#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \ + defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L +namespace { + // There are two incompatible versions of strerror_r: + // a) the XSI/POSIX.1 version, which returns an int, + // indicating success or not + // b) the GNU version, which returns a char*, which may or may not + // be the beginning of the buffer we used + // The GNU libc manpage for strerror_r says you should use the the XSI + // version in portable code. However, it's impossible to do that if + // _GNU_SOURCE is defined so we use C++ overloading to decide what to do + // depending on the return type + static inline QString fromstrerror_helper(int, const QByteArray &buf) + { + return QString::fromLocal8Bit(buf); + } + static inline QString fromstrerror_helper(const char *str, const QByteArray &) + { + return QString::fromLocal8Bit(str); + } +} +#endif QString qt_error_string(int errorCode) { @@ -2122,12 +2143,9 @@ QString qt_error_string(int errorCode) if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND) ret = QString::fromLatin1("The specified module could not be found."); - #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) - QByteArray buf(1024, '\0'); - strerror_r(errorCode, buf.data(), buf.size()); - ret = QString::fromLocal8Bit(buf.constData()); + ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf); #else ret = QString::fromLocal8Bit(strerror(errorCode)); #endif diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index f2cef4e1..bb11d6b 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -755,7 +755,6 @@ qint64 QIODevice::bytesToWrite() const qint64 QIODevice::read(char *data, qint64 maxSize) { Q_D(QIODevice); - CHECK_READABLE(read, qint64(-1)); #if defined QIODEVICE_DEBUG printf("%p QIODevice::read(%p, %d), d->pos = %d, d->buffer.size() = %d\n", @@ -786,13 +785,13 @@ qint64 QIODevice::read(char *data, qint64 maxSize) do { // Try reading from the buffer. int lastReadChunkSize = d->buffer.read(data, maxSize); - *d->pPos += lastReadChunkSize; - readSoFar += lastReadChunkSize; - // fast exit when satisfied by buffer - if (lastReadChunkSize == maxSize && !(d->openMode & Text)) - return readSoFar; - if (lastReadChunkSize > 0) { + *d->pPos += lastReadChunkSize; + readSoFar += lastReadChunkSize; + // fast exit when satisfied by buffer + if (lastReadChunkSize == maxSize && !(d->openMode & Text)) + return readSoFar; + data += lastReadChunkSize; maxSize -= lastReadChunkSize; #if defined QIODEVICE_DEBUG diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 3b86e89..4566ec0 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -43,7 +43,6 @@ #include <private/qthread_p.h> #include <qcoreapplication.h> #include <private/qcoreapplication_p.h> -#include <qdatetime.h> #include <unistd.h> #include <errno.h> @@ -636,6 +635,74 @@ void QSocketActiveObject::deleteLater() } } +#ifdef QT_SYMBIAN_PRIORITY_DROP +class QIdleDetectorThread +{ +public: + QIdleDetectorThread() + : m_state(STATE_RUN), m_stop(false) + { + qt_symbian_throwIfError(m_lock.CreateLocal()); + TInt err = m_idleDetectorThread.Create(KNullDesC(), &idleDetectorThreadFunc, 1024, &User::Allocator(), this); + if (err != KErrNone) + m_lock.Close(); + qt_symbian_throwIfError(err); + m_idleDetectorThread.SetPriority(EPriorityAbsoluteBackgroundNormal); + m_idleDetectorThread.Resume(); + } + + ~QIdleDetectorThread() + { + // close down the idle thread because if corelib is loaded temporarily, this would leak threads into the host process + m_stop = true; + m_lock.Signal(); + m_idleDetectorThread.SetPriority(EPriorityNormal); + TRequestStatus s; + m_idleDetectorThread.Logon(s); + User::WaitForRequest(s); + m_idleDetectorThread.Close(); + m_lock.Close(); + } + + void kick() + { + m_state = STATE_KICKED; + m_lock.Signal(); + } + + bool hasRun() + { + return m_state == STATE_RUN; + } + +private: + static TInt idleDetectorThreadFunc(TAny* self) + { + static_cast<QIdleDetectorThread*>(self)->IdleLoop(); + return KErrNone; + } + + void IdleLoop() + { + while (!m_stop) { + m_lock.Wait(); + m_state = STATE_RUN; + } + } + +private: + enum IdleStates {STATE_KICKED, STATE_RUN} m_state; + bool m_stop; + RThread m_idleDetectorThread; + RFastLock m_lock; +}; + +Q_GLOBAL_STATIC(QIdleDetectorThread, idleDetectorThread); + +const int maxBusyTime = 2000; // maximum time we allow idle detector to be blocked before worrying, in milliseconds +const int baseDelay = 1000; // minimum delay time used when backing off to allow idling, in microseconds +#endif + QEventDispatcherSymbian::QEventDispatcherSymbian(QObject *parent) : QAbstractEventDispatcher(parent), m_selectThread(0), @@ -647,11 +714,15 @@ QEventDispatcherSymbian::QEventDispatcherSymbian(QObject *parent) m_iterationCount(0), m_noSocketEvents(false) { +#ifdef QT_SYMBIAN_PRIORITY_DROP + m_delay = baseDelay; + m_avgEventTime = 0; + idleDetectorThread(); +#endif } QEventDispatcherSymbian::~QEventDispatcherSymbian() { - m_processHandle.Close(); } void QEventDispatcherSymbian::startingUp() @@ -720,23 +791,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla m_interrupt = false; #ifdef QT_SYMBIAN_PRIORITY_DROP - /* - * This QTime variable is used to measure the time it takes to finish - * the event loop. If we take too long in the loop, other processes - * may be starved and killed. After the first event has completed, we - * take the current time, and if the remaining events take longer than - * a preset time, we temporarily lower the priority to force a context - * switch. For applications that do not take unecessarily long in the - * event loop, the priority will not be altered. - */ - QTime time; - enum { - FirstRun, - SubsequentRun, - TimeStarted - } timeState = FirstRun; - - TProcessPriority priority; + QTime eventTimer; #endif while (1) { @@ -752,10 +807,18 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla } #ifdef QT_SYMBIAN_PRIORITY_DROP - if (timeState == SubsequentRun) { - time.start(); - timeState = TimeStarted; + if (idleDetectorThread()->hasRun()) { + if (m_delay > baseDelay) + m_delay -= baseDelay; + m_lastIdleRequestTimer.start(); + idleDetectorThread()->kick(); + } else if (m_lastIdleRequestTimer.elapsed() > maxBusyTime) { + User::AfterHighRes(m_delay); + // allow delay to be up to 1/4 of execution time + if (!idleDetectorThread()->hasRun() && m_delay*3 < m_avgEventTime) + m_delay += baseDelay; } + eventTimer.start(); #endif TInt error; @@ -765,6 +828,12 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla CActiveScheduler::Current()->Error(error); } +#ifdef QT_SYMBIAN_PRIORITY_DROP + int eventDur = eventTimer.elapsed()*1000; + // average is calcualted as a 5% decaying exponential average + m_avgEventTime = (m_avgEventTime * 95 + eventDur * 5) / 100; +#endif + if (!handledSymbianEvent) { qFatal("QEventDispatcherSymbian::processEvents(): Caught Symbian stray signal"); } @@ -773,20 +842,6 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla break; } block = false; -#ifdef QT_SYMBIAN_PRIORITY_DROP - if (timeState == TimeStarted && time.elapsed() > 100) { - priority = m_processHandle.Priority(); - m_processHandle.SetPriority(EPriorityBackground); - time.start(); - // Slight chance of race condition in the next lines, but nothing fatal - // will happen, just wrong priority. - if (m_processHandle.Priority() == EPriorityBackground) { - m_processHandle.SetPriority(priority); - } - } - if (timeState == FirstRun) - timeState = SubsequentRun; -#endif }; emit awake(); diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index 5281199..05758ca 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -62,6 +62,7 @@ #include <qmutex.h> #include <qwaitcondition.h> #include <qsocketnotifier.h> +#include <qdatetime.h> #include <e32base.h> @@ -280,7 +281,9 @@ private: QList<QActiveObject *> m_deferredActiveObjects; - RProcess m_processHandle; + int m_delay; + int m_avgEventTime; + QTime m_lastIdleRequestTimer; }; #ifdef QT_DEBUG diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index c5f70b0..29a7263 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -3814,7 +3814,7 @@ QByteArray QByteArray::number(double n, char f, int prec) accepting a \c{const char *} expected to be '\\0'-terminated will fail. - \sa data(), constData() + \sa setRawData(), data(), constData() */ QByteArray QByteArray::fromRawData(const char *data, int size) @@ -3834,6 +3834,37 @@ QByteArray QByteArray::fromRawData(const char *data, int size) } /*! + \since 4.7 + + Resets the QByteArray to use the first \a size bytes of the + \a data array. The bytes are \e not copied. The QByteArray will + contain the \a data pointer. The caller guarantees that \a data + will not be deleted or modified as long as this QByteArray and any + copies of it exist that have not been modified. + + This function can be used instead of fromRawData() to re-use + existings QByteArray objects to save memory re-allocations. + + \sa fromRawData(), data(), constData() +*/ +QByteArray &QByteArray::setRawData(const char *data, uint size) +{ + if (d->ref != 1 || d->alloc) { + *this = fromRawData(data, size); + } else { + if (data) { + d->data = const_cast<char *>(data); + } else { + d->data = d->array; + size = 0; + } + d->alloc = d->size = size; + *d->array = '\0'; + } + return *this; +} + +/*! Returns a decoded copy of the Base64 array \a base64. Input is not checked for validity; invalid characters in the input are skipped, enabling the decoding process to continue with subsequent characters. @@ -4228,12 +4259,6 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA */ /*! - \fn QByteArray& QByteArray::setRawData(const char *a, uint n) - - Use fromRawData() instead. -*/ - -/*! \fn void QByteArray::resetRawData(const char *data, uint n) Use clear() instead. diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 0b77512..a3fe3f5 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -299,6 +299,7 @@ public: QByteArray &setNum(qulonglong, int base = 10); QByteArray &setNum(float, char f = 'g', int prec = 6); QByteArray &setNum(double, char f = 'g', int prec = 6); + QByteArray &setRawData(const char *a, uint n); // ### Qt 5: use an int static QByteArray number(int, int base = 10); static QByteArray number(uint, int base = 10); @@ -343,8 +344,6 @@ public: inline QT3_SUPPORT QByteArray& duplicate(const QByteArray& a) { *this = a; return *this; } inline QT3_SUPPORT QByteArray& duplicate(const char *a, uint n) { *this = QByteArray(a, n); return *this; } - inline QT3_SUPPORT QByteArray& setRawData(const char *a, uint n) - { *this = fromRawData(a, n); return *this; } inline QT3_SUPPORT void resetRawData(const char *, uint) { clear(); } inline QT3_SUPPORT QByteArray lower() const { return toLower(); } inline QT3_SUPPORT QByteArray upper() const { return toUpper(); } diff --git a/src/corelib/tools/qbytedata_p.h b/src/corelib/tools/qbytedata_p.h index c48bb33..08249e0 100644 --- a/src/corelib/tools/qbytedata_p.h +++ b/src/corelib/tools/qbytedata_p.h @@ -84,7 +84,7 @@ public: } - inline void append(QByteArray& bd) + inline void append(const QByteArray& bd) { if (bd.isEmpty()) return; diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 6f5bb9b..6cc6fc1 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -853,9 +853,7 @@ void **QListData::erase(void **xi) same as takeAt(0). This function assumes the list is not empty. To avoid failure, call isEmpty() before calling this function. - This operation is very fast (\l{constant time}), because QList - preallocates extra space on both sides of its internal buffer to - allow for fast growth at both ends of the list. + This operation takes \l{constant time}. If you don't use the return value, removeFirst() is more efficient. @@ -870,9 +868,7 @@ void **QListData::erase(void **xi) not empty. To avoid failure, call isEmpty() before calling this function. - This operation is very fast (\l{constant time}), because QList - preallocates extra space on both sides of its internal buffer to - allow for fast growth at both ends of the list. + This operation takes \l{constant time}. If you don't use the return value, removeLast() is more efficient. diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 2f12b80..0169b20 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -7056,7 +7056,7 @@ void QString::updateProperties() const '\\0'-terminated string (although utf16() does, at the cost of copying the raw data). - \sa fromUtf16() + \sa fromUtf16(), setRawData() */ QString QString::fromRawData(const QChar *unicode, int size) { @@ -7075,6 +7075,44 @@ QString QString::fromRawData(const QChar *unicode, int size) return QString(x, 0); } +/*! + \since 4.7 + + Resets the QString to use the first \a size Unicode characters + in the array \a unicode. The data in \a unicode is \e not + copied. The caller must be able to guarantee that \a unicode will + not be deleted or modified as long as the QString (or an + unmodified copy of it) exists. + + This function can be used instead of fromRawData() to re-use + existings QString objects to save memory re-allocations. + + \sa fromRawData() +*/ +QString &QString::setRawData(const QChar *unicode, int size) +{ + if (d->ref != 1 || d->alloc) { + *this = fromRawData(unicode, size); + } else { +#ifdef QT3_SUPPORT + if (d->asciiCache) { + Q_ASSERT(asciiCache); + asciiCache->remove(d); + } +#endif + if (unicode) { + d->data = (ushort *)unicode; + } else { + d->data = d->array; + size = 0; + } + d->alloc = d->size = size; + *d->array = '\0'; + d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0; + } + return *this; +} + /*! \class QLatin1String \brief The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal. diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index ea12c2f..a1c4e77 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -343,6 +343,7 @@ public: int toWCharArray(wchar_t *array) const; static QString fromWCharArray(const wchar_t *, int size = -1); + QString &setRawData(const QChar *unicode, int size); QString &setUnicode(const QChar *unicode, int size); inline QString &setUtf16(const ushort *utf16, int size); diff --git a/src/corelib/xml/qxmlstream.g b/src/corelib/xml/qxmlstream.g index 1b882e0..e91408f 100644 --- a/src/corelib/xml/qxmlstream.g +++ b/src/corelib/xml/qxmlstream.g @@ -748,7 +748,7 @@ bool QXmlStreamReaderPrivate::parse() state_stack[tos] = 0; return true; } else if (act > 0) { - if (++tos == stack_size) + if (++tos == stack_size-1) reallocateStack(); Value &val = sym_stack[tos]; diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h index ac421cf..f6ab3a1 100644 --- a/src/corelib/xml/qxmlstream_p.h +++ b/src/corelib/xml/qxmlstream_p.h @@ -61,7 +61,7 @@ class QXmlStreamReader_Table { public: - enum { + enum VariousConstants { EOF_SYMBOL = 0, AMPERSAND = 5, ANY = 41, @@ -1242,7 +1242,7 @@ bool QXmlStreamReaderPrivate::parse() state_stack[tos] = 0; return true; } else if (act > 0) { - if (++tos == stack_size) + if (++tos == stack_size-1) reallocateStack(); Value &val = sym_stack[tos]; diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index bc0c65e..096e4bf 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -1268,11 +1268,6 @@ QDeclarativeKeysAttached *QDeclarativeKeysAttached::qmlAttachedProperties(QObjec */ /*! - \property QDeclarativeItem::effect - \internal -*/ - -/*! \property QDeclarativeItem::focus \internal */ diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index 6c562ef..4fc1338 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -154,7 +154,13 @@ QT_BEGIN_NAMESPACE // Declare/define the bits of EGL_KHR_image_base we need: #if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base) +#ifdef Q_OS_SYMBIAN +//symbian version of eglext.h differs from the khronos reference +typedef int EGLImageKHR; +#else typedef void *EGLImageKHR; +#endif + #define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) #define EGL_IMAGE_PRESERVED_KHR 0x30D2 #define EGL_KHR_image_base diff --git a/src/gui/egl/qegl_stub.cpp b/src/gui/egl/qegl_stub.cpp index 0bd3451..86a7aab 100644 --- a/src/gui/egl/qegl_stub.cpp +++ b/src/gui/egl/qegl_stub.cpp @@ -183,14 +183,6 @@ int QEglContext::configAttrib(int name) const return 0; } -typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*); -typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR); - -// Defined in qegl.cpp: -static _eglCreateImageKHR qt_eglCreateImageKHR = 0; -static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0; - - EGLDisplay QEgl::display() { NOEGL diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 6b22607..569a329 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -845,6 +845,13 @@ inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem inline void QGraphicsItemPrivate::markParentDirty(bool updateBoundingRect) { QGraphicsItemPrivate *parentp = this; +#ifndef QT_NO_GRAPHICSEFFECT + if (updateBoundingRect && parentp->graphicsEffect && !parentp->inSetPosHelper) { + parentp->notifyInvalidated = 1; + static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func() + ->source->d_func())->invalidateCache(); + } +#endif while (parentp->parent) { parentp = parentp->parent->d_ptr.data(); parentp->dirtyChildren = 1; diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index 1f89714..320395e 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -975,6 +975,7 @@ bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event) d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode; } break; +#ifndef QT_NO_TOOLTIP case QEvent::ToolTipChange: // Propagate tooltip change to the proxy. if (!d->tooltipChangeMode) { @@ -983,6 +984,7 @@ bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event) d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode; } break; +#endif default: break; } diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 729837a..80e3ec1 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -183,8 +183,12 @@ public: else QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); #else - QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::ExcludeSocketNotifiers - | QEventLoop::ExcludeUserInputEvents); + // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa) + // is called, which means there's a pending update request. We want to dispatch it + // now because otherwise graphics view updates would require two + // round-trips in the event loop before the item is painted. + extern void qt_mac_dispatchPendingUpdateRequests(QWidget *); + qt_mac_dispatchPendingUpdateRequests(viewport->window()); #endif } diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index bc8ccb01..06a44b7 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -324,11 +324,9 @@ void QGraphicsWidget::resize(const QSizeF &size) */ /*! - \fn QGraphicsWidget::geometryChanged() - This signal gets emitted whenever the geometry of the item changes - \internal + This signal gets emitted whenever the geometry is changed in setGeometry(). */ /*! @@ -408,12 +406,6 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) } /*! - \fn QGraphicsWidget::geometryChanged() - - This signal gets emitted whenever the geometry is changed in setGeometry(). -*/ - -/*! \fn QRectF QGraphicsWidget::rect() const Returns the item's local rect as a QRectF. This function is equivalent diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index c735d1f..5f7813b 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -73,6 +73,7 @@ # endif # include <private/qs60mainapplication_p.h> # include <centralrepository.h> +# include "qs60mainappui.h" #endif #include "private/qstylesheetstyle_p.h" @@ -539,6 +540,14 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) sendMouseEvent(receiver, type, globalPos, button, modifiers); } +#ifdef Q_WS_S60 +void QSymbianControl::HandleStatusPaneSizeChange() +{ + QS60MainAppUi *s60AppUi = static_cast<QS60MainAppUi *>(S60->appUi()); + s60AppUi->HandleStatusPaneSizeChange(); +} +#endif + void QSymbianControl::sendMouseEvent( QWidget *receiver, QEvent::Type type, @@ -982,15 +991,6 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) const TBool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; const TBool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint; buttonGroup->MakeVisible(visible || (isFullscreen && cbaVisibilityHint)); - - // Responsiviness - CEikCba *cba = static_cast<CEikCba *>( buttonGroup->ButtonGroup() ); // downcast from MEikButtonGroup - TUint cbaFlags = cba->ButtonGroupFlags(); - if(qwidget->windowFlags() & Qt::WindowSoftkeysRespondHint) - cbaFlags |= EAknCBAFlagRespondWhenInvisible; - else - cbaFlags &= ~EAknCBAFlagRespondWhenInvisible; - cba->SetButtonGroupFlags(cbaFlags); } #endif } else if (QApplication::activeWindow() == qwidget->window()) { diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index e94d247..8652816 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -363,3 +363,57 @@ QT_END_NAMESPACE } [super displayIfNeeded]; } + +// This is a hack and it should be removed once we find the real cause for +// the painting problems. +// We have a static variable that signals if we have been called before or not. +static bool firstDrawingInvocation = true; + +// The method below exists only as a workaround to draw/not draw the baseline +// in the title bar. This is to support unifiedToolbar look. + +// This method is very special. To begin with, it is a +// method that will get called only if we enable documentMode. +// Furthermore, it won't get called as a normal method, we swap +// this method with the normal implementation of drawRect in +// _NSThemeFrame. When this method is active, its mission is to +// first call the original drawRect implementation so the widget +// gets proper painting. After that, it needs to detect if there +// is a toolbar or not, in order to decide how to handle the unified +// look. The distinction is important since the presence and +// visibility of a toolbar change the way we enter into unified mode. +// When there is a toolbar and that toolbar is visible, the problem +// is as simple as to tell the toolbar not to draw its baseline. +// However when there is not toolbar or the toolbar is not visible, +// we need to draw a line on top of the baseline, because the baseline +// in that case will belong to the title. For this case we need to draw +// a line on top of the baseline. +// As usual, there is a special case. When we first are called, we might +// need to repaint ourselves one more time. We only need that if we +// didn't get the activation, i.e. when we are launched via the command +// line. And this only if the toolbar is visible from the beginning, +// so we have a special flag that signals if we need to repaint or not. +- (void)drawRectSpecial:(NSRect)rect +{ + // Call the original drawing method. + [self drawRectOriginal:rect]; + NSWindow *window = [self window]; + NSToolbar *toolbar = [window toolbar]; + if(!toolbar) { + // There is no toolbar, we have to draw a line on top of the line drawn by Cocoa. + macDrawRectOnTop((void *)window); + } else { + if([toolbar isVisible]) { + // We tell Cocoa to avoid drawing the line at the end. + if(firstDrawingInvocation) { + firstDrawingInvocation = false; + macSyncDrawingOnFirstInvocation((void *)window); + } else + [toolbar setShowsBaselineSeparator:NO]; + } else { + // There is a toolbar but it is not visible so + // we have to draw a line on top of the line drawn by Cocoa. + macDrawRectOnTop((void *)window); + } + } +} diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index dd12f65..4953c48 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -1554,7 +1554,8 @@ Qt::DropAction QDragManager::drag(QDrag *o) qt_button_down = 0; [dndParams.view release]; [image release]; - dragPrivate()->executed_action = Qt::IgnoreAction; + if (dragPrivate()) + dragPrivate()->executed_action = Qt::IgnoreAction; object = 0; Qt::DropAction performedAction(qt_mac_mapNSDragOperation(qMacDnDParams()->performedAction)); // do post drag processing, if required. diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp index e4990b1..6325d95 100644 --- a/src/gui/kernel/qsoftkeymanager_s60.cpp +++ b/src/gui/kernel/qsoftkeymanager_s60.cpp @@ -79,6 +79,8 @@ bool QSoftKeyManagerPrivateS60::skipCbaUpdate() // Note: Cannot use IsDisplayingMenuOrDialog since CBA update can be triggered before // menu/dialog CBA is actually displayed i.e. it is being costructed. CEikButtonGroupContainer *appUiCba = S60->buttonGroupContainer(); + if (!appUiCba) + return true; // CEikButtonGroupContainer::Current returns 0 if CBA is not visible at all CEikButtonGroupContainer *currentCba = CEikButtonGroupContainer::Current(); // Check if softkey need to be update even they are not visible diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index a05c7d5..8cef03c 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -1163,15 +1163,81 @@ void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::H #endif } +#if QT_MAC_USE_COCOA +void qt_mac_replaceDrawRect(void * /*OSWindowRef */window, QWidgetPrivate *widget) +{ + QMacCocoaAutoReleasePool pool; + OSWindowRef theWindow = static_cast<OSWindowRef>(window); + if(!theWindow) + return; + id theClass = [[[theWindow contentView] superview] class]; + // What we do here is basically to add a new selector to NSThemeFrame called + // "drawRectOriginal:" which will contain the original implementation of + // "drawRect:". After that we get the new implementation from QCocoaWindow + // and exchange them. The new implementation is called drawRectSpecial. + // We cannot just add the method because it might have been added before and since + // we cannot remove a method once it has been added we need to ask QCocoaWindow if + // we did the swap or not. + if(!widget->drawRectOriginalAdded) { + Method m2 = class_getInstanceMethod(theClass, @selector(drawRect:)); + if(!m2) { + // This case is pretty extreme, no drawRect means no drawing! + return; + } + class_addMethod(theClass, @selector(drawRectOriginal:), method_getImplementation(m2), method_getTypeEncoding(m2)); + widget->drawRectOriginalAdded = true; + } + if(widget->originalDrawMethod) { + Method m0 = class_getInstanceMethod([theWindow class], @selector(drawRectSpecial:)); + if(!m0) { + // Ok, this means the methods were never swapped. Just ignore + return; + } + Method m1 = class_getInstanceMethod(theClass, @selector(drawRect:)); + if(!m1) { + // Ok, this means the methods were never swapped. Just ignore + return; + } + // We have the original method here. Proceed and swap the methods. + method_exchangeImplementations(m1, m0); + widget->originalDrawMethod = false; + [window display]; + } +} + +void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivate *widget) +{ + QMacCocoaAutoReleasePool pool; + OSWindowRef theWindow = static_cast<OSWindowRef>(window); + id theClass = [[[theWindow contentView] superview] class]; + // Now we need to revert the methods to their original state. + // We cannot remove the method, so we just keep track of it in QCocoaWindow. + Method m0 = class_getInstanceMethod([theWindow class], @selector(drawRectSpecial:)); + if(!m0) { + // Ok, this means the methods were never swapped. Just ignore + return; + } + Method m1 = class_getInstanceMethod(theClass, @selector(drawRect:)); + if(!m1) { + // Ok, this means the methods were never swapped. Just ignore + return; + } + method_exchangeImplementations(m1, m0); + widget->originalDrawMethod = true; + [window display]; +} +#endif // QT_MAC_USE_COCOA + void qt_mac_showBaseLineSeparator(void * /*OSWindowRef */window, bool show) { + if(!window) + return; #if QT_MAC_USE_COCOA QMacCocoaAutoReleasePool pool; OSWindowRef theWindow = static_cast<OSWindowRef>(window); NSToolbar *macToolbar = [theWindow toolbar]; - if (macToolbar) - [macToolbar setShowsBaselineSeparator: show]; -#endif + [macToolbar setShowsBaselineSeparator:show]; +#endif // QT_MAC_USE_COCOA } QStringList qt_mac_NSArrayToQStringList(void *nsarray) @@ -1233,6 +1299,17 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget) return context; } +void qt_mac_dispatchPendingUpdateRequests(QWidget *widget) +{ + if (!widget) + return; +#ifndef QT_MAC_USE_COCOA + HIViewRender(qt_mac_nativeview_for(widget)); +#else + [qt_mac_nativeview_for(widget) displayIfNeeded]; +#endif +} + CGFloat qt_mac_get_scalefactor() { #ifndef QT_MAC_USE_COCOA @@ -1403,4 +1480,52 @@ void qt_mac_post_retranslateAppMenu() #endif } +#ifdef QT_MAC_USE_COCOA +// This method implements the magic for the drawRectSpecial method. +// We draw a line at the upper edge of the content view in order to +// override the title baseline. +void macDrawRectOnTop(void * /*OSWindowRef */window) +{ + OSWindowRef theWindow = static_cast<OSWindowRef>(window); + NSView *contentView = [theWindow contentView]; + if(!contentView) + return; + // Get coordinates of the content view + NSRect contentRect = [contentView frame]; + // Draw a line on top of the already drawn line. + // We need to check if we are active or not to use the proper color. + if([window isKeyWindow] || [window isMainWindow]) { + [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set]; + } else { + [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set]; + } + NSPoint origin = NSMakePoint(0, contentRect.size.height); + NSPoint end = NSMakePoint(contentRect.size.width, contentRect.size.height); + [NSBezierPath strokeLineFromPoint:origin toPoint:end]; +} + +// This method will (or at least should) get called only once. +// Its mission is to find out if we are active or not. If we are active +// we assume that we were launched via finder, otherwise we assume +// we were called from the command line. The distinction is important, +// since in the first case we don't need to trigger a paintEvent, while +// in the second case we do. +void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window) +{ + OSWindowRef theWindow = static_cast<OSWindowRef>(window); + NSApplication *application = [NSApplication sharedApplication]; + NSToolbar *toolbar = [window toolbar]; + if([application isActive]) { + // Launched from finder + [toolbar setShowsBaselineSeparator:NO]; + } else { + // Launched from commandline + [toolbar setVisible:false]; + [toolbar setShowsBaselineSeparator:NO]; + [toolbar setVisible:true]; + [theWindow display]; + } +} +#endif // QT_MAC_USE_COCOA + QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 3fd62a4..5db121a 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -131,6 +131,8 @@ void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow ); void macWindowFlush(void * /*OSWindowRef*/ window); void macSendToolbarChangeEvent(QWidget *widget); void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::HIContentBorderMetrics &metrics); +void qt_mac_replaceDrawRect(void * /*OSWindowRef */window, QWidgetPrivate *widget); +void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivate *widget); void qt_mac_showBaseLineSeparator(void * /*OSWindowRef */window, bool show); void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm); void qt_mac_update_mouseTracking(QWidget *widget); @@ -140,6 +142,9 @@ void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent); #ifdef QT_MAC_USE_COCOA bool qt_dispatchKeyEventWithCocoa(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent); void qt_cocoaChangeOverrideCursor(const QCursor &cursor); +// These methods exists only for supporting unified mode. +void macDrawRectOnTop(void * /*OSWindowRef */ window); +void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window); #endif void qt_mac_menu_collapseSeparators(void * /*NSMenu */ menu, bool collapse); bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent); diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h index 7bfb257..3341ce1 100644 --- a/src/gui/kernel/qt_mac_p.h +++ b/src/gui/kernel/qt_mac_p.h @@ -57,6 +57,7 @@ #ifdef __OBJC__ #include <Cocoa/Cocoa.h> +#include <objc/runtime.h> #endif #include <CoreServices/CoreServices.h> diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index a714221..58da302 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -155,7 +155,7 @@ class QLongTapTimer; class QSymbianControl : public CCoeControl, public QAbstractLongTapObserver #ifdef Q_WS_S60 -, public MAknFadedComponent +, public MAknFadedComponent, public MEikStatusPaneObserver #endif { public: @@ -183,6 +183,7 @@ public: #ifdef Q_WS_S60 void FadeBehindPopup(bool fade){ popupFader.FadeBehindPopup( this, this, fade); } + void HandleStatusPaneSizeChange(); protected: // from MAknFadedComponent TInt CountFadedComponents() {return 1;} diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index fb70d7c..6f4a20f 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -220,6 +220,11 @@ QWidgetPrivate::QWidgetPrivate(int version) isWidget = true; memset(high_attributes, 0, sizeof(high_attributes)); +#if QT_MAC_USE_COCOA + drawRectOriginalAdded = false; + originalDrawMethod = true; + changeMethods = false; +#endif // QT_MAC_USE_COCOA #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; qDebug() << "widgets" << ++count; @@ -12309,6 +12314,28 @@ void QWidgetPrivate::_q_delayedDestroy(WId winId) } #endif +#if QT_MAC_USE_COCOA +void QWidgetPrivate::syncUnifiedMode() { + // The whole purpose of this method is to keep the unifiedToolbar in sync. + // That means making sure we either exchange the drawing methods or we let + // the toolbar know that it does not require to draw the baseline. + Q_Q(QWidget); + // This function makes sense only if this is a top level + if(!q->isWindow()) + return; + OSWindowRef window = qt_mac_window_for(q); + if(changeMethods) { + // Ok, we are in documentMode. + if(originalDrawMethod) + qt_mac_replaceDrawRect(window, this); + } else { + if(!originalDrawMethod) + qt_mac_replaceDrawRectOriginal(window, this); + } +} + +#endif // QT_MAC_USE_COCOA + QT_END_NAMESPACE #include "moc_qwidget.cpp" diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index d7cd2eb..e29b755 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2300,6 +2300,12 @@ void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWin if (q->testAttribute(Qt::WA_DropSiteRegistered)) registerDropSite(true); transferChildren(); + + // Tell Cocoa explicit that we wan't the view to receive key events + // (regardless of focus policy) because this is how it works on other + // platforms (and in the carbon port): + if (!qApp->focusWidget()) + [windowRef makeFirstResponder:nsview]; } if (topExtra->posFromMove) { diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 05a859c..9926b2c 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -774,6 +774,13 @@ public: void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef); void syncCocoaMask(); void finishCocoaMaskSetup(); + void syncUnifiedMode(); + // Did we add the drawRectOriginal method? + bool drawRectOriginalAdded; + // Is the original drawRect method available? + bool originalDrawMethod; + // Do we need to change the methods? + bool changeMethods; #endif void determineWindowClass(); void transferChildren(); diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index bfa7050..a0429d3 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -387,16 +387,7 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de | EPointerFilterMove | EPointerFilterDrag, 0); drawableWindow->EnableVisibilityChangeEvents(); - if (!isOpaque) { - RWindow *const window = static_cast<RWindow *>(drawableWindow); -#ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE - window->SetSurfaceTransparency(true); -#else - const TDisplayMode displayMode = static_cast<TDisplayMode>(window->SetRequiredDisplayMode(EColor16MA)); - if (window->SetTransparencyAlphaChannel() == KErrNone) - window->SetBackgroundColor(TRgb(255, 255, 255, 0)); -#endif - } + s60UpdateIsOpaque(); } q->setAttribute(Qt::WA_WState_Created); @@ -488,6 +479,47 @@ void QWidgetPrivate::show_sys() QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId()); +#ifdef Q_WS_S60 + // Lazily initialize the S60 screen furniture when the first window is shown. + if (!QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) + && !S60->buttonGroupContainer() && !S60->statusPane()) { + + bool isFullscreen = q->windowState() & Qt::WindowFullScreen; + bool cbaRequested = q->windowFlags() & Qt::WindowSoftkeysVisibleHint; + + // If the window is fullscreen and has not explicitly requested that the CBA be visible + // we delay the creation even more. + if ((!isFullscreen || cbaRequested) && !q->testAttribute(Qt::WA_DontShowOnScreen)) { + + // Create the status pane and CBA here + CEikAppUi *ui = static_cast<CEikAppUi *>(S60->appUi()); + MEikAppUiFactory *factory = CEikonEnv::Static()->AppUiFactory(); + TRAP_IGNORE(factory->ReadAppInfoResourceL(0, ui)); + if (S60->buttonGroupContainer()) + S60->buttonGroupContainer()->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); + + if (S60->statusPane()) { + // Use QDesktopWidget as the status pane observer to proxy for the AppUi. + // Can't use AppUi directly because it privately inherits from MEikStatusPaneObserver. + QSymbianControl *desktopControl = static_cast<QSymbianControl *>(QApplication::desktop()->winId()); + S60->statusPane()->SetObserver(desktopControl); + + // Hide the status pane if fullscreen OR + // Fill client area if maximized OR + // Put window below status pane unless the window has an explicit position. + if (isFullscreen) { + S60->statusPane()->MakeVisible(false); + } else if (q->windowState() & Qt::WindowMaximized) { + TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); + id->SetExtent(r.iTl, r.Size()); + } else if (!q->testAttribute(Qt::WA_Moved)) { + id->SetPosition(static_cast<CEikAppUi*>(S60->appUi())->ClientRect().iTl); + } + } + } + } +#endif + id->MakeVisible(true); if(q->isWindow()) @@ -1063,6 +1095,9 @@ void QWidget::setWindowState(Qt::WindowStates newstate) return; if (isWindow()) { + createWinId(); + Q_ASSERT(testAttribute(Qt::WA_WState_Created)); + const bool wasResized = testAttribute(Qt::WA_Resized); const bool wasMoved = testAttribute(Qt::WA_Moved); @@ -1088,35 +1123,35 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if (buttonGroup) { // Visibility buttonGroup->MakeVisible(visible || (isFullscreen && cbaRequested)); - - // Responsiviness - CEikCba *cba = static_cast<CEikCba *>( buttonGroup->ButtonGroup() ); // downcast from MEikButtonGroup - TUint cbaFlags = cba->ButtonGroupFlags(); - if(windowFlags() & Qt::WindowSoftkeysRespondHint) - cbaFlags |= EAknCBAFlagRespondWhenInvisible; - else - cbaFlags &= ~EAknCBAFlagRespondWhenInvisible; - cba->SetButtonGroupFlags(cbaFlags); } #endif // Q_WS_S60 - createWinId(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); // Ensure the initial size is valid, since we store it as normalGeometry below. if (!wasResized && !isVisible()) adjustSize(); QTLWExtra *top = d->topData(); - const QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry; - + QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry; const bool cbaVisibilityHint = windowFlags() & Qt::WindowSoftkeysVisibleHint; - if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint) - setGeometry(qApp->desktop()->screenGeometry(this)); - else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint)) - setGeometry(qApp->desktop()->availableGeometry(this)); - else + if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint) { + window->SetExtentToWholeScreen(); + } else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint)) { + TRect maxExtent = qt_QRect2TRect(qApp->desktop()->availableGeometry(this)); + window->SetExtent(maxExtent.iTl, maxExtent.Size()); + } else { +#ifdef Q_WS_S60 + // With delayed creation of S60 app panes, the normalGeometry calculated above is not + // accurate because it did not consider the status pane. This means that when returning + // normal mode after showing the status pane, the geometry would overlap so we should + // move it if it never had an explicit position. + if (!wasMoved && statusPane && visible) { + TPoint tl = static_cast<CEikAppUi*>(S60->appUi())->ClientRect().iTl; + normalGeometry.setTopLeft(QPoint(tl.iX, tl.iY)); + } +#endif setGeometry(normalGeometry); + } //restore normal geometry top->normalGeometry = normalGeometry; diff --git a/src/gui/painting/qprintengine_ps.cpp b/src/gui/painting/qprintengine_ps.cpp index ac94de3..28e9a7a 100644 --- a/src/gui/painting/qprintengine_ps.cpp +++ b/src/gui/painting/qprintengine_ps.cpp @@ -485,7 +485,6 @@ void QPSPrintEnginePrivate::emitHeader(bool finished) QByteArray header; QPdf::ByteStream s(&header); - s << "%!PS-Adobe-1.0"; qreal scale = 72. / ((qreal) q->metric(QPaintDevice::PdmDpiY)); QRect pageRect = this->pageRect(); @@ -497,28 +496,32 @@ void QPSPrintEnginePrivate::emitHeader(bool finished) int width = pageRect.width(); int height = pageRect.height(); if (finished && pageCount == 1 && copies == 1 && - ((fullPage && qt_gen_epsf) || (outputFileName.endsWith(QLatin1String(".eps")))) - ) { + ((fullPage && qt_gen_epsf) || (outputFileName.endsWith(QLatin1String(".eps"))))) + { + // According to the EPSF 3.0 spec it is required that the PS + // version is PS-Adobe-3.0 + s << "%!PS-Adobe-3.0"; if (!boundingBox.isValid()) boundingBox.setRect(0, 0, width, height); if (orientation == QPrinter::Landscape) { if (!fullPage) boundingBox.translate(-mleft, -mtop); s << " EPSF-3.0\n%%BoundingBox: " - << (int)(printer->height() - boundingBox.bottom())*scale // llx - << (int)(printer->width() - boundingBox.right())*scale - 1 // lly - << (int)(printer->height() - boundingBox.top())*scale + 1 // urx - << (int)(printer->width() - boundingBox.left())*scale; // ury + << int((printer->height() - boundingBox.bottom())*scale) // llx + << int((printer->width() - boundingBox.right())*scale - 1) // lly + << int((printer->height() - boundingBox.top())*scale + 1) // urx + << int((printer->width() - boundingBox.left())*scale); // ury } else { if (!fullPage) boundingBox.translate(mleft, -mtop); s << " EPSF-3.0\n%%BoundingBox: " - << (int)(boundingBox.left())*scale - << (int)(printer->height() - boundingBox.bottom())*scale - 1 - << (int)(boundingBox.right())*scale + 1 - << (int)(printer->height() - boundingBox.top())*scale; + << int((boundingBox.left())*scale) + << int((printer->height() - boundingBox.bottom())*scale - 1) + << int((boundingBox.right())*scale + 1) + << int((printer->height() - boundingBox.top())*scale); } } else { + s << "%!PS-Adobe-1.0"; int w = width + (fullPage ? 0 : mleft + mright); int h = height + (fullPage ? 0 : mtop + mbottom); w = (int)(w*scale); diff --git a/src/gui/painting/qprintengine_win.cpp b/src/gui/painting/qprintengine_win.cpp index ea9dc5d..dd4de99 100644 --- a/src/gui/painting/qprintengine_win.cpp +++ b/src/gui/painting/qprintengine_win.cpp @@ -965,12 +965,13 @@ void QWin32PrintEnginePrivate::queryDefault() return; QStringList info = output.split(QLatin1Char(',')); - if (info.size() > 0) { + int infoSize = info.size(); + if (infoSize > 0) { if (name.isEmpty()) name = info.at(0); - if (program.isEmpty()) + if (program.isEmpty() && infoSize > 1) program = info.at(1); - if (port.isEmpty()) + if (port.isEmpty() && infoSize > 2) port = info.at(2); } } diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp index 3b5b9d3..feffc9f 100644 --- a/src/gui/s60framework/qs60mainappui.cpp +++ b/src/gui/s60framework/qs60mainappui.cpp @@ -112,16 +112,10 @@ void QS60MainAppUi::ConstructL() // ENoAppResourceFile and ENonStandardResourceFile makes UI to work without // resource files in most SDKs. S60 3rd FP1 public seems to require resource file // even these flags are defined - TInt flags = CAknAppUi::EAknEnableSkin; - if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes)) { - flags |= CAknAppUi::ENoScreenFurniture | CAknAppUi::ENonStandardResourceFile; - } + TInt flags = CAknAppUi::EAknEnableSkin + | CAknAppUi::ENoScreenFurniture + | CAknAppUi::ENonStandardResourceFile; BaseConstructL(flags); - - if (!QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes)) { - CEikButtonGroupContainer* nativeContainer = Cba(); - nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); - } } /*! diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index 7587343..90b8be3 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -92,10 +92,10 @@ static const qreal goldenRatio = 1.618; const layoutHeader QS60StylePrivate::m_layoutHeaders[] = { // *** generated layout data *** -{240,320,1,17,"QVGA Landscape"}, -{320,240,1,17,"QVGA Portrait"}, -{360,640,1,17,"NHD Landscape"}, -{640,360,1,17,"NHD Portrait"}, +{240,320,1,18,"QVGA Landscape"}, +{320,240,1,18,"QVGA Portrait"}, +{360,640,1,18,"NHD Landscape"}, +{640,360,1,18,"NHD Portrait"}, {352,800,1,12,"E90 Landscape"} // *** End of generated data *** }; @@ -104,11 +104,11 @@ const int QS60StylePrivate::m_numberOfLayouts = const short QS60StylePrivate::data[][MAX_PIXELMETRICS] = { // *** generated pixel metrics *** -{5,0,-909,0,0,2,0,0,-1,7,12,19,13,13,6,200,-909,-909,-909,20,13,2,0,0,21,7,18,0,3,3,1,-909,-909,0,1,0,0,12,20,15,15,18,18,1,115,18,0,-909,-909,-909,-909,0,0,16,2,-909,0,0,-909,16,-909,-909,-909,-909,32,18,55,24,55,4,4,4,9,13,-909,5,51,11,5,0,3,3,6,8,3,3,-909,2,-909,-909,-909,-909,5,5,3,1, 106}, -{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,0,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,3,3,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1, 106}, -{7,0,-909,0,0,2,0,0,-1,25,69,28,19,19,9,258,-909,-909,-909,23,19,26,0,0,32,25,72,0,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,13,13,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1, 135}, -{7,0,-909,0,0,2,0,0,-1,25,68,28,19,19,9,258,-909,-909,-909,31,19,6,0,0,32,25,60,0,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,12,12,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1, 135}, -{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,0,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1, 106} +{5,0,-909,0,0,2,0,0,-1,7,12,19,13,13,6,200,-909,-909,-909,20,13,2,0,0,21,7,18,30,3,3,1,-909,-909,0,1,0,0,12,20,15,15,18,18,1,115,18,0,-909,-909,-909,-909,0,0,16,2,-909,0,0,-909,16,-909,-909,-909,-909,32,18,55,24,55,4,4,4,9,13,-909,5,51,11,5,0,3,3,6,8,3,3,-909,2,-909,-909,-909,-909,5,5,3,1, 106}, +{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,28,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,3,3,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1, 106}, +{7,0,-909,0,0,2,0,0,-1,25,69,28,19,19,9,258,-909,-909,-909,23,19,26,0,0,32,25,72,44,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,13,13,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1, 135}, +{7,0,-909,0,0,2,0,0,-1,25,68,28,19,19,9,258,-909,-909,-909,31,19,6,0,0,32,25,60,52,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,12,12,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1, 135}, +{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,30,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1, 106} // *** End of generated data *** }; @@ -651,6 +651,8 @@ void QS60StylePrivate::setFont(QWidget *widget) const fontCategory = QS60StyleEnums::FC_Title; } else if (qobject_cast<QMessageBox *>(widget)){ fontCategory = QS60StyleEnums::FC_Primary; + } else if (qobject_cast<QMenu *>(widget)){ + fontCategory = QS60StyleEnums::FC_Primary; } if (fontCategory != QS60StyleEnums::FC_Undefined) { const bool resolveFontSize = widget->testAttribute(Qt::WA_SetFont) @@ -1744,6 +1746,9 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, optionCheckBox.QStyleOptionMenuItem::operator=(*menuItem); optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth)); optionCheckBox.rect.setHeight(pixelMetric(PM_IndicatorHeight)); + optionCheckBox.rect.moveCenter(QPoint( + optionCheckBox.rect.center().x(), + menuItem->rect.center().y())); const int moveByX = optionCheckBox.rect.width() + vSpacing; if (optionMenuItem.direction == Qt::LeftToRight) { textRect.translate(moveByX, 0); @@ -2424,6 +2429,10 @@ int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const if (metricValue == KNotFound) metricValue = QCommonStyle::pixelMetric(metric, option, widget); + // Menu scrollers should be set to zero height for combobox popups + if (metric == PM_MenuScrollerHeight && !qobject_cast<const QMenu *>(widget)) + metricValue = 0; + //if layout direction is mirrored, switch left and right border margins if (option && option->direction == Qt::RightToLeft) { if (metric == PM_LayoutLeftMargin) @@ -2483,7 +2492,14 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt, sz.setHeight(naviPaneSize.height()); } break; + case CT_MenuItem: case CT_ItemViewItem: + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + sz = QSize(); + break; + } + } sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget); if (QS60StylePrivate::isTouchSupported()) //Make itemview easier to use in touch devices @@ -2564,6 +2580,9 @@ int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w case SH_Menu_SelectionWrap: retValue = true; break; + case SH_Menu_MouseTracking: + retValue = true; + break; case SH_ItemView_ShowDecorationSelected: retValue = true; break; @@ -3150,6 +3169,12 @@ bool QS60Style::event(QEvent *e) #ifdef QT_KEYPAD_NAVIGATION case QEvent::FocusIn: if (QWidget *focusWidget = QApplication::focusWidget()) { + + // Menus and combobox popups do not draw focus frame around them + if (qobject_cast<QComboBoxListView *>(focusWidget) || + qobject_cast<QMenu *>(focusWidget)) + break; + if (!d->m_focusFrame) d->m_focusFrame = new QFocusFrame(focusWidget); d->m_focusFrame->setWidget(focusWidget); diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 58a7159..55aa6b0 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -310,7 +310,7 @@ const partMapEntry QS60StyleModeSpecifics::m_partMap[] = { /* SP_QsnFrPopupSideB */ {KAknsIIDQsnFrPopupSideB, ENoDraw, ES60_All, -1,-1}, /* SP_QsnFrPopupSideL */ {KAknsIIDQsnFrPopupSideL, ENoDraw, ES60_All, -1,-1}, /* SP_QsnFrPopupSideR */ {KAknsIIDQsnFrPopupSideR, ENoDraw, ES60_All, -1,-1}, - /* SP_QsnFrPopupCenter */ {KAknsIIDQsnFrPopupCenter, ENoDraw, ES60_All, -1,-1}, + /* SP_QsnFrPopupCenter */ {KAknsIIDQsnFrPopupCenterSubmenu, ENoDraw, ES60_All, -1,-1}, // ToolTip graphics different in 3.1 vs. 3.2+. /* SP_QsnFrPopupPreviewCornerTl */ {KAknsIIDQsnFrPopupCornerTl, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c5}, /* KAknsIIDQsnFrPopupPreviewCornerTl */ @@ -919,7 +919,7 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(QS60StylePrivate::SkinFr result = fromFbsBitmap(frame, NULL, flags, targetSize); } } else { - TDisplayMode maskDepth = EGray2; + TDisplayMode maskDepth = EGray256; // Query the skin item for possible frame graphics mask details. if (skinInstance) { CAknsMaskedBitmapItemData* skinMaskedBmp = static_cast<CAknsMaskedBitmapItemData*>( @@ -983,6 +983,10 @@ void QS60StyleModeSpecifics::frameIdAndCenterId(QS60StylePrivate::SkinFrameEleme frameId.Set(KAknsIIDQsnFrPopupSub); } break; + case QS60StylePrivate::SF_PopupBackground: + centerId.Set(KAknsIIDQsnFrPopupCenterSubmenu); + frameId.Set(KAknsIIDQsnFrPopupSub); + break; case QS60StylePrivate::SF_PanelBackground: // remove center piece for panel graphics, so that only border is drawn centerId.Set(KAknsIIDNone); diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 81b923b..515b6c7 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -1539,7 +1539,9 @@ QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const QHash<const void *, StyleSheet>::const_iterator defaultCacheIt = styleSheetCache->constFind(baseStyle()); if (defaultCacheIt == styleSheetCache->constEnd()) { defaultSs = getDefaultStyleSheet(); - styleSheetCache->insert(baseStyle(), defaultSs); + QStyle *bs = baseStyle(); + styleSheetCache->insert(bs, defaultSs); + QObject::connect(bs, SIGNAL(destroyed(QObject*)), this, SLOT(styleDestroyed(QObject*)), Qt::UniqueConnection); } else { defaultSs = defaultCacheIt.value(); } @@ -2666,6 +2668,11 @@ void QStyleSheetStyle::widgetDestroyed(QObject *o) autoFillDisabledWidgets->remove((const QWidget *)o); } +void QStyleSheetStyle::styleDestroyed(QObject *o) +{ + styleSheetCache->remove(o); +} + /*! * Make sure that the cache will be clean by connecting destroyed if needed. * return false if the widget is not stylable; diff --git a/src/gui/styles/qstylesheetstyle_p.h b/src/gui/styles/qstylesheetstyle_p.h index 50abef9..fd81437 100644 --- a/src/gui/styles/qstylesheetstyle_p.h +++ b/src/gui/styles/qstylesheetstyle_p.h @@ -147,6 +147,7 @@ protected: private Q_SLOTS: void widgetDestroyed(QObject *); + void styleDestroyed(QObject *); private: int refcount; diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 24887b5..21a31a3 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2616,10 +2616,8 @@ void QFontCache::cleanup() } QT_CATCH (const std::bad_alloc &) { // no cache - just ignore } - if (cache && cache->hasLocalData()) { - cache->localData()->clear(); + if (cache && cache->hasLocalData()) cache->setLocalData(0); - } } #endif // QT_NO_THREAD @@ -2631,6 +2629,7 @@ QFontCache::QFontCache() QFontCache::~QFontCache() { + clear(); { EngineDataCache::ConstIterator it = engineDataCache.constBegin(), end = engineDataCache.constEnd(); diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index ae5e9ca..ff29462 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -598,10 +598,10 @@ static QList<QFontDatabase::WritingSystem> determineWritingSystemsFromTrueTypeBi #if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) // class with virtual destructor, derived in qfontdatabase_s60.cpp -class QFontDatabaseS60Store +class QSymbianFontDatabaseExtras { public: - virtual ~QFontDatabaseS60Store() {} + virtual ~QSymbianFontDatabaseExtras() {} }; #endif @@ -614,7 +614,7 @@ public: , stream(0) #endif #if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) - , s60Store(0) + , symbianExtras(0) #endif { } ~QFontDatabasePrivate() { @@ -628,9 +628,9 @@ public: families = 0; count = 0; #if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) - if (s60Store) { - delete s60Store; - s60Store = 0; + if (symbianExtras) { + delete symbianExtras; + symbianExtras = 0; } #endif // don't clear the memory fonts! @@ -675,7 +675,7 @@ public: QDataStream *stream; QStringList fallbackFamilies; #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) - const QFontDatabaseS60Store *s60Store; + const QSymbianFontDatabaseExtras *symbianExtras; #endif }; diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp index ef5e0c4..3ad0806 100644 --- a/src/gui/text/qfontdatabase_s60.cpp +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -92,22 +92,22 @@ QFileInfoList alternativeFilePaths(const QString &path, const QStringList &nameF } #if defined(QT_NO_FREETYPE) -class QFontDatabaseS60StoreImplementation : public QFontDatabaseS60Store +class QSymbianFontDatabaseExtrasImplementation : public QSymbianFontDatabaseExtras { public: - QFontDatabaseS60StoreImplementation(); - ~QFontDatabaseS60StoreImplementation(); + QSymbianFontDatabaseExtrasImplementation(); + ~QSymbianFontDatabaseExtrasImplementation(); - const QFontEngineS60Extensions *extension(const QString &typeface) const; + const QSymbianTypeFaceExtras *extras(const QString &typeface) const; private: RHeap* m_heap; CFontStore *m_store; COpenFontRasterizer *m_rasterizer; - mutable QHash<QString, const QFontEngineS60Extensions *> m_extensions; + mutable QHash<QString, const QSymbianTypeFaceExtras *> m_extras; }; -QFontDatabaseS60StoreImplementation::QFontDatabaseS60StoreImplementation() +QSymbianFontDatabaseExtrasImplementation::QSymbianFontDatabaseExtrasImplementation() { m_heap = User::ChunkHeap(NULL, 0x1000, 0x100000); QT_TRAP_THROWING( @@ -127,10 +127,10 @@ QFontDatabaseS60StoreImplementation::QFontDatabaseS60StoreImplementation() QT_TRAP_THROWING(m_store->AddFileL(fontFilePtr)); } } -QFontDatabaseS60StoreImplementation::~QFontDatabaseS60StoreImplementation() +QSymbianFontDatabaseExtrasImplementation::~QSymbianFontDatabaseExtrasImplementation() { - typedef QHash<QString, const QFontEngineS60Extensions *>::iterator iterator; - for (iterator p = m_extensions.begin(); p != m_extensions.end(); ++p) { + typedef QHash<QString, const QSymbianTypeFaceExtras *>::iterator iterator; + for (iterator p = m_extras.begin(); p != m_extras.end(); ++p) { m_store->ReleaseFont((*p)->fontOwner()); delete *p; } @@ -156,9 +156,9 @@ COpenFont* OpenFontFromBitmapFont(const CBitmapFont* aBitmapFont) } #endif // FNTSTORE_H_INLINES_SUPPORT_FMM -const QFontEngineS60Extensions *QFontDatabaseS60StoreImplementation::extension(const QString &typeface) const +const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &typeface) const { - if (!m_extensions.contains(typeface)) { + if (!m_extras.contains(typeface)) { CFont* font = NULL; TFontSpec spec(qt_QString2TPtrC(typeface), 1); spec.iHeight = 1; @@ -171,9 +171,9 @@ const QFontEngineS60Extensions *QFontDatabaseS60StoreImplementation::extension(c #else OpenFontFromBitmapFont(bitmapFont); #endif // FNTSTORE_H_INLINES_SUPPORT_FMM - m_extensions.insert(typeface, new QFontEngineS60Extensions(font, openFont)); + m_extras.insert(typeface, new QSymbianTypeFaceExtras(font, openFont)); } - return m_extensions.value(typeface); + return m_extras.value(typeface); } #else class QFontEngineFTS60 : public QFontEngineFT @@ -240,14 +240,14 @@ static void initializeDb() return; #if defined(QT_NO_FREETYPE) - if (!db->s60Store) - db->s60Store = new QFontDatabaseS60StoreImplementation; + if (!db->symbianExtras) + db->symbianExtras = new QSymbianFontDatabaseExtrasImplementation; QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces(); - const QFontDatabaseS60StoreImplementation *store = - static_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store); + const QSymbianFontDatabaseExtrasImplementation *dbExtras = + static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); bool fontAdded = false; for (int i = 0; i < numTypeFaces; i++) { TTypefaceSupport typefaceSupport; @@ -273,8 +273,8 @@ static void initializeDb() style->smoothScalable = typefaceSupport.iIsScalable; style->pixelSize(0, true); - const QFontEngineS60Extensions *extension = store->extension(familyName); - const QByteArray os2Table = extension->getSfntTable(MAKE_TAG('O', 'S', '/', '2')); + const QSymbianTypeFaceExtras *typeFaceExtras = dbExtras->extras(familyName); + const QByteArray os2Table = typeFaceExtras->getSfntTable(MAKE_TAG('O', 'S', '/', '2')); const unsigned char* data = reinterpret_cast<const unsigned char*>(os2Table.constData()); const unsigned char* ulUnicodeRange = data + 42; quint32 unicodeRange[4] = { @@ -394,10 +394,10 @@ QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *, const QFo QFontDef request = req; request.family = fontFamily; #if defined(QT_NO_FREETYPE) - const QFontDatabaseS60StoreImplementation *store = - static_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store); - const QFontEngineS60Extensions *extension = store->extension(fontFamily); - fe = new QFontEngineS60(request, extension); + const QSymbianFontDatabaseExtrasImplementation *dbExtras = + static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); + const QSymbianTypeFaceExtras *typeFaceExtras = dbExtras->extras(fontFamily); + fe = new QFontEngineS60(request, typeFaceExtras); #else QFontEngine::FaceId faceId; const QtFontFamily * const reqQtFontFamily = db->family(fontFamily); diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index c9ff661..a9960e4 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE -QFontEngineS60Extensions::QFontEngineS60Extensions(CFont* fontOwner, COpenFont *font) +QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* fontOwner, COpenFont *font) : m_font(font) , m_cmap(0) , m_symbolCMap(false) @@ -68,7 +68,7 @@ QFontEngineS60Extensions::QFontEngineS60Extensions(CFont* fontOwner, COpenFont * Q_ASSERT(m_shapingExtension && m_trueTypeExtension); } -QByteArray QFontEngineS60Extensions::getSfntTable(uint tag) const +QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const { Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag)); TInt error = KErrNone; @@ -79,7 +79,7 @@ QByteArray QFontEngineS60Extensions::getSfntTable(uint tag) const return result; } -bool QFontEngineS60Extensions::getSfntTableData(uint tag, uchar *buffer, uint *length) const +bool QSymbianTypeFaceExtras::getSfntTableData(uint tag, uchar *buffer, uint *length) const { if (!m_trueTypeExtension->HasTrueTypeTable(tag)) return false; @@ -104,7 +104,7 @@ bool QFontEngineS60Extensions::getSfntTableData(uint tag, uchar *buffer, uint *l return result; } -const unsigned char *QFontEngineS60Extensions::cmap() const +const unsigned char *QSymbianTypeFaceExtras::cmap() const { if (!m_cmap) { m_cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); @@ -114,7 +114,7 @@ const unsigned char *QFontEngineS60Extensions::cmap() const return m_cmap; } -QPainterPath QFontEngineS60Extensions::glyphOutline(glyph_t glyph) const +QPainterPath QSymbianTypeFaceExtras::glyphOutline(glyph_t glyph) const { QPainterPath result; QPolygonF polygon; @@ -134,7 +134,7 @@ QPainterPath QFontEngineS60Extensions::glyphOutline(glyph_t glyph) const return result; } -CFont *QFontEngineS60Extensions::fontOwner() const +CFont *QSymbianTypeFaceExtras::fontOwner() const { return m_fontOwner; } @@ -192,8 +192,8 @@ void QFontEngineS60::releaseFont(CFont *&font) } } -QFontEngineS60::QFontEngineS60(const QFontDef &request, const QFontEngineS60Extensions *extensions) - : m_extensions(extensions) +QFontEngineS60::QFontEngineS60(const QFontDef &request, const QSymbianTypeFaceExtras *extras) + : m_extras(extras) , m_originalFont(0) , m_originalFontSizeInPixels((request.pixelSize >= 0)? request.pixelSize:pointsToPixels(request.pointSize)) @@ -220,10 +220,12 @@ bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout } HB_Glyph *g = glyphs->glyphs; - const unsigned char* cmap = m_extensions->cmap(); + const unsigned char* cmap = m_extras->cmap(); + const bool isRtl = (flags & QTextEngine::RightToLeft); for (int i = 0; i < len; ++i) { const unsigned int uc = getChar(characters, i, len); - *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, uc); + *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, + isRtl ? QChar::mirroredChar(uc) : uc); } glyphs->numGlyphs = g - glyphs->glyphs; @@ -241,8 +243,8 @@ void QFontEngineS60::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla Q_UNUSED(flags); for (int i = 0; i < glyphs->numGlyphs; i++) { const glyph_metrics_t bbox = boundingBox_const(glyphs->glyphs[i]); - glyphs->advances_x[i] = glyphs->offsets[i].x = bbox.xoff; - glyphs->advances_y[i] = glyphs->offsets[i].y = bbox.yoff; + glyphs->advances_x[i] = bbox.xoff; + glyphs->advances_y[i] = bbox.yoff; } } @@ -337,7 +339,7 @@ const char *QFontEngineS60::name() const bool QFontEngineS60::canRender(const QChar *string, int len) { - const unsigned char *cmap = m_extensions->cmap(); + const unsigned char *cmap = m_extras->cmap(); for (int i = 0; i < len; ++i) { const unsigned int uc = getChar(string, i, len); if (QFontEngine::getTrueTypeGlyphIndex(cmap, uc) == 0) @@ -348,12 +350,12 @@ bool QFontEngineS60::canRender(const QChar *string, int len) QByteArray QFontEngineS60::getSfntTable(uint tag) const { - return m_extensions->getSfntTable(tag); + return m_extras->getSfntTable(tag); } bool QFontEngineS60::getSfntTableData(uint tag, uchar *buffer, uint *length) const { - return m_extensions->getSfntTableData(tag, buffer, length); + return m_extras->getSfntTableData(tag, buffer, length); } QFontEngine::Type QFontEngineS60::type() const diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h index a80af4d..b6b117f 100644 --- a/src/gui/text/qfontengine_s60_p.h +++ b/src/gui/text/qfontengine_s60_p.h @@ -63,10 +63,10 @@ class CFont; QT_BEGIN_NAMESPACE // ..gives us access to truetype tables, UTF-16<->GlyphID mapping, and glyph outlines -class QFontEngineS60Extensions +class QSymbianTypeFaceExtras { public: - QFontEngineS60Extensions(CFont* fontOwner, COpenFont *font); + QSymbianTypeFaceExtras(CFont* fontOwner, COpenFont *font); QByteArray getSfntTable(uint tag) const; bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; @@ -87,7 +87,7 @@ private: class QFontEngineS60 : public QFontEngine { public: - QFontEngineS60(const QFontDef &fontDef, const QFontEngineS60Extensions *extensions); + QFontEngineS60(const QFontDef &fontDef, const QSymbianTypeFaceExtras *extras); ~QFontEngineS60(); bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; @@ -128,7 +128,7 @@ private: CFont *fontWithSize(qreal size) const; static void releaseFont(CFont *&font); - const QFontEngineS60Extensions *m_extensions; + const QSymbianTypeFaceExtras *m_extras; CFont* m_originalFont; const qreal m_originalFontSizeInPixels; CFont* m_scaledFont; diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 655fc61..c1c4abf 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -740,8 +740,14 @@ bool QLineEdit::validateAndSet(const QString &newText, int newPos, setText(oldText); return false; } - setCursorPosition(newPos); - setSelection(qMin(newMarkAnchor, newMarkDrag), qAbs(newMarkAnchor - newMarkDrag)); + int selstart = qMin(newMarkAnchor, newMarkDrag); + int sellength = qAbs(newMarkAnchor - newMarkDrag); + if (selstart == newPos) { + selstart = qMax(newMarkAnchor, newMarkDrag); + sellength = -sellength; + } + //setSelection also set the position + setSelection(selstart, sellength); return true; } #endif //QT3_SUPPORT diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index e0f1402..4698be4 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -2803,7 +2803,9 @@ void QMenu::mouseMoveEvent(QMouseEvent *e) QAction *action = d->actionAt(e->pos()); if (!action) { - if (d->hasHadMouse) + if (d->hasHadMouse + && (!d->currentAction + || !(d->currentAction->menu() && d->currentAction->menu()->isVisible()))) d->setCurrentAction(0); return; } else if(e->buttons()) { diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index e8400d6..aaa113b 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -2066,6 +2066,7 @@ bool QMenuBarPrivate::macUpdateMenuBarImmediatly() cancelAllMenuTracking(); QWidget *w = findWindowThatShouldDisplayMenubar(); QMenuBar *mb = findMenubarForWindow(w); + extern bool qt_mac_app_fullscreen; //qapplication_mac.mm // We need to see if we are in full screen mode, if so we need to // switch the full screen mode to be able to show or hide the menubar. @@ -2074,12 +2075,14 @@ bool QMenuBarPrivate::macUpdateMenuBarImmediatly() if(w->isFullScreen()) { // Ok, switch to showing the menubar when hovering over it. SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar); + qt_mac_app_fullscreen = true; } } else if(w) { // Removing a menubar if(w->isFullScreen()) { // Ok, switch to not showing the menubar when hovering on it SetSystemUIMode(kUIModeAllHidden, 0); + qt_mac_app_fullscreen = true; } } diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp index d03a2f4..8aaaade 100644 --- a/src/gui/widgets/qtabbar.cpp +++ b/src/gui/widgets/qtabbar.cpp @@ -69,6 +69,7 @@ QT_BEGIN_NAMESPACE + inline static bool verticalTabs(QTabBar::Shape shape) { return shape == QTabBar::RoundedWest @@ -95,9 +96,20 @@ void QTabBarPrivate::updateMacBorderMetrics() metrics.left = 0; metrics.right = 0; qt_mac_updateContentBorderMetricts(window, metrics); - - // hide the base line separator if the tabs have docuemnt mode enabled (Cocoa) - qt_mac_showBaseLineSeparator(window, !documentMode); +#if QT_MAC_USE_COCOA + // In Cocoa we need to keep track of the drawRect method. + // If documentMode is enabled we need to change it, unless + // a toolbar is present. + // Notice that all the information is kept in the window, + // that's why we get the private widget for it instead of + // the private widget for this widget. + QWidgetPrivate *privateWidget = qt_widget_private(q->window()); + if(privateWidget) + privateWidget->changeMethods = documentMode; + // Since in Cocoa there is no simple way to remove the baseline, so we just ask the + // top level to do the magic for us. + privateWidget->syncUnifiedMode(); +#endif // QT_MAC_USE_COCOA } #endif } @@ -2193,6 +2205,7 @@ bool QTabBar::documentMode() const void QTabBar::setDocumentMode(bool enabled) { Q_D(QTabBar); + d->documentMode = enabled; d->updateMacBorderMetrics(); } diff --git a/src/gui/widgets/qtabwidget.cpp b/src/gui/widgets/qtabwidget.cpp index 01e9d40..82dfdef 100644 --- a/src/gui/widgets/qtabwidget.cpp +++ b/src/gui/widgets/qtabwidget.cpp @@ -552,6 +552,8 @@ void QTabWidget::setTabEnabled(int index, bool enable) { Q_D(QTabWidget); d->tabs->setTabEnabled(index, enable); + if (QWidget *widget = d->stack->widget(index)) + widget->setEnabled(enable); } /*! diff --git a/src/imports/multimedia/qdeclarativeaudio.cpp b/src/imports/multimedia/qdeclarativeaudio.cpp index 896f9b7..a163b10 100644 --- a/src/imports/multimedia/qdeclarativeaudio.cpp +++ b/src/imports/multimedia/qdeclarativeaudio.cpp @@ -57,7 +57,21 @@ QT_BEGIN_NAMESPACE import Qt 4.7 import Qt.multimedia 4.7 - Audio { source: "audio/song.mp3" } + Text { + text: "Click Me!"; + font.pointSize: 24; + width: 150; height: 50; + + Audio { + id: playMusic + source: "music.wav" + } + MouseArea { + id: playArea + anchors.fill: parent + onPressed: { playMusic.play() } + } + } \endqml \sa Video diff --git a/src/imports/multimedia/qdeclarativevideo.cpp b/src/imports/multimedia/qdeclarativevideo.cpp index 9b02795..1b51e2c 100644 --- a/src/imports/multimedia/qdeclarativevideo.cpp +++ b/src/imports/multimedia/qdeclarativevideo.cpp @@ -79,7 +79,24 @@ void QDeclarativeVideo::_q_error(int errorCode, const QString &errorString) import Qt 4.7 import Qt.multimedia 4.7 - Video { source: "video/movie.mpg" } + Video { + id: video + width : 800 + height : 600 + source: "video.avi" + + MouseArea { + anchors.fill: parent + onClicked: { + video.play() + } + } + + focus: true + Keys.onSpacePressed: video.paused = !video.paused + Keys.onLeftPressed: video.position -= 5000 + Keys.onRightPressed: video.position += 5000 + } \endqml The Video item supports untransformed, stretched, and uniformly scaled video presentation. diff --git a/src/multimedia/mediaservices/effects/qsoundeffect.cpp b/src/multimedia/mediaservices/effects/qsoundeffect.cpp index 1992ee5..3537566 100644 --- a/src/multimedia/mediaservices/effects/qsoundeffect.cpp +++ b/src/multimedia/mediaservices/effects/qsoundeffect.cpp @@ -64,17 +64,19 @@ QT_BEGIN_NAMESPACE import Qt 4.7 import Qt.multimedia 4.7 - Item { + Text { + text: "Click Me!"; + font.pointSize: 24; + width: 150; height: 50; + SoundEffect { id: playSound - source: "test.wav" + source: "soundeffect.wav" } MouseArea { id: playArea anchors.fill: parent - onPressed: { - playSound.play() - } + onPressed: { playSound.play() } } } \endqml diff --git a/src/multimedia/multimedia/audio/qaudioinput.cpp b/src/multimedia/multimedia/audio/qaudioinput.cpp index c99e870..3676f64 100644 --- a/src/multimedia/multimedia/audio/qaudioinput.cpp +++ b/src/multimedia/multimedia/audio/qaudioinput.cpp @@ -211,7 +211,7 @@ QAudioInput::~QAudioInput() If a problem occurs during this process the error() is set to QAudio::OpenError, state() is set to QAudio::StoppedState and stateChanged() signal is emitted. - \sa {Symbian Platform Security Requirements} + \l{QAudioInput#Symbian Platform Security Requirements} \sa QIODevice */ @@ -233,7 +233,7 @@ void QAudioInput::start(QIODevice* device) If a problem occurs during this process the error() is set to QAudio::OpenError, state() is set to QAudio::StoppedState and stateChanged() signal is emitted. - \sa {Symbian Platform Security Requirements} + \l{QAudioInput#Symbian Platform Security Requirements} \sa QIODevice */ diff --git a/src/multimedia/multimedia/audio/qaudioinput_alsa_p.cpp b/src/multimedia/multimedia/audio/qaudioinput_alsa_p.cpp index 6b15008..c9a8b71 100644 --- a/src/multimedia/multimedia/audio/qaudioinput_alsa_p.cpp +++ b/src/multimedia/multimedia/audio/qaudioinput_alsa_p.cpp @@ -58,8 +58,6 @@ QT_BEGIN_NAMESPACE //#define DEBUG_AUDIO 1 -static const int minimumIntervalTime = 50; - QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat): settings(audioFormat) { @@ -594,10 +592,7 @@ int QAudioInputPrivate::periodSize() const void QAudioInputPrivate::setNotifyInterval(int ms) { - if(ms >= minimumIntervalTime) - intervalTime = ms; - else - intervalTime = minimumIntervalTime; + intervalTime = qMax(0, ms); } int QAudioInputPrivate::notifyInterval() const @@ -649,7 +644,7 @@ bool QAudioInputPrivate::deviceReady() if(deviceState != QAudio::ActiveState) return true; - if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { + if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { emit notify(); elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; timeStamp.restart(); diff --git a/src/multimedia/multimedia/audio/qaudioinput_win32_p.cpp b/src/multimedia/multimedia/audio/qaudioinput_win32_p.cpp index b5d673e..14a1cf3 100644 --- a/src/multimedia/multimedia/audio/qaudioinput_win32_p.cpp +++ b/src/multimedia/multimedia/audio/qaudioinput_win32_p.cpp @@ -57,8 +57,6 @@ QT_BEGIN_NAMESPACE //#define DEBUG_AUDIO 1 -static const int minimumIntervalTime = 50; - QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat): settings(audioFormat) { @@ -74,16 +72,11 @@ QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFor pullMode = true; resuming = false; finished = false; - - connect(this,SIGNAL(processMore()),SLOT(deviceReady())); - - InitializeCriticalSection(&waveInCriticalSection); } QAudioInputPrivate::~QAudioInputPrivate() { stop(); - DeleteCriticalSection(&waveInCriticalSection); } void QT_WIN_CALLBACK QAudioInputPrivate::waveInProc( HWAVEIN hWaveIn, UINT uMsg, @@ -98,20 +91,18 @@ void QT_WIN_CALLBACK QAudioInputPrivate::waveInProc( HWAVEIN hWaveIn, UINT uMsg, if(!qAudio) return; + QMutexLocker(&qAudio->mutex); + switch(uMsg) { case WIM_OPEN: break; case WIM_DATA: - EnterCriticalSection(&qAudio->waveInCriticalSection); if(qAudio->waveFreeBlockCount > 0) qAudio->waveFreeBlockCount--; qAudio->feedback(); - LeaveCriticalSection(&qAudio->waveInCriticalSection); break; case WIM_CLOSE: - EnterCriticalSection(&qAudio->waveInCriticalSection); qAudio->finished = true; - LeaveCriticalSection(&qAudio->waveInCriticalSection); break; default: return; @@ -156,7 +147,7 @@ void QAudioInputPrivate::freeBlocks(WAVEHDR* blockArray) int count = buffer_size/period_size; for(int i = 0; i < count; i++) { - waveInUnprepareHeader(hWaveIn,&blocks[i], sizeof(WAVEHDR)); + waveInUnprepareHeader(hWaveIn,blocks, sizeof(WAVEHDR)); blocks+=sizeof(WAVEHDR); } HeapFree(GetProcessHeap(), 0, blockArray); @@ -283,9 +274,9 @@ bool QAudioInputPrivate::open() return false; } - EnterCriticalSection(&waveInCriticalSection); + mutex.lock(); waveFreeBlockCount = buffer_size/period_size; - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); waveCurrentBlock = 0; @@ -329,13 +320,11 @@ void QAudioInputPrivate::close() Sleep(10); } - EnterCriticalSection(&waveInCriticalSection); - for(int i=0; i<waveFreeBlockCount; i++) { - if(waveBlocks[i].dwFlags & WHDR_PREPARED) - waveInUnprepareHeader(hWaveIn,&waveBlocks[i],sizeof(WAVEHDR)); - } - LeaveCriticalSection(&waveInCriticalSection); + mutex.lock(); + for(int i=0; i<waveFreeBlockCount; i++) + waveInUnprepareHeader(hWaveIn,&waveBlocks[i],sizeof(WAVEHDR)); freeBlocks(waveBlocks); + mutex.unlock(); } int QAudioInputPrivate::bytesReady() const @@ -406,9 +395,10 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) waveInUnprepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); - EnterCriticalSection(&waveInCriticalSection); + mutex.lock(); waveFreeBlockCount++; - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); + waveBlocks[header].dwBytesRecorded=0; waveBlocks[header].dwFlags = 0L; result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); @@ -416,18 +406,22 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); qWarning("QAudioInput: failed to prepare block %d,err=%d",header,result); errorState = QAudio::IOError; - EnterCriticalSection(&waveInCriticalSection); + + mutex.lock(); waveFreeBlockCount--; - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); + return 0; } result = waveInAddBuffer(hWaveIn, &waveBlocks[header], sizeof(WAVEHDR)); if(result != MMSYSERR_NOERROR) { qWarning("QAudioInput: failed to setup block %d,err=%d",header,result); errorState = QAudio::IOError; - EnterCriticalSection(&waveInCriticalSection); + + mutex.lock(); waveFreeBlockCount--; - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); + return 0; } header++; @@ -435,7 +429,7 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) header = 0; p+=l; - EnterCriticalSection(&waveInCriticalSection); + mutex.lock(); if(!pullMode) { if(l+period_size > len && waveFreeBlockCount == buffer_size/period_size) done = true; @@ -443,7 +437,7 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) if(waveFreeBlockCount == buffer_size/period_size) done = true; } - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); written+=l; } @@ -467,9 +461,10 @@ void QAudioInputPrivate::resume() return; } } - EnterCriticalSection(&waveInCriticalSection); + + mutex.lock(); waveFreeBlockCount = buffer_size/period_size; - LeaveCriticalSection(&waveInCriticalSection); + mutex.unlock(); waveCurrentBlock = 0; header = 0; @@ -497,10 +492,7 @@ int QAudioInputPrivate::periodSize() const void QAudioInputPrivate::setNotifyInterval(int ms) { - if(ms >= minimumIntervalTime) - intervalTime = ms; - else - intervalTime = minimumIntervalTime; + intervalTime = qMax(0, ms); } int QAudioInputPrivate::notifyInterval() const @@ -534,14 +526,13 @@ void QAudioInputPrivate::feedback() QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback() INPUT "<<this; #endif - bytesAvailable = bytesReady(); - if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState)) - emit processMore(); + QMetaObject::invokeMethod(this, "deviceReady", Qt::QueuedConnection); } bool QAudioInputPrivate::deviceReady() { + bytesAvailable = bytesReady(); #ifdef DEBUG_AUDIO QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :deviceReady() INPUT"; @@ -558,7 +549,7 @@ bool QAudioInputPrivate::deviceReady() a->trigger(); } - if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { + if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { emit notify(); elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; timeStamp.restart(); diff --git a/src/multimedia/multimedia/audio/qaudioinput_win32_p.h b/src/multimedia/multimedia/audio/qaudioinput_win32_p.h index 66c2535..8a9b02b 100644 --- a/src/multimedia/multimedia/audio/qaudioinput_win32_p.h +++ b/src/multimedia/multimedia/audio/qaudioinput_win32_p.h @@ -62,6 +62,7 @@ #include <QtCore/qstring.h> #include <QtCore/qstringlist.h> #include <QtCore/qdatetime.h> +#include <QtCore/qmutex.h> #include <QtMultimedia/qaudio.h> #include <QtMultimedia/qaudiodeviceinfo.h> @@ -122,7 +123,7 @@ private: volatile int waveFreeBlockCount; int waveCurrentBlock; - CRITICAL_SECTION waveInCriticalSection; + QMutex mutex; static void QT_WIN_CALLBACK waveInProc( HWAVEIN hWaveIn, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ); diff --git a/src/multimedia/multimedia/audio/qaudiooutput_alsa_p.cpp b/src/multimedia/multimedia/audio/qaudiooutput_alsa_p.cpp index cf3726b..49b32c0 100644 --- a/src/multimedia/multimedia/audio/qaudiooutput_alsa_p.cpp +++ b/src/multimedia/multimedia/audio/qaudiooutput_alsa_p.cpp @@ -58,8 +58,6 @@ QT_BEGIN_NAMESPACE //#define DEBUG_AUDIO 1 -static const int minimumIntervalTime = 50; - QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat): settings(audioFormat) { @@ -84,8 +82,7 @@ QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioF resuming = false; opened = false; - QStringList list1 = QString(QLatin1String(device)).split(QLatin1String(":")); - m_device = QByteArray(list1.at(0).toLocal8Bit().constData()); + m_device = device; timer = new QTimer(this); connect(timer,SIGNAL(timeout()),SLOT(userFeed())); @@ -282,11 +279,11 @@ bool QAudioOutputPrivate::open() int count=0; unsigned int freakuency=settings.frequency(); - QString dev = QLatin1String(m_device.constData()); + QString dev = QString(QLatin1String(m_device.constData())); QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput); if(dev.compare(QLatin1String("default")) == 0) { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) - dev = QLatin1String(devices.first().constData()); + dev = QLatin1String(devices.first()); #else dev = QLatin1String("hw:0,0"); #endif @@ -574,10 +571,7 @@ int QAudioOutputPrivate::bufferSize() const void QAudioOutputPrivate::setNotifyInterval(int ms) { - if(ms >= minimumIntervalTime) - intervalTime = ms; - else - intervalTime = minimumIntervalTime; + intervalTime = qMax(0, ms); } int QAudioOutputPrivate::notifyInterval() const @@ -719,7 +713,7 @@ bool QAudioOutputPrivate::deviceReady() if(deviceState != QAudio::ActiveState) return true; - if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { + if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { emit notify(); elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; timeStamp.restart(); diff --git a/src/multimedia/multimedia/audio/qaudiooutput_win32_p.cpp b/src/multimedia/multimedia/audio/qaudiooutput_win32_p.cpp index 13bce58..a8aeb41 100644 --- a/src/multimedia/multimedia/audio/qaudiooutput_win32_p.cpp +++ b/src/multimedia/multimedia/audio/qaudiooutput_win32_p.cpp @@ -56,8 +56,6 @@ QT_BEGIN_NAMESPACE -static const int minimumIntervalTime = 50; - QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat): settings(audioFormat) { @@ -73,17 +71,15 @@ QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioF audioSource = 0; pullMode = true; finished = false; - InitializeCriticalSection(&waveOutCriticalSection); } QAudioOutputPrivate::~QAudioOutputPrivate() { - EnterCriticalSection(&waveOutCriticalSection); + mutex.lock(); finished = true; - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); close(); - DeleteCriticalSection(&waveOutCriticalSection); } void CALLBACK QAudioOutputPrivate::waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, @@ -98,6 +94,8 @@ void CALLBACK QAudioOutputPrivate::waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, if(!qAudio) return; + QMutexLocker(&qAudio->mutex); + switch(uMsg) { case WOM_OPEN: qAudio->feedback(); @@ -105,16 +103,13 @@ void CALLBACK QAudioOutputPrivate::waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, case WOM_CLOSE: return; case WOM_DONE: - EnterCriticalSection(&qAudio->waveOutCriticalSection); if(qAudio->finished || qAudio->buffer_size == 0 || qAudio->period_size == 0) { - LeaveCriticalSection(&qAudio->waveOutCriticalSection); return; } qAudio->waveFreeBlockCount++; if(qAudio->waveFreeBlockCount >= qAudio->buffer_size/qAudio->period_size) qAudio->waveFreeBlockCount = qAudio->buffer_size/qAudio->period_size; qAudio->feedback(); - LeaveCriticalSection(&qAudio->waveOutCriticalSection); break; default: return; @@ -150,7 +145,7 @@ void QAudioOutputPrivate::freeBlocks(WAVEHDR* blockArray) int count = buffer_size/period_size; for(int i = 0; i < count; i++) { - waveOutUnprepareHeader(hWaveOut,&blocks[i], sizeof(WAVEHDR)); + waveOutUnprepareHeader(hWaveOut,blocks, sizeof(WAVEHDR)); blocks+=sizeof(WAVEHDR); } HeapFree(GetProcessHeap(), 0, blockArray); @@ -225,9 +220,9 @@ bool QAudioOutputPrivate::open() } waveBlocks = allocateBlocks(period_size, buffer_size/period_size); - EnterCriticalSection(&waveOutCriticalSection); + mutex.lock(); waveFreeBlockCount = buffer_size/period_size; - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); waveCurrentBlock = 0; @@ -333,10 +328,7 @@ int QAudioOutputPrivate::bufferSize() const void QAudioOutputPrivate::setNotifyInterval(int ms) { - if(ms >= minimumIntervalTime) - intervalTime = ms; - else - intervalTime = minimumIntervalTime; + intervalTime = qMax(0, ms); } int QAudioOutputPrivate::notifyInterval() const @@ -368,12 +360,12 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) int remain; current = &waveBlocks[waveCurrentBlock]; while(l > 0) { - EnterCriticalSection(&waveOutCriticalSection); + mutex.lock(); if(waveFreeBlockCount==0) { - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); break; } - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); if(current->dwFlags & WHDR_PREPARED) waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); @@ -390,15 +382,13 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); - EnterCriticalSection(&waveOutCriticalSection); + mutex.lock(); waveFreeBlockCount--; - LeaveCriticalSection(&waveOutCriticalSection); #ifdef DEBUG_AUDIO - EnterCriticalSection(&waveOutCriticalSection); qDebug("write out l=%d, waveFreeBlockCount=%d", current->dwBufferLength,waveFreeBlockCount); - LeaveCriticalSection(&waveOutCriticalSection); #endif + mutex.unlock(); totalTimeValue += current->dwBufferLength; waveCurrentBlock++; waveCurrentBlock %= buffer_size/period_size; @@ -453,7 +443,7 @@ void QAudioOutputPrivate::feedback() bool QAudioOutputPrivate::deviceReady() { - if(deviceState == QAudio::StoppedState) + if(deviceState == QAudio::StoppedState || deviceState == QAudio::SuspendedState) return false; if(pullMode) { @@ -467,14 +457,16 @@ bool QAudioOutputPrivate::deviceReady() startup = true; bool full=false; - EnterCriticalSection(&waveOutCriticalSection); + + mutex.lock(); if(waveFreeBlockCount==0) full = true; - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); + if (full){ #ifdef DEBUG_AUDIO qDebug() << "Skipping data as unable to write"; #endif - if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime ) { + if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime ) { emit notify(); elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; timeStamp.restart(); @@ -504,12 +496,14 @@ bool QAudioOutputPrivate::deviceReady() bytesAvailable = bytesFree(); int check = 0; - EnterCriticalSection(&waveOutCriticalSection); + + mutex.lock(); check = waveFreeBlockCount; - LeaveCriticalSection(&waveOutCriticalSection); + mutex.unlock(); + if(check == buffer_size/period_size) { - errorState = QAudio::UnderrunError; if (deviceState != QAudio::IdleState) { + errorState = QAudio::UnderrunError; deviceState = QAudio::IdleState; emit stateChanged(deviceState); } @@ -521,19 +515,23 @@ bool QAudioOutputPrivate::deviceReady() } } else { int buffered; - EnterCriticalSection(&waveOutCriticalSection); + + mutex.lock(); buffered = waveFreeBlockCount; - LeaveCriticalSection(&waveOutCriticalSection); - errorState = QAudio::UnderrunError; + mutex.unlock(); + if (buffered >= buffer_size/period_size && deviceState == QAudio::ActiveState) { - deviceState = QAudio::IdleState; - emit stateChanged(deviceState); + if (deviceState != QAudio::IdleState) { + errorState = QAudio::UnderrunError; + deviceState = QAudio::IdleState; + emit stateChanged(deviceState); + } } } if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return true; - if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { + if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { emit notify(); elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; timeStamp.restart(); diff --git a/src/multimedia/multimedia/audio/qaudiooutput_win32_p.h b/src/multimedia/multimedia/audio/qaudiooutput_win32_p.h index 68a40f7..2d19225 100644 --- a/src/multimedia/multimedia/audio/qaudiooutput_win32_p.h +++ b/src/multimedia/multimedia/audio/qaudiooutput_win32_p.h @@ -61,6 +61,7 @@ #include <QtCore/qstring.h> #include <QtCore/qstringlist.h> #include <QtCore/qdatetime.h> +#include <QtCore/qmutex.h> #include <QtMultimedia/qaudio.h> #include <QtMultimedia/qaudiodeviceinfo.h> @@ -119,7 +120,7 @@ private: static void QT_WIN_CALLBACK waveOutProc( HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ); - CRITICAL_SECTION waveOutCriticalSection; + QMutex mutex; WAVEHDR* allocateBlocks(int size, int count); void freeBlocks(WAVEHDR* blockArray); diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp index 7f6df0a..97219f4 100644 --- a/src/network/access/qftp.cpp +++ b/src/network/access/qftp.cpp @@ -2311,7 +2311,7 @@ void QFtpPrivate::_q_piError(int errorCode, const QString &text) Q_Q(QFtp); if (pending.isEmpty()) { - qWarning() << "QFtpPrivate::_q_piError was called without pending command!"; + qWarning("QFtpPrivate::_q_piError was called without pending command!"); return; } diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index a6322a3..559124f 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -489,7 +489,11 @@ void QHttpNetworkConnectionPrivate::fillPipeline(QAbstractSocket *socket) int i = indexOf(socket); - if (! (defaultPipelineLength - channels[i].alreadyPipelinedRequests.length() >= 2)) { + // return fast if there was no reply right now processed + if (channels[i].reply == 0) + return; + + if (! (defaultPipelineLength - channels[i].alreadyPipelinedRequests.length() >= defaultRePipelineLength)) { return; } diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index f9a6de8..3b7bc9e 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -317,6 +317,13 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() return; } + // only run when the QHttpNetworkConnection is not currently being destructed, e.g. + // this function is called from _q_disconnected which is called because + // of ~QHttpNetworkConnectionPrivate + if (!qobject_cast<QHttpNetworkConnection*>(connection)) { + return; + } + qint64 bytes = 0; QAbstractSocket::SocketState socketState = socket->state(); @@ -384,7 +391,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() if (!replyPrivate->expectContent()) { replyPrivate->state = QHttpNetworkReplyPrivate::AllDoneState; allDone(); - return; + break; } } break; diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 7a48c2b..3154ed6 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -726,8 +726,7 @@ void QNetworkAccessHttpBackend::readFromHttp() QByteDataBuffer list; while (httpReply->bytesAvailable() != 0 && nextDownstreamBlockSize() != 0 && nextDownstreamBlockSize() > list.byteAmount()) { - QByteArray data = httpReply->readAny(); - list.append(data); + list.append(httpReply->readAny()); } if (!list.isEmpty()) diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index a0ffb07..95e45f0 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -62,7 +62,7 @@ class QNetworkReply; class QNetworkProxy; class QNetworkProxyFactory; class QSslError; -#ifndef QT_NO_BEARERMANAGEMENT +#if !defined(QT_NO_BEARERMANAGEMENT) && !defined(QT_MOBILITY_BEARER) class QNetworkConfiguration; #endif @@ -121,11 +121,13 @@ public: QNetworkReply *deleteResource(const QNetworkRequest &request); QNetworkReply *sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data = 0); -#ifndef QT_NO_BEARERMANAGEMENT +#if !defined(QT_NO_BEARERMANAGEMENT) && !defined(QT_MOBILITY_BEARER) void setConfiguration(const QNetworkConfiguration &config); QNetworkConfiguration configuration() const; QNetworkConfiguration activeConfiguration() const; +#endif +#ifndef QT_NO_BEARERMANAGEMENT void setNetworkAccessible(NetworkAccessibility accessible); NetworkAccessibility networkAccessible() const; #endif @@ -140,9 +142,11 @@ Q_SIGNALS: void sslErrors(QNetworkReply *reply, const QList<QSslError> &errors); #endif -#ifndef QT_NO_BEARERMANAGEMENT +#if !defined(QT_NO_BEARERMANAGEMENT) && !defined(QT_MOBILITY_BEARER) void networkSessionConnected(); +#endif +#ifndef QT_NO_BEARERMANAGEMENT void networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible); #endif @@ -155,7 +159,7 @@ private: Q_DECLARE_PRIVATE(QNetworkAccessManager) Q_PRIVATE_SLOT(d_func(), void _q_replyFinished()) Q_PRIVATE_SLOT(d_func(), void _q_replySslErrors(QList<QSslError>)) -#ifndef QT_NO_BEARERMANAGEMENT +#if !defined(QT_NO_BEARERMANAGEMENT) && !defined(QT_MOBILITY_BEARER) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionNewConfigurationActivated()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionPreferredConfigurationChanged(QNetworkConfiguration,bool)) diff --git a/src/network/access/qnetworkcookiejar.cpp b/src/network/access/qnetworkcookiejar.cpp index 8727095..0b3a918 100644 --- a/src/network/access/qnetworkcookiejar.cpp +++ b/src/network/access/qnetworkcookiejar.cpp @@ -269,6 +269,7 @@ QList<QNetworkCookie> QNetworkCookieJar::cookiesForUrl(const QUrl &url) const Q_D(const QNetworkCookieJar); QDateTime now = QDateTime::currentDateTime(); QList<QNetworkCookie> result; + bool isEncrypted = url.scheme().toLower() == QLatin1String("https"); // scan our cookies for something that matches QList<QNetworkCookie>::ConstIterator it = d->allCookies.constBegin(), @@ -280,6 +281,8 @@ QList<QNetworkCookie> QNetworkCookieJar::cookiesForUrl(const QUrl &url) const continue; if (!(*it).isSessionCookie() && (*it).expirationDate() < now) continue; + if ((*it).isSecure() && !isEncrypted) + continue; // insert this cookie into result, sorted by path QList<QNetworkCookie>::Iterator insertIt = result.begin(); diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index c3dc168..128d18f 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -478,6 +478,37 @@ qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const return qMax<qint64>(0, readBufferMaxSize - readBuffer.byteAmount()); } +void QNetworkReplyImplPrivate::initCacheSaveDevice() +{ + Q_Q(QNetworkReplyImpl); + + // save the meta data + QNetworkCacheMetaData metaData; + metaData.setUrl(url); + metaData = backend->fetchCacheMetaData(metaData); + + // save the redirect request also in the cache + QVariant redirectionTarget = q->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirectionTarget.isValid()) { + QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes(); + attributes.insert(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget); + metaData.setAttributes(attributes); + } + + cacheSaveDevice = networkCache()->prepare(metaData); + + if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) { + if (cacheSaveDevice && !cacheSaveDevice->isOpen()) + qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- " + "class %s probably needs to be fixed", + networkCache()->metaObject()->className()); + + networkCache()->remove(url); + cacheSaveDevice = 0; + cacheEnabled = false; + } +} + // we received downstream data and send this to the cache // and to our readBuffer (which in turn gets read by the user of QNetworkReply) void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data) @@ -487,36 +518,12 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data) return; if (cacheEnabled && !cacheSaveDevice) { - // save the meta data - QNetworkCacheMetaData metaData; - metaData.setUrl(url); - metaData = backend->fetchCacheMetaData(metaData); - - // save the redirect request also in the cache - QVariant redirectionTarget = q->attribute(QNetworkRequest::RedirectionTargetAttribute); - if (redirectionTarget.isValid()) { - QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes(); - attributes.insert(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget); - metaData.setAttributes(attributes); - } - - cacheSaveDevice = networkCache()->prepare(metaData); - - if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) { - if (cacheSaveDevice && !cacheSaveDevice->isOpen()) - qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- " - "class %s probably needs to be fixed", - networkCache()->metaObject()->className()); - - networkCache()->remove(url); - cacheSaveDevice = 0; - cacheEnabled = false; - } + initCacheSaveDevice(); } qint64 bytesWritten = 0; for (int i = 0; i < data.bufferCount(); i++) { - QByteArray item = data[i]; + QByteArray const &item = data[i]; if (cacheSaveDevice) cacheSaveDevice->write(item.constData(), item.size()); @@ -529,6 +536,13 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data) bytesDownloaded += bytesWritten; lastBytesDownloaded = bytesDownloaded; + appendDownstreamDataSignalEmissions(); +} + +void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() +{ + Q_Q(QNetworkReplyImpl); + QPointer<QNetworkReplyImpl> qq = q; QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); @@ -572,6 +586,15 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QIODevice *data) _q_copyReadyRead(); } +void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) +{ + // TODO implement + + // TODO call + + qFatal("QNetworkReplyImplPrivate::appendDownstreamData not implemented"); +} + void QNetworkReplyImplPrivate::finished() { Q_Q(QNetworkReplyImpl); @@ -689,8 +712,13 @@ QNetworkReplyImpl::QNetworkReplyImpl(QObject *parent) QNetworkReplyImpl::~QNetworkReplyImpl() { Q_D(QNetworkReplyImpl); + + // This code removes the data from the cache if it was prematurely aborted. + // See QNetworkReplyImplPrivate::completeCacheSave(), we disable caching there after the cache + // save had been properly finished. So if it is still enabled it means we got deleted/aborted. if (d->isCachingEnabled()) d->networkCache()->remove(url()); + if (d->outgoingDataBuffer) delete d->outgoingDataBuffer; } diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index bc7e408..38084bd 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -156,8 +156,13 @@ public: void consume(qint64 count); void emitUploadProgress(qint64 bytesSent, qint64 bytesTotal); qint64 nextDownstreamBlockSize() const; + + void initCacheSaveDevice(); + void appendDownstreamDataSignalEmissions(); void appendDownstreamData(QByteDataBuffer &data); void appendDownstreamData(QIODevice *data); + void appendDownstreamData(const QByteArray &data); + void finished(); void error(QNetworkReply::NetworkError code, const QString &errorString); void metaDataChanged(); diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 72ed6be..bf77eda 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1637,7 +1637,14 @@ static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, boo uint *q = (uint*)img.scanLine(y); for (int x=0; x < w; ++x) { const uint pixel = *q; - *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); + if (alpha_format && include_alpha) { + *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) + | (pixel & 0xff00ff00); + } else { + *q = 0xff000000 | ((pixel << 16) & 0xff0000) + | ((pixel >> 16) & 0xff) | (pixel & 0x00ff00); + } + q++; } } @@ -1648,7 +1655,8 @@ static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, boo QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) { - QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32); + QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32 + : QImage::Format_RGB32); int w = size.width(); int h = size.height(); glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 5ae69cd..f602c73 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -182,7 +182,6 @@ public: qreal penScale; // Pen scaling factor from "transform". QTransform pathTransform; // Calculated VG path transformation. - QTransform glyphTransform; // Calculated VG glyph transformation. QTransform imageTransform; // Calculated VG image transformation. bool pathTransformSet; // True if path transform set in the VG context. @@ -507,24 +506,15 @@ void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) // | 1 0 0 | // | 0 -1 devh | // | 0 0 1 | - // The glyph transform uses a slightly different transformation: - // | 1 0 0 | | 1 0 0.5 | | 1 0 0.5 | - // | 0 -1 devh - 1 | * | 0 1 -0.5 | = | 0 -1 (devh - 0.5) | - // | 0 0 1 | | 0 0 1 | | 0 0 1 | // The full VG transform is effectively: // 1. Apply the user's transformation matrix. - // 2. Translate glyphs by an extra (0.5, -0.5). - // 3. Flip the co-ordinate system upside down. + // 2. Flip the co-ordinate system upside down. QTransform viewport(1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, devh, 1.0f); - QTransform gviewport(1.0f, 0.0f, 0.0f, - 0.0f, -1.0f, 0.0f, - 0.5f, devh - 0.5f, 1.0f); // Compute the path transform and determine if it is projective. pathTransform = transform * viewport; - glyphTransform = transform * gviewport; bool projective = (pathTransform.m13() != 0.0f || pathTransform.m23() != 0.0f || pathTransform.m33() != 1.0f); @@ -533,7 +523,6 @@ void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) // so we will have to convert the co-ordinates ourselves. // Change the matrix to just the viewport transformation. pathTransform = viewport; - glyphTransform = gviewport; simpleTransform = false; } else { simpleTransform = true; @@ -3242,10 +3231,10 @@ void QVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, vgImageSubData(vgImage, img.constBits(), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height()); } } - origin[0] = -metrics.x.toReal() + 0.5f; - origin[1] = -metrics.y.toReal() + 0.5f; - escapement[0] = metrics.xoff.toReal(); - escapement[1] = metrics.yoff.toReal(); + origin[0] = -metrics.x.toReal(); + origin[1] = -metrics.y.toReal(); + escapement[0] = 0; + escapement[1] = 0; vgSetGlyphToImage(font, glyph, vgImage, origin, escapement); vgDestroyImage(vgImage); // Reduce reference count. #else @@ -3261,8 +3250,8 @@ void QVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, } origin[0] = 0; origin[1] = 0; - escapement[0] = metrics.xoff.toReal(); - escapement[1] = metrics.yoff.toReal(); + escapement[0] = 0; + escapement[1] = 0; vgSetGlyphToPath(font, glyph, vgPath, VG_FALSE, origin, escapement); vgDestroyPath(vgPath); // Reduce reference count. #endif // !defined(QVG_NO_IMAGE_GLYPHS) @@ -3287,12 +3276,10 @@ void QVGPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) // Get the glyphs and positions associated with the text item. QVarLengthArray<QFixedPoint> positions; QVarLengthArray<glyph_t> glyphs; - QTransform matrix = d->transform; - matrix.translate(p.x(), p.y()); - ti.fontEngine->getGlyphPositions - (ti.glyphs, matrix, ti.flags, glyphs, positions); + QTransform matrix; + ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - if (!drawCachedGlyphs(glyphs.size(), glyphs.data(), ti.font(), ti.fontEngine, p)) + if (!drawCachedGlyphs(glyphs.size(), glyphs.data(), ti.font(), ti.fontEngine, p, positions.data())) QPaintEngineEx::drawTextItem(p, textItem); #else // OpenGL 1.0 does not have support for VGFont and glyphs, @@ -3304,11 +3291,12 @@ void QVGPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) void QVGPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) { drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->font, textItem->fontEngine, - QPointF(0, 0)); + QPointF(0, 0), textItem->glyphPositions); } bool QVGPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFont &font, - QFontEngine *fontEngine, const QPointF &p) + QFontEngine *fontEngine, const QPointF &p, + const QFixedPoint *positions) { #if !defined(QVG_NO_DRAW_GLYPHS) Q_D(QVGPaintEngine); @@ -3334,7 +3322,7 @@ void QVGPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) } // Set the transformation to use for drawing the current glyphs. - QTransform glyphTransform(d->glyphTransform); + QTransform glyphTransform(d->pathTransform); glyphTransform.translate(p.x(), p.y()); #if defined(QVG_NO_IMAGE_GLYPHS) glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY); @@ -3344,10 +3332,18 @@ void QVGPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) // Add the glyphs from the text item into the glyph cache. glyphCache->cacheGlyphs(d, fontEngine, glyphs, numGlyphs); + // Create the array of adjustments between glyphs + QVarLengthArray<VGfloat> adjustments_x(numGlyphs); + QVarLengthArray<VGfloat> adjustments_y(numGlyphs); + for (int i = 1; i < numGlyphs; ++i) { + adjustments_x[i-1] = (positions[i].x - positions[i-1].x).toReal(); + adjustments_y[i-1] = (positions[i].y - positions[i-1].y).toReal(); + } + // Set the glyph drawing origin. VGfloat origin[2]; - origin[0] = 0; - origin[1] = 0; + origin[0] = positions[0].x.toReal(); + origin[1] = positions[0].y.toReal(); vgSetfv(VG_GLYPH_ORIGIN, 2, origin); // Fast anti-aliasing for paths, better for images. @@ -3362,8 +3358,7 @@ void QVGPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) // the Qt pen, not the Qt brush. d->ensureBrush(state()->pen.brush()); vgDrawGlyphs(glyphCache->font, numGlyphs, (VGuint*)glyphs, - NULL, NULL, VG_FILL_PATH, VG_TRUE); - + adjustments_x.data(), adjustments_y.data(), VG_FILL_PATH, VG_TRUE); return true; #else Q_UNUSED(numGlyphs); @@ -3371,6 +3366,7 @@ void QVGPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) Q_UNUSED(font); Q_UNUSED(fontEngine); Q_UNUSED(p); + Q_UNUSED(positions); return false; #endif } diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h index 1e7e26c..33c49ba 100644 --- a/src/openvg/qpaintengine_vg_p.h +++ b/src/openvg/qpaintengine_vg_p.h @@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE +class QFixedPoint; class QVGPaintEnginePrivate; class QPixmapData; class QVGEGLWindowSurfacePrivate; @@ -143,7 +144,8 @@ public: void drawTextItem(const QPointF &p, const QTextItem &textItem); void drawStaticTextItem(QStaticTextItem *staticTextItem); bool drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFont &font, - QFontEngine *fontEngine, const QPointF &p); + QFontEngine *fontEngine, const QPointF &p, + const QFixedPoint *positions); void setState(QPainterState *s); QVGPainterState *state() { return static_cast<QVGPainterState *>(QPaintEngineEx::state()); } diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp index daa827e..f39d538 100644 --- a/src/plugins/accessible/widgets/simplewidgets.cpp +++ b/src/plugins/accessible/widgets/simplewidgets.cpp @@ -605,7 +605,11 @@ int QAccessibleDisplay::navigate(RelationFlag rel, int entry, QAccessibleInterfa /*! \reimp */ QString QAccessibleDisplay::imageDescription() { +#ifndef QT_NO_TOOLTIP return widget()->toolTip(); +#else + return QString::null; +#endif } /*! \reimp */ diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp index 150860f..23675fb 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp @@ -118,7 +118,7 @@ bool DirectShowTimedSample::isReady(IReferenceClock *clock) const } DirectShowSampleScheduler::DirectShowSampleScheduler(IUnknown *pin, QObject *parent) - : QWinEventNotifier(parent) + : QObject(parent) , m_pin(pin) , m_clock(0) , m_allocator(0) @@ -131,13 +131,15 @@ DirectShowSampleScheduler::DirectShowSampleScheduler(IUnknown *pin, QObject *par { m_semaphore.release(m_maximumSamples); - setHandle(m_timeoutEvent); - setEnabled(true); + m_eventNotifier.setHandle(m_timeoutEvent); + m_eventNotifier.setEnabled(true); + + connect(&m_eventNotifier, SIGNAL(activated(HANDLE)), this, SIGNAL(sampleReady())); } DirectShowSampleScheduler::~DirectShowSampleScheduler() { - setEnabled(false); + m_eventNotifier.setEnabled(false); ::CloseHandle(m_timeoutEvent); @@ -398,17 +400,4 @@ bool DirectShowSampleScheduler::scheduleEndOfStream() } } -bool DirectShowSampleScheduler::event(QEvent *event) -{ - if (event->type() == QEvent::WinEventAct) { - QObject::event(event); - - emit sampleReady(); - - return true; - } else { - return QWinEventNotifier::event(event); - } -} - QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h index 007fa99..21823c3 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE class DirectShowTimedSample; -class DirectShowSampleScheduler : public QWinEventNotifier, public IMemInputPin +class DirectShowSampleScheduler : public QObject, public IMemInputPin { Q_OBJECT public: @@ -101,8 +101,6 @@ public: IMediaSample *takeSample(bool *eos); - bool event(QEvent *event); - Q_SIGNALS: void sampleReady(); @@ -118,6 +116,7 @@ private: HANDLE m_timeoutEvent; QSemaphore m_semaphore; QMutex m_mutex; + QWinEventNotifier m_eventNotifier; }; QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/gstreamer/gstreamer.pro b/src/plugins/mediaservices/gstreamer/gstreamer.pro index 0273139..6af9c3f 100644 --- a/src/plugins/mediaservices/gstreamer/gstreamer.pro +++ b/src/plugins/mediaservices/gstreamer/gstreamer.pro @@ -9,39 +9,48 @@ unix:contains(QT_CONFIG, alsa) { } QMAKE_CXXFLAGS += $$QT_CFLAGS_GSTREAMER -LIBS += -lXv $$QT_LIBS_GSTREAMER -lgstinterfaces-0.10 -lgstvideo-0.10 -lgstbase-0.10 -lgstaudio-0.10 +LIBS += $$QT_LIBS_GSTREAMER -lgstinterfaces-0.10 -lgstvideo-0.10 -lgstbase-0.10 -lgstaudio-0.10 # Input HEADERS += \ qgstreamermessage.h \ qgstreamerbushelper.h \ qgstreamervideooutputcontrol.h \ - qgstreamervideorendererinterface.h \ - qgstreamervideowidget.h \ + qgstreamervideorendererinterface.h \ qgstreamerserviceplugin.h \ qgstreamervideoinputdevicecontrol.h \ - qgstreamervideooverlay.h \ qgstreamervideorenderer.h \ qgstvideobuffer.h \ - qvideosurfacegstsink.h \ - qx11videosurface.h \ - qgstxvimagebuffer.h + qvideosurfacegstsink.h SOURCES += \ qgstreamermessage.cpp \ qgstreamerbushelper.cpp \ qgstreamervideooutputcontrol.cpp \ - qgstreamervideorendererinterface.cpp \ - qgstreamervideowidget.cpp \ + qgstreamervideorendererinterface.cpp \ qgstreamerserviceplugin.cpp \ qgstreamervideoinputdevicecontrol.cpp \ - qgstreamervideooverlay.cpp \ qgstreamervideorenderer.cpp \ qgstvideobuffer.cpp \ - qvideosurfacegstsink.cpp \ - qx11videosurface.cpp \ - qgstxvimagebuffer.cpp + qvideosurfacegstsink.cpp + + +x11 { + LIBS += -lXv + + HEADERS += \ + qgstreamervideooverlay.h \ + qgstreamervideowidget.h \ + qx11videosurface.h \ + qgstxvimagebuffer.h + + SOURCES += \ + qgstreamervideooverlay.cpp \ + qgstreamervideowidget.cpp \ + qx11videosurface.cpp \ + qgstxvimagebuffer.cpp +} include(mediaplayer/mediaplayer.pri) diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp index d5d7bd0..3228722 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp @@ -63,7 +63,10 @@ QT_BEGIN_NAMESPACE QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent): - QMediaService(parent) + QMediaService(parent), + m_videoRenderer(0), + m_videoWindow(0), + m_videoWidget(0) { m_session = new QGstreamerPlayerSession(this); m_control = new QGstreamerPlayerControl(m_session, this); @@ -74,13 +77,22 @@ QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent): connect(m_videoOutput, SIGNAL(outputChanged(QVideoOutputControl::Output)), this, SLOT(videoOutputChanged(QVideoOutputControl::Output))); m_videoRenderer = new QGstreamerVideoRenderer(this); + +#ifdef Q_WS_X11 m_videoWindow = new QGstreamerVideoOverlay(this); m_videoWidget = new QGstreamerVideoWidgetControl(this); +#endif + + QList<QVideoOutputControl::Output> outputs; + + if (m_videoRenderer) + outputs << QVideoOutputControl::RendererOutput; + if (m_videoWidget) + outputs << QVideoOutputControl::WidgetOutput; + if (m_videoWindow) + outputs << QVideoOutputControl::WindowOutput; - m_videoOutput->setAvailableOutputs(QList<QVideoOutputControl::Output>() - << QVideoOutputControl::RendererOutput - << QVideoOutputControl::WindowOutput - << QVideoOutputControl::WidgetOutput); + m_videoOutput->setAvailableOutputs(outputs); } QGstreamerPlayerService::~QGstreamerPlayerService() diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp index 76d87ce..596e39d 100644 --- a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp @@ -44,12 +44,16 @@ #include <QtCore/qdebug.h> #include <QMap> #include <QThread> + +#include "qgstvideobuffer.h" + +#ifdef Q_WS_X11 #include <QtGui/qx11info_x11.h> +#include "qgstxvimagebuffer.h" +#endif #include "qvideosurfacegstsink.h" -#include "qgstvideobuffer.h" -#include "qgstxvimagebuffer.h" @@ -131,11 +135,13 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer) QGstVideoBuffer *videoBuffer = 0; +#ifdef Q_WS_X11 if (G_TYPE_CHECK_INSTANCE_TYPE(buffer, QGstXvImageBuffer::get_type())) { QGstXvImageBuffer *xvBuffer = reinterpret_cast<QGstXvImageBuffer *>(buffer); QVariant handle = QVariant::fromValue(xvBuffer->xvImage); videoBuffer = new QGstVideoBuffer(buffer, m_bytesPerLine, XvHandleType, handle); } else +#endif videoBuffer = new QGstVideoBuffer(buffer, m_bytesPerLine); m_frame = QVideoFrame( @@ -387,7 +393,9 @@ void QVideoSurfaceGstSink::instance_init(GTypeInstance *instance, gpointer g_cla Q_UNUSED(g_class); sink->delegate = 0; +#ifdef Q_WS_X11 sink->pool = new QGstXvImageBufferPool(); +#endif sink->lastRequestedCaps = 0; sink->lastBufferCaps = 0; sink->lastSurfaceFormat = new QVideoSurfaceFormat; @@ -396,8 +404,11 @@ void QVideoSurfaceGstSink::instance_init(GTypeInstance *instance, gpointer g_cla void QVideoSurfaceGstSink::finalize(GObject *object) { VO_SINK(object); +#ifdef Q_WS_X11 delete sink->pool; sink->pool = 0; +#endif + delete sink->lastSurfaceFormat; sink->lastSurfaceFormat = 0; @@ -588,6 +599,8 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( *buffer = 0; +#ifdef Q_WS_X11 + if (sink->lastRequestedCaps && gst_caps_is_equal(sink->lastRequestedCaps, caps)) { //qDebug() << "reusing last caps"; *buffer = GST_BUFFER(sink->pool->takeBuffer(*sink->lastSurfaceFormat, sink->lastBufferCaps)); @@ -649,6 +662,7 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( *buffer = GST_BUFFER(sink->pool->takeBuffer(surfaceFormat, intersection)); +#endif return GST_FLOW_OK; } diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h index f59a43c..75fa854 100644 --- a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h @@ -59,8 +59,10 @@ QT_BEGIN_NAMESPACE class QAbstractVideoSurface; +#ifdef Q_WS_X11 class QGstXvImageBuffer; class QGstXvImageBufferPool; +#endif class QVideoSurfaceGstDelegate : public QObject @@ -137,7 +139,11 @@ private: private: QVideoSurfaceGstDelegate *delegate; + +#ifdef Q_WS_X11 QGstXvImageBufferPool *pool; +#endif + GstCaps *lastRequestedCaps; GstCaps *lastBufferCaps; QVideoSurfaceFormat *lastSurfaceFormat; diff --git a/src/plugins/mediaservices/mediaservices.pro b/src/plugins/mediaservices/mediaservices.pro index 6a00a14..27f05bc 100644 --- a/src/plugins/mediaservices/mediaservices.pro +++ b/src/plugins/mediaservices/mediaservices.pro @@ -5,7 +5,9 @@ contains(QT_CONFIG, media-backend) { mac: SUBDIRS += qt7 - unix:!mac:!symbian:contains(QT_CONFIG, xvideo):contains(QT_CONFIG, gstreamer) { + unix:!mac:!symbian:contains(QT_CONFIG, gstreamer) { SUBDIRS += gstreamer } + + symbian:SUBDIRS += symbian } diff --git a/src/plugins/mediaservices/symbian/mediaplayer/mediaplayer.pri b/src/plugins/mediaservices/symbian/mediaplayer/mediaplayer.pri new file mode 100644 index 0000000..205e014 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/mediaplayer.pri @@ -0,0 +1,63 @@ +INCLUDEPATH += $$PWD +LIBS += -lmediaclientvideo \ + -lmediaclientaudio \ + -lws32 \ + -lfbscli \ + -lcone \ + -lmmfcontrollerframework \ + -lefsrv \ + -lbitgdi \ + -lapgrfx \ + -lapmime + + +# We are building Symbian backend with media player support +DEFINES += QMEDIA_MMF_PLAYER + + +HEADERS += \ + $$PWD/s60mediaplayercontrol.h \ + $$PWD/s60mediaplayerservice.h \ + $$PWD/s60mediaplayersession.h \ + $$PWD/s60videoplayersession.h \ + $$PWD/s60mediametadataprovider.h \ + $$PWD/s60videosurface.h \ + $$PWD/s60videooverlay.h \ + $$PWD/s60videorenderer.h \ + $$PWD/s60mediarecognizer.h \ + $$PWD/s60audioplayersession.h \ + $$PWD/ms60mediaplayerresolver.h \ + $$PWD/s60videowidget.h \ + $$PWD/s60mediaplayeraudioendpointselector.h + +SOURCES += \ + $$PWD/s60mediaplayercontrol.cpp \ + $$PWD/s60mediaplayerservice.cpp \ + $$PWD/s60mediaplayersession.cpp \ + $$PWD/s60videoplayersession.cpp \ + $$PWD/s60mediametadataprovider.cpp \ + $$PWD/s60videosurface.cpp \ + $$PWD/s60videooverlay.cpp \ + $$PWD/s60videorenderer.cpp \ + $$PWD/s60mediarecognizer.cpp \ + $$PWD/s60audioplayersession.cpp \ + $$PWD/s60videowidget.cpp \ + $$PWD/s60mediaplayeraudioendpointselector.cpp + +contains(S60_VERSION, 3.1) { + + #3.1 doesn't provide audio routing in videoplayer + DEFINES += HAS_NO_AUDIOROUTING_IN_VIDEOPLAYER + + !exists($${EPOCROOT}epoc32\release\winscw\udeb\audiooutputrouting.lib) { + MMP_RULES += "$${LITERAL_HASH}ifdef WINSCW" \ + "MACRO HAS_NO_AUDIOROUTING" \ + "$${LITERAL_HASH}else" \ + "LIBRARY audiooutputrouting.lib" \ + "$${LITERAL_HASH}endif" + } + +} else { + LIBS += -laudiooutputrouting +} + diff --git a/src/plugins/mediaservices/symbian/mediaplayer/ms60mediaplayerresolver.h b/src/plugins/mediaservices/symbian/mediaplayer/ms60mediaplayerresolver.h new file mode 100644 index 0000000..b655a83 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/ms60mediaplayerresolver.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef MS60MEDIAPLAYERRESOLVER_H +#define MS60MEDIAPLAYERRESOLVER_H + +QT_BEGIN_NAMESPACE + +class S60MediaPlayerSession; + +class MS60MediaPlayerResolver +{ + public: + virtual S60MediaPlayerSession* PlayerSession() = 0; + virtual S60MediaPlayerSession* VideoPlayerSession() = 0; + virtual S60MediaPlayerSession* AudioPlayerSession() = 0; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60audioplayersession.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60audioplayersession.cpp new file mode 100644 index 0000000..f4065e4 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60audioplayersession.cpp @@ -0,0 +1,268 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "s60audioplayersession.h" +#include <QtCore/qdebug.h> +#include <QtCore/qvariant.h> + +#include <AudioOutput.h> +#include <MAudioOutputObserver.h> + +QT_BEGIN_NAMESPACE + +S60AudioPlayerSession::S60AudioPlayerSession(QObject *parent) + : S60MediaPlayerSession(parent) + , m_player(0) + , m_audioOutput(0) + , m_audioEndpoint("Default") +{ + QT_TRAP_THROWING(m_player = CAudioPlayer::NewL(*this, 0, EMdaPriorityPreferenceNone)); + m_player->RegisterForAudioLoadingNotification(*this); +} + +S60AudioPlayerSession::~S60AudioPlayerSession() +{ +#if !defined(HAS_NO_AUDIOROUTING) + if (m_audioOutput) + m_audioOutput->UnregisterObserver(*this); + delete m_audioOutput; +#endif + m_player->Close(); + delete m_player; +} + +void S60AudioPlayerSession::doLoadL(const TDesC &path) +{ + // m_audioOutput needs to be reinitialized after MapcInitComplete + if (m_audioOutput) + m_audioOutput->UnregisterObserver(*this); + delete m_audioOutput; + m_audioOutput = NULL; + + m_player->OpenFileL(path); +} + +qint64 S60AudioPlayerSession::doGetDurationL() const +{ + return m_player->Duration().Int64() / qint64(1000); +} + +qint64 S60AudioPlayerSession::doGetPositionL() const +{ + TTimeIntervalMicroSeconds ms = 0; + m_player->GetPosition(ms); + return ms.Int64() / qint64(1000); +} + +bool S60AudioPlayerSession::isVideoAvailable() const +{ + return false; +} +bool S60AudioPlayerSession::isAudioAvailable() const +{ + return true; // this is a bit happy scenario, but we do emit error that we can't play +} + +void S60AudioPlayerSession::MaloLoadingStarted() +{ + buffering(); +} + +void S60AudioPlayerSession::MaloLoadingComplete() +{ + buffered(); +} + +void S60AudioPlayerSession::doPlay() +{ +// For some reason loading progress callbalck are not called on emulator +#ifdef __WINSCW__ + buffering(); +#endif + m_player->Play(); +#ifdef __WINSCW__ + buffered(); +#endif + +} + +void S60AudioPlayerSession::doPauseL() +{ + m_player->Pause(); +} + +void S60AudioPlayerSession::doStop() +{ + m_player->Stop(); +} + +void S60AudioPlayerSession::doSetVolumeL(int volume) +{ + m_player->SetVolume((volume / 100.0) * m_player->MaxVolume()); +} + +void S60AudioPlayerSession::doSetPositionL(qint64 microSeconds) +{ + m_player->SetPosition(TTimeIntervalMicroSeconds(microSeconds)); +} + +void S60AudioPlayerSession::updateMetaDataEntriesL() +{ + metaDataEntries().clear(); + int numberOfMetaDataEntries = 0; + + m_player->GetNumberOfMetaDataEntries(numberOfMetaDataEntries); + + for (int i = 0; i < numberOfMetaDataEntries; i++) { + CMMFMetaDataEntry *entry = NULL; + entry = m_player->GetMetaDataEntryL(i); + metaDataEntries().insert(QString::fromUtf16(entry->Name().Ptr(), entry->Name().Length()), QString::fromUtf16(entry->Value().Ptr(), entry->Value().Length())); + delete entry; + } + emit metaDataChanged(); +} + +int S60AudioPlayerSession::doGetBufferStatusL() const +{ + int progress = 0; + m_player->GetAudioLoadingProgressL(progress); + return progress; +} + +void S60AudioPlayerSession::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration) +{ + Q_UNUSED(aDuration); + setError(aError); + TRAPD(err, + m_audioOutput = CAudioOutput::NewL(*m_player); + m_audioOutput->RegisterObserverL(*this); + ); + setActiveEndpoint(m_audioEndpoint); + setError(err); + loaded(); +} + +void S60AudioPlayerSession::MapcPlayComplete(TInt aError) +{ + setError(aError); + endOfMedia(); +} + +void S60AudioPlayerSession::doSetAudioEndpoint(const QString& audioEndpoint) +{ + m_audioEndpoint = audioEndpoint; +} + +QString S60AudioPlayerSession::activeEndpoint() const +{ + QString outputName = QString("Default"); +#if !defined(HAS_NO_AUDIOROUTING) + if (m_audioOutput) { + CAudioOutput::TAudioOutputPreference output = m_audioOutput->AudioOutput(); + outputName = qStringFromTAudioOutputPreference(output); + } +#endif + return outputName; +} + +QString S60AudioPlayerSession::defaultEndpoint() const +{ + QString outputName = QString("Default"); +#if !defined(HAS_NO_AUDIOROUTING) + if (m_audioOutput) { + CAudioOutput::TAudioOutputPreference output = m_audioOutput->DefaultAudioOutput(); + outputName = qStringFromTAudioOutputPreference(output); + } +#endif + return outputName; +} + +void S60AudioPlayerSession::setActiveEndpoint(const QString& name) +{ + CAudioOutput::TAudioOutputPreference output = CAudioOutput::ENoPreference; + + if (name == QString("Default")) + output = CAudioOutput::ENoPreference; + else if (name == QString("All")) + output = CAudioOutput::EAll; + else if (name == QString("None")) + output = CAudioOutput::ENoOutput; + else if (name == QString("Earphone")) + output = CAudioOutput::EPrivate; + else if (name == QString("Speaker")) + output = CAudioOutput::EPublic; +#if !defined(HAS_NO_AUDIOROUTING) + if (m_audioOutput) { + TRAPD(err, m_audioOutput->SetAudioOutputL(output)); + setError(err); + + if (m_audioEndpoint != name) { + m_audioEndpoint = name; + emit activeEndpointChanged(name); + } + } +#endif +} + +void S60AudioPlayerSession::DefaultAudioOutputChanged(CAudioOutput& aAudioOutput, + CAudioOutput::TAudioOutputPreference aNewDefault) +{ + // Emit already implemented in setActiveEndpoint function + Q_UNUSED(aAudioOutput) + Q_UNUSED(aNewDefault) +} + +QString S60AudioPlayerSession::qStringFromTAudioOutputPreference(CAudioOutput::TAudioOutputPreference output) const +{ + if (output == CAudioOutput::ENoPreference) + return QString("Default"); + else if (output == CAudioOutput::EAll) + return QString("All"); + else if (output == CAudioOutput::ENoOutput) + return QString("None"); + else if (output == CAudioOutput::EPrivate) + return QString("Earphone"); + else if (output == CAudioOutput::EPublic) + return QString("Speaker"); + return QString("Default"); +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60audioplayersession.h b/src/plugins/mediaservices/symbian/mediaplayer/s60audioplayersession.h new file mode 100644 index 0000000..fca66b3 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60audioplayersession.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60AUDIOPLAYERSESSION_H +#define S60AUDIOPLAYERSESSION_H + +#include "s60mediaplayersession.h" + +#include <mdaaudiosampleplayer.h> +typedef CMdaAudioPlayerUtility CAudioPlayer; +typedef MMdaAudioPlayerCallback MAudioPlayerObserver; + +#include <AudioOutput.h> +#include <MAudioOutputObserver.h> + +QT_BEGIN_NAMESPACE + +class S60AudioPlayerSession : public S60MediaPlayerSession + , public MAudioPlayerObserver + , public MAudioLoadingObserver + , public MAudioOutputObserver +{ + Q_OBJECT + +public: + S60AudioPlayerSession(QObject *parent); + ~S60AudioPlayerSession(); + + //From S60MediaPlayerSession + bool isVideoAvailable() const; + bool isAudioAvailable() const; + + // From MAudioLoadingObserver + void MaloLoadingStarted(); + void MaloLoadingComplete(); + + // From MAudioOutputObserver + void DefaultAudioOutputChanged( CAudioOutput& aAudioOutput, + CAudioOutput::TAudioOutputPreference aNewDefault ); + +public: + // From S60MediaPlayerAudioEndpointSelector + QString activeEndpoint() const; + QString defaultEndpoint() const; +public Q_SLOTS: + void setActiveEndpoint(const QString& name); +Q_SIGNALS: + void activeEndpointChanged(const QString & name); + +protected: + //From S60MediaPlayerSession + void doLoadL(const TDesC &path); + void doLoadUrlL(const TDesC &path){Q_UNUSED(path)/*empty implementation*/} + void doPlay(); + void doStop(); + void doPauseL(); + void doSetVolumeL(int volume); + qint64 doGetPositionL() const; + void doSetPositionL(qint64 microSeconds); + void updateMetaDataEntriesL(); + int doGetBufferStatusL() const; + qint64 doGetDurationL() const; + void doSetAudioEndpoint(const QString& audioEndpoint); + +private: + void MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration); + void MapcPlayComplete(TInt aError); + QString qStringFromTAudioOutputPreference(CAudioOutput::TAudioOutputPreference output) const; + +private: + CAudioPlayer *m_player; + CAudioOutput *m_audioOutput; + QString m_audioEndpoint; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediametadataprovider.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60mediametadataprovider.cpp new file mode 100644 index 0000000..e80c487 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediametadataprovider.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "s60mediametadataprovider.h" +#include "s60mediaplayersession.h" +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +S60MediaMetaDataProvider::S60MediaMetaDataProvider(MS60MediaPlayerResolver& mediaPlayerResolver, QObject *parent) + : QMetaDataControl(parent) + , m_mediaPlayerResolver(mediaPlayerResolver) + , m_session(NULL) +{ +} + +S60MediaMetaDataProvider::~S60MediaMetaDataProvider() +{ +} + +bool S60MediaMetaDataProvider::isMetaDataAvailable() const +{ + m_session = m_mediaPlayerResolver.PlayerSession(); + if (m_session) + return m_session->isMetadataAvailable(); + return false; +} + +bool S60MediaMetaDataProvider::isWritable() const +{ + return false; +} + +QVariant S60MediaMetaDataProvider::metaData(QtMediaServices::MetaData key) const +{ + m_session = m_mediaPlayerResolver.PlayerSession(); + if (m_session && m_session->isMetadataAvailable()) + return m_session->metaData(metaDataKeyAsString(key)); + return QVariant(); +} + +void S60MediaMetaDataProvider::setMetaData(QtMediaServices::MetaData key, QVariant const &value) +{ + Q_UNUSED(key); + Q_UNUSED(value); +} +QList<QtMediaServices::MetaData> S60MediaMetaDataProvider::availableMetaData() const +{ + m_session = m_mediaPlayerResolver.PlayerSession(); + QList<QtMediaServices::MetaData> metaDataTags; + if (m_session && m_session->isMetadataAvailable()) { + for (int i = QtMediaServices::Title; i <= QtMediaServices::DeviceSettingDescription; i++) { + QString metaData = metaDataKeyAsString((QtMediaServices::MetaData)i); + if (!metaData.isEmpty()) { + if (!m_session->metaData(metaData).toString().isEmpty()) { + metaDataTags.append((QtMediaServices::MetaData)i); + } + } + } + } + return metaDataTags; +} + +QVariant S60MediaMetaDataProvider::extendedMetaData(const QString &key) const +{ + m_session = m_mediaPlayerResolver.PlayerSession(); + if (m_session && m_session->isMetadataAvailable()) + return m_session->metaData(key); + return QVariant(); +} + +void S60MediaMetaDataProvider::setExtendedMetaData(const QString &key, QVariant const &value) +{ + Q_UNUSED(key); + Q_UNUSED(value); +} + +QStringList S60MediaMetaDataProvider::availableExtendedMetaData() const +{ + m_session = m_mediaPlayerResolver.PlayerSession(); + if (m_session && m_session->isMetadataAvailable()) + return m_session->availableMetaData().keys(); + return QStringList(); +} + +QString S60MediaMetaDataProvider::metaDataKeyAsString(QtMediaServices::MetaData key) const +{ + switch(key) { + case QtMediaServices::Title: return "title"; + case QtMediaServices::AlbumArtist: return "artist"; + case QtMediaServices::Comment: return "comment"; + case QtMediaServices::Genre: return "genre"; + case QtMediaServices::Year: return "year"; + case QtMediaServices::Copyright: return "copyright"; + case QtMediaServices::AlbumTitle: return "album"; + case QtMediaServices::Composer: return "composer"; + case QtMediaServices::TrackNumber: return "albumtrack"; + case QtMediaServices::AudioBitRate: return "audiobitrate"; + case QtMediaServices::VideoBitRate: return "videobitrate"; + case QtMediaServices::Duration: return "duration"; + case QtMediaServices::MediaType: return "contenttype"; + case QtMediaServices::SubTitle: // TODO: Find the matching metadata keys + case QtMediaServices::Description: + case QtMediaServices::Category: + case QtMediaServices::Date: + case QtMediaServices::UserRating: + case QtMediaServices::Keywords: + case QtMediaServices::Language: + case QtMediaServices::Publisher: + case QtMediaServices::ParentalRating: + case QtMediaServices::RatingOrganisation: + case QtMediaServices::Size: + case QtMediaServices::AudioCodec: + case QtMediaServices::AverageLevel: + case QtMediaServices::ChannelCount: + case QtMediaServices::PeakValue: + case QtMediaServices::SampleRate: + case QtMediaServices::Author: + case QtMediaServices::ContributingArtist: + case QtMediaServices::Conductor: + case QtMediaServices::Lyrics: + case QtMediaServices::Mood: + case QtMediaServices::TrackCount: + case QtMediaServices::CoverArtUrlSmall: + case QtMediaServices::CoverArtUrlLarge: + case QtMediaServices::Resolution: + case QtMediaServices::PixelAspectRatio: + case QtMediaServices::VideoFrameRate: + case QtMediaServices::VideoCodec: + case QtMediaServices::PosterUrl: + case QtMediaServices::ChapterNumber: + case QtMediaServices::Director: + case QtMediaServices::LeadPerformer: + case QtMediaServices::Writer: + case QtMediaServices::CameraManufacturer: + case QtMediaServices::CameraModel: + case QtMediaServices::Event: + case QtMediaServices::Subject: + default: + break; + } + + return QString(); +} + +QT_END_NAMESPACE + diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediametadataprovider.h b/src/plugins/mediaservices/symbian/mediaplayer/s60mediametadataprovider.h new file mode 100644 index 0000000..07ae494 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediametadataprovider.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60MEDIAMETADATAPROVIDER_H +#define S60MEDIAMETADATAPROVIDER_H + +#include <qmetadatacontrol.h> +#include "ms60mediaplayerresolver.h" + +QT_BEGIN_NAMESPACE + +class S60MediaPlayerSession; + +class S60MediaMetaDataProvider : public QMetaDataControl +{ + Q_OBJECT + +public: + S60MediaMetaDataProvider(MS60MediaPlayerResolver& mediaPlayerResolver, QObject *parent = 0); + ~S60MediaMetaDataProvider(); + + bool isMetaDataAvailable() const; + bool isWritable() const; + + QVariant metaData(QtMediaServices::MetaData key) const; + void setMetaData(QtMediaServices::MetaData key, const QVariant &value); + QList<QtMediaServices::MetaData> availableMetaData() const; + + QVariant extendedMetaData(const QString &key) const ; + void setExtendedMetaData(const QString &key, const QVariant &value); + QStringList availableExtendedMetaData() const; + +private: + QString metaDataKeyAsString(QtMediaServices::MetaData key) const; + +private: + MS60MediaPlayerResolver& m_mediaPlayerResolver; + mutable S60MediaPlayerSession *m_session; +}; + +QT_END_NAMESPACE + +#endif // S60VIDEOMETADATAPROVIDER_H diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayeraudioendpointselector.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayeraudioendpointselector.cpp new file mode 100644 index 0000000..dbeed90 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayeraudioendpointselector.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "s60mediaplayercontrol.h" +#include "s60mediaplayersession.h" +#include "s60mediaplayeraudioendpointselector.h" + +#include <QtGui/QIcon> +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +S60MediaPlayerAudioEndpointSelector::S60MediaPlayerAudioEndpointSelector(QObject *control, QObject *parent) + :QMediaControl(parent) + , m_control(0) + , m_audioEndpointNames(0) +{ + m_control = qobject_cast<S60MediaPlayerControl*>(control); +} + +S60MediaPlayerAudioEndpointSelector::~S60MediaPlayerAudioEndpointSelector() +{ + delete m_audioEndpointNames; +} + +QList<QString> S60MediaPlayerAudioEndpointSelector::availableEndpoints() const +{ + if(m_audioEndpointNames->count() == 0) { + m_audioEndpointNames->append("Default"); + m_audioEndpointNames->append("All"); + m_audioEndpointNames->append("None"); + m_audioEndpointNames->append("Earphone"); + m_audioEndpointNames->append("Speaker"); + } + return *m_audioEndpointNames; +} + +QString S60MediaPlayerAudioEndpointSelector::endpointDescription(const QString& name) const +{ + if (name == QString("Default")) //ENoPreference + return QString("Used to indicate that the playing audio can be routed to" + "any speaker. This is the default value for audio."); + else if (name == QString("All")) //EAll + return QString("Used to indicate that the playing audio should be routed to all speakers."); + else if (name == QString("None")) //ENoOutput + return QString("Used to indicate that the playing audio should not be routed to any output."); + else if (name == QString("Earphone")) //EPrivate + return QString("Used to indicate that the playing audio should be routed to" + "the default private speaker. A private speaker is one that can only" + "be heard by one person."); + else if (name == QString("Speaker")) //EPublic + return QString("Used to indicate that the playing audio should be routed to" + "the default public speaker. A public speaker is one that can " + "be heard by multiple people."); + + return QString(); +} + +QString S60MediaPlayerAudioEndpointSelector::activeEndpoint() const +{ + if (m_control->session()) + return m_control->session()->activeEndpoint(); + else + return m_control->mediaControlSettings().audioEndpoint(); +} + +QString S60MediaPlayerAudioEndpointSelector::defaultEndpoint() const +{ + if (m_control->session()) + return m_control->session()->defaultEndpoint(); + else + return m_control->mediaControlSettings().audioEndpoint(); +} + +void S60MediaPlayerAudioEndpointSelector::setActiveEndpoint(const QString& name) +{ + QString oldEndpoint = m_control->mediaControlSettings().audioEndpoint(); + + if (name != oldEndpoint && (name == QString("Default") || name == QString("All") || + name == QString("None") || name == QString("Earphone") || name == QString("Speaker"))) { + + if (m_control->session()) { + m_control->session()->setActiveEndpoint(name); + } + m_control->setAudioEndpoint(name); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayeraudioendpointselector.h b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayeraudioendpointselector.h new file mode 100644 index 0000000..a110ae8 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayeraudioendpointselector.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60MEDIAPLAYERAUDIOENDPOINTSELECTOR_H +#define S60MEDIAPLAYERAUDIOENDPOINTSELECTOR_H + +#include <QStringList> + +#include <QtMediaServices/qmediacontrol.h> + +QT_BEGIN_NAMESPACE + +class S60MediaPlayerControl; +class S60MediaPlayerSession; + +class S60MediaPlayerAudioEndpointSelector : public QMediaControl +{ + +Q_OBJECT + +public: + S60MediaPlayerAudioEndpointSelector(QObject *control, QObject *parent = 0); + ~S60MediaPlayerAudioEndpointSelector(); + + QList<QString> availableEndpoints() const ; + QString endpointDescription(const QString& name) const; + QString defaultEndpoint() const; + QString activeEndpoint() const; + +public Q_SLOTS: + void setActiveEndpoint(const QString& name); + +private: + S60MediaPlayerControl* m_control; + QString m_audioInput; + QList<QString> *m_audioEndpointNames; +}; + +#define QAudioEndpointSelector_iid "com.nokia.Qt.QAudioEndpointSelector/1.0" + +QT_END_NAMESPACE + +#endif // S60MEDIAPLAYERAUDIOENDPOINTSELECTOR_H diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayercontrol.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayercontrol.cpp new file mode 100644 index 0000000..8e03afd --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayercontrol.cpp @@ -0,0 +1,274 @@ + +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "s60mediaplayercontrol.h" +#include "s60mediaplayersession.h" + +#include <QtCore/qdir.h> +#include <QtCore/qurl.h> +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +S60MediaPlayerControl::S60MediaPlayerControl(MS60MediaPlayerResolver& mediaPlayerResolver, QObject *parent) + : QMediaPlayerControl(parent), + m_mediaPlayerResolver(mediaPlayerResolver), + m_session(NULL), + m_stream(NULL) +{ +} + +S60MediaPlayerControl::~S60MediaPlayerControl() +{ +} + +qint64 S60MediaPlayerControl::position() const +{ + if (m_session) + return m_session->position(); + return 0; +} + +qint64 S60MediaPlayerControl::duration() const +{ + if (m_session) + return m_session->duration(); + return -1; +} + +QMediaPlayer::State S60MediaPlayerControl::state() const +{ + if (m_session) + return m_session->state(); + return QMediaPlayer::StoppedState; +} + +QMediaPlayer::MediaStatus S60MediaPlayerControl::mediaStatus() const +{ + if (m_session) + return m_session->mediaStatus(); + return m_mediaSettings.mediaStatus(); +} + +int S60MediaPlayerControl::bufferStatus() const +{ + if (m_session) + return m_session->bufferStatus(); + return 0; +} + +int S60MediaPlayerControl::volume() const +{ + if (m_session) + return m_session->volume(); + return m_mediaSettings.volume(); +} + +bool S60MediaPlayerControl::isMuted() const +{ + if (m_session) + return m_session->isMuted(); + return m_mediaSettings.isMuted(); +} + +bool S60MediaPlayerControl::isSeekable() const +{ + if (m_session) + return m_session->isSeekable(); + return false; +} + +QMediaTimeRange S60MediaPlayerControl::availablePlaybackRanges() const +{ + QMediaTimeRange ranges; + + if(m_session && m_session->isSeekable()) + ranges.addInterval(0, m_session->duration()); + + return ranges; +} + +qreal S60MediaPlayerControl::playbackRate() const +{ + //None of symbian players supports this. + return m_mediaSettings.playbackRate(); +} + +void S60MediaPlayerControl::setPlaybackRate(qreal rate) +{ + //None of symbian players supports this. + m_mediaSettings.setPlaybackRate(rate); + emit playbackRateChanged(playbackRate()); + +} + +void S60MediaPlayerControl::setPosition(qint64 pos) +{ + if (m_session) + m_session->setPosition(pos); +} + +void S60MediaPlayerControl::play() +{ + if (m_session) + m_session->play(); +} + +void S60MediaPlayerControl::pause() +{ + if (m_session) + m_session->pause(); +} + +void S60MediaPlayerControl::stop() +{ + if (m_session) + m_session->stop(); +} + +void S60MediaPlayerControl::setVolume(int volume) +{ + int boundVolume = qBound(0, volume, 100); + if (boundVolume == m_mediaSettings.volume()) + return; + + m_mediaSettings.setVolume(boundVolume); + if (m_session) + m_session->setVolume(boundVolume); + + emit volumeChanged(boundVolume); +} + +void S60MediaPlayerControl::setMuted(bool muted) +{ + if (m_mediaSettings.isMuted() == muted) + return; + + m_mediaSettings.setMuted(muted); + if (m_session) + m_session->setMuted(muted); + + emit mutedChanged(muted); +} + +QMediaContent S60MediaPlayerControl::media() const +{ + return m_currentResource; +} + +const QIODevice *S60MediaPlayerControl::mediaStream() const +{ + return m_stream; +} + +void S60MediaPlayerControl::setMedia(const QMediaContent &source, QIODevice *stream) +{ + Q_UNUSED(stream) + // we don't want to set & load media again when it is already loaded + if (m_session && m_currentResource == source) + return; + + // store to variable as session is created based on the content type. + m_currentResource = source; + S60MediaPlayerSession *newSession = m_mediaPlayerResolver.PlayerSession(); + m_mediaSettings.setMediaStatus(QMediaPlayer::UnknownMediaStatus); + + if (m_session) + m_session->reset(); + else { + emit mediaStatusChanged(QMediaPlayer::UnknownMediaStatus); + emit error(QMediaPlayer::NoError, QString()); + } + + m_session = newSession; + + if (m_session) + m_session->load(source.canonicalUrl()); + else { + QMediaPlayer::MediaStatus status = (source.isNull()) ? QMediaPlayer::NoMedia : QMediaPlayer::InvalidMedia; + m_mediaSettings.setMediaStatus(status); + emit stateChanged(QMediaPlayer::StoppedState); + emit error((source.isNull()) ? QMediaPlayer::NoError : QMediaPlayer::ResourceError, + (source.isNull()) ? "" : tr("Media couldn't be resolved")); + emit mediaStatusChanged(status); + } + emit mediaChanged(m_currentResource); + } + +S60MediaPlayerSession* S60MediaPlayerControl::session() +{ + return m_session; +} + +void S60MediaPlayerControl::setVideoOutput(QObject *output) +{ + S60MediaPlayerSession *session = NULL; + session = m_mediaPlayerResolver.VideoPlayerSession(); + session->setVideoRenderer(output); +} + +bool S60MediaPlayerControl::isAudioAvailable() const +{ + if (m_session) + return m_session->isAudioAvailable(); + return false; +} + +bool S60MediaPlayerControl::isVideoAvailable() const +{ + if (m_session) + return m_session->isVideoAvailable(); + return false; +} + +const S60MediaSettings& S60MediaPlayerControl::mediaControlSettings() const +{ + return m_mediaSettings; +} + +void S60MediaPlayerControl::setAudioEndpoint(const QString& name) +{ + m_mediaSettings.setAudioEndpoint(name); +} + +QT_END_NAMESPACE + diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayercontrol.h b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayercontrol.h new file mode 100644 index 0000000..3d26a5e --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayercontrol.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60MEDIAPLAYERCONTROL_H +#define S60MEDIAPLAYERCONTROL_H + +#include <QtCore/qobject.h> + +#include <qmediaplayercontrol.h> + +#include "ms60mediaplayerresolver.h" +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +class QMediaPlayer; +class QMediaTimeRange; +class QMediaContent; + + +class S60MediaPlayerSession; +class S60MediaPlayerService; + +class S60MediaSettings +{ + +public: + S60MediaSettings() + : m_volume(0) + , m_muted(false) + , m_playbackRate(0) + , m_mediaStatus(QMediaPlayer::UnknownMediaStatus) + , m_audioEndpoint(QString("Default")) + { + } + + void setVolume(int volume) { m_volume = volume; } + void setMuted(bool muted) { m_muted = muted; } + void setPlaybackRate(int rate) { m_playbackRate = rate; } + void setMediaStatus(QMediaPlayer::MediaStatus status) {m_mediaStatus=status;} + void setAudioEndpoint(const QString& audioEndpoint) { m_audioEndpoint = audioEndpoint; } + + int volume() const { return m_volume; } + bool isMuted() const { return m_muted; } + qreal playbackRate() const { return m_playbackRate; } + QMediaPlayer::MediaStatus mediaStatus() const {return m_mediaStatus;} + QString audioEndpoint() const { return m_audioEndpoint; } + +private: + int m_volume; + bool m_muted; + qreal m_playbackRate; + QMediaPlayer::MediaStatus m_mediaStatus; + QString m_audioEndpoint; +}; + +class S60MediaPlayerControl : public QMediaPlayerControl +{ + Q_OBJECT + +public: + S60MediaPlayerControl(MS60MediaPlayerResolver& mediaPlayerResolver, QObject *parent = 0); + ~S60MediaPlayerControl(); + + // from QMediaPlayerControl + virtual QMediaPlayer::State state() const; + virtual QMediaPlayer::MediaStatus mediaStatus() const; + virtual qint64 duration() const; + virtual qint64 position() const; + virtual void setPosition(qint64 pos); + virtual int volume() const; + virtual void setVolume(int volume); + virtual bool isMuted() const; + virtual void setMuted(bool muted); + virtual int bufferStatus() const; + virtual bool isAudioAvailable() const; + virtual bool isVideoAvailable() const; + virtual bool isSeekable() const; + virtual QMediaTimeRange availablePlaybackRanges() const; + virtual qreal playbackRate() const; + virtual void setPlaybackRate(qreal rate); + virtual QMediaContent media() const; + virtual const QIODevice *mediaStream() const; + virtual void setMedia(const QMediaContent&, QIODevice *); + virtual void play(); + virtual void pause(); + virtual void stop(); + S60MediaPlayerSession* session(); + void setAudioEndpoint(const QString& name); + + // Own methods + void setVideoOutput(QObject *output); + const S60MediaSettings& mediaControlSettings() const; + +private: + MS60MediaPlayerResolver &m_mediaPlayerResolver; + S60MediaPlayerSession *m_session; + QMediaContent m_currentResource; + QIODevice *m_stream; + S60MediaSettings m_mediaSettings; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayerservice.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayerservice.cpp new file mode 100644 index 0000000..0b1c7d5 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayerservice.cpp @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qvariant.h> +#include <QtCore/qdebug.h> +#include <QtGui/qwidget.h> + +#include "s60mediaplayerservice.h" +#include "s60mediaplayercontrol.h" +#include "s60videoplayersession.h" +#include "s60audioplayersession.h" +#include "s60mediametadataprovider.h" +#include "s60videowidget.h" +#include "s60mediarecognizer.h" +//#include <qmediatimerange.h> +#include "s60videooverlay.h" +#include "s60videorenderer.h" +#include "s60mediaplayeraudioendpointselector.h" + +#include <qmediaplaylistnavigator.h> +#include <qmediaplaylist.h> + +QT_BEGIN_NAMESPACE + +S60MediaPlayerService::S60MediaPlayerService(QObject *parent) + : QMediaService(parent) + , m_control(NULL) + , m_videoOutput(NULL) + , m_videoPlayerSession(NULL) + , m_audioPlayerSession(NULL) + , m_metaData(NULL) + , m_videoWidget(NULL) + , m_videoWindow(NULL) + , m_videoRenderer(NULL) + , m_audioEndpointSelector(NULL) +{ + m_control = new S60MediaPlayerControl(*this, this); + m_metaData = new S60MediaMetaDataProvider(*this); + m_audioEndpointSelector = new S60MediaPlayerAudioEndpointSelector(m_control, this); +} + +S60MediaPlayerService::~S60MediaPlayerService() +{ + delete m_videoWidget; + delete m_videoRenderer; + delete m_videoWindow; + delete m_videoOutput; +} + +QMediaControl *S60MediaPlayerService::control(const char *name) const +{ + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) + return m_control; + + if (qstrcmp(name, QMetaDataControl_iid) == 0) { + return m_metaData; + } + + if (qstrcmp(name, QVideoOutputControl_iid) == 0) { + if (!m_videoOutput) { + m_videoOutput = new S60VideoOutputControl; + connect(m_videoOutput, SIGNAL(outputChanged(QVideoOutputControl::Output)), + this, SLOT(videoOutputChanged(QVideoOutputControl::Output))); + m_videoOutput->setAvailableOutputs(QList<QVideoOutputControl::Output>() +// << QVideoOutputControl::RendererOutput +// << QVideoOutputControl::WindowOutput + << QVideoOutputControl::WidgetOutput); + + } + return m_videoOutput; + } + + if (qstrcmp(name, QVideoWidgetControl_iid) == 0) { + if (!m_videoWidget) + m_videoWidget = new S60VideoWidgetControl; + return m_videoWidget; + } + + if (qstrcmp(name, QVideoRendererControl_iid) == 0) { + if (m_videoRenderer) + m_videoRenderer = new S60VideoRenderer; + return m_videoRenderer; + } + + if (qstrcmp(name, QVideoWindowControl_iid) == 0) { + if (!m_videoWindow) + m_videoWindow = new S60VideoOverlay; + return m_videoWindow; + } + + if (qstrcmp(name, QAudioEndpointSelector_iid) == 0) { + return m_audioEndpointSelector; + } + + return 0; + +} + +void S60MediaPlayerService::videoOutputChanged(QVideoOutputControl::Output output) +{ + switch (output) { + case QVideoOutputControl::NoOutput: + m_control->setVideoOutput(0); + break; + + case QVideoOutputControl::RendererOutput: + m_control->setVideoOutput(m_videoRenderer); + break; + case QVideoOutputControl::WindowOutput: + m_control->setVideoOutput(m_videoWindow); + break; + + case QVideoOutputControl::WidgetOutput: + m_control->setVideoOutput(m_videoWidget); + break; + default: + qWarning("Invalid video output selection"); + break; + } +} + +S60MediaPlayerSession* S60MediaPlayerService::PlayerSession() +{ + QUrl url = m_control->media().canonicalUrl(); + + if (url.isEmpty() == true) { + return NULL; + } + + S60MediaRecognizer *m_mediaRecognizer = new S60MediaRecognizer(this); + S60MediaRecognizer::MediaType mediaType = m_mediaRecognizer->mediaType(url); + + switch (mediaType) { + case S60MediaRecognizer::Video: + case S60MediaRecognizer::Url: + return VideoPlayerSession(); + case S60MediaRecognizer::Audio: + return AudioPlayerSession(); + default: + break; + } + + return NULL; +} + +S60MediaPlayerSession* S60MediaPlayerService::VideoPlayerSession() +{ + if (!m_videoPlayerSession) { + m_videoPlayerSession = new S60VideoPlayerSession(this); + + connect(m_videoPlayerSession, SIGNAL(positionChanged(qint64)), + m_control, SIGNAL(positionChanged(qint64))); + connect(m_videoPlayerSession, SIGNAL(durationChanged(qint64)), + m_control, SIGNAL(durationChanged(qint64))); + connect(m_videoPlayerSession, SIGNAL(stateChanged(QMediaPlayer::State)), + m_control, SIGNAL(stateChanged(QMediaPlayer::State))); + connect(m_videoPlayerSession, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), + m_control, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + connect(m_videoPlayerSession,SIGNAL(bufferStatusChanged(int)), + m_control, SIGNAL(bufferStatusChanged(int))); + connect(m_videoPlayerSession, SIGNAL(videoAvailableChanged(bool)), + m_control, SIGNAL(videoAvailableChanged(bool))); + connect(m_videoPlayerSession, SIGNAL(audioAvailableChanged(bool)), + m_control, SIGNAL(audioAvailableChanged(bool))); + connect(m_videoPlayerSession, SIGNAL(seekableChanged(bool)), + m_control, SIGNAL(seekableChanged(bool))); + connect(m_videoPlayerSession, SIGNAL(availablePlaybackRangesChanged(const QMediaTimeRange&)), + m_control, SIGNAL(availablePlaybackRangesChanged(const QMediaTimeRange&))); + connect(m_videoPlayerSession, SIGNAL(error(int, const QString &)), + m_control, SIGNAL(error(int, const QString &))); + connect(m_videoPlayerSession, SIGNAL(metaDataChanged()), + m_metaData, SIGNAL(metaDataChanged())); + connect(m_videoPlayerSession, SIGNAL(activeEndpointChanged(const QString&)), + m_audioEndpointSelector, SIGNAL(activeEndpointChanged(const QString&))); + } + + m_videoPlayerSession->setVolume(m_control->mediaControlSettings().volume()); + m_videoPlayerSession->setMuted(m_control->mediaControlSettings().isMuted()); + m_videoPlayerSession->setAudioEndpoint(m_control->mediaControlSettings().audioEndpoint()); + return m_videoPlayerSession; +} + +S60MediaPlayerSession* S60MediaPlayerService::AudioPlayerSession() +{ + if (!m_audioPlayerSession) { + m_audioPlayerSession = new S60AudioPlayerSession(this); + + connect(m_audioPlayerSession, SIGNAL(positionChanged(qint64)), + m_control, SIGNAL(positionChanged(qint64))); + connect(m_audioPlayerSession, SIGNAL(durationChanged(qint64)), + m_control, SIGNAL(durationChanged(qint64))); + connect(m_audioPlayerSession, SIGNAL(stateChanged(QMediaPlayer::State)), + m_control, SIGNAL(stateChanged(QMediaPlayer::State))); + connect(m_audioPlayerSession, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), + m_control, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + connect(m_audioPlayerSession,SIGNAL(bufferStatusChanged(int)), + m_control, SIGNAL(bufferStatusChanged(int))); + connect(m_audioPlayerSession, SIGNAL(videoAvailableChanged(bool)), + m_control, SIGNAL(videoAvailableChanged(bool))); + connect(m_audioPlayerSession, SIGNAL(audioAvailableChanged(bool)), + m_control, SIGNAL(audioAvailableChanged(bool))); + connect(m_audioPlayerSession, SIGNAL(seekableChanged(bool)), + m_control, SIGNAL(seekableChanged(bool))); + connect(m_audioPlayerSession, SIGNAL(availablePlaybackRangesChanged(const QMediaTimeRange&)), + m_control, SIGNAL(availablePlaybackRangesChanged(const QMediaTimeRange&))); + connect(m_audioPlayerSession, SIGNAL(error(int, const QString &)), + m_control, SIGNAL(error(int, const QString &))); + connect(m_audioPlayerSession, SIGNAL(metaDataChanged()), + m_metaData, SIGNAL(metaDataChanged())); + connect(m_audioPlayerSession, SIGNAL(activeEndpointChanged(const QString&)), + m_audioEndpointSelector, SIGNAL(activeEndpointChanged(const QString&))); + } + + m_audioPlayerSession->setVolume(m_control->mediaControlSettings().volume()); + m_audioPlayerSession->setMuted(m_control->mediaControlSettings().isMuted()); + m_audioPlayerSession->setAudioEndpoint(m_control->mediaControlSettings().audioEndpoint()); + return m_audioPlayerSession; +} + +QT_END_NAMESPACE + diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayerservice.h b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayerservice.h new file mode 100644 index 0000000..6c8155d --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayerservice.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60VIDEOPLAYERSERVICE_H +#define S60VIDEOPLAYERSERVICE_H + +#include <QtCore/qobject.h> + +#include <qmediaservice.h> +#include <qvideooutputcontrol.h> + +#include "s60videooutputcontrol.h" +#include "ms60mediaplayerresolver.h" + +#include "s60mediaplayeraudioendpointselector.h" + +QT_BEGIN_NAMESPACE + +class QMediaMetaData; +class QMediaPlayerControl; +class QMediaPlaylist; + + +class S60VideoPlayerSession; +class S60AudioPlayerSession; +class S60MediaPlayerControl; +class S60MediaMetaDataProvider; +class S60VideoWidgetControl; +class S60MediaRecognizer; +class S60VideoRenderer; +class S60VideoOverlay; + +class QMediaPlaylistNavigator; + +class S60MediaPlayerService : public QMediaService, public MS60MediaPlayerResolver +{ + Q_OBJECT + +public: + S60MediaPlayerService(QObject *parent = 0); + ~S60MediaPlayerService(); + + QMediaControl *control(const char *name) const; + +private slots: + void videoOutputChanged(QVideoOutputControl::Output output); + +protected: // From MS60MediaPlayerResolver + S60MediaPlayerSession* PlayerSession(); + S60MediaPlayerSession* VideoPlayerSession(); + S60MediaPlayerSession* AudioPlayerSession(); + +private: + S60MediaPlayerControl *m_control; + mutable S60VideoOutputControl *m_videoOutput; + S60VideoPlayerSession *m_videoPlayerSession; + S60AudioPlayerSession *m_audioPlayerSession; + mutable S60MediaMetaDataProvider *m_metaData; + mutable S60VideoWidgetControl *m_videoWidget; + mutable S60VideoOverlay *m_videoWindow; + mutable S60VideoRenderer *m_videoRenderer; + S60MediaPlayerAudioEndpointSelector *m_audioEndpointSelector; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayersession.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayersession.cpp new file mode 100644 index 0000000..693c103 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayersession.cpp @@ -0,0 +1,496 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "s60mediaplayersession.h" + +#include <QtCore/qdebug.h> +#include <QtCore/qdir.h> +#include <QtCore/qvariant.h> +#include <QtCore/qtimer.h> +#include <mmf/common/mmferrors.h> +#include <qmediatimerange.h> + +QT_BEGIN_NAMESPACE + +S60MediaPlayerSession::S60MediaPlayerSession(QObject *parent) + : QObject(parent) + , m_playbackRate(0) + , m_muted(false) + , m_volume(0) + , m_state(QMediaPlayer::StoppedState) + , m_mediaStatus(QMediaPlayer::UnknownMediaStatus) + , m_progressTimer(new QTimer(this)) + , m_stalledTimer(new QTimer(this)) + , m_error(KErrNone) + , m_play_requested(false) + , m_stream(false) +{ + connect(m_progressTimer, SIGNAL(timeout()), this, SLOT(tick())); + connect(m_stalledTimer, SIGNAL(timeout()), this, SLOT(stalled())); +} + +S60MediaPlayerSession::~S60MediaPlayerSession() +{ +} + +int S60MediaPlayerSession::volume() const +{ + return m_volume; +} + +void S60MediaPlayerSession::setVolume(int volume) +{ + if (m_volume == volume) + return; + + m_volume = volume; + // Dont set symbian players volume until media loaded. + // Leaves with KerrNotReady although documentation says otherwise. + if (!m_muted && + ( mediaStatus() == QMediaPlayer::LoadedMedia + || mediaStatus() == QMediaPlayer::StalledMedia + || mediaStatus() == QMediaPlayer::BufferingMedia + || mediaStatus() == QMediaPlayer::BufferedMedia + || mediaStatus() == QMediaPlayer::EndOfMedia)) { + TRAPD(err, doSetVolumeL(m_volume)); + setError(err); + } +} + +bool S60MediaPlayerSession::isMuted() const +{ + return m_muted; +} + +bool S60MediaPlayerSession::isSeekable() const +{ + return (m_stream)?false:true; +} + +void S60MediaPlayerSession::setMediaStatus(QMediaPlayer::MediaStatus status) +{ + if (m_mediaStatus == status) + return; + + m_mediaStatus = status; + + emit mediaStatusChanged(m_mediaStatus); + + if (m_play_requested) + play(); +} + +void S60MediaPlayerSession::setState(QMediaPlayer::State state) +{ + if (m_state == state) + return; + + m_state = state; + emit stateChanged(m_state); +} + +QMediaPlayer::State S60MediaPlayerSession::state() const +{ + return m_state; +} + +QMediaPlayer::MediaStatus S60MediaPlayerSession::mediaStatus() const +{ + return m_mediaStatus; +} + +void S60MediaPlayerSession::load(QUrl url) +{ + setMediaStatus(QMediaPlayer::LoadingMedia); + startStalledTimer(); + m_stream = (url.scheme() == "file")?false:true; + TRAPD(err, + if(m_stream) + doLoadUrlL(QString2TPtrC(url.toString())); + else + doLoadL(QString2TPtrC(QDir::toNativeSeparators(url.toLocalFile())))); + setError(err); +} + +void S60MediaPlayerSession::play() +{ + if (state() == QMediaPlayer::PlayingState + || mediaStatus() == QMediaPlayer::UnknownMediaStatus + || mediaStatus() == QMediaPlayer::NoMedia + || mediaStatus() == QMediaPlayer::InvalidMedia) + return; + + if (mediaStatus() == QMediaPlayer::LoadingMedia) { + m_play_requested = true; + return; + } + + m_play_requested = false; + setState(QMediaPlayer::PlayingState); + startProgressTimer(); + doPlay(); +} + +void S60MediaPlayerSession::pause() +{ + if (mediaStatus() == QMediaPlayer::NoMedia || + mediaStatus() == QMediaPlayer::InvalidMedia) + return; + + setState(QMediaPlayer::PausedState); + stopProgressTimer(); + TRAP_IGNORE(doPauseL()); +} + +void S60MediaPlayerSession::stop() +{ + m_play_requested = false; + setState(QMediaPlayer::StoppedState); + if (mediaStatus() == QMediaPlayer::BufferingMedia || + mediaStatus() == QMediaPlayer::BufferedMedia) + setMediaStatus(QMediaPlayer::LoadedMedia); + if (mediaStatus() == QMediaPlayer::LoadingMedia) + setMediaStatus(QMediaPlayer::UnknownMediaStatus); + stopProgressTimer(); + stopStalledTimer(); + doStop(); + emit positionChanged(0); +} +void S60MediaPlayerSession::reset() +{ + m_play_requested = false; + setError(KErrNone, QString(), true); + stopProgressTimer(); + stopStalledTimer(); + doStop(); + setState(QMediaPlayer::StoppedState); + setMediaStatus(QMediaPlayer::UnknownMediaStatus); +} + +void S60MediaPlayerSession::setVideoRenderer(QObject *renderer) +{ + Q_UNUSED(renderer); +} + +int S60MediaPlayerSession::bufferStatus() +{ + if( mediaStatus() == QMediaPlayer::LoadingMedia + || mediaStatus() == QMediaPlayer::UnknownMediaStatus + || mediaStatus() == QMediaPlayer::NoMedia + || mediaStatus() == QMediaPlayer::InvalidMedia) + return 0; + + int progress = 0; + TRAPD(err, progress = doGetBufferStatusL()); + + // If buffer status query not supported by codec return 100 + // do not set error + if(err == KErrNotSupported) + return 100; + + setError(err); + return progress; +} + +bool S60MediaPlayerSession::isMetadataAvailable() const +{ + return !m_metaDataMap.isEmpty(); +} + +QVariant S60MediaPlayerSession::metaData(const QString &key) const +{ + return m_metaDataMap.value(key); +} + +QMap<QString, QVariant> S60MediaPlayerSession::availableMetaData() const +{ + return m_metaDataMap; +} + +void S60MediaPlayerSession::setMuted(bool muted) +{ + m_muted = muted; + + if( m_mediaStatus == QMediaPlayer::LoadedMedia + || m_mediaStatus == QMediaPlayer::StalledMedia + || m_mediaStatus == QMediaPlayer::BufferingMedia + || m_mediaStatus == QMediaPlayer::BufferedMedia + || m_mediaStatus == QMediaPlayer::EndOfMedia) { + TRAPD(err, doSetVolumeL((m_muted)?0:m_volume)); + setError(err); + } +} + +qint64 S60MediaPlayerSession::duration() const +{ + if( mediaStatus() == QMediaPlayer::LoadingMedia + || mediaStatus() == QMediaPlayer::UnknownMediaStatus + || mediaStatus() == QMediaPlayer::NoMedia + || mediaStatus() == QMediaPlayer::InvalidMedia) + return -1; + + qint64 pos = 0; + TRAP_IGNORE(pos = doGetDurationL()); + return pos; +} + +qint64 S60MediaPlayerSession::position() const +{ + if( mediaStatus() == QMediaPlayer::LoadingMedia + || mediaStatus() == QMediaPlayer::UnknownMediaStatus + || mediaStatus() == QMediaPlayer::NoMedia + || mediaStatus() == QMediaPlayer::InvalidMedia) + return 0; + + qint64 pos = 0; + TRAP_IGNORE(pos = doGetPositionL()); + return pos; +} + +void S60MediaPlayerSession::setPosition(qint64 pos) +{ + if (position() == pos) + return; + + if (state() == QMediaPlayer::PlayingState) + pause(); + + TRAPD(err, doSetPositionL(pos * 1000)); + setError(err); + + if (state() == QMediaPlayer::PausedState) + play(); + + emit positionChanged(position()); +} + +void S60MediaPlayerSession::setAudioEndpoint(const QString& audioEndpoint) +{ + doSetAudioEndpoint(audioEndpoint); +} + +void S60MediaPlayerSession::loaded() +{ + stopStalledTimer(); + if (m_error == KErrNone || m_error == KErrMMPartialPlayback) { + setMediaStatus(QMediaPlayer::LoadedMedia); + TRAPD(err, updateMetaDataEntriesL()); + setError(err); + setVolume(m_volume); + setMuted(m_muted); + emit durationChanged(duration()); + emit videoAvailableChanged(isVideoAvailable()); + emit audioAvailableChanged(isAudioAvailable()); + } +} + +void S60MediaPlayerSession::endOfMedia() +{ + setMediaStatus(QMediaPlayer::EndOfMedia); + setState(QMediaPlayer::StoppedState); + emit positionChanged(0); +} + +void S60MediaPlayerSession::buffering() +{ + startStalledTimer(); + setMediaStatus(QMediaPlayer::BufferingMedia); +} + +void S60MediaPlayerSession::buffered() +{ + stopStalledTimer(); + setMediaStatus(QMediaPlayer::BufferedMedia); +} +void S60MediaPlayerSession::stalled() +{ + setMediaStatus(QMediaPlayer::StalledMedia); +} + +QMap<QString, QVariant>& S60MediaPlayerSession::metaDataEntries() +{ + return m_metaDataMap; +} + +QMediaPlayer::Error S60MediaPlayerSession::fromSymbianErrorToMultimediaError(int error) +{ + switch(error) { + case KErrNoMemory: + case KErrNotFound: + case KErrBadHandle: + case KErrAbort: + case KErrNotSupported: + case KErrCorrupt: + case KErrGeneral: + case KErrArgument: + case KErrPathNotFound: + case KErrDied: + case KErrServerTerminated: + case KErrServerBusy: + case KErrCompletion: + case KErrBadPower: + return QMediaPlayer::ResourceError; + + case KErrMMPartialPlayback: + return QMediaPlayer::FormatError; + + case KErrMMAudioDevice: + case KErrMMVideoDevice: + case KErrMMDecoder: + case KErrUnknown: + return QMediaPlayer::ServiceMissingError; + + case KErrMMNotEnoughBandwidth: + case KErrMMSocketServiceNotFound: + case KErrMMNetworkRead: + case KErrMMNetworkWrite: + case KErrMMServerSocket: + case KErrMMServerNotSupported: + case KErrMMUDPReceive: + case KErrMMInvalidProtocol: + case KErrMMInvalidURL: + case KErrMMMulticast: + case KErrMMProxyServer: + case KErrMMProxyServerNotSupported: + case KErrMMProxyServerConnect: + return QMediaPlayer::NetworkError; + + case KErrNotReady: + case KErrInUse: + case KErrAccessDenied: + case KErrLocked: + case KErrMMDRMNotAuthorized: + case KErrPermissionDenied: + case KErrCancel: + case KErrAlreadyExists: + return QMediaPlayer::AccessDeniedError; + + case KErrNone: + default: + return QMediaPlayer::NoError; + } +} + +void S60MediaPlayerSession::setError(int error, const QString &errorString, bool forceReset) +{ + if( forceReset ) { + m_error = KErrNone; + emit this->error(QMediaPlayer::NoError, QString()); + return; + } + + // If error does not change and m_error is reseted without forceReset flag + if (error == m_error || + (m_error != KErrNone && error == KErrNone)) + return; + + m_error = error; + QMediaPlayer::Error mediaError = fromSymbianErrorToMultimediaError(m_error); + QString symbianError = QString(errorString); + + if (mediaError != QMediaPlayer::NoError) { + // TODO: fix to user friendly string at some point + // These error string are only dev usable + symbianError.append("Symbian:"); + symbianError.append(QString::number(m_error)); + } + + emit this->error(mediaError, symbianError); + + switch(mediaError){ + case QMediaPlayer::ResourceError: + case QMediaPlayer::NetworkError: + case QMediaPlayer::AccessDeniedError: + case QMediaPlayer::ServiceMissingError: + m_play_requested = false; + setMediaStatus(QMediaPlayer::InvalidMedia); + stop(); + break; + } +} + +void S60MediaPlayerSession::tick() +{ + emit positionChanged(position()); + + if (bufferStatus() < 100) + emit bufferStatusChanged(bufferStatus()); +} + +void S60MediaPlayerSession::startProgressTimer() +{ + m_progressTimer->start(500); +} + +void S60MediaPlayerSession::stopProgressTimer() +{ + m_progressTimer->stop(); +} + +void S60MediaPlayerSession::startStalledTimer() +{ + m_stalledTimer->start(30000); +} + +void S60MediaPlayerSession::stopStalledTimer() +{ + m_stalledTimer->stop(); +} +QString S60MediaPlayerSession::TDesC2QString(const TDesC& aDescriptor) +{ + return QString::fromUtf16(aDescriptor.Ptr(), aDescriptor.Length()); +} +TPtrC S60MediaPlayerSession::QString2TPtrC( const QString& string ) +{ + // Returned TPtrC is valid as long as the given parameter is valid and unmodified + return TPtrC16(static_cast<const TUint16*>(string.utf16()), string.length()); +} +QRect S60MediaPlayerSession::TRect2QRect(const TRect& tr) +{ + return QRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height()); +} +TRect S60MediaPlayerSession::QRect2TRect(const QRect& qr) +{ + return TRect(TPoint(qr.left(), qr.top()), TSize(qr.width(), qr.height())); +} + +QT_END_NAMESPACE + diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayersession.h b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayersession.h new file mode 100644 index 0000000..bb9eddd --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediaplayersession.h @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60MEDIAPLAYERSESSION_H +#define S60MEDIAPLAYERSESSION_H + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtCore/qpair.h> +#include <qmediaplayer.h> +#include <e32cmn.h> // for TDesC +#include <QRect> +#include "s60mediaplayerservice.h" + +QT_BEGIN_NAMESPACE + +class QMediaTimeRange; + +class QTimer; + +class S60MediaPlayerSession : public QObject +{ + Q_OBJECT + +public: + S60MediaPlayerSession(QObject *parent); + virtual ~S60MediaPlayerSession(); + + // for player control interface to use + QMediaPlayer::State state() const; + QMediaPlayer::MediaStatus mediaStatus() const; + qint64 duration() const; + qint64 position() const; + void setPosition(qint64 pos); + int volume() const; + void setVolume(int volume); + bool isMuted() const; + void setMuted(bool muted); + virtual bool isVideoAvailable() const = 0; + virtual bool isAudioAvailable() const = 0; + bool isSeekable() const; + void play(); + void pause(); + void stop(); + void reset(); + bool isMetadataAvailable() const; + QVariant metaData(const QString &key) const; + QMap<QString, QVariant> availableMetaData() const; + void load(QUrl url); + int bufferStatus(); + virtual void setVideoRenderer(QObject *renderer); + void setMediaStatus(QMediaPlayer::MediaStatus); + void setState(QMediaPlayer::State state); + void setAudioEndpoint(const QString& audioEndpoint); + +protected: + virtual void doLoadL(const TDesC &path) = 0; + virtual void doLoadUrlL(const TDesC &path) = 0; + virtual void doPlay() = 0; + virtual void doStop() = 0; + virtual void doPauseL() = 0; + virtual void doSetVolumeL(int volume) = 0; + virtual void doSetPositionL(qint64 microSeconds) = 0; + virtual qint64 doGetPositionL() const = 0; + virtual void updateMetaDataEntriesL() = 0; + virtual int doGetBufferStatusL() const = 0; + virtual qint64 doGetDurationL() const = 0; + virtual void doSetAudioEndpoint(const QString& audioEndpoint) = 0; + +public: + // From S60MediaPlayerAudioEndpointSelector + virtual QString activeEndpoint() const = 0; + virtual QString defaultEndpoint() const = 0; +public Q_SLOTS: + virtual void setActiveEndpoint(const QString& name) = 0; + +protected: + void setError(int error, const QString &errorString = QString(), bool forceReset = false); + void loaded(); + void buffering(); + void buffered(); + void endOfMedia(); + QMap<QString, QVariant>& metaDataEntries(); + QMediaPlayer::Error fromSymbianErrorToMultimediaError(int error); + void startProgressTimer(); + void stopProgressTimer(); + void startStalledTimer(); + void stopStalledTimer(); + QString TDesC2QString(const TDesC& aDescriptor); + TPtrC QString2TPtrC( const QString& string ); + QRect TRect2QRect(const TRect& tr); + TRect QRect2TRect(const QRect& qr); + + +protected slots: + void tick(); + void stalled(); + +signals: + void durationChanged(qint64 duration); + void positionChanged(qint64 position); + void stateChanged(QMediaPlayer::State state); + void mediaStatusChanged(QMediaPlayer::MediaStatus mediaStatus); + void videoAvailableChanged(bool videoAvailable); + void audioAvailableChanged(bool audioAvailable); + void bufferStatusChanged(int percentFilled); + void seekableChanged(bool); + void availablePlaybackRangesChanged(const QMediaTimeRange&); + void metaDataChanged(); + void error(int error, const QString &errorString); + void activeEndpointChanged(const QString &name); + +private: + qreal m_playbackRate; + QMap<QString, QVariant> m_metaDataMap; + bool m_muted; + int m_volume; + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_mediaStatus; + QTimer *m_progressTimer; + QTimer *m_stalledTimer; + int m_error; + bool m_play_requested; + bool m_stream; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediarecognizer.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60mediarecognizer.cpp new file mode 100644 index 0000000..b563dd9 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediarecognizer.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "S60mediarecognizer.h" +#include <e32def.h> +#include <e32cmn.h> +#include <QtCore/qurl.h> +#include <QtCore/qdir.h> +#include <QtCore/qdebug.h> + +#include <apgcli.h> + +QT_BEGIN_NAMESPACE + +static const TInt KMimeTypePrefixLength = 6; // "audio/" or "video/" +_LIT(KMimeTypePrefixAudio, "audio/"); +_LIT(KMimeTypePrefixVideo, "video/"); + +S60MediaRecognizer::S60MediaRecognizer(QObject *parent) : QObject(parent) +{ +} + +S60MediaRecognizer::~S60MediaRecognizer() +{ + m_file.Close(); + m_fileServer.Close(); + m_recognizer.Close(); +} + +S60MediaRecognizer::MediaType S60MediaRecognizer::mediaType(const QUrl &url) +{ + bool isStream = (url.scheme() == "file")?false:true; + + if (isStream) + return Url; + else + return identifyMediaType(url.toLocalFile()); +} + +S60MediaRecognizer::MediaType S60MediaRecognizer::identifyMediaType(const QString& fileName) +{ + S60MediaRecognizer::MediaType result = NotSupported; + bool recognizerOpened = false; + + TInt err = m_recognizer.Connect(); + if (err == KErrNone) { + recognizerOpened = true; + } + + err = m_fileServer.Connect(); + if (err == KErrNone) { + recognizerOpened = true; + } + + // This is needed for sharing file handles for the recognizer + err = m_fileServer.ShareProtected(); + if (err == KErrNone) { + recognizerOpened = true; + } + + if (recognizerOpened) { + m_file.Close(); + err = m_file.Open(m_fileServer, QString2TPtrC(QDir::toNativeSeparators(fileName)), EFileRead | + EFileShareReadersOnly); + + if (err == KErrNone) { + TDataRecognitionResult recognizerResult; + err = m_recognizer.RecognizeData(m_file, recognizerResult); + if (err == KErrNone) { + const TPtrC mimeType = recognizerResult.iDataType.Des(); + + if (mimeType.Left(KMimeTypePrefixLength).Compare(KMimeTypePrefixAudio) == 0) { + result = Audio; + } else if (mimeType.Left(KMimeTypePrefixLength).Compare(KMimeTypePrefixVideo) == 0) { + result = Video; + } + } + } + } + return result; +} + +TPtrC S60MediaRecognizer::QString2TPtrC( const QString& string ) +{ + // Returned TPtrC is valid as long as the given parameter is valid and unmodified + return TPtrC16(static_cast<const TUint16*>(string.utf16()), string.length()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60mediarecognizer.h b/src/plugins/mediaservices/symbian/mediaplayer/s60mediarecognizer.h new file mode 100644 index 0000000..320c34c --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60mediarecognizer.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60MEDIARECOGNIZER_H_ +#define S60MEDIARECOGNIZER_H_ + +#include <QtCore/qobject.h> + +#include <apgcli.h> +#include <f32file.h> + +QT_BEGIN_NAMESPACE + +class QUrl; + +class S60MediaRecognizer : public QObject +{ + Q_OBJECT + +public: + enum MediaType { + Audio, + Video, + Url, + NotSupported = -1 + }; + + S60MediaRecognizer(QObject *parent = 0); + ~S60MediaRecognizer(); + + S60MediaRecognizer::MediaType mediaType(const QUrl &url); + S60MediaRecognizer::MediaType identifyMediaType(const QString& fileName); + +protected: + TPtrC QString2TPtrC( const QString& string ); + +private: + RApaLsSession m_recognizer; + RFile m_file; + RFs m_fileServer; +}; + +QT_END_NAMESPACE + +#endif /* S60MEDIARECOGNIZER_H_ */ diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60videooverlay.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60videooverlay.cpp new file mode 100644 index 0000000..489b2e3 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60videooverlay.cpp @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtMultimedia/qvideosurfaceformat.h> +#include "s60videooverlay.h" +#include "s60videosurface.h" + +QT_BEGIN_NAMESPACE + +S60VideoOverlay::S60VideoOverlay(QObject *parent) + : QVideoWindowControl(parent) + , m_surface(new S60VideoSurface) + , m_aspectRatioMode(Qt::KeepAspectRatio) + , m_fullScreen(false) +{ + connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), + this, SLOT(surfaceFormatChanged())); +} + +S60VideoOverlay::~S60VideoOverlay() +{ + delete m_surface; +} + +WId S60VideoOverlay::winId() const +{ + return m_surface->winId(); +} + +void S60VideoOverlay::setWinId(WId id) +{ + m_surface->setWinId(id); +} + +QRect S60VideoOverlay::displayRect() const +{ + return m_displayRect; +} + +void S60VideoOverlay::setDisplayRect(const QRect &rect) +{ + m_displayRect = rect; + + setScaledDisplayRect(); +} + +Qt::AspectRatioMode S60VideoOverlay::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void S60VideoOverlay::setAspectRatioMode(Qt::AspectRatioMode ratio) +{ + m_aspectRatioMode = ratio; + + setScaledDisplayRect(); +} + +QSize S60VideoOverlay::customAspectRatio() const +{ + return m_aspectRatio; +} + +void S60VideoOverlay::setCustomAspectRatio(const QSize &customRatio) +{ + m_aspectRatio = customRatio; + + setScaledDisplayRect(); +} + +void S60VideoOverlay::repaint() +{ +} + +int S60VideoOverlay::brightness() const +{ + return m_surface->brightness(); +} + +void S60VideoOverlay::setBrightness(int brightness) +{ + m_surface->setBrightness(brightness); + + emit brightnessChanged(m_surface->brightness()); +} + +int S60VideoOverlay::contrast() const +{ + return m_surface->contrast(); +} + +void S60VideoOverlay::setContrast(int contrast) +{ + m_surface->setContrast(contrast); + + emit contrastChanged(m_surface->contrast()); +} + +int S60VideoOverlay::hue() const +{ + return m_surface->hue(); +} + +void S60VideoOverlay::setHue(int hue) +{ + m_surface->setHue(hue); + + emit hueChanged(m_surface->hue()); +} + +int S60VideoOverlay::saturation() const +{ + return m_surface->saturation(); +} + +void S60VideoOverlay::setSaturation(int saturation) +{ + m_surface->setSaturation(saturation); + + emit saturationChanged(m_surface->saturation()); +} + +bool S60VideoOverlay::isFullScreen() const +{ + return m_fullScreen; +} + +void S60VideoOverlay::setFullScreen(bool fullScreen) +{ + emit fullScreenChanged(m_fullScreen = fullScreen); +} + +QSize S60VideoOverlay::nativeSize() const +{ + return m_surface->surfaceFormat().sizeHint(); +} + +QAbstractVideoSurface *S60VideoOverlay::surface() const +{ + return m_surface; +} + +void S60VideoOverlay::surfaceFormatChanged() +{ + setScaledDisplayRect(); + + emit nativeSizeChanged(); +} + +void S60VideoOverlay::setScaledDisplayRect() +{ + switch (m_aspectRatioMode) { + case Qt::KeepAspectRatio: + { + QSize size = m_surface->surfaceFormat().viewport().size(); + + size.scale(m_displayRect.size(), Qt::KeepAspectRatio); + + QRect rect(QPoint(0, 0), size); + rect.moveCenter(m_displayRect.center()); + + m_surface->setDisplayRect(rect); + } + break; + case Qt::IgnoreAspectRatio: + m_surface->setDisplayRect(m_displayRect); + break; + }; +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60videooverlay.h b/src/plugins/mediaservices/symbian/mediaplayer/s60videooverlay.h new file mode 100644 index 0000000..d846f32 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60videooverlay.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60VIDEOOVERLAY_H +#define S60VIDEOOVERLAY_H + +#include <QtCore/qobject.h> +#include <qvideowindowcontrol.h> + +QT_BEGIN_NAMESPACE + +class QAbstractVideoSurface; +class S60VideoSurface; + +class S60VideoOverlay : public QVideoWindowControl +{ + Q_OBJECT + +public: + S60VideoOverlay(QObject *parent = 0); + ~S60VideoOverlay(); + + WId winId() const; + void setWinId(WId id); + + QRect displayRect() const; + void setDisplayRect(const QRect &rect); + + bool isFullScreen() const; + void setFullScreen(bool fullScreen); + + QSize nativeSize() const; + + Qt::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(Qt::AspectRatioMode mode); + + QSize customAspectRatio() const; + void setCustomAspectRatio(const QSize &customRatio); + + void repaint(); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + + QAbstractVideoSurface *surface() const; + +private slots: + void surfaceFormatChanged(); + +private: + void setScaledDisplayRect(); + + S60VideoSurface *m_surface; + Qt::AspectRatioMode m_aspectRatioMode; + QRect m_displayRect; + QSize m_aspectRatio; + bool m_fullScreen; +}; + +QT_END_NAMESPACE + +#endif // S60VIDEOOVERLAY_H diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60videoplayersession.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60videoplayersession.cpp new file mode 100644 index 0000000..134d5a0 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60videoplayersession.cpp @@ -0,0 +1,486 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "s60videoplayersession.h" +#include "s60videowidget.h" +#include "s60mediaplayerservice.h" +#include "s60videooverlay.h" + +#include <QtCore/qdebug.h> +#include <QtGui/qwidget.h> +#include <QtCore/qtimer.h> +#include <QApplication> + +#include <coecntrl.h> +#include <coemain.h> // For CCoeEnv +#include <w32std.h> +#include <mmf/common/mmfcontrollerframeworkbase.h> + +#include <AudioOutput.h> +#include <MAudioOutputObserver.h> + +QT_BEGIN_NAMESPACE + +S60VideoPlayerSession::S60VideoPlayerSession(QMediaService *service) + : S60MediaPlayerSession(service) + , m_player(0) + , m_rect(0, 0, 0, 0) + , m_output(QVideoOutputControl::NoOutput) + , m_windowId(0) + , m_dsaActive(false) + , m_dsaStopped(false) + , m_wsSession(CCoeEnv::Static()->WsSession()) + , m_screenDevice(*CCoeEnv::Static()->ScreenDevice()) + , m_window(0) + , m_service(*service) + , m_aspectRatioMode(Qt::KeepAspectRatio) + , m_originalSize(1, 1) + , m_audioOutput(0) + , m_audioEndpoint("Default") +{ + resetNativeHandles(); + QT_TRAP_THROWING(m_player = CVideoPlayerUtility::NewL( + *this, + 0, + EMdaPriorityPreferenceNone, + m_wsSession, + m_screenDevice, + *m_window, + m_rect, + m_rect)); + m_dsaActive = true; + m_player->RegisterForVideoLoadingNotification(*this); +} + +S60VideoPlayerSession::~S60VideoPlayerSession() +{ +#if !defined(HAS_NO_AUDIOROUTING_IN_VIDEOPLAYER) + if (m_audioOutput) + m_audioOutput->UnregisterObserver(*this); + delete m_audioOutput; +#endif + m_player->Close(); + delete m_player; +} + +void S60VideoPlayerSession::doLoadL(const TDesC &path) +{ + // m_audioOutput needs to be reinitialized after MapcInitComplete + if (m_audioOutput) + m_audioOutput->UnregisterObserver(*this); + delete m_audioOutput; + m_audioOutput = NULL; + + m_player->OpenFileL(path); +} + +void S60VideoPlayerSession::doLoadUrlL(const TDesC &path) +{ + // m_audioOutput needs to be reinitialized after MapcInitComplete + if (m_audioOutput) + m_audioOutput->UnregisterObserver(*this); + delete m_audioOutput; + m_audioOutput = NULL; + + m_player->OpenUrlL(path); +} + +int S60VideoPlayerSession::doGetBufferStatusL() const +{ + int progress = 0; + m_player->GetVideoLoadingProgressL(progress); + return progress; +} + +qint64 S60VideoPlayerSession::doGetDurationL() const +{ + return m_player->DurationL().Int64() / qint64(1000); +} + +void S60VideoPlayerSession::setVideoRenderer(QObject *videoOutput) +{ + Q_UNUSED(videoOutput) + QVideoOutputControl *videoControl = qobject_cast<QVideoOutputControl *>(m_service.control(QVideoOutputControl_iid)); + + //Render changes + if (m_output != videoControl->output()) { + + if (m_output == QVideoOutputControl::WidgetOutput) { + S60VideoWidgetControl *widgetControl = qobject_cast<S60VideoWidgetControl *>(m_service.control(QVideoWidgetControl_iid)); + disconnect(widgetControl, SIGNAL(widgetUpdated()), this, SLOT(resetVideoDisplay())); + disconnect(widgetControl, SIGNAL(beginVideoWindowNativePaint()), this, SLOT(suspendDirectScreenAccess())); + disconnect(widgetControl, SIGNAL(endVideoWindowNativePaint()), this, SLOT(resumeDirectScreenAccess())); + disconnect(this, SIGNAL(stateChanged(QMediaPlayer::State)), widgetControl, SLOT(videoStateChanged(QMediaPlayer::State))); + } + + if (videoControl->output() == QVideoOutputControl::WidgetOutput) { + S60VideoWidgetControl *widgetControl = qobject_cast<S60VideoWidgetControl *>(m_service.control(QVideoWidgetControl_iid)); + connect(widgetControl, SIGNAL(widgetUpdated()), this, SLOT(resetVideoDisplay())); + connect(widgetControl, SIGNAL(beginVideoWindowNativePaint()), this, SLOT(suspendDirectScreenAccess())); + connect(widgetControl, SIGNAL(endVideoWindowNativePaint()), this, SLOT(resumeDirectScreenAccess())); + connect(this, SIGNAL(stateChanged(QMediaPlayer::State)), widgetControl, SLOT(videoStateChanged(QMediaPlayer::State))); + } + + m_output = videoControl->output(); + resetVideoDisplay(); + } +} + +bool S60VideoPlayerSession::resetNativeHandles() +{ + QVideoOutputControl* videoControl = qobject_cast<QVideoOutputControl *>(m_service.control(QVideoOutputControl_iid)); + WId newId = 0; + TRect newRect = TRect(0,0,0,0); + Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio; + + if (videoControl->output() == QVideoOutputControl::WidgetOutput) { + S60VideoWidgetControl* widgetControl = qobject_cast<S60VideoWidgetControl *>(m_service.control(QVideoWidgetControl_iid)); + QWidget *videoWidget = widgetControl->videoWidget(); + newId = widgetControl->videoWidgetWId(); + newRect = QRect2TRect(QRect(videoWidget->mapToGlobal(videoWidget->pos()), videoWidget->size())); + aspectRatioMode = widgetControl->aspectRatioMode(); + } else if (videoControl->output() == QVideoOutputControl::WindowOutput) { + S60VideoOverlay* windowControl = qobject_cast<S60VideoOverlay *>(m_service.control(QVideoWindowControl_iid)); + newId = windowControl->winId(); + newRect = TRect( newId->DrawableWindow()->AbsPosition(), newId->DrawableWindow()->Size()); + } else { + if (QApplication::activeWindow()) + newId = QApplication::activeWindow()->effectiveWinId(); + + if (!newId && QApplication::allWidgets().count()) + newId = QApplication::allWidgets().at(0)->effectiveWinId(); + + Q_ASSERT(newId != 0); + } + + if (newRect == m_rect && newId == m_windowId && aspectRatioMode == m_aspectRatioMode) + return false; + + if (newId) { + m_rect = newRect; + m_windowId = newId; + m_window = m_windowId->DrawableWindow(); + m_aspectRatioMode = aspectRatioMode; + return true; + } + return false; +} + +bool S60VideoPlayerSession::isVideoAvailable() const +{ +#ifdef PRE_S60_50_PLATFORM + return true; // this is not support in pre 5th platforms +#else + if (m_player) + return m_player->VideoEnabledL(); + else + return false; +#endif +} + +bool S60VideoPlayerSession::isAudioAvailable() const +{ + if (m_player) + return m_player->AudioEnabledL(); + else + return false; +} + +void S60VideoPlayerSession::doPlay() +{ + m_player->Play(); +} + +void S60VideoPlayerSession::doPauseL() +{ + m_player->PauseL(); +} + +void S60VideoPlayerSession::doStop() +{ + m_player->Stop(); +} + +qint64 S60VideoPlayerSession::doGetPositionL() const +{ + return m_player->PositionL().Int64() / qint64(1000); +} + +void S60VideoPlayerSession::doSetPositionL(qint64 microSeconds) +{ + m_player->SetPositionL(TTimeIntervalMicroSeconds(microSeconds)); +} + +void S60VideoPlayerSession::doSetVolumeL(int volume) +{ + m_player->SetVolumeL((volume / 100.0)* m_player->MaxVolume()); +} + +QPair<qreal, qreal> S60VideoPlayerSession::scaleFactor() +{ + QSize scaled = m_originalSize; + if (m_aspectRatioMode == Qt::IgnoreAspectRatio) + scaled.scale(TRect2QRect(m_rect).size(), Qt::IgnoreAspectRatio); + else if(m_aspectRatioMode == Qt::KeepAspectRatio) + scaled.scale(TRect2QRect(m_rect).size(), Qt::KeepAspectRatio); + + qreal width = qreal(scaled.width()) / qreal(m_originalSize.width()) * qreal(100); + qreal height = qreal(scaled.height()) / qreal(m_originalSize.height()) * qreal(100); + + return QPair<qreal, qreal>(width, height); +} + +void S60VideoPlayerSession::startDirectScreenAccess() +{ + if(m_dsaActive) + return; + + TRAPD(err, m_player->StartDirectScreenAccessL()); + if(err == KErrNone) + m_dsaActive = true; + setError(err); +} + +bool S60VideoPlayerSession::stopDirectScreenAccess() +{ + if(!m_dsaActive) + return false; + + TRAPD(err, m_player->StopDirectScreenAccessL()); + if(err == KErrNone) + m_dsaActive = false; + + setError(err); + return true; +} + +void S60VideoPlayerSession::MvpuoOpenComplete(TInt aError) +{ + setError(aError); + m_player->Prepare(); +} + +void S60VideoPlayerSession::MvpuoPrepareComplete(TInt aError) +{ + setError(aError); + TRAPD(err, + m_player->SetDisplayWindowL(m_wsSession, + m_screenDevice, + *m_window, + m_rect, + m_rect); + TSize originalSize; + m_player->VideoFrameSizeL(originalSize); + m_originalSize = QSize(originalSize.iWidth, originalSize.iHeight); + m_player->SetScaleFactorL(scaleFactor().first, scaleFactor().second, true)); + + setError(err); + m_dsaActive = true; +#if !defined(HAS_NO_AUDIOROUTING_IN_VIDEOPLAYER) + TRAP(err, + m_audioOutput = CAudioOutput::NewL(*m_player); + m_audioOutput->RegisterObserverL(*this); + ); + setActiveEndpoint(m_audioEndpoint); + setError(err); +#endif + loaded(); +} + +void S60VideoPlayerSession::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError) +{ + Q_UNUSED(aFrame); + Q_UNUSED(aError); +} + +void S60VideoPlayerSession::MvpuoPlayComplete(TInt aError) +{ + setError(aError); + endOfMedia(); +} + +void S60VideoPlayerSession::MvpuoEvent(const TMMFEvent &aEvent) +{ + Q_UNUSED(aEvent); +} + +void S60VideoPlayerSession::updateMetaDataEntriesL() +{ + metaDataEntries().clear(); + int numberOfMetaDataEntries = 0; + + numberOfMetaDataEntries = m_player->NumberOfMetaDataEntriesL(); + + for (int i = 0; i < numberOfMetaDataEntries; i++) { + CMMFMetaDataEntry *entry = NULL; + entry = m_player->MetaDataEntryL(i); + metaDataEntries().insert(TDesC2QString(entry->Name()), TDesC2QString(entry->Value())); + delete entry; + } + emit metaDataChanged(); +} + +void S60VideoPlayerSession::resetVideoDisplay() +{ + if (resetNativeHandles()) { + TRAPD(err, + m_player->SetDisplayWindowL(m_wsSession, + m_screenDevice, + *m_window, + m_rect, + m_rect)); + setError(err); + if( mediaStatus() == QMediaPlayer::LoadedMedia + || mediaStatus() == QMediaPlayer::StalledMedia + || mediaStatus() == QMediaPlayer::BufferingMedia + || mediaStatus() == QMediaPlayer::BufferedMedia + || mediaStatus() == QMediaPlayer::EndOfMedia) { + TRAPD(err, m_player->SetScaleFactorL(scaleFactor().first, scaleFactor().second, true)); + setError(err); + } + } +} + +void S60VideoPlayerSession::suspendDirectScreenAccess() +{ + m_dsaStopped = stopDirectScreenAccess(); +} + +void S60VideoPlayerSession::resumeDirectScreenAccess() +{ + if(!m_dsaStopped) + return; + + startDirectScreenAccess(); + m_dsaStopped = false; +} + +void S60VideoPlayerSession::MvloLoadingStarted() +{ + buffering(); +} + +void S60VideoPlayerSession::MvloLoadingComplete() +{ + buffered(); +} + +void S60VideoPlayerSession::doSetAudioEndpoint(const QString& audioEndpoint) +{ + m_audioEndpoint = audioEndpoint; +} + +QString S60VideoPlayerSession::activeEndpoint() const +{ + QString outputName = QString("Default"); +#if !defined(HAS_NO_AUDIOROUTING_IN_VIDEOPLAYER) + if (m_audioOutput) { + CAudioOutput::TAudioOutputPreference output = m_audioOutput->AudioOutput(); + outputName = qStringFromTAudioOutputPreference(output); + } +#endif + return outputName; +} + +QString S60VideoPlayerSession::defaultEndpoint() const +{ + QString outputName = QString("Default"); +#if !defined(HAS_NO_AUDIOROUTING_IN_VIDEOPLAYER) + if (m_audioOutput) { + CAudioOutput::TAudioOutputPreference output = m_audioOutput->DefaultAudioOutput(); + outputName = qStringFromTAudioOutputPreference(output); + } +#endif + return outputName; +} + +void S60VideoPlayerSession::setActiveEndpoint(const QString& name) +{ + CAudioOutput::TAudioOutputPreference output = CAudioOutput::ENoPreference; + + if (name == QString("Default")) + output = CAudioOutput::ENoPreference; + else if (name == QString("All")) + output = CAudioOutput::EAll; + else if (name == QString("None")) + output = CAudioOutput::ENoOutput; + else if (name == QString("Earphone")) + output = CAudioOutput::EPrivate; + else if (name == QString("Speaker")) + output = CAudioOutput::EPublic; +#if !defined(HAS_NO_AUDIOROUTING_IN_VIDEOPLAYER) + if (m_audioOutput) { + TRAPD(err, m_audioOutput->SetAudioOutputL(output)); + setError(err); + + if (m_audioEndpoint != name) { + m_audioEndpoint = name; + emit activeEndpointChanged(name); + } + } +#endif +} + +void S60VideoPlayerSession::DefaultAudioOutputChanged( CAudioOutput& aAudioOutput, + CAudioOutput::TAudioOutputPreference aNewDefault ) +{ + // Emit already implemented in setActiveEndpoint function + Q_UNUSED(aAudioOutput) + Q_UNUSED(aNewDefault) +} + +QString S60VideoPlayerSession::qStringFromTAudioOutputPreference(CAudioOutput::TAudioOutputPreference output) const +{ + if (output == CAudioOutput::ENoPreference) + return QString("Default"); + else if (output == CAudioOutput::EAll) + return QString("All"); + else if (output == CAudioOutput::ENoOutput) + return QString("None"); + else if (output == CAudioOutput::EPrivate) + return QString("Earphone"); + else if (output == CAudioOutput::EPublic) + return QString("Speaker"); + return QString("Default"); +} + +QT_END_NAMESPACE + diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60videoplayersession.h b/src/plugins/mediaservices/symbian/mediaplayer/s60videoplayersession.h new file mode 100644 index 0000000..52e311a --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60videoplayersession.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60VIDEOPLAYERSESSION_H +#define S60VIDEOPLAYERSESSION_H + +#include "s60mediaplayersession.h" +#include "s60mediaplayeraudioendpointselector.h" +#include <videoplayer.h> +#include <QtGui/qwidget.h> +#include <qvideowidget.h> + +#include <AudioOutput.h> +#include <MAudioOutputObserver.h> + +QT_BEGIN_NAMESPACE + +class QTimer; + +class S60VideoPlayerSession : public S60MediaPlayerSession, + public MVideoPlayerUtilityObserver, + public MVideoLoadingObserver, + public MAudioOutputObserver +{ + Q_OBJECT + +public: + S60VideoPlayerSession(QMediaService *service); + ~S60VideoPlayerSession(); + + //From S60MediaPlayerSession + bool isVideoAvailable() const; + bool isAudioAvailable() const; + void setVideoRenderer(QObject *renderer); + + //From MVideoLoadingObserver + void MvloLoadingStarted(); + void MvloLoadingComplete(); + + // From MAudioOutputObserver + void DefaultAudioOutputChanged(CAudioOutput& aAudioOutput, + CAudioOutput::TAudioOutputPreference aNewDefault); + +public: + // From S60MediaPlayerAudioEndpointSelector + QString activeEndpoint() const; + QString defaultEndpoint() const; +public Q_SLOTS: + void setActiveEndpoint(const QString& name); +Q_SIGNALS: + void activeEndpointChanged(const QString &name); + +protected: + //From S60MediaPlayerSession + void doLoadL(const TDesC &path); + void doLoadUrlL(const TDesC &path); + void doPlay(); + void doStop(); + void doPauseL(); + void doSetVolumeL(int volume); + qint64 doGetPositionL() const; + void doSetPositionL(qint64 microSeconds); + void updateMetaDataEntriesL(); + int doGetBufferStatusL() const; + qint64 doGetDurationL() const; + void doSetAudioEndpoint(const QString& audioEndpoint); + +private slots: + void resetVideoDisplay(); + void suspendDirectScreenAccess(); + void resumeDirectScreenAccess(); + +private: + bool resetNativeHandles(); + QPair<qreal, qreal> scaleFactor(); + void startDirectScreenAccess(); + bool stopDirectScreenAccess(); + QString qStringFromTAudioOutputPreference(CAudioOutput::TAudioOutputPreference output) const; + + + // From MVideoPlayerUtilityObserver + void MvpuoOpenComplete(TInt aError); + void MvpuoPrepareComplete(TInt aError); + void MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError); + void MvpuoPlayComplete(TInt aError); + void MvpuoEvent(const TMMFEvent &aEvent); + +private: + // Qwn + CVideoPlayerUtility *m_player; + TRect m_rect; + QVideoOutputControl::Output m_output; + WId m_windowId; + bool m_dsaActive; + bool m_dsaStopped; + + //Reference + RWsSession &m_wsSession; + CWsScreenDevice &m_screenDevice; + RWindowBase *m_window; + QMediaService &m_service; + Qt::AspectRatioMode m_aspectRatioMode; + QSize m_originalSize; + CAudioOutput *m_audioOutput; + QString m_audioEndpoint; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60videorenderer.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60videorenderer.cpp new file mode 100644 index 0000000..269dd43 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60videorenderer.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "s60videorenderer.h" + +#include <QtCore/qcoreevent.h> +#include <QtGui/qapplication.h> + +QT_BEGIN_NAMESPACE + +S60VideoRenderer::S60VideoRenderer(QObject *parent) + : QVideoRendererControl(parent) +{ +} + +S60VideoRenderer::~S60VideoRenderer() +{ +} + + +QAbstractVideoSurface *S60VideoRenderer::surface() const +{ + return m_surface; +} + +void S60VideoRenderer::setSurface(QAbstractVideoSurface *surface) +{ + m_surface = surface; +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60videorenderer.h b/src/plugins/mediaservices/symbian/mediaplayer/s60videorenderer.h new file mode 100644 index 0000000..260dc8b --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60videorenderer.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60VIDEORENDERER_H +#define S60VIDEORENDERER_H + +#include <QtCore/qobject.h> +#include <qvideorenderercontrol.h> + +QT_BEGIN_NAMESPACE + +class S60VideoRenderer : public QVideoRendererControl +{ + Q_OBJECT + +public: + S60VideoRenderer(QObject *parent = 0); + virtual ~S60VideoRenderer(); + + QAbstractVideoSurface *surface() const; + void setSurface(QAbstractVideoSurface *surface); + +private: + + QAbstractVideoSurface *m_surface; +}; + +QT_END_NAMESPACE + +#endif // S60VIDEORENDERER_H diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60videosurface.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60videosurface.cpp new file mode 100644 index 0000000..bfa7a13 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60videosurface.cpp @@ -0,0 +1,478 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//#include <QtGui/qx11info_x11.h> + +#include "s60videosurface.h" + +QT_BEGIN_NAMESPACE + +/*struct XvFormatRgb +{ + QVideoFrame::PixelFormat pixelFormat; + int bits_per_pixel; + int format; + int num_planes; + + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + +};*/ +/* +bool operator ==(const XvImageFormatValues &format, const XvFormatRgb &rgb) +{ + return format.type == XvRGB + && format.bits_per_pixel == rgb.bits_per_pixel + && format.format == rgb.format + && format.num_planes == rgb.num_planes + && format.depth == rgb.depth + && format.red_mask == rgb.red_mask + && format.blue_mask == rgb.blue_mask; +} + +static const XvFormatRgb qt_xvRgbLookup[] = +{ + { QVideoFrame::Format_ARGB32, 32, XvPacked, 1, 32, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { QVideoFrame::Format_RGB32 , 32, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { QVideoFrame::Format_RGB24 , 24, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { QVideoFrame::Format_RGB565, 16, XvPacked, 1, 16, 0x0000F800, 0x000007E0, 0x0000001F }, + { QVideoFrame::Format_BGRA32, 32, XvPacked, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00 }, + { QVideoFrame::Format_BGR32 , 32, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { QVideoFrame::Format_BGR24 , 24, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { QVideoFrame::Format_BGR565, 16, XvPacked, 1, 16, 0x0000F800, 0x000007E0, 0x0000001F } +}; + +struct XvFormatYuv +{ + QVideoFrame::PixelFormat pixelFormat; + int bits_per_pixel; + int format; + int num_planes; + + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; +}; + +bool operator ==(const XvImageFormatValues &format, const XvFormatYuv &yuv) +{ + return format.type == XvYUV + && format.bits_per_pixel == yuv.bits_per_pixel + && format.format == yuv.format + && format.num_planes == yuv.num_planes + && format.y_sample_bits == yuv.y_sample_bits + && format.u_sample_bits == yuv.u_sample_bits + && format.v_sample_bits == yuv.v_sample_bits + && format.horz_y_period == yuv.horz_y_period + && format.horz_u_period == yuv.horz_u_period + && format.horz_v_period == yuv.horz_v_period + && format.horz_y_period == yuv.vert_y_period + && format.vert_u_period == yuv.vert_u_period + && format.vert_v_period == yuv.vert_v_period + && qstrncmp(format.component_order, yuv.component_order, 32) == 0; +} + +static const XvFormatYuv qt_xvYuvLookup[] = +{ + { QVideoFrame::Format_YUV444 , 24, XvPacked, 1, 8, 8, 8, 1, 1, 1, 1, 1, 1, "YUV" }, + { QVideoFrame::Format_YUV420P, 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" }, + { QVideoFrame::Format_YV12 , 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" }, + { QVideoFrame::Format_UYVY , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "UYVY" }, + { QVideoFrame::Format_YUYV , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUYV" }, + { QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" }, + { QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" }, + { QVideoFrame::Format_Y8 , 8 , XvPlanar, 1, 8, 0, 0, 1, 0, 0, 1, 0, 0, "Y" } +}; +*/ + +S60VideoSurface::S60VideoSurface(QObject *parent) + : QAbstractVideoSurface(parent) + , m_winId(0) + //, m_portId(0) + //, m_gc(0) + //, m_image(0) +{ +} + +S60VideoSurface::~S60VideoSurface() +{ + /*if (m_gc) + XFreeGC(QX11Info::display(), m_gc); + + if (m_portId != 0) + XvUngrabPort(QX11Info::display(), m_portId, 0); + */ +} + +WId S60VideoSurface::winId() const +{ + return m_winId; +} + +void S60VideoSurface::setWinId(WId id) +{ + /*if (id == m_winId) + return; + + if (m_image) + XFree(m_image); + + if (m_gc) { + XFreeGC(QX11Info::display(), m_gc); + m_gc = 0; + } + + if (m_portId != 0) + XvUngrabPort(QX11Info::display(), m_portId, 0); + + m_supportedPixelFormats.clear(); + m_formatIds.clear(); + + m_winId = id; + + if (m_winId && findPort()) { + querySupportedFormats(); + + m_gc = XCreateGC(QX11Info::display(), m_winId, 0, 0); + + if (m_image) { + m_image = 0; + + if (!start(surfaceFormat())) + QAbstractVideoSurface::stop(); + } + } else if (m_image) { + m_image = 0; + + QAbstractVideoSurface::stop(); + }*/ +} + +QRect S60VideoSurface::displayRect() const +{ + return m_displayRect; +} + +void S60VideoSurface::setDisplayRect(const QRect &rect) +{ + m_displayRect = rect; +} + +int S60VideoSurface::brightness() const +{ + //return getAttribute("XV_BRIGHTNESS", m_brightnessRange.first, m_brightnessRange.second); +} + +void S60VideoSurface::setBrightness(int brightness) +{ + //setAttribute("XV_BRIGHTNESS", brightness, m_brightnessRange.first, m_brightnessRange.second); +} + +int S60VideoSurface::contrast() const +{ + //return getAttribute("XV_CONTRAST", m_contrastRange.first, m_contrastRange.second); +} + +void S60VideoSurface::setContrast(int contrast) +{ + //setAttribute("XV_CONTRAST", contrast, m_contrastRange.first, m_contrastRange.second); +} + +int S60VideoSurface::hue() const +{ + //return getAttribute("XV_HUE", m_hueRange.first, m_hueRange.second); +} + +void S60VideoSurface::setHue(int hue) +{ + // setAttribute("XV_HUE", hue, m_hueRange.first, m_hueRange.second); +} + +int S60VideoSurface::saturation() const +{ + //return getAttribute("XV_SATURATION", m_saturationRange.first, m_saturationRange.second); +} + +void S60VideoSurface::setSaturation(int saturation) +{ + //setAttribute("XV_SATURATION", saturation, m_saturationRange.first, m_saturationRange.second); +} + +int S60VideoSurface::getAttribute(const char *attribute, int minimum, int maximum) const +{ + /*if (m_portId != 0) { + Display *display = QX11Info::display(); + + Atom atom = XInternAtom(display, attribute, True); + + int value = 0; + + XvGetPortAttribute(display, m_portId, atom, &value); + + return redistribute(value, minimum, maximum, -100, 100); + } else { + return 0; + }*/ +} + +void S60VideoSurface::setAttribute(const char *attribute, int value, int minimum, int maximum) +{ + /* if (m_portId != 0) { + Display *display = QX11Info::display(); + + Atom atom = XInternAtom(display, attribute, True); + + XvSetPortAttribute( + display, m_portId, atom, redistribute(value, -100, 100, minimum, maximum)); + }*/ +} + +int S60VideoSurface::redistribute( + int value, int fromLower, int fromUpper, int toLower, int toUpper) +{ + /*return fromUpper != fromLower + ? ((value - fromLower) * (toUpper - toLower) / (fromUpper - fromLower)) + toLower + : 0;*/ +} + +QList<QVideoFrame::PixelFormat> S60VideoSurface::supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const +{ + /*return handleType == QAbstractVideoBuffer::NoHandle + ? m_supportedPixelFormats + : QList<QVideoFrame::PixelFormat>();*/ +} + +bool S60VideoSurface::start(const QVideoSurfaceFormat &format) +{ + /*if (m_image) + XFree(m_image); + + int xvFormatId = 0; + for (int i = 0; i < m_supportedPixelFormats.count(); ++i) { + if (m_supportedPixelFormats.at(i) == format.pixelFormat()) { + xvFormatId = m_formatIds.at(i); + break; + } + } + + if (xvFormatId == 0) { + setError(UnsupportedFormatError); + } else { + XvImage *image = XvCreateImage( + QX11Info::display(), + m_portId, + xvFormatId, + 0, + format.frameWidth(), + format.frameHeight()); + + if (!image) { + setError(ResourceError); + } else { + m_viewport = format.viewport(); + m_image = image; + + return QAbstractVideoSurface::start(format); + } + } + + if (m_image) { + m_image = 0; + + QAbstractVideoSurface::stop(); + } +*/ + return false; +} + +void S60VideoSurface::stop() +{/* + if (m_image) { + XFree(m_image); + m_image = 0; + + QAbstractVideoSurface::stop(); + }*/ +} + +bool S60VideoSurface::present(const QVideoFrame &frame) +{/* + if (!m_image) { + setError(StoppedError); + return false; + } else if (m_image->width != frame.width() || m_image->height != frame.height()) { + setError(IncorrectFormatError); + return false; + } else { + QVideoFrame frameCopy(frame); + + if (!frameCopy.map(QAbstractVideoBuffer::ReadOnly)) { + setError(IncorrectFormatError); + return false; + } else { + bool presented = false; + + if (m_image->data_size > frame.numBytes()) { + qWarning("Insufficient frame buffer size"); + setError(IncorrectFormatError); + } else if (m_image->num_planes > 0 && m_image->pitches[0] != frame.bytesPerLine()) { + qWarning("Incompatible frame pitches"); + setError(IncorrectFormatError); + } else { + m_image->data = reinterpret_cast<char *>(frameCopy.bits()); + + XvPutImage( + QX11Info::display(), + m_portId, + m_winId, + m_gc, + m_image, + m_viewport.x(), + m_viewport.y(), + m_viewport.width(), + m_viewport.height(), + m_displayRect.x(), + m_displayRect.y(), + m_displayRect.width(), + m_displayRect.height()); + + m_image->data = 0; + + presented = true; + } + + frameCopy.unmap(); + + return presented; + } + }*/ +} + +bool S60VideoSurface::findPort() +{/* + unsigned int count = 0; + XvAdaptorInfo *adaptors = 0; + bool portFound = false; + + if (XvQueryAdaptors(QX11Info::display(), m_winId, &count, &adaptors) == Success) { + for (unsigned int i = 0; i < count && !portFound; ++i) { + if (adaptors[i].type & XvImageMask) { + m_portId = adaptors[i].base_id; + + for (unsigned int j = 0; j < adaptors[i].num_ports && !portFound; ++j, ++m_portId) + portFound = XvGrabPort(QX11Info::display(), m_portId, 0) == Success; + } + } + XvFreeAdaptorInfo(adaptors); + } + + return portFound;*/ +} + +void S60VideoSurface::querySupportedFormats() +{/* + int count = 0; + if (XvImageFormatValues *imageFormats = XvListImageFormats( + QX11Info::display(), m_portId, &count)) { + const int rgbCount = sizeof(qt_xvRgbLookup) / sizeof(XvFormatRgb); + const int yuvCount = sizeof(qt_xvYuvLookup) / sizeof(XvFormatYuv); + + for (int i = 0; i < count; ++i) { + switch (imageFormats[i].type) { + case XvRGB: + for (int j = 0; j < rgbCount; ++j) { + if (imageFormats[i] == qt_xvRgbLookup[j]) { + m_supportedPixelFormats.append(qt_xvRgbLookup[j].pixelFormat); + m_formatIds.append(imageFormats[i].id); + break; + } + } + break; + case XvYUV: + for (int j = 0; j < yuvCount; ++j) { + if (imageFormats[i] == qt_xvYuvLookup[j]) { + m_supportedPixelFormats.append(qt_xvYuvLookup[j].pixelFormat); + m_formatIds.append(imageFormats[i].id); + break; + } + } + break; + } + } + XFree(imageFormats); + } + + m_brightnessRange = qMakePair(0, 0); + m_contrastRange = qMakePair(0, 0); + m_hueRange = qMakePair(0, 0); + m_saturationRange = qMakePair(0, 0); + + if (XvAttribute *attributes = XvQueryPortAttributes(QX11Info::display(), m_portId, &count)) { + for (int i = 0; i < count; ++i) { + if (qstrcmp(attributes[i].name, "XV_BRIGHTNESS") == 0) + m_brightnessRange = qMakePair(attributes[i].min_value, attributes[i].max_value); + else if (qstrcmp(attributes[i].name, "XV_CONTRAST") == 0) + m_contrastRange = qMakePair(attributes[i].min_value, attributes[i].max_value); + else if (qstrcmp(attributes[i].name, "XV_HUE") == 0) + m_hueRange = qMakePair(attributes[i].min_value, attributes[i].max_value); + else if (qstrcmp(attributes[i].name, "XV_SATURATION") == 0) + m_saturationRange = qMakePair(attributes[i].min_value, attributes[i].max_value); + } + + XFree(attributes); + }*/ +} + +bool S60VideoSurface::isFormatSupported(const QVideoSurfaceFormat &format) const +{ +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60videosurface.h b/src/plugins/mediaservices/symbian/mediaplayer/s60videosurface.h new file mode 100644 index 0000000..836e52f --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60videosurface.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60VIDEOSURFACE_H +#define S60VIDEOSURFACE_H + +#include <QtGui/qwidget.h> +#include <QtMultimedia/qabstractvideosurface.h> + +QT_BEGIN_NAMESPACE + +class QVideoSurfaceFormat; + +class S60VideoSurface : public QAbstractVideoSurface +{ + Q_OBJECT +public: + S60VideoSurface(QObject *parent = 0); + ~S60VideoSurface(); + + WId winId() const; + void setWinId(WId id); + + QRect displayRect() const; + void setDisplayRect(const QRect &rect); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + + QList<QVideoFrame::PixelFormat> supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const; + + bool isFormatSupported(const QVideoSurfaceFormat &format) const; + + bool start(const QVideoSurfaceFormat &format); + void stop(); + + bool present(const QVideoFrame &frame); + +private: + WId m_winId; + //XvPortID m_portId; + //GC m_gc; + //XvImage *m_image; + QList<QVideoFrame::PixelFormat> m_supportedPixelFormats; + QVector<int> m_formatIds; + QRect m_viewport; + QRect m_displayRect; + QPair<int, int> m_brightnessRange; + QPair<int, int> m_contrastRange; + QPair<int, int> m_hueRange; + QPair<int, int> m_saturationRange; + + bool findPort(); + void querySupportedFormats(); + + int getAttribute(const char *attribute, int minimum, int maximum) const; + void setAttribute(const char *attribute, int value, int minimum, int maximum); + + static int redistribute(int value, int fromLower, int fromUpper, int toLower, int toUpper); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60videowidget.cpp b/src/plugins/mediaservices/symbian/mediaplayer/s60videowidget.cpp new file mode 100644 index 0000000..84000d5 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60videowidget.cpp @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "s60videowidget.h" +#include <QtGui/private/qwidget_p.h> +#include <QEvent> +#include <coemain.h> // For CCoeEnv + +QT_BEGIN_NAMESPACE + +QBlackWidget::QBlackWidget(QWidget *parent) + : QWidget(parent) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + setAttribute(Qt::WA_OpaquePaintEvent, true); + setAttribute(Qt::WA_NoSystemBackground, true); + setAutoFillBackground(false); + setPalette(QPalette(Qt::black)); +#if QT_VERSION >= 0x040601 && !defined(__WINSCW__) + qt_widget_private(this)->extraData()->nativePaintMode = QWExtra::ZeroFill; + qt_widget_private(this)->extraData()->receiveNativePaintEvents = true; +#endif +} + +QBlackWidget::~QBlackWidget() +{ +} + +void QBlackWidget::beginNativePaintEvent(const QRect& /*controlRect*/) +{ + emit beginVideoWindowNativePaint(); +} + +void QBlackWidget::endNativePaintEvent(const QRect& /*controlRect*/) +{ + CCoeEnv::Static()->WsSession().Flush(); + emit endVideoWindowNativePaint(); +} + +void QBlackWidget::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + // Do nothing +} + +S60VideoWidgetControl::S60VideoWidgetControl(QObject *parent) + : QVideoWidgetControl(parent) + , m_widget(0) + , m_aspectRatioMode(Qt::KeepAspectRatio) +{ + m_widget = new QBlackWidget(); + connect(m_widget, SIGNAL(beginVideoWindowNativePaint()), this, SIGNAL(beginVideoWindowNativePaint())); + connect(m_widget, SIGNAL(endVideoWindowNativePaint()), this, SIGNAL(endVideoWindowNativePaint())); + m_widget->installEventFilter(this); + m_widget->winId(); +} + +S60VideoWidgetControl::~S60VideoWidgetControl() +{ + delete m_widget; +} + +QWidget *S60VideoWidgetControl::videoWidget() +{ + return m_widget; +} + +Qt::AspectRatioMode S60VideoWidgetControl::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void S60VideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode ratio) +{ + if (m_aspectRatioMode == ratio) + return; + + m_aspectRatioMode = ratio; + emit widgetUpdated(); +} + +bool S60VideoWidgetControl::isFullScreen() const +{ + return m_widget->isFullScreen(); +} + +void S60VideoWidgetControl::setFullScreen(bool fullScreen) +{ + emit fullScreenChanged(fullScreen); +} + +int S60VideoWidgetControl::brightness() const +{ + return 0; +} + +void S60VideoWidgetControl::setBrightness(int brightness) +{ + Q_UNUSED(brightness); +} + +int S60VideoWidgetControl::contrast() const +{ + return 0; +} + +void S60VideoWidgetControl::setContrast(int contrast) +{ + Q_UNUSED(contrast); +} + +int S60VideoWidgetControl::hue() const +{ + return 0; +} + +void S60VideoWidgetControl::setHue(int hue) +{ + Q_UNUSED(hue); +} + +int S60VideoWidgetControl::saturation() const +{ + return 0; +} + +void S60VideoWidgetControl::setSaturation(int saturation) +{ + Q_UNUSED(saturation); +} + +bool S60VideoWidgetControl::eventFilter(QObject *object, QEvent *e) +{ + if (object == m_widget) { + if ( e->type() == QEvent::Resize + || e->type() == QEvent::Move + || e->type() == QEvent::WinIdChange + || e->type() == QEvent::ParentChange + || e->type() == QEvent::Show) + emit widgetUpdated(); + } + return false; +} + +WId S60VideoWidgetControl::videoWidgetWId() +{ + if (m_widget->internalWinId()) + return m_widget->internalWinId(); + + if (m_widget->effectiveWinId()) + return m_widget->effectiveWinId(); + + return NULL; +} + +void S60VideoWidgetControl::videoStateChanged(QMediaPlayer::State state) +{ + if (state == QMediaPlayer::StoppedState) { +#if QT_VERSION <= 0x040600 && !defined(FF_QT) + qt_widget_private(m_widget)->extraData()->disableBlit = false; +#endif + m_widget->repaint(); + } else if (state == QMediaPlayer::PlayingState) { +#if QT_VERSION <= 0x040600 && !defined(FF_QT) + qt_widget_private(m_widget)->extraData()->disableBlit = true; +#endif + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/symbian/mediaplayer/s60videowidget.h b/src/plugins/mediaservices/symbian/mediaplayer/s60videowidget.h new file mode 100644 index 0000000..28a1455 --- /dev/null +++ b/src/plugins/mediaservices/symbian/mediaplayer/s60videowidget.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60VIDEOWIDGET_H +#define S60VIDEOWIDGET_H + +#include <qvideowidgetcontrol.h> +#include <qmediaplayer.h> + +QT_BEGIN_NAMESPACE + +class QBlackWidget : public QWidget +{ + Q_OBJECT + +public: + QBlackWidget(QWidget *parent = 0); + virtual ~QBlackWidget(); + +signals: + void beginVideoWindowNativePaint(); + void endVideoWindowNativePaint(); + +public slots: + void beginNativePaintEvent(const QRect&); + void endNativePaintEvent(const QRect&); + +protected: + void paintEvent(QPaintEvent *event); +}; + +class S60VideoWidgetControl : public QVideoWidgetControl +{ + Q_OBJECT + +public: + S60VideoWidgetControl(QObject *parent = 0); + virtual ~S60VideoWidgetControl(); + + // from QVideoWidgetControl + QWidget *videoWidget(); + Qt::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(Qt::AspectRatioMode ratio); + bool isFullScreen() const; + void setFullScreen(bool fullScreen); + int brightness() const; + void setBrightness(int brightness); + int contrast() const; + void setContrast(int contrast); + int hue() const; + void setHue(int hue); + int saturation() const; + void setSaturation(int saturation); + + // from QObject + bool eventFilter(QObject *object, QEvent *event); + + //new methods + WId videoWidgetWId(); + +signals: + void widgetUpdated(); + void beginVideoWindowNativePaint(); + void endVideoWindowNativePaint(); + +private slots: + void videoStateChanged(QMediaPlayer::State state); + +private: + QBlackWidget *m_widget; + Qt::AspectRatioMode m_aspectRatioMode; +}; + +QT_END_NAMESPACE + + +#endif // S60VIDEOWIDGET_H diff --git a/src/plugins/mediaservices/symbian/s60mediaserviceplugin.cpp b/src/plugins/mediaservices/symbian/s60mediaserviceplugin.cpp new file mode 100644 index 0000000..1185583 --- /dev/null +++ b/src/plugins/mediaservices/symbian/s60mediaserviceplugin.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qstring.h> +#include <QtCore/qdebug.h> + +#include "s60mediaserviceplugin.h" +#ifdef QMEDIA_MMF_RADIO +#include "s60radiotunerservice.h" +#endif +#ifdef QMEDIA_MMF_PLAYER +#include "s60mediaplayerservice.h" +#endif +#ifdef QMEDIA_MMF_CAPTURE +#include "s60audiocaptureservice.h" +#endif + +QT_BEGIN_NAMESPACE + +QStringList S60MediaServicePlugin::keys() const +{ + QStringList list; +#ifdef QMEDIA_MMF_RADIO + list << QLatin1String(Q_MEDIASERVICE_RADIO); +#endif + +#ifdef QMEDIA_MMF_PLAYER + list << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER); +#endif +#ifdef QMEDIA_MMF_CAPTURE + list << QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE); +#endif + return list; +} + +QMediaService* S60MediaServicePlugin::create(QString const& key) +{ +#ifdef QMEDIA_MMF_PLAYER + if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) + return new S60MediaPlayerService; +#endif +#ifdef QMEDIA_MMF_CAPTURE + if (key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE)) + return new S60AudioCaptureService; +#endif +#ifdef QMEDIA_MMF_RADIO + if (key == QLatin1String(Q_MEDIASERVICE_RADIO)) + return new S60RadioTunerService; +#endif + + return 0; +} + +void S60MediaServicePlugin::release(QMediaService *service) +{ + delete service; +} + +QT_END_NAMESPACE + +Q_EXPORT_PLUGIN2(qmmfengine, S60MediaServicePlugin); + diff --git a/src/plugins/mediaservices/symbian/s60mediaserviceplugin.h b/src/plugins/mediaservices/symbian/s60mediaserviceplugin.h new file mode 100644 index 0000000..be2e05d --- /dev/null +++ b/src/plugins/mediaservices/symbian/s60mediaserviceplugin.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef S60SERVICEPLUGIN_H +#define S60SERVICEPLUGIN_H + +#include <QtCore/qobject.h> +#include <qmediaservice.h> +#include <qmediaserviceproviderplugin.h> + +QT_BEGIN_NAMESPACE + +class S60MediaServicePlugin : public QMediaServiceProviderPlugin +{ + Q_OBJECT +public: + + QStringList keys() const; + QMediaService* create(QString const& key); + void release(QMediaService *service); +}; + +QT_END_NAMESPACE + +#endif // S60SERVICEPLUGIN_H diff --git a/src/plugins/mediaservices/symbian/s60videooutputcontrol.cpp b/src/plugins/mediaservices/symbian/s60videooutputcontrol.cpp new file mode 100644 index 0000000..da07a7d --- /dev/null +++ b/src/plugins/mediaservices/symbian/s60videooutputcontrol.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "s60videooutputcontrol.h" + +QT_BEGIN_NAMESPACE + +S60VideoOutputControl::S60VideoOutputControl(QObject *parent) + : QVideoOutputControl(parent) + , m_output(NoOutput) +{ +} + +QList<QVideoOutputControl::Output> S60VideoOutputControl::availableOutputs() const +{ + return m_outputs; +} + +void S60VideoOutputControl::setAvailableOutputs(const QList<Output> &outputs) +{ + emit availableOutputsChanged(m_outputs = outputs); +} + +QVideoOutputControl::Output S60VideoOutputControl::output() const +{ + return m_output; +} + +void S60VideoOutputControl::setOutput(Output output) +{ + if (!m_outputs.contains(output)) + output = NoOutput; + + if (m_output != output) + emit outputChanged(m_output = output); +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/symbian/s60videooutputcontrol.h b/src/plugins/mediaservices/symbian/s60videooutputcontrol.h new file mode 100644 index 0000000..dbad889 --- /dev/null +++ b/src/plugins/mediaservices/symbian/s60videooutputcontrol.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef S60VIDEOOUTPUTCONTROL_H +#define S60VIDEOOUTPUTCONTROL_H + +#include <QObject> +#include <qvideooutputcontrol.h> + +QT_BEGIN_NAMESPACE + +class S60VideoOutputControl : public QVideoOutputControl +{ + Q_OBJECT +public: + S60VideoOutputControl(QObject *parent = 0); + + QList<Output> availableOutputs() const; + void setAvailableOutputs(const QList<Output> &outputs); + + Output output() const; + void setOutput(Output output); + +Q_SIGNALS: + void outputChanged(QVideoOutputControl::Output output); + +private: + QList<Output> m_outputs; + Output m_output; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/mediaservices/symbian/symbian.pro b/src/plugins/mediaservices/symbian/symbian.pro new file mode 100644 index 0000000..f76858f --- /dev/null +++ b/src/plugins/mediaservices/symbian/symbian.pro @@ -0,0 +1,27 @@ +TARGET = qmmfengine +QT += multimedia mediaservices + +load(data_caging_paths) + +include (../../qpluginbase.pri) +include(mediaplayer/mediaplayer.pri) + +HEADERS += s60mediaserviceplugin.h \ + s60videooutputcontrol.h + +SOURCES += s60mediaserviceplugin.cpp \ + s60videooutputcontrol.cpp + +contains(S60_VERSION, 3.2)|contains(S60_VERSION, 3.1) { + DEFINES += PRE_S60_50_PLATFORM +} + +INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE +symbian-abld:INCLUDEPATH += $$QT_BUILD_TREE/include/QtWidget/private + +# This is needed for having the .qtplugin file properly created on Symbian. +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/mediaservices +target.path += $$[QT_INSTALL_PLUGINS]/mediaservices +INSTALLS += target + +TARGET.UID3=0x20021318 diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index d0a446b..e309e25 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -3122,7 +3122,7 @@ EXPORTS ?reset@QIODevice@@UAE_NXZ @ 3121 NONAME ; bool QIODevice::reset(void) ?reset@QMetaProperty@@QBE_NPAVQObject@@@Z @ 3122 NONAME ; bool QMetaProperty::reset(class QObject *) const ?reset@QTextStream@@QAEXXZ @ 3123 NONAME ; void QTextStream::reset(void) - ?resetCurrentSender@QObjectPrivate@@SAXPAVQObject@@PAUSender@1@1@Z @ 3124 NONAME ; void QObjectPrivate::resetCurrentSender(class QObject *, struct QObjectPrivate::Sender *, struct QObjectPrivate::Sender *) + ?resetCurrentSender@QObjectPrivate@@SAXPAVQObject@@PAUSender@1@1@Z @ 3124 NONAME ABSENT ; void QObjectPrivate::resetCurrentSender(class QObject *, struct QObjectPrivate::Sender *, struct QObjectPrivate::Sender *) ?resetDeleteWatch@QObjectPrivate@@SAXPAV1@PAHH@Z @ 3125 NONAME ; void QObjectPrivate::resetDeleteWatch(class QObjectPrivate *, int *, int) ?resetStatus@QDataStream@@QAEXXZ @ 3126 NONAME ; void QDataStream::resetStatus(void) ?resetStatus@QTextStream@@QAEXXZ @ 3127 NONAME ; void QTextStream::resetStatus(void) @@ -3281,7 +3281,7 @@ EXPORTS ?setCoords@QRectF@@QAEXMMMM@Z @ 3280 NONAME ; void QRectF::setCoords(float, float, float, float) ?setCurrent@QDir@@SA_NABVQString@@@Z @ 3281 NONAME ; bool QDir::setCurrent(class QString const &) ?setCurrentPath@QFSFileEngine@@SA_NABVQString@@@Z @ 3282 NONAME ; bool QFSFileEngine::setCurrentPath(class QString const &) - ?setCurrentSender@QObjectPrivate@@SAPAUSender@1@PAVQObject@@PAU21@@Z @ 3283 NONAME ; struct QObjectPrivate::Sender * QObjectPrivate::setCurrentSender(class QObject *, struct QObjectPrivate::Sender *) + ?setCurrentSender@QObjectPrivate@@SAPAUSender@1@PAVQObject@@PAU21@@Z @ 3283 NONAME ABSENT ; struct QObjectPrivate::Sender * QObjectPrivate::setCurrentSender(class QObject *, struct QObjectPrivate::Sender *) ?setCurrentTime@QAbstractAnimation@@QAEXH@Z @ 3284 NONAME ; void QAbstractAnimation::setCurrentTime(int) ?setCurrentTime@QTimeLine@@QAEXH@Z @ 3285 NONAME ; void QTimeLine::setCurrentTime(int) ?setCurveShape@QTimeLine@@QAEXW4CurveShape@1@@Z @ 3286 NONAME ; void QTimeLine::setCurveShape(enum QTimeLine::CurveShape) diff --git a/src/s60installs/bwins/QtDeclarativeu.def b/src/s60installs/bwins/QtDeclarativeu.def index ec25b5c..5f05f08 100644 --- a/src/s60installs/bwins/QtDeclarativeu.def +++ b/src/s60installs/bwins/QtDeclarativeu.def @@ -3950,7 +3950,7 @@ EXPORTS ?qmlInfo@@YA?AVQDeclarativeInfo@@PBVQObject@@ABVQDeclarativeError@@@Z @ 3949 NONAME ; class QDeclarativeInfo qmlInfo(class QObject const *, class QDeclarativeError const &) ?error@QDeclarativeCustomParser@@IAEXABVQString@@@Z @ 3950 NONAME ; void QDeclarativeCustomParser::error(class QString const &) ?activeChanged@QDeclarativeDrag@@IAEXXZ @ 3951 NONAME ; void QDeclarativeDrag::activeChanged(void) - ??0QDeclarativeInfo@@AAE@PAUQDeclarativeInfoPrivate@@@Z @ 3952 NONAME ; QDeclarativeInfo::QDeclarativeInfo(struct QDeclarativeInfoPrivate *) + ??0QDeclarativeInfo@@AAE@PAUQDeclarativeInfoPrivate@@@Z @ 3952 NONAME ABSENT ; QDeclarativeInfo::QDeclarativeInfo(struct QDeclarativeInfoPrivate *) ?warnings@QDeclarativeEngine@@IAEXABV?$QList@VQDeclarativeError@@@@@Z @ 3953 NONAME ; void QDeclarativeEngine::warnings(class QList<class QDeclarativeError> const &) ?parentModelIndex@QDeclarativeVisualDataModel@@QBE?AVQVariant@@XZ @ 3954 NONAME ; class QVariant QDeclarativeVisualDataModel::parentModelIndex(void) const ?usedAnchors@QDeclarativeAnchors@@QBE?AV?$QFlags@W4Anchor@QDeclarativeAnchors@@@@XZ @ 3955 NONAME ; class QFlags<enum QDeclarativeAnchors::Anchor> QDeclarativeAnchors::usedAnchors(void) const diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index daa9dc6..92a4020 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3697,4 +3697,5 @@ EXPORTS _ZN16QDeclarativeData9destroyedE @ 3696 NONAME DATA 4 ABSENT _ZN24QAbstractDeclarativeData13parentChangedE @ 3697 NONAME DATA 4 _ZN24QAbstractDeclarativeData9destroyedE @ 3698 NONAME DATA 4 + _ZN23QEventDispatcherSymbian12selectThreadEv @ 3699 NONAME diff --git a/src/s60installs/eabi/QtDeclarativeu.def b/src/s60installs/eabi/QtDeclarativeu.def index 953d0a1..ad12166 100644 --- a/src/s60installs/eabi/QtDeclarativeu.def +++ b/src/s60installs/eabi/QtDeclarativeu.def @@ -3496,4 +3496,44 @@ EXPORTS _ZTIN14QDeclarativeJS3AST18FunctionExpressionE @ 3495 NONAME ABSENT _ZTIN14QDeclarativeJS3AST4NodeE @ 3496 NONAME ABSENT _ZTIN14QDeclarativeJS3AST9StatementE @ 3497 NONAME ABSENT + _Z7qmlInfoPK7QObjectRK17QDeclarativeError @ 3498 NONAME + _Z7qmlInfoPK7QObjectRK5QListI17QDeclarativeErrorE @ 3499 NONAME + _ZN16QDeclarativeDrag13activeChangedEv @ 3500 NONAME + _ZN16QDeclarativeDrag9setActiveEb @ 3501 NONAME + _ZN16QDeclarativeInfoC1EP23QDeclarativeInfoPrivate @ 3502 NONAME + _ZN16QDeclarativeInfoC1ERKS_ @ 3503 NONAME + _ZN16QDeclarativeInfoC2EP23QDeclarativeInfoPrivate @ 3504 NONAME + _ZN16QDeclarativeInfoC2ERKS_ @ 3505 NONAME + _ZN16QDeclarativeItem10forceFocusEv @ 3506 NONAME + _ZN16QDeclarativeView11eventFilterEP7QObjectP6QEvent @ 3507 NONAME + _ZN18QDeclarativeEngine32setOutputWarningsToStandardErrorEb @ 3508 NONAME + _ZN18QDeclarativeEngine8warningsERK5QListI17QDeclarativeErrorE @ 3509 NONAME + _ZN18QDeclarativeLoader20resetSourceComponentEv @ 3510 NONAME + _ZN20QDeclarativeFlipable15retransformBackEv @ 3511 NONAME + _ZN20QDeclarativeGridView11animStoppedEv @ 3512 NONAME + _ZN21QDeclarativeFlickable17setBoundsBehaviorENS_14BoundsBehaviorE @ 3513 NONAME + _ZN21QDeclarativeFlickable21boundsBehaviorChangedEv @ 3514 NONAME + _ZN21QDeclarativeMouseArea15geometryChangedERK6QRectFS2_ @ 3515 NONAME + _ZN21QDeclarativeMouseArea20mousePositionChangedEP22QDeclarativeMouseEvent @ 3516 NONAME + _ZN22QDeclarativeExpression8evaluateEPb @ 3517 NONAME + _ZN23QDeclarativeItemPrivate16transformChangedEv @ 3518 NONAME + _ZN24QDeclarativeCustomParser5errorERK7QString @ 3519 NONAME + _ZN24QDeclarativeDebugService18hasDebuggingClientEv @ 3520 NONAME + _ZN24QDeclarativeParentChange7executeEN23QDeclarativeActionEvent6ReasonE @ 3521 NONAME + _ZN24QDeclarativeParentChange7reverseEN23QDeclarativeActionEvent6ReasonE @ 3522 NONAME + _ZN25QDeclarativeAnchorChanges7executeEN23QDeclarativeActionEvent6ReasonE @ 3523 NONAME + _ZN25QDeclarativeAnchorChanges7reverseEN23QDeclarativeActionEvent6ReasonE @ 3524 NONAME + _ZN27QDeclarativeVisualDataModel12setRootIndexERK8QVariant @ 3525 NONAME + _ZN29QDeclarativeStateChangeScript7executeEN23QDeclarativeActionEvent6ReasonE @ 3526 NONAME + _ZNK16QDeclarativeDrag6activeEv @ 3527 NONAME + _ZNK16QDeclarativeType16noCreationReasonEv @ 3528 NONAME + _ZNK18QDeclarativeEngine29outputWarningsToStandardErrorEv @ 3529 NONAME + _ZNK21QDeclarativeFlickable14boundsBehaviorEv @ 3530 NONAME + _ZNK27QDeclarativeVisualDataModel10modelIndexEi @ 3531 NONAME + _ZNK27QDeclarativeVisualDataModel16parentModelIndexEv @ 3532 NONAME + _ZThn8_N24QDeclarativeParentChange7executeEN23QDeclarativeActionEvent6ReasonE @ 3533 NONAME + _ZThn8_N24QDeclarativeParentChange7reverseEN23QDeclarativeActionEvent6ReasonE @ 3534 NONAME + _ZThn8_N25QDeclarativeAnchorChanges7executeEN23QDeclarativeActionEvent6ReasonE @ 3535 NONAME + _ZThn8_N25QDeclarativeAnchorChanges7reverseEN23QDeclarativeActionEvent6ReasonE @ 3536 NONAME + _ZThn8_N29QDeclarativeStateChangeScript7executeEN23QDeclarativeActionEvent6ReasonE @ 3537 NONAME diff --git a/src/s60installs/eabi/QtNetworku.def b/src/s60installs/eabi/QtNetworku.def index 2796778..2566415 100644 --- a/src/s60installs/eabi/QtNetworku.def +++ b/src/s60installs/eabi/QtNetworku.def @@ -1166,4 +1166,5 @@ EXPORTS _ZNK13QBearerEngine15requiresPollingEv @ 1165 NONAME _ZNK13QBearerEngine19configurationsInUseEv @ 1166 NONAME _ZNK21QNetworkAccessManager17networkAccessibleEv @ 1167 NONAME + _ZN35QNetworkConfigurationManagerPrivate12capabilitiesEv @ 1168 NONAME diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index ad196a8..dfd2694 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -151,9 +151,18 @@ symbian: { graphicssystems_plugins.sources += $$QT_BUILD_TREE/plugins/graphicssystems/qvggraphicssystem$${QT_LIBINFIX}.dll } - contains(QT_CONFIG, multimedia) { + contains(QT_CONFIG, multimedia):contains(QT_CONFIG, mediaservices):contains(QT_CONFIG, media-backend) { qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtMultimedia$${QT_LIBINFIX}.dll + } + + contains(QT_CONFIG, media-backend) { qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtMediaServices$${QT_LIBINFIX}.dll + + mediaservices_plugins.path = c:$$QT_PLUGINS_BASE_DIR/mediaservices + mediaservices_plugins.sources += $$QT_BUILD_TREE/plugins/mediaservices/qmmfengine$${QT_LIBINFIX}.dll + + DEPLOYMENT += mediaservices_plugins + } BLD_INF_RULES.prj_exports += "qt.iby $$CORE_MW_LAYER_IBY_EXPORT_PATH(qt.iby)" diff --git a/src/script/bridge/qscriptqobject_p.h b/src/script/bridge/qscriptqobject_p.h index b82bcb7..412a784 100644 --- a/src/script/bridge/qscriptqobject_p.h +++ b/src/script/bridge/qscriptqobject_p.h @@ -303,7 +303,7 @@ public: } protected: - static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSObject::StructureFlags; + static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSC::ImplementsHasInstance | JSObject::StructureFlags; Data *data; }; diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index 24dcad9..4344af4 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -259,6 +259,7 @@ bool QSQLiteResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int i q->setAt(QSql::AfterLastRow); sqlite3_reset(stmt); return false; + case SQLITE_CONSTRAINT: case SQLITE_ERROR: // SQLITE_ERROR is a generic error code and we must call sqlite3_reset() // to get the specific error message. diff --git a/src/testlib/qtestlogger.cpp b/src/testlib/qtestlogger.cpp index 6c76388..f0be6be 100644 --- a/src/testlib/qtestlogger.cpp +++ b/src/testlib/qtestlogger.cpp @@ -211,10 +211,7 @@ void QTestLogger::addIncident(IncidentTypes type, const char *description, QTest::qt_snprintf(buf, sizeof(buf), "%i", line); failureElement->addAttribute(QTest::AI_Line, buf); failureElement->addAttribute(QTest::AI_Description, description); - const char* tag = QTestResult::currentDataTag(); - if (tag) { - failureElement->addAttribute(QTest::AI_Tag, tag); - } + addTag(failureElement); currentLogElement->addLogElement(failureElement); } @@ -279,6 +276,27 @@ void QTestLogger::addBenchmarkResult(const QBenchmarkResult &result) currentLogElement->addLogElement(benchmarkElement); } +void QTestLogger::addTag(QTestElement* element) +{ + const char *tag = QTestResult::currentDataTag(); + const char *gtag = QTestResult::currentGlobalDataTag(); + const char *filler = (tag && gtag) ? ":" : ""; + if ((!tag || !tag[0]) && (!gtag || !gtag[0])) { + return; + } + + if (!tag) { + tag = ""; + } + if (!gtag) { + gtag = ""; + } + + QTestCharBuffer buf; + QTest::qt_asprintf(&buf, "%s%s%s", gtag, filler, tag); + element->addAttribute(QTest::AI_Tag, buf.constData()); +} + void QTestLogger::addMessage(MessageTypes type, const char *message, const char *file, int line) { QTestElement *errorElement = new QTestElement(QTest::LET_Error); @@ -299,7 +317,7 @@ void QTestLogger::addMessage(MessageTypes type, const char *message, const char break; case QAbstractTestLogger::QWarning: ++qwarnCounter; - typeBuf = "qwarning"; + typeBuf = "qwarn"; break; case QAbstractTestLogger::QFatal: ++qfatalCounter; @@ -320,6 +338,7 @@ void QTestLogger::addMessage(MessageTypes type, const char *message, const char errorElement->addAttribute(QTest::AI_Type, typeBuf); errorElement->addAttribute(QTest::AI_Description, message); + addTag(errorElement); if(file) errorElement->addAttribute(QTest::AI_File, file); diff --git a/src/testlib/qtestlogger_p.h b/src/testlib/qtestlogger_p.h index 31f7d55..bb7a358 100644 --- a/src/testlib/qtestlogger_p.h +++ b/src/testlib/qtestlogger_p.h @@ -83,6 +83,7 @@ class QTestLogger : public QAbstractTestLogger void addIncident(IncidentTypes type, const char *description, const char *file = 0, int line = 0); void addBenchmarkResult(const QBenchmarkResult &result); + void addTag(QTestElement* element); void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0); diff --git a/src/testlib/qtestxmlstreamer.cpp b/src/testlib/qtestxmlstreamer.cpp index b9946e5..f63c221 100644 --- a/src/testlib/qtestxmlstreamer.cpp +++ b/src/testlib/qtestxmlstreamer.cpp @@ -111,12 +111,20 @@ void QTestXmlStreamer::formatStart(const QTestElement *element, QTestCharBuffer QXmlTestLogger::xmlQuote("edFile, element->attributeValue(QTest::AI_File)); QXmlTestLogger::xmlCdata(&cdataDesc, element->attributeValue(QTest::AI_Description)); - QTest::qt_asprintf(formatted, "<Message type=\"%s\" %s=\"%s\" %s=\"%s\">\n <Description><![CDATA[%s]]></Description>\n</Message>\n", + QTestCharBuffer tagbuf; + if (element->attribute(QTest::AI_Tag)) { + QTestCharBuffer cdataTag; + QXmlTestLogger::xmlCdata(&cdataTag, element->attributeValue(QTest::AI_Tag)); + QTest::qt_asprintf(&tagbuf, " <DataTag><![CDATA[%s]]></DataTag>\n", cdataTag.constData()); + } + + QTest::qt_asprintf(formatted, "<Message type=\"%s\" %s=\"%s\" %s=\"%s\">\n%s <Description><![CDATA[%s]]></Description>\n</Message>\n", element->attributeValue(QTest::AI_Type), element->attributeName(QTest::AI_File), quotedFile.constData(), element->attributeName(QTest::AI_Line), element->attributeValue(QTest::AI_Line), + tagbuf.constData(), cdataDesc.constData()); break; } @@ -149,7 +157,29 @@ void QTestXmlStreamer::formatEnd(const QTestElement *element, QTestCharBuffer *f return; if (element->elementType() == QTest::LET_TestCase) { - QTest::qt_asprintf(formatted, "</TestFunction>\n"); + bool failed = false; + for (QTestElement* child = element->childElements(); child; child = child->nextElement()) { + if ( child->elementType() == QTest::LET_Failure + && child->attribute(QTest::AI_Result) + && ( !strcmp(child->attributeValue(QTest::AI_Result), "fail") + || !strcmp(child->attributeValue(QTest::AI_Result), "xpass")) + ) + { + failed = true; + break; + } + } + + // For passing functions, no Incident has been output yet. + // For failing functions, we already output one. + // Please note: we are outputting "pass" even if there was an xfail etc. + // This is by design (arguably bad design, but dangerous to change now!) + if (element->attribute(QTest::AI_Result) && !failed) { + QTest::qt_asprintf(formatted, "<Incident type=\"pass\" file=\"\" line=\"0\" />\n</TestFunction>\n"); + } + else { + QTest::qt_asprintf(formatted, "</TestFunction>\n"); + } } else { formatted->data()[0] = '\0'; } @@ -157,29 +187,11 @@ void QTestXmlStreamer::formatEnd(const QTestElement *element, QTestCharBuffer *f void QTestXmlStreamer::formatBeforeAttributes(const QTestElement *element, QTestCharBuffer *formatted) const { - if(!element || !formatted) + Q_UNUSED(element); + if (!formatted) return; - if (element->elementType() == QTest::LET_TestCase && element->attribute(QTest::AI_Result)){ - QTestCharBuffer buf; - QTestCharBuffer quotedFile; - QXmlTestLogger::xmlQuote("edFile, element->attributeValue(QTest::AI_File)); - - QTest::qt_asprintf(&buf, "%s=\"%s\" %s=\"%s\"", - element->attributeName(QTest::AI_File), - quotedFile.constData(), - element->attributeName(QTest::AI_Line), - element->attributeValue(QTest::AI_Line)); - - if( !element->childElements() ) { - QTest::qt_asprintf(formatted, "<Incident type=\"%s\" %s/>\n", - element->attributeValue(QTest::AI_Result), buf.constData()); - } else { - formatted->data()[0] = '\0'; - } - } else { - formatted->data()[0] = '\0'; - } + formatted->data()[0] = '\0'; } void QTestXmlStreamer::output(QTestElement *element) const diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp index 2236666..07e8ef0 100644 --- a/src/testlib/qxmltestlogger.cpp +++ b/src/testlib/qxmltestlogger.cpp @@ -244,7 +244,7 @@ void QXmlTestLogger::addBenchmarkResult(const QBenchmarkResult &result) QTestCharBuffer quotedTag; xmlQuote("edMetric, - benchmarkMetricUnit(result.metric)); + benchmarkMetricName(result.metric)); xmlQuote("edTag, result.context.tag.toAscii().constData()); QTest::qt_asprintf( diff --git a/src/xmlpatterns/schema/qxsdschemaresolver.cpp b/src/xmlpatterns/schema/qxsdschemaresolver.cpp index 34eb12c..f3d1ed0 100644 --- a/src/xmlpatterns/schema/qxsdschemaresolver.cpp +++ b/src/xmlpatterns/schema/qxsdschemaresolver.cpp @@ -632,7 +632,14 @@ void XsdSchemaResolver::resolveSimpleContentComplexTypes(const XsdComplexType::P } else { // 1.2 const XsdSimpleType::Ptr anonType(new XsdSimpleType()); - anonType->setCategory(complexBaseType->contentType()->simpleType()->category()); + XsdSimpleType::TypeCategory baseCategory = complexBaseType->contentType()->simpleType()->category(); + anonType->setCategory(baseCategory); + + if (baseCategory == XsdSimpleType::SimpleTypeList) { + const XsdSimpleType::Ptr baseSimpleType = complexBaseType->contentType()->simpleType(); + anonType->setItemType(baseSimpleType->itemType()); + } + anonType->setDerivationMethod(XsdSimpleType::DerivationRestriction); anonType->setWxsSuperType(complexBaseType->contentType()->simpleType()); anonType->setFacets(complexTypeFacets(complexType)); diff --git a/src/xmlpatterns/xmlpatterns.pro b/src/xmlpatterns/xmlpatterns.pro index a224762..e50d184 100644 --- a/src/xmlpatterns/xmlpatterns.pro +++ b/src/xmlpatterns/xmlpatterns.pro @@ -24,13 +24,14 @@ include($$PWD/schema/schema.pri) include($$PWD/type/type.pri) include($$PWD/utils/utils.pri) include($$PWD/qobjectmodel/qobjectmodel.pri, "", true) -wince*:# The Microsoft MIPS compiler crashes if /Og is specified -: -# -O2/1 expands to /Og plus additional arguments. -contains(DEFINES, MIPS): { - QMAKE_CXXFLAGS_RELEASE ~= s/-O2/-Oi -Ot -Oy -Ob2/ - QMAKE_CXXFLAGS_RELEASE ~= s/-O1/-Os -Oy -Ob2/ +wince* { + # The Microsoft MIPS compiler crashes if /Og is specified. + # -O2/1 expands to /Og plus additional arguments. + contains(DEFINES, MIPS) { + QMAKE_CXXFLAGS_RELEASE ~= s/-O2/-Oi -Ot -Oy -Ob2/ + QMAKE_CXXFLAGS_RELEASE ~= s/-O1/-Os -Oy -Ob2/ + } } + symbian:TARGET.UID3 = 0x2001E62B -HEADERS += |