summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/phonon/qt7
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/phonon/qt7')
-rw-r--r--src/3rdparty/phonon/qt7/CMakeLists.txt58
-rw-r--r--src/3rdparty/phonon/qt7/ConfigureChecks.cmake16
-rw-r--r--src/3rdparty/phonon/qt7/audioconnection.h84
-rw-r--r--src/3rdparty/phonon/qt7/audioconnection.mm152
-rw-r--r--src/3rdparty/phonon/qt7/audiodevice.h52
-rw-r--r--src/3rdparty/phonon/qt7/audiodevice.mm176
-rw-r--r--src/3rdparty/phonon/qt7/audioeffects.h80
-rw-r--r--src/3rdparty/phonon/qt7/audioeffects.mm254
-rw-r--r--src/3rdparty/phonon/qt7/audiograph.h86
-rw-r--r--src/3rdparty/phonon/qt7/audiograph.mm320
-rw-r--r--src/3rdparty/phonon/qt7/audiomixer.h91
-rw-r--r--src/3rdparty/phonon/qt7/audiomixer.mm181
-rw-r--r--src/3rdparty/phonon/qt7/audionode.h86
-rw-r--r--src/3rdparty/phonon/qt7/audionode.mm243
-rw-r--r--src/3rdparty/phonon/qt7/audiooutput.h88
-rw-r--r--src/3rdparty/phonon/qt7/audiooutput.mm168
-rw-r--r--src/3rdparty/phonon/qt7/audiopartoutput.h47
-rw-r--r--src/3rdparty/phonon/qt7/audiopartoutput.mm69
-rw-r--r--src/3rdparty/phonon/qt7/audiosplitter.h50
-rw-r--r--src/3rdparty/phonon/qt7/audiosplitter.mm52
-rw-r--r--src/3rdparty/phonon/qt7/backend.h61
-rw-r--r--src/3rdparty/phonon/qt7/backend.mm276
-rw-r--r--src/3rdparty/phonon/qt7/backendheader.h184
-rw-r--r--src/3rdparty/phonon/qt7/backendheader.mm127
-rw-r--r--src/3rdparty/phonon/qt7/backendinfo.h48
-rw-r--r--src/3rdparty/phonon/qt7/backendinfo.mm311
-rw-r--r--src/3rdparty/phonon/qt7/lgpl-2.1.txt504
-rw-r--r--src/3rdparty/phonon/qt7/lgpl-3.txt165
-rw-r--r--src/3rdparty/phonon/qt7/medianode.h85
-rw-r--r--src/3rdparty/phonon/qt7/medianode.mm261
-rw-r--r--src/3rdparty/phonon/qt7/medianodeevent.h71
-rw-r--r--src/3rdparty/phonon/qt7/medianodeevent.mm37
-rw-r--r--src/3rdparty/phonon/qt7/medianodevideopart.h42
-rw-r--r--src/3rdparty/phonon/qt7/medianodevideopart.mm37
-rw-r--r--src/3rdparty/phonon/qt7/mediaobject.h171
-rw-r--r--src/3rdparty/phonon/qt7/mediaobject.mm852
-rw-r--r--src/3rdparty/phonon/qt7/mediaobjectaudionode.h75
-rw-r--r--src/3rdparty/phonon/qt7/mediaobjectaudionode.mm209
-rw-r--r--src/3rdparty/phonon/qt7/quicktimeaudioplayer.h112
-rw-r--r--src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm493
-rw-r--r--src/3rdparty/phonon/qt7/quicktimemetadata.h67
-rw-r--r--src/3rdparty/phonon/qt7/quicktimemetadata.mm187
-rw-r--r--src/3rdparty/phonon/qt7/quicktimestreamreader.h71
-rw-r--r--src/3rdparty/phonon/qt7/quicktimestreamreader.mm137
-rw-r--r--src/3rdparty/phonon/qt7/quicktimevideoplayer.h167
-rw-r--r--src/3rdparty/phonon/qt7/quicktimevideoplayer.mm955
-rw-r--r--src/3rdparty/phonon/qt7/videoeffect.h63
-rw-r--r--src/3rdparty/phonon/qt7/videoeffect.mm76
-rw-r--r--src/3rdparty/phonon/qt7/videoframe.h98
-rw-r--r--src/3rdparty/phonon/qt7/videoframe.mm378
-rw-r--r--src/3rdparty/phonon/qt7/videowidget.h71
-rw-r--r--src/3rdparty/phonon/qt7/videowidget.mm885
52 files changed, 9629 insertions, 0 deletions
diff --git a/src/3rdparty/phonon/qt7/CMakeLists.txt b/src/3rdparty/phonon/qt7/CMakeLists.txt
new file mode 100644
index 0000000..5310be1
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/CMakeLists.txt
@@ -0,0 +1,58 @@
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+#
+# This library is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 2 or 3 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library. If not, see <http://www.gnu.org/licenses/>.
+project(phonon-qt7)
+include(ConfigureChecks.cmake)
+
+include_directories(${OPENGL_INCLUDE_DIR})
+
+if (BUILD_PHONON_QT7)
+ set(phonon_qt7_SRCS
+ quicktimevideoplayer.mm
+ backendheader.mm
+ medianodevideopart.mm
+ medianodeevent.mm
+ audiooutput.mm
+ backendinfo.mm
+ audiosplitter.mm
+ audioeffects.mm
+ quicktimestreamreader.mm
+ medianode.mm
+ backend.mm
+ mediaobject.mm
+ mediaobjectaudionode.mm
+ audiomixer.mm
+ quicktimeaudioplayer.mm
+ videoframe.mm
+ quicktimemetadata.mm
+ audiodevice.mm
+ audioconnection.mm
+ audiograph.mm
+ audionode.mm
+ videowidget.mm
+ )
+
+ automoc4_add_library(phonon_qt7 MODULE ${phonon_qt7_SRCS})
+ target_link_libraries(phonon_qt7
+ ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY}
+ ${PHONON_LIBS}
+ "-framework QuickTime"
+ "-framework AudioUnit"
+ "-framework AudioToolbox"
+ "-framework CoreAudio"
+ "-framework QuartzCore"
+ "-framework QTKit"
+ )
+ install(TARGETS phonon_qt7 DESTINATION ${PLUGIN_INSTALL_DIR})
+
+endif (BUILD_PHONON_QT7)
diff --git a/src/3rdparty/phonon/qt7/ConfigureChecks.cmake b/src/3rdparty/phonon/qt7/ConfigureChecks.cmake
new file mode 100644
index 0000000..9644867
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/ConfigureChecks.cmake
@@ -0,0 +1,16 @@
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+#
+# This library is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 2 or 3 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+# Find the frameworks if necessary
+set(BUILD_PHONON_QT7 TRUE)
diff --git a/src/3rdparty/phonon/qt7/audioconnection.h b/src/3rdparty/phonon/qt7/audioconnection.h
new file mode 100644
index 0000000..2129744
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audioconnection.h
@@ -0,0 +1,84 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AudioConnection_H
+#define Phonon_QT7_AudioConnection_H
+
+#include <QtCore/QObject>
+#include "backendheader.h"
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class MediaNode;
+ class AudioNode;
+ class AudioGraph;
+
+ class AudioConnection {
+ public:
+ AudioConnection();
+ AudioConnection(MediaNode *sink);
+ AudioConnection(MediaNode *source, int output, MediaNode *sink, int input);
+
+ AudioConnection(AudioNode *sink);
+ AudioConnection(AudioNode *source, int output, AudioNode *sink, int input);
+
+ ~AudioConnection();
+
+ bool connect(AudioGraph *graph);
+ bool disconnect(AudioGraph *graph);
+
+ bool updateStreamSpecification();
+ bool isBetween(MediaNode *source, MediaNode *sink);
+ bool isValid();
+ bool isSinkOnly();
+ void freeMemoryAllocations();
+ void invalidate();
+
+ MediaNode *m_source;
+ AudioNode *m_sourceAudioNode;
+ int m_sourceOutputBus;
+
+ MediaNode *m_sink;
+ AudioNode *m_sinkAudioNode;
+ int m_sinkInputBus;
+
+ AudioChannelLayout *m_sourceChannelLayout;
+ UInt32 m_sourceChannelLayoutSize;
+
+ AudioChannelLayout *m_sinkChannelLayout;
+ UInt32 m_sinkChannelLayoutSize;
+
+ AudioStreamBasicDescription m_sourceStreamDescription;
+ AudioStreamBasicDescription m_sinkStreamDescription;
+
+ bool m_hasSourceSpecification;
+ bool m_hasSinkSpecification;
+ bool m_connected;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AudioConnection_H
diff --git a/src/3rdparty/phonon/qt7/audioconnection.mm b/src/3rdparty/phonon/qt7/audioconnection.mm
new file mode 100644
index 0000000..39b8b30
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audioconnection.mm
@@ -0,0 +1,152 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audioconnection.h"
+#include "medianode.h"
+#include "audionode.h"
+#include "audiograph.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+ AudioConnection::AudioConnection()
+ : m_source(0), m_sourceAudioNode(0), m_sourceOutputBus(0),
+ m_sink(0), m_sinkAudioNode(0), m_sinkInputBus(0),
+ m_sourceChannelLayout(0), m_sinkChannelLayout(0),
+ m_hasSourceSpecification(false), m_hasSinkSpecification(false), m_connected(false)
+ {}
+
+ AudioConnection::AudioConnection(MediaNode *source, int output, MediaNode *sink, int input)
+ : m_source(source), m_sourceAudioNode(source->m_audioNode), m_sourceOutputBus(output),
+ m_sink(sink), m_sinkAudioNode(sink->m_audioNode), m_sinkInputBus(input),
+ m_sourceChannelLayout(0), m_sinkChannelLayout(0),
+ m_hasSourceSpecification(false), m_hasSinkSpecification(false), m_connected(false)
+ {}
+
+ AudioConnection::AudioConnection(MediaNode *sink)
+ : m_source(0), m_sourceAudioNode(0), m_sourceOutputBus(0),
+ m_sink(sink), m_sinkAudioNode(sink->m_audioNode), m_sinkInputBus(0),
+ m_sourceChannelLayout(0), m_sinkChannelLayout(0), m_connected(false)
+ {}
+
+ AudioConnection::AudioConnection(AudioNode *source, int output, AudioNode *sink, int input)
+ : m_source(0), m_sourceAudioNode(source), m_sourceOutputBus(output),
+ m_sink(0), m_sinkAudioNode(sink), m_sinkInputBus(input),
+ m_sourceChannelLayout(0), m_sinkChannelLayout(0),
+ m_hasSourceSpecification(false), m_hasSinkSpecification(false), m_connected(false)
+ {}
+
+ AudioConnection::AudioConnection(AudioNode *sink)
+ : m_source(0), m_sourceAudioNode(0), m_sourceOutputBus(0),
+ m_sink(0), m_sinkAudioNode(sink), m_sinkInputBus(0),
+ m_sourceChannelLayout(0), m_sinkChannelLayout(0), m_connected(false)
+ {}
+
+ AudioConnection::~AudioConnection()
+ {
+ freeMemoryAllocations();
+ }
+
+ void AudioConnection::freeMemoryAllocations()
+ {
+ if (m_sinkChannelLayout && m_sourceChannelLayout != m_sinkChannelLayout)
+ free(m_sinkChannelLayout);
+ if (m_sourceChannelLayout)
+ free(m_sourceChannelLayout);
+ m_sinkChannelLayout = 0;
+ m_sourceChannelLayout = 0;
+ }
+
+ bool AudioConnection::updateStreamSpecification()
+ {
+ m_hasSourceSpecification = false;
+ m_hasSinkSpecification = false;
+ freeMemoryAllocations();
+
+ bool updateOk;
+ if (m_sourceAudioNode){
+ updateOk = m_sourceAudioNode->fillInStreamSpecification(this, AudioNode::Source);
+ if (!updateOk)
+ return false;
+ updateOk = m_sourceAudioNode->setStreamSpecification(this, AudioNode::Source);
+ if (!updateOk)
+ return false;
+ }
+ updateOk = m_sinkAudioNode->fillInStreamSpecification(this, AudioNode::Sink);
+ if (!updateOk)
+ return false;
+ updateOk = m_sinkAudioNode->setStreamSpecification(this, AudioNode::Sink);
+ if (!updateOk)
+ return false;
+ return true;
+ }
+
+ bool AudioConnection::connect(AudioGraph *graph)
+ {
+ if (m_connected || !m_sourceAudioNode)
+ return true;
+
+ DEBUG_AUDIO_GRAPH("Connection" << int(this) << "connect"
+ << int(m_sourceAudioNode) << m_sourceOutputBus << "->"
+ << int(m_sinkAudioNode) << m_sinkInputBus)
+
+ AUNode sourceOut = m_sourceAudioNode->getOutputAUNode();
+ AUNode sinkIn = m_sinkAudioNode->getInputAUNode();
+ OSStatus err = AUGraphConnectNodeInput(graph->audioGraphRef(), sourceOut, m_sourceOutputBus, sinkIn, m_sinkInputBus);
+ m_connected = (err == noErr) ? true : false;
+ return m_connected;
+ }
+
+ bool AudioConnection::disconnect(AudioGraph *graph)
+ {
+ if (!m_connected || !m_sourceAudioNode)
+ return true;
+
+ DEBUG_AUDIO_GRAPH("Connection" << int(this) << "disconnect"
+ << int(m_sourceAudioNode) << m_sourceOutputBus << "->"
+ << int(m_sinkAudioNode) << m_sinkInputBus)
+
+ AUNode sinkIn = m_sinkAudioNode->getInputAUNode();
+ AUGraphDisconnectNodeInput(graph->audioGraphRef(), sinkIn, m_sinkInputBus);
+ m_connected = false;
+ return true;
+ }
+
+ void AudioConnection::invalidate()
+ {
+ m_connected = false;
+ }
+
+ bool AudioConnection::isBetween(MediaNode *source, MediaNode *sink){
+ return (source == m_source) && (sink == m_sink);
+ }
+
+ bool AudioConnection::isValid(){
+ return (m_sourceAudioNode != 0);
+ }
+
+ bool AudioConnection::isSinkOnly(){
+ return (m_sourceAudioNode == 0) && (m_sinkAudioNode != 0);
+ }
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/audiodevice.h b/src/3rdparty/phonon/qt7/audiodevice.h
new file mode 100644
index 0000000..36e937e
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiodevice.h
@@ -0,0 +1,52 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIODEVICE_H
+#define Phonon_QT7_AUDIODEVICE_H
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioDevice
+ {
+ public:
+ enum Scope {In, Out};
+
+ static QList<AudioDeviceID> devices(Scope scope);
+ static AudioDeviceID defaultDevice(Scope scope);
+ static AudioDeviceID defaultSystemDevice(Scope scope);
+ static AudioDeviceID currentDevice(AudioUnit unit, Scope scope);
+ static bool setDevice(AudioUnit unit, AudioDeviceID deviceID, Scope scope);
+ static QString deviceName(AudioDeviceID deviceId);
+ static QString deviceSourceName(AudioDeviceID deviceID);
+ static QString deviceSourceNameElseDeviceName(AudioDeviceID deviceID);
+ static QString deviceNameElseDeviceSourceName(AudioDeviceID deviceID);
+ static QString deviceUID(AudioDeviceID deviceID);
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIODEVICE_H
diff --git a/src/3rdparty/phonon/qt7/audiodevice.mm b/src/3rdparty/phonon/qt7/audiodevice.mm
new file mode 100644
index 0000000..3aae0ee
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiodevice.mm
@@ -0,0 +1,176 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiodevice.h"
+#include "audiograph.h"
+#include <QtCore/QVector>
+#include "backendheader.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+QList<AudioDeviceID> AudioDevice::devices(Scope scope)
+{
+ QList<AudioDeviceID> devices;
+
+ // Insert the default device explicit
+ if (AudioDeviceID defdev = defaultDevice(scope))
+ devices << defdev;
+
+ // How many input/output devices are awailable:
+ UInt32 deviceCount = 0;
+ OSStatus err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &deviceCount, 0);
+ BACKEND_ASSERT3(err == noErr, "Could not get number of audio devices awailable.", FATAL_ERROR, devices)
+
+ // Get list of all devices:
+ AudioDeviceID deviceArray[deviceCount];
+ err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &deviceCount, &deviceArray);
+ BACKEND_ASSERT3(err == noErr, "Could not get audio devices list.", FATAL_ERROR, devices)
+
+ for (uint i=0; i<deviceCount; i++){
+ if (!devices.contains(deviceArray[i])){
+ // Check if the current device is input or output:
+ UInt32 size;
+ err = AudioDeviceGetPropertyInfo(deviceArray[i], 0, scope == In, kAudioDevicePropertyStreams, &size, 0);
+ if (err == noErr && size > 0)
+ devices << deviceArray[i];
+ }
+ }
+ return devices;
+}
+
+AudioDeviceID AudioDevice::defaultSystemDevice(Scope scope)
+{
+ ARGUMENT_UNSUPPORTED(scope, In, NORMAL_ERROR, 0)
+ AudioDeviceID deviceID = 0;
+ UInt32 size = sizeof(deviceID);
+ OSStatus err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultSystemOutputDevice, &size, &deviceID);
+ BACKEND_ASSERT3(err == noErr, "Could not get default system audio device.", FATAL_ERROR, 0)
+ return deviceID;
+}
+
+AudioDeviceID AudioDevice::defaultDevice(Scope scope)
+{
+ ARGUMENT_UNSUPPORTED(scope, In, NORMAL_ERROR, 0)
+ AudioDeviceID deviceID = 0;
+ UInt32 size = sizeof(deviceID);
+ OSStatus err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &deviceID);
+ BACKEND_ASSERT3(err == noErr, "Could not get default output audio device.", FATAL_ERROR, 0)
+ return deviceID;
+}
+
+AudioDeviceID AudioDevice::currentDevice(AudioUnit /*unit*/, Scope /*scope*/)
+{
+ return 0;
+#if 0
+
+kAudioDevicePropertyDeviceUID
+
+ if (!m_audioUnit)
+ return 0;
+ AudioDeviceID deviceID = 0;
+ UInt32 size = sizeof(deviceID);
+ OSStatus err = AudioUnitGetProperty(m_audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &size, &deviceID);
+ BACKEND_ASSERT3(err == noErr, "Could not get current audio device.", FATAL_ERROR, 0)
+ return deviceID;
+#endif
+}
+
+bool AudioDevice::setDevice(AudioUnit unit, AudioDeviceID deviceID, Scope scope)
+{
+ ARGUMENT_UNSUPPORTED(scope, In, NORMAL_ERROR, false)
+ UInt32 size = sizeof(deviceID);
+ OSStatus err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceID, size);
+ if (err != noErr)
+ return false;
+ return true;
+}
+
+QString AudioDevice::deviceSourceNameElseDeviceName(AudioDeviceID deviceID)
+{
+ QString name = deviceSourceName(deviceID);
+ if (name.isEmpty())
+ name = deviceName(deviceID);
+ return name;
+}
+
+QString AudioDevice::deviceNameElseDeviceSourceName(AudioDeviceID deviceID)
+{
+ QString name = deviceName(deviceID);
+ if (name.isEmpty())
+ name = deviceSourceName(deviceID);
+ return name;
+}
+
+QString AudioDevice::deviceName(AudioDeviceID deviceID)
+{
+ if (!deviceID)
+ return QString();
+ CFStringRef cfString = 0;
+ UInt32 size = sizeof(cfString);
+ OSStatus err = AudioDeviceGetProperty(deviceID, 0, 0, kAudioDevicePropertyDeviceNameCFString, &size, &cfString);
+ if (err != noErr)
+ return QString();
+ QString name = PhononCFString::toQString(cfString);
+ CFRelease(cfString);
+ return name;
+}
+
+QString AudioDevice::deviceSourceName(AudioDeviceID deviceID)
+{
+ if (!deviceID)
+ return QString();
+ UInt32 dataSource = 0;
+ UInt32 size = sizeof(dataSource);
+ OSStatus err = AudioDeviceGetProperty(deviceID, 0, 0, kAudioDevicePropertyDataSource, &size, &dataSource);
+ if (err != noErr)
+ return QString();
+
+ CFStringRef cfName = 0;
+ AudioValueTranslation translation = {&dataSource, sizeof(dataSource), &cfName, sizeof(cfName)};
+ size = sizeof(translation);
+ err = AudioDeviceGetProperty(deviceID, 0, 0, kAudioDevicePropertyDataSourceNameForIDCFString, &size, &translation);
+ if (err != noErr){
+ return QString();
+ }
+ QString name = PhononCFString::toQString(cfName);
+ CFRelease(cfName);
+ return name;
+}
+
+QString AudioDevice::deviceUID(AudioDeviceID deviceID)
+{
+ if (!deviceID)
+ return QString();
+
+ CFStringRef cfString = 0;
+ UInt32 size = sizeof(cfString);
+ OSStatus err = AudioDeviceGetProperty(deviceID, 0, 0, kAudioDevicePropertyDeviceUID, &size, &cfString);
+ if (err != noErr)
+ return QString();
+ QString uid = PhononCFString::toQString(cfString);
+ CFRelease(cfString);
+ return uid;
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/audioeffects.h b/src/3rdparty/phonon/qt7/audioeffects.h
new file mode 100644
index 0000000..33fff1c
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audioeffects.h
@@ -0,0 +1,80 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOEFFECTS_H
+#define Phonon_QT7_AUDIOEFFECTS_H
+
+#include <QtCore/QVariant>
+#include <QtCore/QHash>
+#include <phonon/effectinterface.h>
+#include <phonon/effectparameter.h>
+#include "medianode.h"
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioEffectAudioNode : public AudioNode
+ {
+ public:
+ AudioEffectAudioNode(int effectType);
+ int m_effectType;
+
+ ComponentDescription getAudioNodeDescription() const;
+ void initializeAudioUnit();
+
+ QVariant parameterValue(const Phonon::EffectParameter &value) const;
+ void setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue);
+
+ private:
+ QHash<int, float> m_alteredParameters;
+ };
+
+///////////////////////////////////////////////////////////////////////
+
+ class AudioEffect : public MediaNode, Phonon::EffectInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::EffectInterface)
+
+ public:
+ AudioEffect(int effectType, QObject *parent = 0);
+ AudioEffectAudioNode *m_audioNode;
+
+ QString name();
+ QString description();
+
+ // EffectInterface:
+ virtual QList<Phonon::EffectParameter> parameters() const;
+ virtual QVariant parameterValue(const Phonon::EffectParameter &parameter) const;
+ virtual void setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue);
+
+ static QList<int> effectList();
+
+ private:
+ Phonon::EffectParameter createParameter(const AudioUnit &audioUnit, const AudioUnitParameterID &id) const;
+ };
+
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIOEFFECTS_H
diff --git a/src/3rdparty/phonon/qt7/audioeffects.mm b/src/3rdparty/phonon/qt7/audioeffects.mm
new file mode 100644
index 0000000..b0ec3cc
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audioeffects.mm
@@ -0,0 +1,254 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audioeffects.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioEffectAudioNode::AudioEffectAudioNode(int effectType)
+ : AudioNode(1, 1), m_effectType(effectType)
+{
+}
+
+ComponentDescription AudioEffectAudioNode::getAudioNodeDescription() const
+{
+ ComponentDescription d;
+ d.componentType = kAudioUnitType_Effect;
+ d.componentSubType = m_effectType;
+ d.componentManufacturer = kAudioUnitManufacturer_Apple;
+ d.componentFlags = 0;
+ d.componentFlagsMask = 0;
+ return d;
+}
+
+void AudioEffectAudioNode::initializeAudioUnit()
+{
+ if (!m_audioUnit)
+ return;
+ foreach(int id, m_alteredParameters.keys()){
+ Float32 value = m_alteredParameters.value(id);
+ ComponentResult res = AudioUnitSetParameter(m_audioUnit, id, kAudioUnitScope_Global, 0, value, 0);
+ BACKEND_ASSERT2(res == noErr, "Could not initialize audio effect.", NORMAL_ERROR)
+ }
+}
+
+QVariant AudioEffectAudioNode::parameterValue(const Phonon::EffectParameter &parameter) const
+{
+ if (m_audioUnit){
+ Float32 value = 0;
+ AudioUnitGetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, &value);
+ return QVariant(value);
+ } else if (m_alteredParameters.contains(parameter.id())){
+ return QVariant(m_alteredParameters.value(parameter.id()));
+ } else {
+ // Use default value:
+ AudioUnit tmpAudioUnit;
+ ComponentDescription description = getAudioNodeDescription();
+ Component component = FindNextComponent(0, &description);
+ BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant())
+ OSErr err = OpenAComponent(component, &tmpAudioUnit);
+ BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant())
+ AudioUnitParameterInfo info;
+ UInt32 size = sizeof(info);
+ ComponentResult res = AudioUnitGetProperty(tmpAudioUnit,
+ kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size);
+ BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, QVariant())
+ return QVariant(info.defaultValue);
+ }
+}
+
+void AudioEffectAudioNode::setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue)
+{
+ Float32 value = 0;
+ if (newValue.isValid()){
+ value = newValue.toDouble();
+ m_alteredParameters.insert(parameter.id(), value);
+ } else {
+ // Use default value:
+ m_alteredParameters.remove(parameter.id());
+ if (m_audioUnit){
+ AudioUnit tmpAudioUnit;
+ ComponentDescription description = getAudioNodeDescription();
+ Component component = FindNextComponent(0, &description);
+ BACKEND_ASSERT2(component, "Could not get parameters of audio effect.", NORMAL_ERROR)
+ OSErr err = OpenAComponent(component, &tmpAudioUnit);
+ BACKEND_ASSERT2(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR)
+ AudioUnitParameterInfo info;
+ UInt32 size = sizeof(info);
+ ComponentResult res = AudioUnitGetProperty(tmpAudioUnit,
+ kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size);
+ BACKEND_ASSERT2(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR)
+ value = info.defaultValue;
+ }
+ }
+
+ if (m_audioUnit){
+ ComponentResult res = AudioUnitSetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, value, 0);
+ BACKEND_ASSERT2(res == noErr, "Could not set effect parameter value.", NORMAL_ERROR)
+ }
+}
+
+///////////////////////////////////////////////////////////////////////
+
+AudioEffect::AudioEffect(int effectType, QObject *parent)
+ : MediaNode(AudioSink | AudioSource, 0, parent)
+{
+ m_audioNode = new AudioEffectAudioNode(effectType);
+ setAudioNode(m_audioNode);
+}
+
+QList<Phonon::EffectParameter> AudioEffect::parameters() const
+{
+ QList<Phonon::EffectParameter> effectList;
+ // Create a temporary audio unit:
+ AudioUnit audioUnit;
+ ComponentDescription description = m_audioNode->getAudioNodeDescription();
+ Component component = FindNextComponent(0, &description);
+ BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList)
+ OSErr err = OpenAComponent(component, &audioUnit);
+ BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList)
+
+ UInt32 size = 0;
+ // Get parameter count:
+ ComponentResult res = AudioUnitGetProperty(audioUnit,
+ kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, 0, &size);
+ BACKEND_ASSERT3(res == noErr, "Could not get parameter count from audio effect.", NORMAL_ERROR, effectList)
+ int paramCount = size / sizeof(AudioUnitParameterID);
+
+ // Get parameters:
+ AudioUnitParameterID parameters[paramCount];
+ res = AudioUnitGetProperty(audioUnit,
+ kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, &parameters, &size);
+ BACKEND_ASSERT3(res == noErr, "Could not get parameter list from audio effect.", NORMAL_ERROR, effectList)
+
+ for (int i=0; i<paramCount; ++i)
+ effectList << createParameter(audioUnit, parameters[i]);
+
+ CloseComponent(audioUnit);
+ return effectList;
+}
+
+QString AudioEffect::name()
+{
+ ComponentDescription description = m_audioNode->getAudioNodeDescription();
+ Component component = FindNextComponent(0, &description);
+ BACKEND_ASSERT3(component, "Could not get audio effect name.", NORMAL_ERROR, QLatin1String("<unknown effect>"))
+
+ ComponentDescription cDesc;
+ Handle nameH = NewHandle(0);
+ GetComponentInfo(component, &cDesc, nameH, 0, 0);
+ HLock(nameH);
+ char *namePtr = *nameH;
+ int len = *namePtr++;
+ namePtr[len] = 0;
+ QString qsName = QString::fromUtf8(namePtr);
+ DisposeHandle(nameH);
+ return qsName;
+}
+
+QString AudioEffect::description()
+{
+ ComponentDescription description = m_audioNode->getAudioNodeDescription();
+ Component component = FindNextComponent(0, &description);
+ BACKEND_ASSERT3(component, "Could not get audio effect description.", NORMAL_ERROR, QLatin1String("<unknown effect>"))
+
+ ComponentDescription cDesc;
+ Handle descH = NewHandle(0);
+ GetComponentInfo(component, &cDesc, 0, descH, 0);
+ HLock(descH);
+ char *descPtr = *descH;
+ int len = *descPtr++;
+ descPtr[len] = 0;
+ QString qsDesc = QString::fromUtf8(descPtr);
+ DisposeHandle(descH);
+ return qsDesc;
+}
+
+QList<int> AudioEffect::effectList()
+{
+ QList<int> effects;
+
+ ComponentDescription d;
+ d.componentType = kAudioUnitType_Effect;
+ d.componentSubType = 0;
+ d.componentManufacturer = 0;
+ d.componentFlags = 0;
+ d.componentFlagsMask = 0;
+ Component component = FindNextComponent(0, &d);
+
+ while (component) {
+ ComponentDescription cDesc;
+ GetComponentInfo(component, &cDesc, 0, 0, 0);
+ effects << cDesc.componentSubType;
+ component = FindNextComponent(component, &d);
+ }
+ return effects;
+}
+
+Phonon::EffectParameter AudioEffect::createParameter(const AudioUnit &audioUnit, const AudioUnitParameterID &id) const
+{
+ AudioUnitParameterInfo info;
+ UInt32 size = sizeof(info);
+ ComponentResult res = AudioUnitGetProperty(audioUnit,
+ kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, id, &info, &size);
+ BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, Phonon::EffectParameter())
+
+ QString name = info.flags & kAudioUnitParameterFlag_HasCFNameString
+ ? PhononCFString::toQString(info.cfNameString) : QLatin1String("<unknown parameter>");
+
+ Phonon::EffectParameter::Hint hint;
+ switch(info.unit){
+ case (kAudioUnitParameterUnit_Indexed):
+ case (kAudioUnitParameterUnit_Seconds):
+ case (kAudioUnitParameterUnit_SampleFrames):
+ case (kAudioUnitParameterUnit_Milliseconds):
+ hint = Phonon::EffectParameter::IntegerHint;
+ break;
+ case (kAudioUnitParameterUnit_Boolean):
+ hint = Phonon::EffectParameter::ToggledHint;
+ break;
+ default:
+ hint = Phonon::EffectParameter::LogarithmicHint;
+ break;
+ }
+
+ QVariant def(info.defaultValue);
+ QVariant min(info.minValue);
+ QVariant max(info.maxValue);
+ return Phonon::EffectParameter(id, name, hint, def, min, max, QVariantList(), name);
+}
+
+QVariant AudioEffect::parameterValue(const Phonon::EffectParameter &value) const
+{
+ return m_audioNode->parameterValue(value);
+}
+
+void AudioEffect::setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue)
+{
+ m_audioNode->setParameterValue(parameter, newValue);
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_audioeffects.cpp"
diff --git a/src/3rdparty/phonon/qt7/audiograph.h b/src/3rdparty/phonon/qt7/audiograph.h
new file mode 100644
index 0000000..76bc21a
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiograph.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOGRAPH_H
+#define Phonon_QT7_AUDIOGRAPH_H
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+
+#include <QtCore/qnamespace.h>
+#include "audioconnection.h"
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioGraph : public MediaNode
+ {
+ public:
+ AudioGraph(MediaNode *root);
+ virtual ~AudioGraph();
+ AUGraph audioGraphRef();
+ void startAllOverFromScratch();
+
+ bool openAndInit();
+ void start();
+ void tryStartGraph();
+ void stop();
+ void prepare();
+ void rebuildGraph();
+ void update();
+ bool isRunning();
+ void setPaused(bool pause);
+ bool graphCannotPlay();
+ void rebuildGraphIfNeeded();
+ void updateStreamSpecifications();
+ void setStatusCannotPlay();
+ MediaNode *root();
+ void notify(const MediaNodeEvent *event, bool propagate = true);
+
+ private:
+ friend class MediaNode;
+ friend class AudioNode;
+
+ void deleteGraph();
+ bool updateStreamSpecificationRecursive(AudioConnection *connection);
+ void createAndConnectAuNodesRecursive(AudioConnection *connection);
+ bool createAudioUnitsRecursive(AudioConnection *connection);
+
+ void connectLate(AudioConnection *connection);
+ void disconnectLate(AudioConnection *connection);
+
+ int nodeCount();
+
+ bool m_initialized;
+ bool m_startedLogically;
+ bool m_rebuildLater;
+ bool m_graphCannotPlay;
+ bool m_paused;
+
+ AUGraph m_audioGraphRef;
+ MediaNode *m_root;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIOGRAPH_H
diff --git a/src/3rdparty/phonon/qt7/audiograph.mm b/src/3rdparty/phonon/qt7/audiograph.mm
new file mode 100644
index 0000000..0d096e3
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiograph.mm
@@ -0,0 +1,320 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiograph.h"
+#include "quicktimeaudioplayer.h"
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioGraph::AudioGraph(MediaNode *root) : MediaNode(AudioGraphNode, 0, root), m_root(root)
+{
+ m_audioGraphRef = 0;
+ m_initialized = false;
+ m_startedLogically = false;
+ m_graphCannotPlay = false;
+ m_paused = false;
+}
+
+AudioGraph::~AudioGraph()
+{
+ deleteGraph();
+}
+
+void AudioGraph::startAllOverFromScratch()
+{
+ MediaNodeEvent event(MediaNodeEvent::AudioGraphAboutToBeDeleted, this);
+ m_root->notify(&event);
+ deleteGraph();
+}
+
+void AudioGraph::deleteGraph()
+{
+ if (m_audioGraphRef){
+ AUGraphStop(m_audioGraphRef);
+ AUGraphUninitialize(m_audioGraphRef);
+ AUGraphClose(m_audioGraphRef);
+ DisposeAUGraph(m_audioGraphRef);
+ m_initialized = false;
+ m_graphCannotPlay = false;
+ DEBUG_AUDIO_GRAPH("Graph ref in" << int(this) << "is deleted")
+ }
+}
+
+MediaNode *AudioGraph::root()
+{
+ return m_root;
+}
+
+AUGraph AudioGraph::audioGraphRef()
+{
+ return m_audioGraphRef;
+}
+
+void AudioGraph::setStatusCannotPlay()
+{
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "received 'cannot play' request")
+ if (!m_graphCannotPlay){
+ stop();
+ m_graphCannotPlay = true;
+ MediaNodeEvent e(MediaNodeEvent::AudioGraphCannotPlay, this);
+ m_root->notify(&e);
+ }
+}
+
+void AudioGraph::rebuildGraph()
+{
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "is rebuilding")
+ startAllOverFromScratch();
+ if (!openAndInit()){
+ setStatusCannotPlay();
+ } else {
+ tryStartGraph();
+ m_graphCannotPlay = false;
+ }
+}
+
+bool AudioGraph::graphCannotPlay()
+{
+ return m_graphCannotPlay;
+}
+
+void AudioGraph::updateStreamSpecifications()
+{
+ if (!m_initialized){
+ if (m_graphCannotPlay)
+ rebuildGraph();
+ return;
+ }
+
+ AudioConnection rootConnection(m_root);
+ bool updateOk = updateStreamSpecificationRecursive(&rootConnection);
+ if (!updateOk){
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "could not update stream specification. Rebuild.")
+ rebuildGraph();
+ }
+}
+
+bool AudioGraph::updateStreamSpecificationRecursive(AudioConnection *connection)
+{
+ bool updateOk = connection->updateStreamSpecification();
+ if (!updateOk)
+ return false;
+
+ for (int i=0; i<connection->m_sink->m_audioSinkList.size(); ++i){
+ if (!updateStreamSpecificationRecursive(connection->m_sink->m_audioSinkList[i]))
+ return false;
+ }
+ return true;
+}
+
+bool AudioGraph::openAndInit()
+{
+ OSStatus err;
+ err = NewAUGraph(&m_audioGraphRef);
+ BACKEND_ASSERT3(err == noErr, "Could not create audio graph.", NORMAL_ERROR, false)
+
+ MediaNodeEvent eventNew(MediaNodeEvent::NewAudioGraph, this);
+ m_root->notify(&eventNew);
+
+ AudioConnection rootConnection(m_root);
+ createAndConnectAuNodesRecursive(&rootConnection);
+ err = AUGraphOpen(m_audioGraphRef);
+ BACKEND_ASSERT3(err == noErr, "Could not create audio graph.", NORMAL_ERROR, false)
+
+ if (!createAudioUnitsRecursive(&rootConnection))
+ return false;
+
+ err = AUGraphInitialize(m_audioGraphRef);
+ BACKEND_ASSERT3(err == noErr, "Could not initialize audio graph.", NORMAL_ERROR, false)
+
+ m_initialized = true;
+ MediaNodeEvent eventInit(MediaNodeEvent::AudioGraphInitialized, this);
+ m_root->notify(&eventInit);
+ return true;
+}
+
+void AudioGraph::createAndConnectAuNodesRecursive(AudioConnection *connection)
+{
+ connection->m_sink->m_audioNode->createAndConnectAUNodes();
+ for (int i=0; i<connection->m_sink->m_audioSinkList.size(); ++i){
+ AudioConnection *c = connection->m_sink->m_audioSinkList[i];
+ createAndConnectAuNodesRecursive(c);
+ bool ok = c->connect(this);
+ BACKEND_ASSERT2(ok, "Could not connect an audio nodes pair in the audio graph.", NORMAL_ERROR)
+ }
+}
+
+bool AudioGraph::createAudioUnitsRecursive(AudioConnection *connection)
+{
+ connection->m_sink->m_audioNode->createAudioUnits();
+ bool ok = connection->updateStreamSpecification();
+ if (!ok)
+ return false;
+ for (int i=0; i<connection->m_sink->m_audioSinkList.size(); ++i){
+ if (!createAudioUnitsRecursive(connection->m_sink->m_audioSinkList[i]))
+ return false;
+ }
+ return true;
+}
+
+void AudioGraph::tryStartGraph()
+{
+ // The graph will only start if the background AUGraph
+ // is valid. Therefore we just try. If it fails, user
+ // actions like connect etc. migh make the graph valid
+ // at a later point.
+ if (m_startedLogically && !isRunning()){
+ OSStatus err = AUGraphStart(m_audioGraphRef);
+ if (err == noErr)
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "started")
+ else
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "could not start")
+ }
+}
+
+bool AudioGraph::isRunning()
+{
+ Boolean running = false;
+ AUGraphIsRunning(m_audioGraphRef, &running);
+ return running;
+}
+
+void AudioGraph::setPaused(bool pause)
+{
+ // This function should only make
+ // a difference if the graph is
+ // running before pausing.
+ if (pause){
+ if (isRunning()){
+ stop();
+ m_paused = true;
+ }
+ } else if (m_paused){
+ start();
+ m_paused = false;
+ }
+}
+
+void AudioGraph::connectLate(AudioConnection *connection)
+{
+ MediaNodeEvent event(MediaNodeEvent::NewAudioGraph, this);
+ connection->m_sink->notify(&event);
+
+ if (!m_initialized)
+ return;
+
+ DEBUG_AUDIO_GRAPH("Graph:" << int(this) << "create and connect audio sink after init:" << int(connection->m_sink->m_audioNode))
+ AudioConnection startConnection(connection->m_source);
+ createAndConnectAuNodesRecursive(&startConnection);
+
+ if (!createAudioUnitsRecursive(&startConnection)){
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "could not update stream specification. Rebuild.")
+ rebuildGraph();
+ }
+}
+
+void AudioGraph::disconnectLate(AudioConnection *connection)
+{
+ if (!m_initialized)
+ return;
+
+ DEBUG_AUDIO_GRAPH("Graph:" << int(this) << "disconnect audio sink after init:" << int(connection->m_sink->m_audioNode))
+
+ if (!connection->disconnect(this)){
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "could not disconnect audio sink. Rebuild.")
+ rebuildGraph();
+ }
+}
+
+void AudioGraph::update()
+{
+ if (m_startedLogically){
+ if (m_initialized){
+ // Quick solution:
+ AUGraphUpdate(m_audioGraphRef, 0);
+ tryStartGraph();
+ } else
+ rebuildGraph();
+ }
+}
+
+int AudioGraph::nodeCount()
+{
+ if (!m_audioGraphRef)
+ return 0;
+ UInt32 count;
+ AUGraphGetNodeCount(m_audioGraphRef, &count);
+ return int(count);
+}
+
+void AudioGraph::prepare()
+{
+ if (!m_initialized)
+ rebuildGraph();
+}
+
+void AudioGraph::start()
+{
+ // Start does not mean 'start to play
+ // music'. It means 'prepare to receive
+ // audio from the player units'.
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "asked to start (cannot play:" << m_graphCannotPlay << ")")
+ m_startedLogically = true;
+
+ if (m_graphCannotPlay)
+ return;
+
+ if (!m_initialized)
+ rebuildGraph();
+
+ if (!m_graphCannotPlay)
+ tryStartGraph();
+}
+
+void AudioGraph::stop()
+{
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "asked to stop")
+ if (m_audioGraphRef)
+ AUGraphStop(m_audioGraphRef);
+ m_startedLogically = false;
+}
+
+void AudioGraph::notify(const MediaNodeEvent *event, bool propagate)
+{
+ switch (event->type()){
+ case MediaNodeEvent::StartConnectionChange:
+ if (m_graphCannotPlay)
+ startAllOverFromScratch();
+ break;
+ case MediaNodeEvent::EndConnectionChange:
+ update();
+ break;
+ default:
+ break;
+ }
+ m_root->notify(event, propagate);
+}
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/audiomixer.h b/src/3rdparty/phonon/qt7/audiomixer.h
new file mode 100644
index 0000000..275d7df
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiomixer.h
@@ -0,0 +1,91 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOMIXER_H
+#define Phonon_QT7_AUDIOMIXER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QTime>
+#include <QtCore/QEvent>
+#include <phonon/effectinterface.h>
+#include <phonon/effectparameter.h>
+#include <phonon/volumefaderinterface.h>
+#include "medianode.h"
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioMixerAudioNode : public AudioNode
+ {
+ public:
+ AudioMixerAudioNode();
+ void setVolume(float volume, int bus = 0);
+ float volume(int bus = 0);
+
+ protected:
+ ComponentDescription getAudioNodeDescription() const;
+ void initializeAudioUnit();
+
+ private:
+ friend class AudioMixer;
+ int m_numberOfBusses;
+ float m_volume;
+ };
+
+ class AudioMixer : public MediaNode, Phonon::EffectInterface, Phonon::VolumeFaderInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::EffectInterface Phonon::VolumeFaderInterface)
+
+ public:
+ AudioMixer(QObject *parent = 0);
+ ~AudioMixer();
+ AudioMixerAudioNode *m_audioNode;
+ Phonon::VolumeFaderEffect::FadeCurve m_fadeCurve;
+
+ int m_fadeTimer;
+ int m_fadeDuration;
+ float m_fadeToVolume;
+ float m_fadeFromVolume;
+ QTime m_fadeStartTime;
+
+ // EffectInterface:
+ QList<Phonon::EffectParameter> parameters() const;
+ QVariant parameterValue(const Phonon::EffectParameter &parameter) const;
+ void setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue);
+
+ // VolumeFaderInterface:
+ float volume() const;
+ void setVolume(float volume);
+ Phonon::VolumeFaderEffect::FadeCurve fadeCurve() const;
+ void setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve fadeCurve);
+ void fadeTo(float volume, int fadeTime);
+ void updateFade();
+
+ protected:
+ bool event(QEvent *event);
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIOMIXER_H
diff --git a/src/3rdparty/phonon/qt7/audiomixer.mm b/src/3rdparty/phonon/qt7/audiomixer.mm
new file mode 100644
index 0000000..30b1e6f
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiomixer.mm
@@ -0,0 +1,181 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiomixer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioMixerAudioNode::AudioMixerAudioNode() : AudioNode(30, 1)
+{
+ m_numberOfBusses = 2;
+ m_volume = 1.0f;
+}
+
+ComponentDescription AudioMixerAudioNode::getAudioNodeDescription() const
+{
+ ComponentDescription description;
+ description.componentType = kAudioUnitType_Mixer;
+ description.componentSubType = kAudioUnitSubType_StereoMixer;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+ return description;
+}
+
+void AudioMixerAudioNode::initializeAudioUnit()
+{
+ // Set bus count:
+ OSStatus err = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_BusCount, kAudioUnitScope_Input, 0, &m_numberOfBusses, sizeof(int));
+ BACKEND_ASSERT2(err == noErr, "Could not set number of busses on audio mixer node.", FATAL_ERROR)
+}
+
+void AudioMixerAudioNode::setVolume(float volume, int bus)
+{
+ if (volume < 0)
+ m_volume = 0;
+ else if (volume > 1)
+ m_volume = 1;
+ else
+ m_volume = volume;
+
+ if (m_audioUnit){
+// Float32 db = Float32(volume);//Float32(20.0 * log10(volume)); // convert to db
+ Float32 db = Float32(volume);
+ OSStatus err = AudioUnitSetParameter(m_audioUnit, kStereoMixerParam_Volume, kAudioUnitScope_Input, bus, db, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not set volume on audio mixer node.", NORMAL_ERROR)
+ }
+}
+
+float AudioMixerAudioNode::volume(int bus)
+{
+ if (!m_audioUnit)
+ return 0;
+
+ Float32 db;
+ OSStatus err = AudioUnitGetParameter(m_audioUnit, kStereoMixerParam_Volume, kAudioUnitScope_Input, bus, &db);
+ BACKEND_ASSERT3(err == noErr, "Could not get volume on audio mixer node.", NORMAL_ERROR, 0)
+ return float(db);
+}
+
+///////////////////////////////////////////////////////////////////////
+
+AudioMixer::AudioMixer(QObject *parent) : MediaNode(AudioSink | AudioSource, 0, parent)
+{
+ m_audioNode = new AudioMixerAudioNode();
+ setAudioNode(m_audioNode);
+ m_fadeCurve = Phonon::VolumeFaderEffect::Fade3Decibel;
+ m_fadeTimer = 0;
+ m_fadeDuration = 0;
+ m_fadeFromVolume = 0;
+ m_fadeToVolume = 0;
+}
+
+AudioMixer::~AudioMixer()
+{
+ if (m_fadeTimer)
+ killTimer(m_fadeTimer);
+}
+
+QList<Phonon::EffectParameter> AudioMixer::parameters() const
+{
+ QList<Phonon::EffectParameter> ret;
+ return ret;
+}
+
+QVariant AudioMixer::parameterValue(const Phonon::EffectParameter &value) const
+{
+ NOT_IMPLEMENTED;
+ Q_UNUSED(value);
+ return QVariant();
+}
+
+void AudioMixer::setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue)
+{
+ NOT_IMPLEMENTED;
+ Q_UNUSED(parameter);
+ Q_UNUSED(newValue);
+}
+
+float AudioMixer::volume() const
+{
+ return m_audioNode->volume(0);
+}
+
+void AudioMixer::setVolume(float volume)
+{
+ m_audioNode->setVolume(volume, 0);
+}
+
+Phonon::VolumeFaderEffect::FadeCurve AudioMixer::fadeCurve() const
+{
+ return m_fadeCurve;
+}
+
+void AudioMixer::setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve fadeCurve)
+{
+ m_fadeCurve = fadeCurve;
+}
+
+void AudioMixer::fadeTo(float volume, int fadeTime)
+{
+ m_fadeToVolume = volume;
+ m_fadeDuration = fadeTime;
+ m_fadeFromVolume = m_audioNode->volume(0);
+
+ m_fadeStartTime.start();
+ if (m_fadeTimer)
+ killTimer(m_fadeTimer);
+ m_fadeTimer = startTimer(100);
+}
+
+void AudioMixer::updateFade()
+{
+ float step = float(m_fadeStartTime.elapsed()) / float(m_fadeDuration);
+ if (step > 1){
+ step = 1;
+ if (m_fadeTimer)
+ killTimer(m_fadeTimer);
+ }
+ float volume = m_fadeFromVolume + ((m_fadeToVolume - m_fadeFromVolume) * step);
+ m_audioNode->setVolume(volume, 0);
+}
+
+bool AudioMixer::event(QEvent *event)
+{
+ switch (event->type()){
+ case QEvent::Timer:{
+ QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);
+ if (timerEvent->timerId() == m_fadeTimer)
+ updateFade();
+ break; }
+ default:
+ break;
+ }
+ return MediaNode::event(event);
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_audiomixer.cpp"
diff --git a/src/3rdparty/phonon/qt7/audionode.h b/src/3rdparty/phonon/qt7/audionode.h
new file mode 100644
index 0000000..dfec817
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audionode.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AudioNode_H
+#define Phonon_QT7_AudioNode_H
+
+#include <QtCore/QObject>
+#include "backendheader.h"
+#include "audioconnection.h"
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioGraph;
+ class MediaNodeEvent;
+ class MediaNode;
+
+ class MediaNodeConnection{
+ MediaNode *source;
+ MediaNode *sink;
+ int inputPort;
+ int outputPort;
+ };
+
+ class AudioNode
+ {
+ public:
+ enum ConnectionSide {Source, Sink};
+
+ AudioNode(int maxInput, int maxOutput);
+ virtual ~AudioNode();
+
+ virtual void createAndConnectAUNodes();
+ virtual void createAudioUnits();
+ virtual void setGraph(AudioGraph *audioGraph);
+ virtual AUNode getInputAUNode();
+ virtual AUNode getOutputAUNode();
+ virtual bool fillInStreamSpecification(AudioConnection *connection, ConnectionSide side);
+ virtual bool setStreamSpecification(AudioConnection *connection, ConnectionSide side);
+ void notify(const MediaNodeEvent *event);
+
+ virtual void mediaNodeEvent(const MediaNodeEvent *event);
+ Float64 getTimeInSamples(int timeProperty);
+
+ AudioGraph *m_audioGraph;
+ AudioConnection *m_lastConnectionIn;
+
+ int m_maxInputBusses;
+ int m_maxOutputBusses;
+
+ protected:
+ AUNode m_auNode;
+ AudioUnit m_audioUnit;
+
+ // Only the following methods needs to
+ // be overridden by only_one-audio-unit nodes:
+ virtual ComponentDescription getAudioNodeDescription() const;
+ virtual void initializeAudioUnit();
+
+ private:
+ bool setStreamHelp(AudioConnection *c, int bus, OSType scope, bool fromSource);
+ };
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AudioNode_H
diff --git a/src/3rdparty/phonon/qt7/audionode.mm b/src/3rdparty/phonon/qt7/audionode.mm
new file mode 100644
index 0000000..77cd627
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audionode.mm
@@ -0,0 +1,243 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audionode.h"
+#include "audiograph.h"
+#include "audioconnection.h"
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioNode::AudioNode(int maxInputBusses, int maxOutputBusses)
+{
+ m_auNode = 0;
+ m_audioUnit = 0;
+ m_audioGraph = 0;
+ m_maxInputBusses = maxInputBusses;
+ m_maxOutputBusses = maxOutputBusses;
+ m_lastConnectionIn = 0;
+}
+
+AudioNode::~AudioNode()
+{
+ setGraph(0);
+}
+
+void AudioNode::setGraph(AudioGraph *audioGraph)
+{
+ if (m_audioGraph == audioGraph)
+ return;
+
+ DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "is setting graph:" << int(audioGraph))
+ if (m_auNode){
+ AUGraphRemoveNode(m_audioGraph->audioGraphRef(), m_auNode);
+ m_auNode = 0;
+ }
+
+ m_audioUnit = 0;
+ m_lastConnectionIn = 0;
+ m_audioGraph = audioGraph;
+}
+
+void AudioNode::createAndConnectAUNodes()
+{
+ if (m_auNode)
+ return;
+
+ ComponentDescription description = getAudioNodeDescription();
+ DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "creates AUNode"
+ << QString(!FindNextComponent(0, &description) ? "ERROR: COMPONENT NOT FOUND!" : "OK!"))
+
+ OSStatus err = noErr;
+
+ // The proper function to call here is AUGraphAddNode() but the type has
+ // changed between 10.5 and 10.6. it's still OK to call this function, but
+ // if we want to use the proper thing we need to move over to
+ // AudioComponentDescription everywhere, which is very similar to the
+ // ComponentDescription, but a different size. however,
+ // AudioComponentDescription only exists on 10.6+. More fun than we need to
+ // deal with at the moment, so we'll take the "deprecated" warning instead.
+ err = AUGraphNewNode(m_audioGraph->audioGraphRef(), &description, 0, 0, &m_auNode);
+
+ BACKEND_ASSERT2(err != kAUGraphErr_OutputNodeErr, "A MediaObject can only be connected to one audio output device.", FATAL_ERROR)
+ BACKEND_ASSERT2(err == noErr, "Could not create new AUNode.", FATAL_ERROR)
+}
+
+AUNode AudioNode::getInputAUNode()
+{
+ return m_auNode;
+}
+
+AUNode AudioNode::getOutputAUNode()
+{
+ return m_auNode;
+}
+
+void AudioNode::createAudioUnits()
+{
+ if (m_audioUnit)
+ return;
+
+ DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "creates AudioUnit")
+ OSStatus err = AUGraphGetNodeInfo(m_audioGraph->audioGraphRef(), m_auNode, 0, 0, 0, &m_audioUnit);
+ BACKEND_ASSERT2(err == noErr, "Could not get audio unit from audio node.", FATAL_ERROR)
+ initializeAudioUnit();
+}
+
+ComponentDescription AudioNode::getAudioNodeDescription() const
+{
+ // Override if needed.
+ ComponentDescription cd;
+ Q_UNUSED(cd);
+ return cd;
+}
+
+bool AudioNode::setStreamHelp(AudioConnection *c, int bus, OSType scope, bool fromSource)
+{
+ if (fromSource){
+ OSStatus err = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope,
+ bus, &c->m_sourceStreamDescription, sizeof(AudioStreamBasicDescription));
+ if (err != noErr){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " - failed setting stream format")
+ return false;
+ }
+ AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_AudioChannelLayout, scope,
+ bus, c->m_sourceChannelLayout, c->m_sourceChannelLayoutSize);
+ } else {
+ OSStatus err = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope,
+ bus, &c->m_sinkStreamDescription, sizeof(AudioStreamBasicDescription));
+ if (err != noErr){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " - failed setting stream format")
+ return false;
+ }
+ AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_AudioChannelLayout, scope,
+ bus, c->m_sinkChannelLayout, c->m_sourceChannelLayoutSize);
+ }
+ return true;
+}
+
+bool AudioNode::setStreamSpecification(AudioConnection *connection, ConnectionSide side)
+{
+ if (side == Source){
+ // This object am source of connection:
+ if (connection->m_hasSourceSpecification){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification out"
+ << connection->m_sourceOutputBus << "from connection source")
+ return setStreamHelp(connection, connection->m_sourceOutputBus, kAudioUnitScope_Output, true);
+ } else {
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "did not set stream specification out")
+ }
+ } else {
+ if (connection->m_hasSinkSpecification){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification"
+ << connection->m_sinkInputBus << "from connection sink")
+ return setStreamHelp(connection, connection->m_sinkInputBus, kAudioUnitScope_Input, false);
+ } else if (connection->m_hasSourceSpecification){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification"
+ << connection->m_sinkInputBus << "from connection source")
+ return setStreamHelp(connection, connection->m_sinkInputBus, kAudioUnitScope_Input, true);
+ } else {
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "did not set stream specification in")
+ }
+ }
+ return true;
+}
+
+bool AudioNode::fillInStreamSpecification(AudioConnection *connection, ConnectionSide side)
+{
+ if (side == Source){
+ // As default, use the last description to describe the source:
+ if (m_lastConnectionIn->m_hasSinkSpecification){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is source, and fills in stream spec using last connection sink.")
+ connection->m_sourceStreamDescription = m_lastConnectionIn->m_sinkStreamDescription;
+ connection->m_sourceChannelLayout = (AudioChannelLayout *) malloc(m_lastConnectionIn->m_sinkChannelLayoutSize);
+ memcpy(connection->m_sourceChannelLayout, m_lastConnectionIn->m_sinkChannelLayout, m_lastConnectionIn->m_sinkChannelLayoutSize);
+ connection->m_sourceChannelLayoutSize = m_lastConnectionIn->m_sinkChannelLayoutSize;
+ connection->m_hasSourceSpecification = true;
+ } else if (m_lastConnectionIn->m_hasSourceSpecification){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is source, and fills in stream spec using last connection source.")
+ connection->m_sourceStreamDescription = m_lastConnectionIn->m_sourceStreamDescription;
+ connection->m_sourceChannelLayout = (AudioChannelLayout *) malloc(m_lastConnectionIn->m_sourceChannelLayoutSize);
+ memcpy(connection->m_sourceChannelLayout, m_lastConnectionIn->m_sourceChannelLayout, m_lastConnectionIn->m_sourceChannelLayoutSize);
+ connection->m_sourceChannelLayoutSize = m_lastConnectionIn->m_sourceChannelLayoutSize;
+ connection->m_hasSourceSpecification = true;
+ } else {
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " __WARNING__: could not get stream specification...")
+ }
+ } else {
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is sink, skips filling in stream.")
+ if (!connection->isSinkOnly())
+ m_lastConnectionIn = connection;
+ }
+ return true;
+}
+
+/**
+ Let timeProperty be one of e.g
+ {kAudioUnitProperty_Latency, kAudioUnitProperty_TailTime,
+ kAudioOutputUnitProperty_StartTime, kAudioUnitProperty_CurrentPlayTime}
+*/
+Float64 AudioNode::getTimeInSamples(int timeProperty)
+{
+ if (!m_audioUnit)
+ return 0;
+
+ AudioTimeStamp timeStamp;
+ UInt32 size = sizeof(timeStamp);
+ memset(&timeStamp, 0, sizeof(timeStamp));
+ OSStatus err = AudioUnitGetProperty(m_audioUnit,
+ timeProperty, kAudioUnitScope_Global,
+ 0, &timeStamp, &size);
+ if (err != noErr)
+ return 0;
+ return timeStamp.mSampleTime;
+}
+
+void AudioNode::notify(const MediaNodeEvent *event)
+{
+ switch(event->type()){
+ case MediaNodeEvent::AudioGraphAboutToBeDeleted:
+ setGraph(0);
+ break;
+ case MediaNodeEvent::NewAudioGraph:
+ setGraph(static_cast<AudioGraph *>(event->data()));
+ break;
+ default:
+ break;
+ }
+
+ mediaNodeEvent(event);
+}
+
+void AudioNode::mediaNodeEvent(const MediaNodeEvent */*event*/)
+{
+ // Override if needed
+}
+
+void AudioNode::initializeAudioUnit()
+{
+ // Override if needed.
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/audiooutput.h b/src/3rdparty/phonon/qt7/audiooutput.h
new file mode 100644
index 0000000..c4a0526
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiooutput.h
@@ -0,0 +1,88 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOOUTPUT_H
+#define Phonon_QT7_AUDIOOUTPUT_H
+
+#include <QtCore/QObject>
+#include <phonon/audiooutputinterface.h>
+#include <phonon/abstractaudiooutput.h>
+
+#include "medianode.h"
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioOutputAudioPart : public QObject, AudioNode
+ {
+ Q_OBJECT
+ public:
+ AudioOutputAudioPart();
+
+ void setVolume(float volume);
+ float volume();
+
+ protected:
+ ComponentDescription getAudioNodeDescription() const;
+ void initializeAudioUnit();
+
+ signals:
+ void volumeChanged(qreal newVolume);
+ void audioDeviceFailed();
+
+ private:
+ friend class AudioOutput;
+ qreal m_volume;
+ AudioDeviceID m_audioDevice;
+ void setAudioDevice(AudioDeviceID device);
+ };
+
+ class AudioOutput : public MediaNode, public AudioOutputInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::AudioOutputInterface)
+
+ public:
+ AudioOutput(QObject *parent = 0);
+ ~AudioOutput();
+
+ qreal volume() const;
+ void setVolume(qreal);
+ int outputDevice() const;
+ bool setOutputDevice(int);
+
+ signals:
+ void volumeChanged(qreal newVolume);
+ void audioDeviceFailed();
+
+ protected:
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+ private:
+ AudioOutputAudioPart *m_audioOutput;
+ int m_device;
+ bool m_redirectToMovie;
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_AUDIOOUTPUT_H
diff --git a/src/3rdparty/phonon/qt7/audiooutput.mm b/src/3rdparty/phonon/qt7/audiooutput.mm
new file mode 100644
index 0000000..38066d5
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiooutput.mm
@@ -0,0 +1,168 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiooutput.h"
+#include "audiograph.h"
+#include "audiodevice.h"
+#include "mediaobject.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioOutputAudioPart::AudioOutputAudioPart() : AudioNode(1, 0)
+{
+ m_audioDevice = AudioDevice::defaultDevice(AudioDevice::Out);
+ m_volume = 1;
+}
+
+ComponentDescription AudioOutputAudioPart::getAudioNodeDescription() const
+{
+ ComponentDescription description;
+ description.componentType = kAudioUnitType_Output;
+ description.componentSubType = kAudioUnitSubType_DefaultOutput;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+ return description;
+}
+
+void AudioOutputAudioPart::initializeAudioUnit()
+{
+ setAudioDevice(m_audioDevice);
+ setVolume(m_volume);
+}
+
+void AudioOutputAudioPart::setAudioDevice(AudioDeviceID device)
+{
+ m_audioDevice = device;
+ if (!m_audioDevice)
+ return;
+ if (!m_audioUnit)
+ return;
+ bool ok = AudioDevice::setDevice(m_audioUnit, m_audioDevice, AudioDevice::Out);
+ if (!ok)
+ emit audioDeviceFailed();
+}
+
+void AudioOutputAudioPart::setVolume(float volume)
+{
+ if (volume < 0)
+ m_volume = 0;
+ if (volume > 1)
+ m_volume = 1;
+ else
+ m_volume = volume;
+
+ if (m_audioUnit){
+ float db = volume;//20.0 * log10(volume); // convert to db
+ OSStatus err = AudioUnitSetParameter(m_audioUnit, kHALOutputParam_Volume, kAudioUnitScope_Input, 0, db, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not set volume on output audio unit.", FATAL_ERROR)
+ emit volumeChanged(qreal(db));
+ }
+}
+
+float AudioOutputAudioPart::volume()
+{
+ return m_volume;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+AudioOutput::AudioOutput(QObject *parent) : MediaNode(AudioSink, parent)
+{
+ m_audioOutput = new AudioOutputAudioPart();
+ setAudioNode(m_audioOutput);
+ connect(m_audioOutput, SIGNAL(volumeChanged(qreal)), this, SIGNAL(volumeChanged(qreal)));
+ connect(m_audioOutput, SIGNAL(audioDeviceFailed()), this, SIGNAL(audioDeviceFailed()));
+ m_redirectToMovie = false;
+}
+
+AudioOutput::~AudioOutput()
+{
+}
+
+void AudioOutput::setVolume(qreal volume)
+{
+ IMPLEMENTED;
+ m_audioOutput->setVolume(float(volume));
+ if (m_owningMediaObject)
+ m_owningMediaObject->setVolumeOnMovie(volume);
+
+ emit volumeChanged(m_audioOutput->volume());
+}
+
+qreal AudioOutput::volume() const
+{
+ IMPLEMENTED;
+ return qreal(m_audioOutput->volume());
+}
+
+bool AudioOutput::setOutputDevice(int device)
+{
+ IMPLEMENTED;
+ if (device == -1)
+ return false;
+
+ if (m_owningMediaObject){
+ bool ok = m_owningMediaObject->setAudioDeviceOnMovie(device);
+ if (!ok)
+ return false;
+ }
+
+ if (m_audioGraph){
+ MediaNodeEvent event1(MediaNodeEvent::AboutToRestartAudioStream, this);
+ m_audioGraph->notify(&event1);
+ }
+
+ m_audioOutput->setAudioDevice(device);
+
+ if (m_audioGraph){
+ MediaNodeEvent event2(MediaNodeEvent::RestartAudioStreamRequest, this);
+ m_audioGraph->notify(&event2);
+ }
+ return true;
+}
+
+int AudioOutput::outputDevice() const
+{
+ IMPLEMENTED;
+ return m_audioOutput->m_audioDevice;
+}
+
+void AudioOutput::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()){
+ case MediaNodeEvent::SetMediaObject:
+ if (static_cast<MediaObject *>(event->data())){
+ setVolume(volume());
+ setOutputDevice(outputDevice());
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_audiooutput.cpp"
diff --git a/src/3rdparty/phonon/qt7/audiopartoutput.h b/src/3rdparty/phonon/qt7/audiopartoutput.h
new file mode 100644
index 0000000..0ccdfb6
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiopartoutput.h
@@ -0,0 +1,47 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOPARTOUTPUT_H
+#define Phonon_QT7_AUDIOPARTOUTPUT_H
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+#include "audionode.h"
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioPartOutput : public AudioNode
+ {
+ public:
+ AudioPartOutput();
+ virtual ~AudioPartOutput();
+
+ private:
+ ComponentDescription getAudioNodeDescription() const;
+ void initializeAudioUnit(AudioNode *source);
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIOPARTOUTPUT_H
diff --git a/src/3rdparty/phonon/qt7/audiopartoutput.mm b/src/3rdparty/phonon/qt7/audiopartoutput.mm
new file mode 100644
index 0000000..b985e69
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiopartoutput.mm
@@ -0,0 +1,69 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiopartoutput.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioPartOutput::AudioPartOutput()
+ : AudioNode()
+{
+}
+
+AudioPartOutput::~AudioPartOutput()
+{
+}
+
+ComponentDescription AudioPartOutput::getAudioNodeDescription() const
+{
+ ComponentDescription description;
+ description.componentType = kAudioUnitType_Output;
+ description.componentSubType = kAudioUnitSubType_DefaultOutput;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+ return description;
+}
+
+void AudioPartOutput::initializeAudioUnit(AudioNode *source)
+{
+ m_audioStreamDescription = source->outputStreamDescription();
+ m_audioChannelLayout = source->outputChannelLayout();
+ m_audioChannelLayoutSize = source->outputChannelLayoutSize();
+
+ // Specify the stream format:
+ OSStatus err;
+ err = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
+ 0, m_audioStreamDescription, sizeof(AudioStreamBasicDescription));
+ BACKEND_ASSERT2(err == noErr, "Could not set stream format on audio output unit.", FATAL_ERROR)
+
+ // Set the channel layout:
+ err = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input,
+ 0, m_audioChannelLayout, m_audioChannelLayoutSize);
+ BACKEND_ASSERT2(err == noErr, "Could not set channel layout on audio output unit.", FATAL_ERROR)
+}
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/audiosplitter.h b/src/3rdparty/phonon/qt7/audiosplitter.h
new file mode 100644
index 0000000..ed6101f
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiosplitter.h
@@ -0,0 +1,50 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOSPLITTER_H
+#define Phonon_QT7_AUDIOSPLITTER_H
+
+#include <QtCore/QFile>
+
+#include "medianode.h"
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioNodeSplitter : public AudioNode
+ {
+ public:
+ AudioNodeSplitter();
+ ComponentDescription getAudioNodeDescription() const;
+ };
+
+ class AudioSplitter : public MediaNode
+ {
+ public:
+ AudioSplitter(QObject *parent = 0);
+ ~AudioSplitter();
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIOSPLITTER_H
diff --git a/src/3rdparty/phonon/qt7/audiosplitter.mm b/src/3rdparty/phonon/qt7/audiosplitter.mm
new file mode 100644
index 0000000..685ea12
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiosplitter.mm
@@ -0,0 +1,52 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiosplitter.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioNodeSplitter::AudioNodeSplitter() : AudioNode(1, 2)
+{
+}
+
+ComponentDescription AudioNodeSplitter::getAudioNodeDescription() const
+{
+ ComponentDescription description;
+ description.componentType = kAudioUnitType_FormatConverter;
+ description.componentSubType = kAudioUnitSubType_Splitter;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+ return description;
+}
+
+AudioSplitter::AudioSplitter(QObject *parent) : MediaNode(AudioSink | AudioSource, new AudioNodeSplitter(), parent)
+{
+}
+
+AudioSplitter::~AudioSplitter()
+{
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/backend.h b/src/3rdparty/phonon/qt7/backend.h
new file mode 100644
index 0000000..287fcec
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backend.h
@@ -0,0 +1,61 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_BACKEND_H
+#define Phonon_QT7_BACKEND_H
+
+#include <QtCore/QList>
+#include <QtCore/QPointer>
+#include <QtCore/QStringList>
+#include <phonon/backendinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class Backend : public QObject, public BackendInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::BackendInterface)
+
+ public:
+ Backend();
+ Backend(QObject *parent, const QStringList &args);
+ virtual ~Backend();
+
+ QObject *createObject(BackendInterface::Class, QObject *parent, const QList<QVariant> &args);
+ QStringList availableMimeTypes() const;
+ QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const;
+ QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const;
+
+ bool startConnectionChange(QSet<QObject *> nodes);
+ bool connectNodes(QObject *source, QObject *sink);
+ bool disconnectNodes(QObject *source, QObject *sink);
+ bool endConnectionChange(QSet<QObject *> nodes);
+
+ Q_SIGNALS:
+ void objectDescriptionChanged(ObjectDescriptionType);
+
+ private:
+ bool quickTime7Available();
+ };
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_BACKEND_H
diff --git a/src/3rdparty/phonon/qt7/backend.mm b/src/3rdparty/phonon/qt7/backend.mm
new file mode 100644
index 0000000..b3ca106
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backend.mm
@@ -0,0 +1,276 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backend.h"
+#include <QtCore/QDebug>
+#include <QtCore/QSet>
+#include <QtCore/QVariant>
+#include <QtCore/QtPlugin>
+
+#include "backendheader.h"
+
+#include "videowidget.h"
+#include "audiooutput.h"
+#include "mediaobject.h"
+#include "videoeffect.h"
+#include "medianode.h"
+#include "audiodevice.h"
+#include "audiomixer.h"
+#include "backendinfo.h"
+#include "quicktimeaudioplayer.h"
+
+#include "audiograph.h"
+#include "audiomixer.h"
+#include "audiooutput.h"
+#include "audiosplitter.h"
+#include "audioeffects.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+Backend::Backend()
+{
+ IMPLEMENTED << "Creating backend QT7";
+}
+
+Backend::Backend(QObject *parent, const QStringList &) : QObject(parent)
+{
+ IMPLEMENTED << "Creating backend QT7";
+ setProperty("identifier", QLatin1String("Mac OS X/QuickTime7"));
+ setProperty("backendName", QLatin1String("Mac OS X/QuickTime7"));
+ setProperty("backendComment", QLatin1String("Developed by Trolltech"));
+ setProperty("backendVersion", QLatin1String("0.1"));
+ setProperty("backendIcon", QLatin1String(""));
+ setProperty("backendWebsite", QLatin1String("http://qt.nokia.com/"));
+}
+
+Backend::~Backend()
+{
+}
+
+bool Backend::quickTime7Available()
+{
+ static bool ok = BackendInfo::isQuickTimeVersionAvailable(0x0700);
+ if (!ok){
+ static bool messageWritten = false;
+ if (!messageWritten && qgetenv("PHONON_DEBUG") == "1"){
+ messageWritten = true;
+ QString str("WARNING: Phonon backend plugin need QuickTime 7 or newer to work.");
+ str += " This computer has version "
+ + BackendInfo::quickTimeVersionString()
+ + " installed.";
+ qWarning(str.toAscii().data());
+ }
+ return false;
+ }
+ return true;
+}
+
+QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
+{
+ if (!quickTime7Available())
+ return 0;
+
+ switch (c) {
+ case MediaObjectClass:
+ IMPLEMENTED << "Creating new MediaObjectClass.";
+ return new MediaObject(parent);
+ break;
+ case VolumeFaderEffectClass:
+ IMPLEMENTED << "Creating new VolumeFaderEffectClass.";
+ return new AudioMixer(parent);
+ break;
+ case AudioOutputClass:
+ IMPLEMENTED << "Creating new AudioOutputClass.";
+ return new AudioOutput(parent);
+ break;
+ case AudioDataOutputClass:
+ NOT_IMPLEMENTED << "Creating new AudioDataOutputClass.";
+ break;
+ case VisualizationClass:
+ NOT_IMPLEMENTED << "Creating new VisualizationClass.";
+ break;
+ case VideoDataOutputClass:
+ NOT_IMPLEMENTED << "Creating new VideoDataOutputClass.";
+ break;
+ case EffectClass:
+ IMPLEMENTED << "Creating new EffectClass.";
+ return new AudioEffect(args[0].toInt());
+ break;
+ case VideoWidgetClass:
+ IMPLEMENTED << "Creating new VideoWidget.";
+ return new VideoWidget(parent);
+ break;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+bool Backend::startConnectionChange(QSet<QObject *> objects)
+{
+ IMPLEMENTED;
+ QList<AudioGraph *> notifiedGraphs;
+ for (int i=0; i<objects.size(); i++){
+ MediaNode *node = qobject_cast<MediaNode*>(objects.values()[i]);
+ if (node && node->m_audioGraph && !notifiedGraphs.contains(node->m_audioGraph)){
+ MediaNodeEvent event(MediaNodeEvent::StartConnectionChange);
+ node->m_audioGraph->notify(&event);
+ notifiedGraphs << node->m_audioGraph;
+ }
+ }
+ return true;
+}
+
+bool Backend::endConnectionChange(QSet<QObject *> objects)
+{
+ IMPLEMENTED;
+ QList<AudioGraph *> notifiedGraphs;
+ for (int i=0; i<objects.size(); i++){
+ MediaNode *node = qobject_cast<MediaNode*>(objects.values()[i]);
+ if (node && node->m_audioGraph && !notifiedGraphs.contains(node->m_audioGraph)){
+ MediaNodeEvent event(MediaNodeEvent::EndConnectionChange);
+ node->m_audioGraph->notify(&event);
+ notifiedGraphs << node->m_audioGraph;
+ }
+ }
+ return true;
+}
+
+bool Backend::connectNodes(QObject *aSource, QObject *aSink)
+{
+ IMPLEMENTED;
+ MediaNode *source = qobject_cast<MediaNode*>(aSource);
+ if (!source) return false;
+ MediaNode *sink = qobject_cast<MediaNode*>(aSink);
+ if (!sink) return false;
+
+ return source->connectToSink(sink);
+}
+
+
+bool Backend::disconnectNodes(QObject *aSource, QObject *aSink)
+{
+ IMPLEMENTED;
+ MediaNode *source = qobject_cast<MediaNode*>(aSource);
+ if (!source) return false;
+ MediaNode *sink = qobject_cast<MediaNode*>(aSink);
+ if (!sink) return false;
+
+ return source->disconnectToSink(sink);
+}
+
+
+QStringList Backend::availableMimeTypes() const
+{
+ IMPLEMENTED;
+ return BackendInfo::quickTimeMimeTypes(BackendInfo::In);
+}
+
+/**
+* Returns a set of indexes that acts as identifiers for the various properties
+* this backend supports for the given ObjectDescriptionType.
+* More information for a given property/index can be
+* looked up in Backend::objectDescriptionProperties(...).
+*/
+QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
+{
+ QList<int> ret;
+
+ switch (type){
+ case AudioOutputDeviceType:{
+ IMPLEMENTED_SILENT << "Creating index set for type: AudioOutputDeviceType";
+ QList<AudioDeviceID> devices = AudioDevice::devices(AudioDevice::Out);
+ for (int i=0; i<devices.size(); i++)
+ ret << int(devices[i]);
+ break; }
+ case EffectType:{
+ IMPLEMENTED_SILENT << "Creating index set for type: EffectType";
+ if (QuickTimeAudioPlayer::soundPlayerIsAwailable())
+ ret = AudioEffect::effectList();
+ break; }
+
+#if 0 // will be awailable in a later version of phonon.
+ case AudioCaptureDeviceType:{
+ IMPLEMENTED_SILENT << "Creating index set for type: AudioCaptureDeviceType";
+ QList<AudioDeviceID> devices = AudioDevice::devices(AudioDevice::In).keys();
+ for (int i=0; i<devices.size(); i++)
+ ret <<int(devices[i]);
+ break; }
+ case VideoEffectType:{
+ // Just count the number of filters awailable (c), and
+ // add return a set with the numbers 1..c inserted:
+ IMPLEMENTED_SILENT << "Creating index set for type: VideoEffectType";
+ QList<QtCore/QString> filters = objc_getCiFilterInfo()->filterDisplayNames;
+ for (int i=0; i<filters.size(); i++)
+ ret << insert(i);
+ break; }
+#endif
+ default:
+ NOT_IMPLEMENTED;
+ break;
+ }
+ return ret;
+}
+
+QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescriptionType type, int index) const
+{
+ QHash<QByteArray, QVariant> ret;
+
+ switch (type){
+ case AudioOutputDeviceType:{
+ IMPLEMENTED_SILENT << "Creating description hash for type: AudioOutputDeviceType";
+ ret.insert("name", AudioDevice::deviceSourceNameElseDeviceName(index));
+ ret.insert("description", AudioDevice::deviceNameElseDeviceSourceName(index));
+ break; }
+ case EffectType:{
+ AudioEffect e(index);
+ ret.insert("name", e.name());
+ ret.insert("description", e.description());
+ break; }
+
+#if 0 // will be awailable in a later version of phonon.
+ case VideoEffectType:{
+ // Get list of effects, pick out filter at index, and return its name:
+ IMPLEMENTED_SILENT << "Creating description hash for type: VideoEffectType";
+ QList<QtCore/QString> filters = objc_getCiFilterInfo()->filterDisplayNames;
+ ret.insert("name", filters[index]);
+ case AudioCaptureDeviceType:{
+ IMPLEMENTED_SILENT << "Creating description hash for type: AudioCaptureDeviceType";
+ QMap<AudioDeviceID, QString> devices = AudioDevice::devices(AudioDevice::In);
+ ret.insert("name", devices.value(index));
+ break; }
+#endif
+ default:
+ NOT_IMPLEMENTED;
+ break;
+ }
+
+ return ret;
+}
+
+Q_EXPORT_PLUGIN2(phonon_qt7, Backend)
+}}
+
+QT_END_NAMESPACE
+
+#include "moc_backend.cpp"
+
diff --git a/src/3rdparty/phonon/qt7/backendheader.h b/src/3rdparty/phonon/qt7/backendheader.h
new file mode 100644
index 0000000..fd0d892
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backendheader.h
@@ -0,0 +1,184 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_BACKENDHEADER_H
+#define Phonon_QT7_BACKENDHEADER_H
+
+#include <QtCore/QString>
+#import <Foundation/NSAutoreleasePool.h>
+#include <CoreFoundation/CFBase.h>
+
+#ifndef Q_WS_MAC64
+#define QUICKTIME_C_API_AVAILABLE
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+// Implemented in error.cpp:
+void gSetErrorString(const QString &errorString);
+QString gGetErrorString();
+void gSetErrorLocation(const QString &errorLocation);
+void gSetErrorType(int type);
+int gGetErrorType();
+void gClearError();
+
+#define NO_ERROR 0
+#define NORMAL_ERROR 1
+#define FATAL_ERROR 2
+
+#define ERROR_LOCATION \
+ QLatin1String("Function: ") + QLatin1String(__FUNCTION__) \
+ + QLatin1String(", File: ") + QLatin1String(__FILE__) \
+ + QLatin1String(", Line: ") + QString::number(__LINE__)
+
+#define SET_ERROR(string, type){ \
+ Phonon::QT7::gSetErrorString(string); \
+ Phonon::QT7::gSetErrorType(type); \
+ Phonon::QT7::gSetErrorLocation(ERROR_LOCATION); }
+
+#define BACKEND_ASSERT(test, string, type) \
+ bool fail = !test; \
+ if (fail) \
+ SET_ERROR(QLatin1String(string), type) \
+ if (fail)
+
+#define BACKEND_ASSERT2(test, string, type) \
+ if (!(test)) { \
+ SET_ERROR(QLatin1String(string), type) \
+ return; \
+ }
+
+#define BACKEND_ASSERT3(test, string, type, ret) \
+ if (!(test)) { \
+ SET_ERROR(QLatin1String(string), type) \
+ return ret; \
+ }
+
+#define ARGUMENT_UNSUPPORTED(a, x, type, ret) \
+ if ((a) == (x)) { \
+ SET_ERROR("Argument value not supported: "#a" == "#x, type); \
+ return ret; \
+ }
+
+#define CASE_UNSUPPORTED(string, type) SET_ERROR(string, type)
+
+#ifdef SET_DEBUG_IMPLEMENTED
+#define IMPLEMENTED qDebug() << "QT7:" << __FUNCTION__ << "(" << __FILE__ << "):"
+#else
+#define IMPLEMENTED if (1); else qDebug()
+#endif
+
+#ifdef SET_DEBUG_HALF_IMPLEMENTED
+#define HALF_IMPLEMENTED qDebug() << "QT7: --- HALF IMPLEMENTED:" << __FUNCTION__ << "(" << __FILE__ << "," << __LINE__ << "):"
+#else
+#define HALF_IMPLEMENTED if (1); else qDebug()
+#endif
+
+#ifdef SET_DEBUG_NOT_IMPLEMENTED
+#define NOT_IMPLEMENTED qDebug() << "QT7: *** NOT IMPLEMENTED:" << __FUNCTION__ << "(" << __FILE__ << "," << __LINE__ << "):"
+#else
+#define NOT_IMPLEMENTED if (1); else qDebug()
+#endif
+
+#ifdef SET_DEBUG_IMPLEMENTED_SILENT
+#define IMPLEMENTED_SILENT qDebug() << "QT7: (silent)" << __FUNCTION__ << "(" << __FILE__ << "," << __LINE__ << "):"
+#else
+#define IMPLEMENTED_SILENT if (1); else qDebug()
+#endif
+
+#ifdef SET_DEBUG_AUDIO_GRAPH
+#define DEBUG_AUDIO_GRAPH(x) qDebug() << "QT7 DEBUG GRAPH:" << x;
+#else
+#define DEBUG_AUDIO_GRAPH(x) {}
+#endif
+
+#ifdef SET_DEBUG_AUDIO_STREAM
+#define DEBUG_AUDIO_STREAM(x) qDebug() << "QT7 DEBUG STREAM:" << x;
+#else
+#define DEBUG_AUDIO_STREAM(x) {}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class PhononAutoReleasePool
+{
+private:
+ void *pool;
+public:
+ PhononAutoReleasePool();
+ ~PhononAutoReleasePool();
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+class PhononCFType
+{
+public:
+ inline PhononCFType(const T &t = 0) : type(t) {}
+ inline PhononCFType(const PhononCFType &helper) : type(helper.type) { if (type) CFRetain(type); }
+ inline ~PhononCFType() { if (type) CFRelease(type); }
+ inline operator T() { return type; }
+ inline PhononCFType operator =(const PhononCFType &helper)
+ {
+ if (helper.type)
+ CFRetain(helper.type);
+ CFTypeRef type2 = type;
+ type = helper.type;
+ if (type2)
+ CFRelease(type2);
+ return *this;
+ }
+ inline T *operator&() { return &type; }
+ static PhononCFType constructFromGet(const T &t)
+ {
+ CFRetain(t);
+ return PhononCFType<T>(t);
+ }
+protected:
+ T type;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class PhononCFString : public PhononCFType<CFStringRef>
+{
+public:
+ inline PhononCFString(const QString &str) : PhononCFType<CFStringRef>(0), string(str) {}
+ inline PhononCFString(const CFStringRef cfstr = 0) : PhononCFType<CFStringRef>(cfstr) {}
+ inline PhononCFString(const PhononCFType<CFStringRef> &other) : PhononCFType<CFStringRef>(other) {}
+ operator QString() const;
+ operator CFStringRef() const;
+ static QString toQString(CFStringRef cfstr);
+ static CFStringRef toCFStringRef(const QString &str);
+private:
+ QString string;
+};
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#ifdef Q_CC_INTEL
+#pragma warning (disable : 1899) // mute icc warning for the use of 4cc
+#endif
+
+#endif // Phonon_QT7_BACKENDHEADER_H
diff --git a/src/3rdparty/phonon/qt7/backendheader.mm b/src/3rdparty/phonon/qt7/backendheader.mm
new file mode 100644
index 0000000..3a73389
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backendheader.mm
@@ -0,0 +1,127 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backendheader.h"
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <QVarLengthArray>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+Q_GLOBAL_STATIC(QString, gErrorString)
+int gErrorType = NO_ERROR;
+
+void gSetErrorString(const QString &errorString)
+{
+ if (qgetenv("PHONON_DEBUG") == "1"){
+ qDebug() << "Error:" << errorString;
+ }
+
+ if (!gErrorString()->isEmpty())
+ return; // not yet caught.
+
+ *gErrorString() = errorString;
+}
+
+QString gGetErrorString()
+{
+ return *gErrorString();
+}
+
+void gSetErrorLocation(const QString &errorLocation)
+{
+ if (qgetenv("PHONON_DEBUG") == "1"){
+ qDebug() << "Location:" << errorLocation;
+ }
+}
+
+void gSetErrorType(int errorType)
+{
+ if (gErrorType != NO_ERROR)
+ return; // not yet caught.
+ gErrorType = errorType;
+}
+
+int gGetErrorType()
+{
+ return gErrorType;
+}
+
+void gClearError()
+{
+ gErrorString()->clear();
+ gErrorType = NO_ERROR;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+PhononAutoReleasePool::PhononAutoReleasePool()
+{
+ pool = (void*)[[NSAutoreleasePool alloc] init];
+}
+
+PhononAutoReleasePool::~PhononAutoReleasePool()
+{
+ [(NSAutoreleasePool*)pool release];
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+QString PhononCFString::toQString(CFStringRef str)
+{
+ if(!str)
+ return QString();
+ CFIndex length = CFStringGetLength(str);
+ const UniChar *chars = CFStringGetCharactersPtr(str);
+ if (chars)
+ return QString(reinterpret_cast<const QChar *>(chars), length);
+
+ QVarLengthArray<UniChar> buffer(length);
+ CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data());
+ return QString(reinterpret_cast<const QChar *>(buffer.constData()), length);
+}
+
+PhononCFString::operator QString() const
+{
+ if (string.isEmpty() && type)
+ const_cast<PhononCFString*>(this)->string = toQString(type);
+ return string;
+}
+
+CFStringRef PhononCFString::toCFStringRef(const QString &string)
+{
+ return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
+ string.length());
+}
+
+PhononCFString::operator CFStringRef() const
+{
+ if (!type)
+ const_cast<PhononCFString*>(this)->type = toCFStringRef(string);
+ return type;
+}
+
+}}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/backendinfo.h b/src/3rdparty/phonon/qt7/backendinfo.h
new file mode 100644
index 0000000..c30cda3
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backendinfo.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_BACKENDINFO_H
+#define Phonon_QT7_BACKENDINFO_H
+
+#include <phonon/mediasource.h>
+#include <Carbon/Carbon.h>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class BackendInfo
+ {
+ public:
+ enum Scope {In, Out};
+
+ static QString quickTimeVersionString();
+ static bool isQuickTimeVersionAvailable(int minHexVersion);
+ static QStringList quickTimeMimeTypes(Scope scope);
+ static QStringList quickTimeCompressionFormats();
+ static QStringList coreAudioCodecs(Scope scope);
+ static QStringList coreAudioFileTypes(Scope scope);
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_BACKENDINFO_H
diff --git a/src/3rdparty/phonon/qt7/backendinfo.mm b/src/3rdparty/phonon/qt7/backendinfo.mm
new file mode 100644
index 0000000..d84e014
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backendinfo.mm
@@ -0,0 +1,311 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#import <QTKit/QTMovie.h>
+#ifdef QUICKTIME_C_API_AVAILABLE
+ #include <QuickTime/QuickTime.h>
+ #undef check // avoid name clash;
+#endif
+
+#include "backendinfo.h"
+#include "backendheader.h"
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+#include <CoreServices/CoreServices.h>
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+QString BackendInfo::quickTimeVersionString()
+{
+ SInt32 version;
+ OSStatus err = Gestalt(gestaltQuickTimeVersion, &version);
+ if (err != noErr)
+ return QString("00.0.0.0000");
+ QString versionString = QString("%1%2.%3.%4.%5%6%7%8")
+ .arg((version >> (7*4)) & 0xF)
+ .arg((version >> (6*4)) & 0xF)
+ .arg((version >> (5*4)) & 0xF)
+ .arg((version >> (4*4)) & 0xF)
+ .arg((version >> (3*4)) & 0xF)
+ .arg((version >> (2*4)) & 0xF)
+ .arg((version >> (1*4)) & 0xF)
+ .arg((version >> (0*4)) & 0xF);
+ return versionString;
+}
+
+bool BackendInfo::isQuickTimeVersionAvailable(int minHexVersion)
+{
+ // minHexVersion == 0x0741 means version 7.4.1
+ SInt32 qtHexVersion;
+ OSStatus err = Gestalt(gestaltQuickTimeVersion, &qtHexVersion);
+ return (err == noErr) ? ((qtHexVersion >> 16) >= minHexVersion) : 0;
+}
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+static QString getMimeTypeTag(QTAtomContainer mimeList, int index, OSType type)
+{
+ QTAtom mimeAtom = QTFindChildByIndex(mimeList, kParentAtomIsContainer, type, index, 0);
+ char mimeCharArray[256];
+ long length;
+ OSStatus err = QTCopyAtomDataToPtr(mimeList, mimeAtom, true, sizeof(mimeCharArray)-1, mimeCharArray, &length);
+ if (err == noErr)
+ return QString::fromAscii(mimeCharArray, length);
+ return QString();
+}
+#endif // QUICKTIME_C_API_AVAILABLE
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+QStringList BackendInfo::quickTimeMimeTypes(Scope scope)
+{
+ QStringList mimeTypes;
+ ARGUMENT_UNSUPPORTED(scope, Out, NORMAL_ERROR, mimeTypes)
+
+ ComponentDescription description;
+ description.componentType = MovieImportType;
+ description.componentSubType = 0;
+ description.componentManufacturer = 0;
+ description.componentFlags = hasMovieImportMIMEList | canMovieImportFiles;
+ description.componentFlagsMask = canMovieImportFiles | movieImportSubTypeIsFileExtension | hasMovieImportMIMEList;
+ Component component = FindNextComponent(0, &description);
+
+ while (component) {
+ QTAtomContainer mimeList = 0;
+ OSStatus err = MovieImportGetMIMETypeList((MovieImportComponent)component, &mimeList);
+ if (err == noErr){
+ int count = QTCountChildrenOfType(mimeList, kParentAtomIsContainer, 0);
+ for (int i=1; i<=count; ++i){
+ QString mimeType = getMimeTypeTag(mimeList, i, kMimeInfoMimeTypeTag);
+ if (mimeType.startsWith(QLatin1String("audio")) || mimeType.startsWith(QLatin1String("video"))){
+ if (err == noErr && !mimeType.isEmpty())
+ mimeTypes << mimeType;
+ }
+ }
+ }
+ QTDisposeAtomContainer(mimeList);
+ component = FindNextComponent(component, &description);
+ }
+ mimeTypes.sort();
+ return mimeTypes;
+}
+
+#else // QUICKTIME_C_API_AVAILABLE == false
+
+QString mimeForExtensionAudio(const QString &ext)
+{
+ if (ext == "3g2") return QLatin1String("audio/3g2");
+ if (ext == "3gp") return QLatin1String("audio/3gp");
+ if (ext == "aac") return QLatin1String("audio/aac");
+ if (ext == "ac3") return QLatin1String("audio/ac3");
+ if (ext == "aif") return QLatin1String("audio/aif");
+ if (ext == "aifc") return QLatin1String("audio/aifc");
+ if (ext == "aiff") return QLatin1String("audio/aiff");
+ if (ext == "amr") return QLatin1String("audio/amr");
+ if (ext == "au") return QLatin1String("audio/au");
+ if (ext == "bwf") return QLatin1String("audio/bwf");
+ if (ext == "caf") return QLatin1String("audio/caf");
+ if (ext == "cdda") return QLatin1String("audio/cdda");
+ if (ext == "gsm") return QLatin1String("audio/gsm");
+ if (ext == "kar") return QLatin1String("audio/kar");
+ if (ext == "m1a") return QLatin1String("audio/m1a");
+ if (ext == "m1s") return QLatin1String("audio/m1s");
+ if (ext == "m3u") return QLatin1String("audio/m3u");
+ if (ext == "m3url") return QLatin1String("audio/m3url");
+ if (ext == "mid") return QLatin1String("audio/mid");
+ if (ext == "midi") return QLatin1String("audio/midi");
+ if (ext == "mka") return QLatin1String("audio/mka");
+ if (ext == "mp3") return QLatin1String("audio/mp3");
+ if (ext == "mp4") return QLatin1String("audio/mp4");
+ if (ext == "mpa") return QLatin1String("audio/mpa");
+ if (ext == "mpeg") return QLatin1String("audio/mpeg");
+ if (ext == "mpg") return QLatin1String("audio/mpg");
+ if (ext == "mpg4") return QLatin1String("audio/mpg4");
+ if (ext == "mpm") return QLatin1String("audio/mpm");
+ if (ext == "qcp") return QLatin1String("audio/qcp");
+ if (ext == "sd2") return QLatin1String("audio/sd2");
+ if (ext == "smf") return QLatin1String("audio/smf");
+ if (ext == "snd") return QLatin1String("audio/snd");
+ if (ext == "ulw") return QLatin1String("audio/ulw");
+ if (ext == "wav") return QLatin1String("audio/wav");
+ if (ext == "wax") return QLatin1String("audio/wax");
+ if (ext == "wma") return QLatin1String("audio/wma");
+ return QString();
+}
+
+QString mimeForExtensionVideo(const QString &ext)
+{
+ if (ext == "3g2") return QLatin1String("video/3g2");
+ if (ext == "3gp") return QLatin1String("video/3gp");
+ if (ext == "asf") return QLatin1String("video/asf");
+ if (ext == "asx") return QLatin1String("video/asx");
+ if (ext == "avi") return QLatin1String("video/avi");
+ if (ext == "dif") return QLatin1String("video/dif");
+ if (ext == "dv") return QLatin1String("video/dv");
+ if (ext == "flc") return QLatin1String("video/flc");
+ if (ext == "fli") return QLatin1String("video/fli");
+ if (ext == "m15") return QLatin1String("video/m15");
+ if (ext == "m1a") return QLatin1String("video/m1a");
+ if (ext == "m1s") return QLatin1String("video/m1s");
+ if (ext == "m1v") return QLatin1String("video/m1v");
+ if (ext == "m75") return QLatin1String("video/m75");
+ if (ext == "mkv") return QLatin1String("video/mkv");
+ if (ext == "mp4") return QLatin1String("video/mp4");
+ if (ext == "mpa") return QLatin1String("video/mpa");
+ if (ext == "mpeg") return QLatin1String("video/mpeg");
+ if (ext == "mpg") return QLatin1String("video/mpg");
+ if (ext == "mpg4") return QLatin1String("video/mpg4");
+ if (ext == "mpm") return QLatin1String("video/mpm");
+ if (ext == "mpv") return QLatin1String("video/mpv");
+ if (ext == "vfw") return QLatin1String("video/vfw");
+ if (ext == "wm") return QLatin1String("video/wm");
+ if (ext == "wmv") return QLatin1String("video/wmv");
+ if (ext == "wmx") return QLatin1String("video/wmx");
+ if (ext == "wvx") return QLatin1String("video/wvx");
+ return QString();
+}
+
+QStringList BackendInfo::quickTimeMimeTypes(Scope scope)
+{
+ QStringList mimeTypes;
+ QStringList fileExtensions;
+ ARGUMENT_UNSUPPORTED(scope, Out, NORMAL_ERROR, mimeTypes)
+
+ PhononAutoReleasePool pool;
+ NSArray *fileTypes = [QTMovie movieFileTypes:QTIncludeAllTypes];
+ for (NSString *type in fileTypes){
+ QString formattedType = QString::fromUtf8([type UTF8String]);
+ formattedType = formattedType.remove('\'').remove('.').toLower();
+ QString audioMime = mimeForExtensionAudio(formattedType);
+ QString videoMime = mimeForExtensionVideo(formattedType);
+ if (!audioMime.isEmpty())
+ mimeTypes << audioMime;
+ if (!videoMime.isEmpty())
+ mimeTypes << videoMime;
+ if (audioMime.isEmpty() && videoMime.isEmpty())
+ fileExtensions << QLatin1String("application/x-qt-") + formattedType;
+ }
+ mimeTypes.sort();
+ fileExtensions.sort();
+ return mimeTypes + fileExtensions;
+}
+#endif // QUICKTIME_C_API_AVAILABLE
+
+QStringList BackendInfo::quickTimeCompressionFormats()
+{
+ QStringList result;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+ ComponentInstance component = 0;
+ OSStatus err = OpenADefaultComponent(StandardCompressionType, StandardCompressionSubTypeAudio, &component);
+ BACKEND_ASSERT3(err == noErr, "Could not open component for retrieving awailable compression formats", NORMAL_ERROR, result)
+
+ UInt32 size;
+ err = QTGetComponentPropertyInfo(component, kQTPropertyClass_SCAudio, kQTSCAudioPropertyID_AvailableCompressionFormatNamesList, 0, &size,0);
+ BACKEND_ASSERT3(err == noErr, "Could not get awailable compression formats", NORMAL_ERROR, result)
+
+ CFArrayRef formats[size];
+ err = QTGetComponentProperty(component, kQTPropertyClass_SCAudio, kQTSCAudioPropertyID_AvailableCompressionFormatNamesList, size, &formats, &size);
+ BACKEND_ASSERT3(err == noErr, "Could not get awailable compression formats", NORMAL_ERROR, result)
+
+ CFIndex count = CFArrayGetCount(*formats);
+ for (CFIndex i=0; i<count; ++i){
+ const CFStringRef name = (const struct __CFString *) CFArrayGetValueAtIndex(*formats, i);
+ result << PhononCFString::toQString(name);
+ }
+
+#endif // QUICKTIME_C_API_AVAILABLE
+ return result;
+}
+
+
+QStringList BackendInfo::coreAudioCodecs(Scope scope)
+{
+ QStringList result;
+ UInt32 size;
+ OSStatus err;
+ OSType *formatIDs;
+
+ OSType encodersOrDecoders = (scope == In)
+ ? kAudioFormatProperty_EncodeFormatIDs : kAudioFormatProperty_DecodeFormatIDs;
+
+ err = AudioFormatGetPropertyInfo(encodersOrDecoders, 0, NULL, &size);
+ BACKEND_ASSERT3(err == noErr, "Could not get awailable decoders/encoders", NORMAL_ERROR, result)
+
+ formatIDs = (OSType*)malloc(size);
+ UInt32 numFormats = size / sizeof(OSType);
+ err = AudioFormatGetProperty(encodersOrDecoders, 0, NULL, &size, formatIDs);
+ BACKEND_ASSERT(err == noErr, "Could not get awailable decoders/encoders", NORMAL_ERROR){
+ free(formatIDs);
+ return result;
+ }
+
+ for (UInt32 i=0; i<numFormats; ++i){
+ AudioStreamBasicDescription absd;
+ memset(&absd, 0, sizeof(absd));
+ absd.mFormatID = formatIDs[i];
+
+ CFStringRef name;
+ size = sizeof(CFStringRef);
+ err = AudioFormatGetProperty(kAudioFormatProperty_FormatName, sizeof(absd), &absd, &size, &name);
+ BACKEND_ASSERT(err == noErr, "Could not get awailable decoder/encoder names", NORMAL_ERROR){
+ free(formatIDs);
+ return result;
+ }
+ result << PhononCFString::toQString(name);
+ }
+ free(formatIDs);
+ return result;
+}
+
+QStringList BackendInfo::coreAudioFileTypes(Scope scope)
+{
+ QStringList result;
+ OSStatus err;
+ UInt32 propertySize;
+
+ OSType readOrwrite = (scope == In)
+ ? kAudioFileGlobalInfo_ReadableTypes : kAudioFileGlobalInfo_WritableTypes;
+
+ err = AudioFileGetGlobalInfoSize(readOrwrite, 0, NULL, &propertySize);
+ BACKEND_ASSERT3(err == noErr, "Could not get core audio file types", NORMAL_ERROR, result)
+
+ OSType *types = (OSType*)malloc(propertySize);
+ err = AudioFileGetGlobalInfo(readOrwrite, 0, NULL, &propertySize, types);
+ BACKEND_ASSERT3(err == noErr, "Could not get core audio file types", NORMAL_ERROR, result)
+
+ UInt32 numTypes = propertySize / sizeof(OSType);
+ for (UInt32 i=0; i<numTypes; ++i){
+ CFStringRef name;
+ UInt32 outSize = sizeof(name);
+ err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_FileTypeName, sizeof(OSType), types+i, &outSize, &name);
+ BACKEND_ASSERT3(err == noErr, "Could not get core audio file type names", NORMAL_ERROR, result)
+ result << PhononCFString::toQString(name);
+ }
+ return result;
+}
+
+}}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/qt7/lgpl-2.1.txt b/src/3rdparty/phonon/qt7/lgpl-2.1.txt
new file mode 100644
index 0000000..5ab7695
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/lgpl-2.1.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/src/3rdparty/phonon/qt7/lgpl-3.txt b/src/3rdparty/phonon/qt7/lgpl-3.txt
new file mode 100644
index 0000000..fc8a5de
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/lgpl-3.txt
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/src/3rdparty/phonon/qt7/medianode.h b/src/3rdparty/phonon/qt7/medianode.h
new file mode 100644
index 0000000..595e4da
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianode.h
@@ -0,0 +1,85 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_MediaNode_H
+#define Phonon_QT7_MediaNode_H
+
+#include <QtCore/QObject>
+#include "backendheader.h"
+#include "medianodeevent.h"
+#include "audioconnection.h"
+#include "videoframe.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioNode;
+ class AudioGraph;
+ class MediaObject;
+ class AudioConnection;
+
+ class MediaNode : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ enum NodeDescriptionEnum {
+ AudioSource = 1,
+ AudioSink = 2,
+ VideoSource = 4,
+ VideoSink = 8,
+ AudioGraphNode = 16
+ };
+ Q_DECLARE_FLAGS(NodeDescription, NodeDescriptionEnum);
+
+ MediaNode(NodeDescription description, QObject *parent);
+ MediaNode(NodeDescription description, AudioNode *audioPart, QObject *parent);
+ virtual ~MediaNode();
+
+ void setAudioNode(AudioNode *audioPart);
+ bool connectToSink(MediaNode *sink);
+ bool disconnectToSink(MediaNode *sink);
+ AudioConnection *getAudioConnectionToSink(MediaNode *sink);
+
+ void notify(const MediaNodeEvent *event, bool propagate = true);
+ void sendEventToSinks(const MediaNodeEvent *event);
+ virtual void mediaNodeEvent(const MediaNodeEvent *event);
+
+ virtual void updateVideo(VideoFrame &frame);
+ AudioGraph *m_audioGraph;
+
+ AudioNode *m_audioNode;
+ QList<AudioConnection *> m_audioSinkList;
+ QList<AudioConnection *> m_audioSourceList;
+ QList<MediaNode *> m_videoSinkList;
+
+ int availableAudioInputBus();
+ int availableAudioOutputBus();
+
+ NodeDescription m_description;
+ MediaObject *m_owningMediaObject;
+ };
+
+ Q_DECLARE_OPERATORS_FOR_FLAGS(MediaNode::NodeDescription);
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_MediaNode_H
diff --git a/src/3rdparty/phonon/qt7/medianode.mm b/src/3rdparty/phonon/qt7/medianode.mm
new file mode 100644
index 0000000..00f8340
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianode.mm
@@ -0,0 +1,261 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "medianode.h"
+#include "audiograph.h"
+#include "audionode.h"
+#include "backendheader.h"
+
+#include "mediaobject.h"
+#include "audiooutput.h"
+#include "quicktimevideoplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+MediaNode::MediaNode(NodeDescription description, QObject *parent)
+ : QObject(parent), m_audioGraph(0), m_audioNode(0), m_description(description), m_owningMediaObject(0)
+{
+}
+
+MediaNode::MediaNode(NodeDescription description, AudioNode *audioPart, QObject *parent)
+ : QObject(parent), m_audioGraph(0), m_audioNode(audioPart), m_description(description)
+{
+}
+
+void MediaNode::setAudioNode(AudioNode *audioPart)
+{
+ if (m_audioNode)
+ delete m_audioNode;
+ m_audioNode = audioPart;
+}
+
+MediaNode::~MediaNode()
+{
+ delete m_audioNode;
+ qDeleteAll(m_audioSinkList);
+}
+
+AudioConnection *MediaNode::getAudioConnectionToSink(MediaNode *sink)
+{
+ AudioConnection *connection = 0;
+ for (int i=0; i<m_audioSinkList.size(); ++i){
+ if (m_audioSinkList[i]->isBetween(this, sink)){
+ connection = m_audioSinkList[i];
+ break;
+ }
+ }
+ return connection;
+}
+
+bool MediaNode::connectToSink(MediaNode *sink)
+{
+ if ((m_description & AudioSource) && (sink->m_description & AudioSink)){
+ // Check that they don't belong to different graphs. If they do, but
+ // sink is not connected to any source, accept it:
+ if (m_owningMediaObject && sink->m_owningMediaObject
+ && m_owningMediaObject != sink->m_owningMediaObject
+ && !sink->m_audioSourceList.isEmpty()){
+ return false;
+ }
+
+ // Check that the connection doesn't already exists:
+ AudioConnection *connection = getAudioConnectionToSink(sink);
+ if (connection)
+ return true;
+
+ // Check that there are awailable input/output busses:
+ int inputBus = sink->availableAudioInputBus();
+ int outputBus = availableAudioOutputBus();
+ if (inputBus >= sink->m_audioNode->m_maxInputBusses || outputBus >= m_audioNode->m_maxOutputBusses)
+ return false;
+
+ // All OK. Create connection:
+ connection = new AudioConnection(this, outputBus, sink, inputBus);
+ m_audioSinkList << connection;
+ sink->m_audioSourceList << connection;
+
+ if (m_audioNode->m_audioGraph)
+ m_audioNode->m_audioGraph->connectLate(connection);
+
+ MediaNodeEvent event1(MediaNodeEvent::AudioSinkAdded, connection);
+ notify(&event1, false);
+ MediaNodeEvent event2(MediaNodeEvent::AudioSourceAdded, connection);
+ sink->notify(&event2, false);
+ return true;
+ }
+
+ if ((m_description & VideoSource) && (sink->m_description & VideoSink)){
+ // Check that the connection doesn't already exists:
+ if (m_videoSinkList.contains(sink))
+ return true;
+
+ m_videoSinkList << sink;
+ MediaNodeEvent event1(MediaNodeEvent::VideoSinkAdded, sink);
+ notify(&event1, false);
+ MediaNodeEvent event2(MediaNodeEvent::VideoSourceAdded, this);
+ sink->notify(&event2, false);
+ return true;
+ }
+
+ return false;
+}
+
+bool MediaNode::disconnectToSink(MediaNode *sink)
+{
+ if ((m_description & AudioSource) && (sink->m_description & AudioSink)){
+ AudioConnection *connection = getAudioConnectionToSink(sink);
+ if (!connection)
+ return false;
+
+ m_audioSinkList.removeOne(connection);
+ sink->m_audioSourceList.removeOne(connection);
+
+ if (m_audioNode->m_audioGraph)
+ m_audioNode->m_audioGraph->disconnectLate(connection);
+
+ MediaNodeEvent event1(MediaNodeEvent::AudioSinkRemoved, connection);
+ notify(&event1, false);
+ MediaNodeEvent event2(MediaNodeEvent::AudioSourceRemoved, connection);
+ sink->notify(&event2, false);
+
+ delete connection;
+ return true;
+ }
+
+ if ((m_description & VideoSource) && (sink->m_description & VideoSink)){
+ m_videoSinkList.removeOne(sink);
+
+ MediaNodeEvent event1(MediaNodeEvent::VideoSinkRemoved, sink);
+ notify(&event1, false);
+ MediaNodeEvent event2(MediaNodeEvent::VideoSourceRemoved, this);
+ sink->notify(&event2, false);
+ return true;
+ }
+
+ return false;
+}
+
+int MediaNode::availableAudioInputBus()
+{
+ // Scan through all the connection <u>in</u> to this
+ // node, and find an awailable index:
+ int index = -1;
+ bool available = false;
+
+ while (!available){
+ ++index;
+ available = true;
+ for (int i=0; i<m_audioSourceList.size(); ++i){
+ if (m_audioSourceList[i]->m_sinkInputBus == index){
+ available = false;
+ break;
+ }
+ }
+ }
+ return index;
+}
+
+int MediaNode::availableAudioOutputBus()
+{
+ // Scan through all the connection <u>out</u> from this
+ // node, and find an awailable index:
+ int bus = -1;
+ bool available = false;
+
+ while (!available){
+ ++bus;
+ available = true;
+ for (int i=0; i<m_audioSinkList.size(); ++i){
+ if (m_audioSinkList[i]->m_sourceOutputBus == bus){
+ available = false;
+ break;
+ }
+ }
+ }
+ return bus;
+}
+
+void MediaNode::notify(const MediaNodeEvent *event, bool propagate)
+{
+ // Let subclass handle the event first:
+ mediaNodeEvent(event);
+
+ switch(event->type()){
+ case MediaNodeEvent::AudioGraphAboutToBeDeleted:
+ if (m_audioNode){
+ foreach(AudioConnection *connection, m_audioSinkList)
+ connection->invalidate();
+ }
+ break;
+ case MediaNodeEvent::NewAudioGraph:
+ m_audioGraph = static_cast<AudioGraph *>(event->data());
+ break;
+ case MediaNodeEvent::AudioSinkAdded:
+ case MediaNodeEvent::VideoSinkAdded:
+ if (m_owningMediaObject){
+ MediaNodeEvent e1(MediaNodeEvent::SetMediaObject, m_owningMediaObject);
+ sendEventToSinks(&e1);
+ QRect videoRect = m_owningMediaObject->videoPlayer()->videoRect();
+ MediaNodeEvent e2(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
+ sendEventToSinks(&e2);
+ }
+ break;
+ case MediaNodeEvent::SetMediaObject:
+ m_owningMediaObject = static_cast<MediaObject *>(event->data());
+ break;
+ default:
+ break;
+ }
+
+ // Inform the audio node as well:
+ if (m_audioNode)
+ m_audioNode->notify(event);
+
+ // And perhaps the sinks:
+ if (propagate)
+ sendEventToSinks(event);
+}
+
+void MediaNode::sendEventToSinks(const MediaNodeEvent *event)
+{
+ for (int i=0; i<m_audioSinkList.size(); ++i)
+ m_audioSinkList[i]->m_sink->notify(event);
+ for (int i=0; i<m_videoSinkList.size(); ++i)
+ m_videoSinkList[i]->notify(event);
+}
+
+void MediaNode::updateVideo(VideoFrame &frame){
+ for (int i=0; i<m_videoSinkList.size(); ++i)
+ m_videoSinkList[i]->updateVideo(frame);
+}
+
+void MediaNode::mediaNodeEvent(const MediaNodeEvent */*event*/)
+{
+ // Override if needed.
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_medianode.cpp"
+
diff --git a/src/3rdparty/phonon/qt7/medianodeevent.h b/src/3rdparty/phonon/qt7/medianodeevent.h
new file mode 100644
index 0000000..ad6e212
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianodeevent.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_MEDIANODEEVENT_H
+#define Phonon_QT7_MEDIANODEEVENT_H
+
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeVideoPlayer;
+
+ class MediaNodeEvent
+ {
+ public:
+ enum Type {
+ AudioGraphAboutToBeDeleted,
+ NewAudioGraph,
+ AudioGraphInitialized,
+ AudioGraphCannotPlay,
+ AboutToRestartAudioStream,
+ RestartAudioStreamRequest,
+ VideoSinkAdded,
+ VideoSinkRemoved,
+ AudioSinkAdded,
+ AudioSinkRemoved,
+ VideoSourceAdded,
+ VideoSourceRemoved,
+ AudioSourceAdded,
+ AudioSourceRemoved,
+ VideoOutputCountChanged,
+ VideoFrameSizeChanged,
+ SetMediaObject,
+ StartConnectionChange,
+ EndConnectionChange,
+ MediaPlaying
+ };
+
+ MediaNodeEvent(Type type, void *data = 0);
+ virtual ~MediaNodeEvent();
+ inline Type type() const{ return eventType; };
+ inline void* data() const { return eventData; };
+
+ private:
+ Type eventType;
+ void *eventData;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_MEDIANODEEVENT_H
diff --git a/src/3rdparty/phonon/qt7/medianodeevent.mm b/src/3rdparty/phonon/qt7/medianodeevent.mm
new file mode 100644
index 0000000..664fbbc
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianodeevent.mm
@@ -0,0 +1,37 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "medianodeevent.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+MediaNodeEvent::MediaNodeEvent(Type type, void *data) : eventType(type), eventData(data)
+{
+}
+
+MediaNodeEvent::~MediaNodeEvent()
+{
+}
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/medianodevideopart.h b/src/3rdparty/phonon/qt7/medianodevideopart.h
new file mode 100644
index 0000000..fb1f89c
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianodevideopart.h
@@ -0,0 +1,42 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_MEDIANODEVIDEOPART_H
+#define Phonon_QT7_MEDIANODEVIDEOPART_H
+
+#include <QtCore/qnamespace.h>
+#include "backendheader.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class MediaNodeVideoPart
+ {
+ public:
+ MediaNodeVideoPart();
+ virtual ~MediaNodeVideoPart();
+ virtual void updateVideo(void *ciImage) = 0;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_MEDIANODEVIDEOPART_H
diff --git a/src/3rdparty/phonon/qt7/medianodevideopart.mm b/src/3rdparty/phonon/qt7/medianodevideopart.mm
new file mode 100644
index 0000000..da060da
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianodevideopart.mm
@@ -0,0 +1,37 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "medianodevideopart.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+MediaNodeVideoPart::MediaNodeVideoPart()
+{
+}
+
+MediaNodeVideoPart::~MediaNodeVideoPart()
+{
+}
+
+}}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/mediaobject.h b/src/3rdparty/phonon/qt7/mediaobject.h
new file mode 100644
index 0000000..27949ec
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/mediaobject.h
@@ -0,0 +1,171 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_MEDIAOBJECT_H
+#define Phonon_QT7_MEDIAOBJECT_H
+
+#include <QtCore/QStringList>
+#include <QtCore/QTime>
+#include <phonon/mediaobjectinterface.h>
+#include <phonon/addoninterface.h>
+
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeVideoPlayer;
+ class QuickTimeAudioPlayer;
+ class QuickTimeMetaData;
+ class AudioGraph;
+ class MediaObjectAudioNode;
+
+ class MediaObject : public MediaNode,
+ public Phonon::MediaObjectInterface, public Phonon::AddonInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::MediaObjectInterface Phonon::AddonInterface)
+
+ public:
+ MediaObject(QObject *parent);
+ ~MediaObject();
+
+ QStringList availableAudioStreams() const;
+ QStringList availableVideoStreams() const;
+ QStringList availableSubtitleStreams() const;
+ QString currentAudioStream(const QObject *audioPath) const;
+ QString currentVideoStream(const QObject *videoPath) const;
+ QString currentSubtitleStream(const QObject *videoPath) const;
+
+ void setCurrentAudioStream(const QString &streamName,const QObject *audioPath);
+ void setCurrentVideoStream(const QString &streamName,const QObject *videoPath);
+ void setCurrentSubtitleStream(const QString &streamName,const QObject *videoPath);
+
+ void play();
+ void pause();
+ void stop();
+ void seek(qint64 milliseconds);
+
+ qint32 tickInterval() const;
+ void setTickInterval(qint32 interval);
+ bool hasVideo() const;
+ bool isSeekable() const;
+ qint64 currentTime() const;
+ Phonon::State state() const;
+
+ QString errorString() const;
+ Phonon::ErrorType errorType() const;
+
+ qint64 totalTime() const;
+ MediaSource source() const;
+ void setSource(const MediaSource &);
+ void setNextSource(const MediaSource &source);
+ qint32 prefinishMark() const;
+ void setPrefinishMark(qint32);
+ qint32 transitionTime() const;
+ void setTransitionTime(qint32);
+ bool hasInterface(Interface interface) const;
+ QVariant interfaceCall(Interface interface, int command, const QList<QVariant> &arguments = QList<QVariant>());
+
+ QuickTimeVideoPlayer* videoPlayer() const;
+ QuickTimeAudioPlayer* audioPlayer() const;
+
+ void setVolumeOnMovie(float volume);
+ bool setAudioDeviceOnMovie(int id);
+
+ int videoOutputCount();
+
+ signals:
+ void stateChanged(Phonon::State,Phonon::State);
+ void tick(qint64);
+ void seekableChanged(bool);
+ void hasVideoChanged(bool);
+ void bufferStatus(int);
+ void finished();
+ void aboutToFinish();
+ void prefinishMarkReached(qint32);
+ void totalTimeChanged(qint64);
+ void metaDataChanged(QMultiMap<QString,QString>);
+ void currentSourceChanged(const MediaSource &newSource);
+
+ protected:
+ void mediaNodeEvent(const MediaNodeEvent *event);
+ bool event(QEvent *event);
+
+ private:
+ enum AudioSystem {AS_Unset, AS_Video, AS_Graph, AS_Silent} m_audioSystem;
+ Phonon::State m_state;
+
+ QuickTimeVideoPlayer *m_videoPlayer;
+ QuickTimeAudioPlayer *m_audioPlayer;
+ QuickTimeVideoPlayer *m_nextVideoPlayer;
+ QuickTimeAudioPlayer *m_nextAudioPlayer;
+ MediaObjectAudioNode *m_mediaObjectAudioNode;
+ QuickTimeMetaData *m_metaData;
+
+ qint32 m_tickInterval;
+ qint32 m_transitionTime;
+ quint32 m_prefinishMark;
+ quint32 m_currentTime;
+ float m_percentageLoaded;
+
+ int m_tickTimer;
+ int m_bufferTimer;
+ int m_rapidTimer;
+
+ bool m_waitNextSwap;
+ int m_swapTimeLeft;
+ QTime m_swapTime;
+
+ void synchAudioVideo();
+ void updateCurrentTime();
+ void swapCurrentWithNext(qint32 transitionTime);
+ bool setState(Phonon::State state);
+ void pause_internal();
+ void play_internal();
+ void setupAudioSystem();
+ void updateTimer(int &timer, int interval);
+ void bufferAudioVideo();
+ void updateRapidly();
+ void updateCrossFade();
+ void updateAudioBuffers();
+ void updateLipSynch(int allowedOffset);
+ void updateVideoFrames();
+ void updateBufferStatus();
+ void setMute(bool mute);
+ void inspectAudioGraphRecursive(AudioConnection *connection, int &effectCount, int &outputCount);
+ void inspectVideoGraphRecursive(MediaNode *node, int &effectCount, int &outputCount);
+ void inspectGraph();
+ bool isCrossFading();
+
+ QString m_errorString;
+ Phonon::ErrorType m_errorType;
+ bool checkForError();
+
+ int m_audioEffectCount;
+ int m_audioOutputCount;
+ int m_videoEffectCount;
+ int m_videoOutputCount;
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_MEDIAOBJECT_H
diff --git a/src/3rdparty/phonon/qt7/mediaobject.mm b/src/3rdparty/phonon/qt7/mediaobject.mm
new file mode 100644
index 0000000..002c337
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/mediaobject.mm
@@ -0,0 +1,852 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <QtCore/QEvent>
+#include "mediaobject.h"
+#include "backendheader.h"
+#include "videowidget.h"
+#include "videoframe.h"
+#include "audiooutput.h"
+#include "quicktimevideoplayer.h"
+#include "quicktimemetadata.h"
+#include "audiograph.h"
+#include "mediaobjectaudionode.h"
+#include "quicktimeaudioplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource, parent)
+{
+ m_owningMediaObject = this;
+ m_state = Phonon::LoadingState;
+
+ m_videoPlayer = new QuickTimeVideoPlayer();
+ m_audioPlayer = new QuickTimeAudioPlayer();
+ m_nextVideoPlayer = new QuickTimeVideoPlayer();
+ m_nextAudioPlayer = new QuickTimeAudioPlayer();
+ m_mediaObjectAudioNode = new MediaObjectAudioNode(m_audioPlayer, m_nextAudioPlayer);
+ setAudioNode(m_mediaObjectAudioNode);
+
+ m_metaData = new QuickTimeMetaData();
+ m_audioGraph = new AudioGraph(this);
+
+ m_tickInterval = 0;
+ m_prefinishMark = 0;
+ m_currentTime = 0;
+ m_transitionTime = 0;
+ m_percentageLoaded = 0;
+ m_waitNextSwap = false;
+ m_audioEffectCount = 0;
+ m_audioOutputCount = 0;
+ m_videoEffectCount = 0;
+ m_videoOutputCount = 0;
+ m_audioSystem = AS_Unset;
+ m_errorType = Phonon::NoError;
+
+ m_tickTimer = 0;
+ m_bufferTimer = 0;
+ m_rapidTimer = 0;
+
+ checkForError();
+}
+
+MediaObject::~MediaObject()
+{
+ // m_mediaObjectAudioNode is owned by super class.
+ m_audioPlayer->unsetVideoPlayer();
+ m_nextAudioPlayer->unsetVideoPlayer();
+ delete m_videoPlayer;
+ delete m_nextVideoPlayer;
+ delete m_metaData;
+ checkForError();
+}
+
+bool MediaObject::setState(Phonon::State state)
+{
+ Phonon::State prevState = m_state;
+ m_state = state;
+ if (prevState != m_state){
+ emit stateChanged(m_state, prevState);
+ if (m_state != state){
+ // End-application did something
+ // upon receiving the signal.
+ return false;
+ }
+ }
+ return true;
+}
+
+void MediaObject::inspectAudioGraphRecursive(AudioConnection *connection, int &effectCount, int &outputCount)
+{
+ if ((connection->m_sink->m_description & (AudioSource | AudioSink)) == (AudioSource | AudioSink))
+ ++effectCount;
+ else if (connection->m_sink->m_description & AudioSink)
+ ++outputCount;
+
+ for (int i=0; i<connection->m_sink->m_audioSinkList.size(); ++i)
+ inspectAudioGraphRecursive(connection->m_sink->m_audioSinkList[i], effectCount, outputCount);
+}
+
+void MediaObject::inspectVideoGraphRecursive(MediaNode *node, int &effectCount, int &outputCount)
+{
+ if ((node->m_description & (VideoSource | VideoSink)) == (VideoSource | VideoSink))
+ ++effectCount;
+ else if (node->m_description & VideoSink)
+ ++outputCount;
+
+ for (int i=0; i<node->m_videoSinkList.size(); ++i)
+ inspectVideoGraphRecursive(node->m_videoSinkList[i], effectCount, outputCount);
+}
+
+void MediaObject::inspectGraph()
+{
+ // Inspect the graph to check wether there are any
+ // effects or outputs connected. This will have
+ // influence on the audio system and video system that ends up beeing used:
+ int prevVideoOutputCount = m_videoOutputCount;
+ m_audioEffectCount = 0;
+ m_audioOutputCount = 0;
+ m_videoEffectCount = 0;
+ m_videoOutputCount = 0;
+ AudioConnection rootConnection(this);
+ inspectAudioGraphRecursive(&rootConnection, m_audioEffectCount, m_audioOutputCount);
+ inspectVideoGraphRecursive(this, m_videoEffectCount, m_videoOutputCount);
+
+ if (m_videoOutputCount != prevVideoOutputCount){
+ MediaNodeEvent e1(MediaNodeEvent::VideoOutputCountChanged, &m_videoOutputCount);
+ notify(&e1);
+ }
+}
+
+void MediaObject::setupAudioSystem()
+{
+ // Select which audio system to use:
+ AudioSystem newAudioSystem = AS_Unset;
+ if (!m_audioOutputCount || !m_videoPlayer->canPlayMedia()){
+ newAudioSystem = AS_Silent;
+ } else if (m_audioEffectCount == 0){
+ newAudioSystem = AS_Video;
+ } else if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_4){
+ newAudioSystem = AS_Video;
+ SET_ERROR("Audio effects are not supported for Mac OS 10.3 and below", NORMAL_ERROR);
+ } else if (m_videoPlayer->isDrmProtected()){
+ newAudioSystem = AS_Video;
+ SET_ERROR("Audio effects are not supported for DRM protected media", NORMAL_ERROR);
+ } else if (m_audioGraph->graphCannotPlay()){
+ newAudioSystem = AS_Video;
+ SET_ERROR("Audio effects are not supported for the current codec", NORMAL_ERROR);
+#ifdef QUICKTIME_C_API_AVAILABLE
+ } else {
+ newAudioSystem = AS_Graph;
+ }
+#else
+ } else {
+ newAudioSystem = AS_Video;
+ SET_ERROR("Audio effects are not supported for the 64-bit version of the Phonon QT7 backend", NORMAL_ERROR);
+ }
+#endif
+
+ if (newAudioSystem == m_audioSystem)
+ return;
+
+ // Enable selected audio system:
+ m_audioSystem = newAudioSystem;
+ switch (newAudioSystem){
+ case AS_Silent:
+ m_audioGraph->stop();
+ m_videoPlayer->enableAudio(false);
+ m_nextVideoPlayer->enableAudio(false);
+ m_audioPlayer->enableAudio(false);
+ m_nextAudioPlayer->enableAudio(false);
+ break;
+ case AS_Graph:
+ if (m_state == Phonon::PausedState)
+ m_audioGraph->prepare();
+ else
+ m_audioGraph->start();
+ // Starting the graph can lead to a recursive call
+ // telling us that we must direct audio through
+ // video. If that has happened, we must not proceed:
+ if (m_audioSystem != AS_Graph)
+ return;
+ m_videoPlayer->enableAudio(false);
+ m_nextVideoPlayer->enableAudio(false);
+ m_audioPlayer->enableAudio(true);
+ m_audioPlayer->seek(m_videoPlayer->currentTime());
+ m_nextAudioPlayer->enableAudio(true);
+ m_audioPlayer->seek(m_videoPlayer->currentTime());
+ m_nextAudioPlayer->seek(m_nextVideoPlayer->currentTime());
+ break;
+ case AS_Video:
+ case AS_Unset:
+ m_audioGraph->stop();
+ m_videoPlayer->enableAudio(true);
+ m_nextVideoPlayer->enableAudio(true);
+ m_audioPlayer->enableAudio(false);
+ m_nextAudioPlayer->enableAudio(false);
+ m_videoPlayer->seek(m_audioPlayer->currentTime());
+ m_nextVideoPlayer->seek(m_nextAudioPlayer->currentTime());
+ break;
+ }
+}
+
+void MediaObject::setSource(const MediaSource &source)
+{
+ IMPLEMENTED;
+ PhononAutoReleasePool pool;
+ setState(Phonon::LoadingState);
+
+ // Save current state for event/signal handling below:
+ bool prevHasVideo = m_videoPlayer->hasVideo();
+ qint64 prevTotalTime = totalTime();
+ m_waitNextSwap = false;
+
+ // Cancel cross-fade if any:
+ m_nextVideoPlayer->pause();
+ m_nextAudioPlayer->pause();
+ m_mediaObjectAudioNode->cancelCrossFade();
+
+ // Set new source:
+ m_audioPlayer->unsetVideoPlayer();
+ m_videoPlayer->setMediaSource(source);
+ m_audioPlayer->setVideoPlayer(m_videoPlayer);
+ m_metaData->setVideo(m_videoPlayer);
+
+ m_audioGraph->updateStreamSpecifications();
+ m_nextAudioPlayer->unsetVideoPlayer();
+ m_nextVideoPlayer->unsetVideo();
+ m_currentTime = 0;
+
+ // Emit/notify information about the new source:
+ QRect videoRect = m_videoPlayer->videoRect();
+ MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
+ notify(&e1);
+
+ // Clear video widgets:
+ VideoFrame emptyFrame;
+ updateVideo(emptyFrame);
+
+ emit currentSourceChanged(source);
+ emit metaDataChanged(m_metaData->metaData());
+
+ if (prevHasVideo != m_videoPlayer->hasVideo())
+ emit hasVideoChanged(m_videoPlayer->hasVideo());
+ if (prevTotalTime != totalTime())
+ emit totalTimeChanged(totalTime());
+ if (checkForError())
+ return;
+ if (!m_videoPlayer->isDrmAuthorized())
+ SET_ERROR("This computer is not authorized to play current media (DRM protected).", FATAL_ERROR)
+ if (checkForError())
+ return;
+ if (!m_videoPlayer->canPlayMedia())
+ SET_ERROR("Cannot play media.", FATAL_ERROR)
+
+ // The state might have changed from LoadingState
+ // as a response to an error state change. So we
+ // need to check it before stopping:
+ if (m_state == Phonon::LoadingState)
+ stop();
+
+ setupAudioSystem();
+ checkForError();
+}
+
+void MediaObject::setNextSource(const MediaSource &source)
+{
+ IMPLEMENTED;
+ m_nextAudioPlayer->unsetVideoPlayer();
+ m_nextVideoPlayer->setMediaSource(source);
+ m_nextAudioPlayer->setVideoPlayer(m_nextVideoPlayer);
+ checkForError();
+}
+
+void MediaObject::swapCurrentWithNext(qint32 transitionTime)
+{
+ PhononAutoReleasePool pool;
+ setState(Phonon::LoadingState);
+ // Save current state for event/signal handling below:
+ bool prevHasVideo = m_videoPlayer->hasVideo();
+ qint64 prevTotalTime = totalTime();
+
+ qSwap(m_audioPlayer, m_nextAudioPlayer);
+ qSwap(m_videoPlayer, m_nextVideoPlayer);
+ m_mediaObjectAudioNode->startCrossFade(transitionTime);
+ m_audioGraph->updateStreamSpecifications();
+ m_metaData->setVideo(m_videoPlayer);
+
+ m_waitNextSwap = false;
+ m_currentTime = 0;
+
+ // Emit/notify information about the new source:
+ QRect videoRect = m_videoPlayer->videoRect();
+ MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
+ notify(&e1);
+
+ emit currentSourceChanged(m_videoPlayer->mediaSource());
+ emit metaDataChanged(m_metaData->metaData());
+
+ if (prevHasVideo != m_videoPlayer->hasVideo())
+ emit hasVideoChanged(m_videoPlayer->hasVideo());
+ if (prevTotalTime != totalTime())
+ emit totalTimeChanged(totalTime());
+ if (checkForError())
+ return;
+ if (!m_videoPlayer->isDrmAuthorized())
+ SET_ERROR("This computer is not authorized to play current media (DRM protected).", FATAL_ERROR)
+ if (checkForError())
+ return;
+ if (!m_videoPlayer->canPlayMedia())
+ SET_ERROR("Cannot play next media.", FATAL_ERROR)
+
+ setupAudioSystem();
+ checkForError();
+ if (m_state == Phonon::LoadingState){
+ if (setState(Phonon::PlayingState))
+ play_internal();
+ checkForError();
+ }
+}
+
+void MediaObject::updateTimer(int &timer, int interval)
+{
+ if (timer)
+ killTimer(timer);
+ timer = 0;
+ if (interval >= 0)
+ timer = startTimer(interval);
+}
+
+void MediaObject::play_internal()
+{
+ // Play main audio/video:
+ m_videoPlayer->play();
+ m_audioPlayer->play();
+ updateLipSynch(0);
+ // Play old audio/video to finish cross-fade:
+ if (m_nextVideoPlayer->currentTime() > 0){
+ m_nextVideoPlayer->play();
+ m_nextAudioPlayer->play();
+ }
+ bufferAudioVideo();
+ updateTimer(m_rapidTimer, 100);
+}
+
+void MediaObject::pause_internal()
+{
+ m_audioGraph->stop();
+ m_audioPlayer->pause();
+ m_nextAudioPlayer->pause();
+ m_videoPlayer->pause();
+ m_nextVideoPlayer->pause();
+ updateTimer(m_rapidTimer, -1);
+ updateTimer(m_bufferTimer, -1);
+
+ if (m_waitNextSwap)
+ m_swapTimeLeft = m_swapTime.msecsTo(QTime::currentTime());
+}
+
+void MediaObject::play()
+{
+ IMPLEMENTED;
+ if (m_state == Phonon::PlayingState)
+ return;
+ if (m_waitNextSwap){
+ // update swap time after pause:
+ m_swapTime = QTime::currentTime();
+ m_swapTime.addMSecs(m_swapTimeLeft);
+ setState(Phonon::PlayingState);
+ return;
+ }
+ if (m_currentTime == m_videoPlayer->duration())
+ return;
+ if (!m_videoPlayer->canPlayMedia())
+ return;
+ if (!setState(Phonon::PlayingState))
+ return;
+ if (m_audioSystem == AS_Graph){
+ m_audioGraph->start();
+ m_mediaObjectAudioNode->setMute(true);
+ }
+ // Inform the graph that we are about to play:
+ bool playing = true;
+ MediaNodeEvent e1(MediaNodeEvent::MediaPlaying, &playing);
+ notify(&e1);
+ // Start to play:
+ play_internal();
+ m_mediaObjectAudioNode->setMute(false);
+ checkForError();
+}
+
+void MediaObject::pause()
+{
+ IMPLEMENTED;
+ if (m_state == Phonon::PausedState)
+ return;
+ if (!setState(Phonon::PausedState))
+ return;
+ pause_internal();
+ // Inform the graph that we are no longer playing:
+ bool playing = false;
+ MediaNodeEvent e1(MediaNodeEvent::MediaPlaying, &playing);
+ notify(&e1);
+ // But be prepared:
+ if (m_audioSystem == AS_Graph)
+ m_audioGraph->prepare();
+ checkForError();
+}
+
+void MediaObject::stop()
+{
+ IMPLEMENTED;
+ if (m_state == Phonon::StoppedState)
+ return;
+ if (!setState(Phonon::StoppedState))
+ return;
+ m_waitNextSwap = false;
+ m_nextVideoPlayer->unsetVideo();
+ m_nextAudioPlayer->unsetVideoPlayer();
+ pause_internal();
+ seek(0);
+ checkForError();
+}
+
+void MediaObject::seek(qint64 milliseconds)
+{
+ IMPLEMENTED;
+ if (m_state == Phonon::ErrorState)
+ return;
+
+ // Stop cross-fade if any:
+ m_nextVideoPlayer->unsetVideo();
+ m_nextAudioPlayer->unsetVideoPlayer();
+ m_mediaObjectAudioNode->cancelCrossFade();
+
+ // Seek to new position:
+ m_mediaObjectAudioNode->setMute(true);
+ m_videoPlayer->seek(milliseconds);
+ m_audioPlayer->seek(m_videoPlayer->currentTime());
+ m_mediaObjectAudioNode->setMute(false);
+
+ // Update time and cancel pending swap:
+ if (m_currentTime < m_videoPlayer->duration())
+ m_waitNextSwap = false;
+
+ updateCurrentTime();
+ if (m_state != Phonon::PlayingState)
+ updateVideoFrames();
+ checkForError();
+}
+
+QStringList MediaObject::availableAudioStreams() const
+{
+ NOT_IMPLEMENTED;
+ return QStringList();
+}
+
+QStringList MediaObject::availableVideoStreams() const
+{
+ NOT_IMPLEMENTED;
+ return QStringList();
+}
+
+QStringList MediaObject::availableSubtitleStreams() const
+{
+ NOT_IMPLEMENTED;
+ return QStringList();
+}
+
+QString MediaObject::currentAudioStream(const QObject */*audioPath*/) const
+{
+ NOT_IMPLEMENTED;
+ return QString();
+}
+
+QString MediaObject::currentVideoStream(const QObject */*videoPath*/) const
+{
+ NOT_IMPLEMENTED;
+ return QString();
+}
+
+QString MediaObject::currentSubtitleStream(const QObject */*videoPath*/) const
+{
+ NOT_IMPLEMENTED;
+ return QString();
+}
+
+void MediaObject::setCurrentAudioStream(const QString &/*streamName*/,const QObject */*audioPath*/)
+{
+ NOT_IMPLEMENTED;
+}
+
+void MediaObject::setCurrentVideoStream(const QString &/*streamName*/,const QObject */*videoPath*/)
+{
+ NOT_IMPLEMENTED;
+}
+
+void MediaObject::setCurrentSubtitleStream(const QString &/*streamName*/,const QObject */*videoPath*/)
+{
+ NOT_IMPLEMENTED;
+}
+
+int MediaObject::videoOutputCount()
+{
+ return m_videoOutputCount;
+}
+
+void MediaObject::synchAudioVideo()
+{
+ if (m_state != Phonon::PlayingState)
+ return;
+ if (m_videoSinkList.isEmpty() || m_audioSinkList.isEmpty())
+ return;
+
+ seek(m_currentTime);
+ checkForError();
+}
+
+qint32 MediaObject::tickInterval() const
+{
+ IMPLEMENTED;
+ return m_tickInterval;
+}
+
+void MediaObject::setTickInterval(qint32 interval)
+{
+ IMPLEMENTED;
+ m_tickInterval = interval;
+ if (m_tickInterval > 0)
+ m_tickTimer = startTimer(m_tickInterval);
+ else{
+ killTimer(m_tickTimer);
+ m_tickTimer = 0;
+ }
+}
+
+bool MediaObject::hasVideo() const
+{
+ IMPLEMENTED;
+ return m_videoPlayer ? m_videoPlayer->hasVideo() : false;
+}
+
+bool MediaObject::isSeekable() const
+{
+ IMPLEMENTED;
+ return m_videoPlayer ? m_videoPlayer->isSeekable() : false;
+}
+
+qint64 MediaObject::currentTime() const
+{
+ IMPLEMENTED_SILENT;
+ const_cast<MediaObject *>(this)->updateCurrentTime();
+ return m_currentTime;
+}
+
+void MediaObject::updateCurrentTime()
+{
+ quint64 lastUpdateTime = m_currentTime;
+ m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
+ quint64 total = m_videoPlayer->duration();
+
+ // Check if it's time to emit aboutToFinish:
+ quint32 mark = qMax(quint64(0), qMin(total, total + m_transitionTime - 2000));
+ if (lastUpdateTime < mark && mark <= m_currentTime)
+ emit aboutToFinish();
+
+ // Check if it's time to emit prefinishMarkReached:
+ mark = qMax(quint64(0), total - m_prefinishMark);
+ if (lastUpdateTime < mark && mark <= m_currentTime)
+ emit prefinishMarkReached(total - m_currentTime);
+
+ if (m_nextVideoPlayer->state() == QuickTimeVideoPlayer::NoMedia){
+ // There is no next source in que.
+ // Check if it's time to emit finished:
+ if (lastUpdateTime < m_currentTime && m_currentTime == total){
+ emit finished();
+ m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
+ if (m_state == Phonon::PlayingState && m_currentTime == total)
+ pause();
+ }
+ } else {
+ // We have a next source.
+ // Check if it's time to swap to next source:
+ mark = qMax(quint64(0), total + m_transitionTime);
+ if (m_waitNextSwap && m_state == Phonon::PlayingState &&
+ m_transitionTime < m_swapTime.msecsTo(QTime::currentTime())){
+ swapCurrentWithNext(0);
+ } else if (mark >= total){
+ if (lastUpdateTime < total && total == m_currentTime){
+ m_swapTime = QTime::currentTime();
+ m_swapTime.addMSecs(mark - total);
+ m_waitNextSwap = true;
+ }
+ } else if (lastUpdateTime < mark && mark <= m_currentTime){
+ swapCurrentWithNext(total - m_currentTime);
+ }
+ }
+}
+
+qint64 MediaObject::totalTime() const
+{
+ IMPLEMENTED_SILENT;
+ return m_videoPlayer->duration();
+}
+
+Phonon::State MediaObject::state() const
+{
+ IMPLEMENTED;
+ return m_state;
+}
+
+QString MediaObject::errorString() const
+{
+ IMPLEMENTED;
+ return m_errorString;
+}
+
+Phonon::ErrorType MediaObject::errorType() const
+{
+ IMPLEMENTED;
+ return m_errorType;
+}
+
+bool MediaObject::checkForError()
+{
+ int type = gGetErrorType();
+ if (type == NO_ERROR)
+ return false;
+
+ m_errorType = (type == NORMAL_ERROR) ? Phonon::NormalError : Phonon::FatalError;
+ m_errorString = gGetErrorString();
+ pause_internal();
+ gClearError();
+ setState(Phonon::ErrorState);
+ return true;
+}
+
+QuickTimeVideoPlayer* MediaObject::videoPlayer() const
+{
+ return m_videoPlayer;
+}
+
+MediaSource MediaObject::source() const
+{
+ IMPLEMENTED;
+ return m_videoPlayer->mediaSource();
+}
+
+qint32 MediaObject::prefinishMark() const
+{
+ IMPLEMENTED;
+ return m_prefinishMark;
+}
+
+void MediaObject::setPrefinishMark(qint32 mark)
+{
+ IMPLEMENTED;
+ m_prefinishMark = mark;
+}
+
+qint32 MediaObject::transitionTime() const
+{
+ IMPLEMENTED;
+ return m_transitionTime;
+}
+
+void MediaObject::setTransitionTime(qint32 transitionTime)
+{
+ IMPLEMENTED;
+ m_transitionTime = transitionTime;
+}
+
+void MediaObject::setVolumeOnMovie(float volume)
+{
+ m_videoPlayer->setMasterVolume(volume);
+ m_nextVideoPlayer->setMasterVolume(volume);
+}
+
+bool MediaObject::setAudioDeviceOnMovie(int id)
+{
+ m_nextVideoPlayer->setAudioDevice(id);
+ return m_videoPlayer->setAudioDevice(id);
+}
+
+void MediaObject::updateCrossFade()
+{
+ m_mediaObjectAudioNode->updateCrossFade(m_currentTime);
+ // Clean-up previous movie if done fading:
+ if (m_mediaObjectAudioNode->m_fadeDuration == 0){
+ if (m_nextVideoPlayer->isPlaying() || m_nextAudioPlayer->isPlaying()){
+ m_nextVideoPlayer->unsetVideo();
+ m_nextAudioPlayer->unsetVideoPlayer();
+ }
+ }
+}
+
+void MediaObject::updateBufferStatus()
+{
+ float percent = m_videoPlayer->percentageLoaded();
+ if (percent != m_percentageLoaded){
+ m_percentageLoaded = percent;
+ emit bufferStatus(m_percentageLoaded * 100);
+ }
+}
+
+void MediaObject::updateAudioBuffers()
+{
+ // Schedule audio slices:
+ m_audioPlayer->scheduleAudioToGraph();
+ m_nextAudioPlayer->scheduleAudioToGraph();
+}
+
+bool MediaObject::isCrossFading()
+{
+ return m_mediaObjectAudioNode->isCrossFading();
+}
+
+void MediaObject::updateVideoFrames()
+{
+ // Draw next frame if awailable:
+ if (m_videoPlayer->videoFrameChanged()){
+ updateLipSynch(50);
+ VideoFrame frame(m_videoPlayer);
+ if (m_nextVideoPlayer->isPlaying()
+ && m_nextVideoPlayer->hasVideo()
+ && isCrossFading()){
+ VideoFrame bgFrame(m_nextVideoPlayer);
+ frame.setBackgroundFrame(bgFrame);
+ frame.setBaseOpacity(m_mediaObjectAudioNode->m_volume1);
+ }
+
+ // Send the frame through the graph:
+ updateVideo(frame);
+ checkForError();
+ }
+}
+
+void MediaObject::updateLipSynch(int allowedOffset)
+{
+ if (m_audioSystem != AS_Graph || !m_audioGraph->isRunning())
+ return;
+ if (m_videoSinkList.isEmpty() || m_audioSinkList.isEmpty())
+ return;
+
+ if (m_videoPlayer->hasVideo()){
+ qint64 diff = m_audioPlayer->currentTime() - m_videoPlayer->currentTime();
+ if (-allowedOffset > diff || diff > allowedOffset)
+ m_audioPlayer->seek(m_videoPlayer->currentTime());
+ }
+
+ if (isCrossFading() && m_nextVideoPlayer->hasVideo()){
+ qint64 diff = m_nextAudioPlayer->currentTime() - m_nextVideoPlayer->currentTime();
+ if (-(allowedOffset*2) > diff || diff > (allowedOffset*2))
+ m_nextAudioPlayer->seek(m_nextVideoPlayer->currentTime());
+ }
+}
+
+void MediaObject::bufferAudioVideo()
+{
+ long nextVideoUpdate = m_videoPlayer->hasVideo() ? 30 : INT_MAX;
+ long nextAudioUpdate = m_audioPlayer->regularTaskFrequency();
+ updateAudioBuffers();
+ updateVideoFrames();
+ if (m_state == Phonon::PlayingState)
+ updateTimer(m_bufferTimer, qMin(nextVideoUpdate, nextAudioUpdate));
+}
+
+void MediaObject::updateRapidly()
+{
+ updateCurrentTime();
+ updateCrossFade();
+ updateBufferStatus();
+}
+
+void MediaObject::setMute(bool mute)
+{
+ m_mediaObjectAudioNode->setMute(mute);
+ m_videoPlayer->setMute(mute);
+ m_nextVideoPlayer->setMute(mute);
+}
+
+void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()){
+ case MediaNodeEvent::EndConnectionChange:
+ m_mediaObjectAudioNode->setMute(true);
+ inspectGraph();
+ setupAudioSystem();
+ synchAudioVideo();
+ checkForError();
+ m_mediaObjectAudioNode->setMute(false);
+ if (m_state == Phonon::PlayingState)
+ bufferAudioVideo();
+ break;
+ case MediaNodeEvent::AudioGraphCannotPlay:
+ case MediaNodeEvent::AudioGraphInitialized:
+ if (m_state != Phonon::LoadingState){
+ m_mediaObjectAudioNode->setMute(true);
+ setupAudioSystem();
+ updateLipSynch(0);
+ checkForError();
+ m_mediaObjectAudioNode->setMute(false);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+bool MediaObject::event(QEvent *event)
+{
+ switch (event->type()){
+ case QEvent::Timer: {
+ QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);
+ if (timerEvent->timerId() == m_rapidTimer)
+ updateRapidly();
+ else if (timerEvent->timerId() == m_tickTimer)
+ emit tick(currentTime());
+ else if (timerEvent->timerId() == m_bufferTimer)
+ bufferAudioVideo();
+ }
+ break;
+ default:
+ break;
+ }
+ return QObject::event(event);
+}
+
+bool MediaObject::hasInterface(Interface /*interface*/) const
+{
+ return false;
+}
+
+QVariant MediaObject::interfaceCall(Interface /*interface*/, int /*command*/, const QList<QVariant> &/*arguments*/)
+{
+ return QVariant();
+}
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_mediaobject.cpp"
+
diff --git a/src/3rdparty/phonon/qt7/mediaobjectaudionode.h b/src/3rdparty/phonon/qt7/mediaobjectaudionode.h
new file mode 100644
index 0000000..7939aaa
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/mediaobjectaudionode.h
@@ -0,0 +1,75 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_MEDIAOBJECTAUDIONODE_H
+#define Phonon_QT7_MEDIAOBJECTAUDIONODE_H
+
+#include <QtCore/qnamespace.h>
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeAudioPlayer;
+ class AudioMixerAudioNode;
+ class AudioConnection;
+
+ class MediaObjectAudioNode : public AudioNode
+ {
+ public:
+ MediaObjectAudioNode(QuickTimeAudioPlayer *player1, QuickTimeAudioPlayer *player2);
+ ~MediaObjectAudioNode();
+
+ // Overridden section from AudioNode:
+ void createAndConnectAUNodes();
+ void createAudioUnits();
+ void setGraph(AudioGraph *audioGraph);
+ AUNode getOutputAUNode();
+ bool fillInStreamSpecification(AudioConnection *connection, ConnectionSide side);
+ bool setStreamSpecification(AudioConnection *connection, ConnectionSide side);
+
+ void startCrossFade(qint64 duration);
+ void updateCrossFade(qint64 currentTime);
+ void cancelCrossFade();
+ void setMute(bool mute);
+ bool isCrossFading();
+
+ QuickTimeAudioPlayer *m_player1;
+ QuickTimeAudioPlayer *m_player2;
+ AudioMixerAudioNode *m_mixer;
+
+ AudioConnection *m_connection1;
+ AudioConnection *m_connection2;
+
+ float m_fadeDuration;
+ float m_volume1;
+ float m_volume2;
+ float m_mute;
+
+ float applyCurve(float volume);
+ void updateVolume();
+
+ void mediaNodeEvent(const MediaNodeEvent *event);
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_MEDIAOBJECTAUDIONODE_H
diff --git a/src/3rdparty/phonon/qt7/mediaobjectaudionode.mm b/src/3rdparty/phonon/qt7/mediaobjectaudionode.mm
new file mode 100644
index 0000000..39b0d4e
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/mediaobjectaudionode.mm
@@ -0,0 +1,209 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#import <QTKit/QTMovie.h>
+
+#include "mediaobjectaudionode.h"
+#include "quicktimeaudioplayer.h"
+#include "quicktimevideoplayer.h"
+#include "audiomixer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+MediaObjectAudioNode::MediaObjectAudioNode(QuickTimeAudioPlayer *player1, QuickTimeAudioPlayer *player2) : AudioNode(0, 1)
+{
+ m_mute = false;
+ m_player1 = player1;
+ m_player2 = player2;
+ m_mixer = new AudioMixerAudioNode();
+
+ m_connection1 = new AudioConnection(m_player1, 0, m_mixer, 0);
+ m_connection2 = new AudioConnection(m_player2, 0, m_mixer, 1);
+
+ m_fadeDuration = 0;
+}
+
+MediaObjectAudioNode::~MediaObjectAudioNode()
+{
+ setGraph(0);
+ delete m_player1;
+ delete m_player2;
+ delete m_mixer;
+ delete m_connection1;
+ delete m_connection2;
+}
+
+void MediaObjectAudioNode::createAndConnectAUNodes()
+{
+ DEBUG_AUDIO_GRAPH("(MediaObjectAudioNode" << int(this) << "createAndConnectAUNodes called)" )
+ m_player1->createAndConnectAUNodes();
+ m_player2->createAndConnectAUNodes();
+ m_mixer->createAndConnectAUNodes();
+
+ m_connection1->connect(m_audioGraph);
+ m_connection2->connect(m_audioGraph);
+}
+
+void MediaObjectAudioNode::createAudioUnits()
+{
+ DEBUG_AUDIO_GRAPH("(MediaObjectAudioNode" << int(this) << "createAudioUnits called)" )
+ m_player1->createAudioUnits();
+ m_player2->createAudioUnits();
+ m_mixer->createAudioUnits();
+}
+
+void MediaObjectAudioNode::setGraph(AudioGraph *audioGraph)
+{
+ DEBUG_AUDIO_GRAPH("MediaObjectAudioNode" << int(this) << "is setting graph:" << int(audioGraph))
+ m_audioGraph = audioGraph;
+ m_player1->setGraph(audioGraph);
+ m_player2->setGraph(audioGraph);
+ m_mixer->setGraph(audioGraph);
+}
+
+AUNode MediaObjectAudioNode::getOutputAUNode()
+{
+ return m_mixer->getOutputAUNode();
+}
+
+bool MediaObjectAudioNode::fillInStreamSpecification(AudioConnection *connection, ConnectionSide side)
+{
+ if (side == Source){
+ DEBUG_AUDIO_STREAM("(MediaObjectAudioNode" << int(this) << "fillInStreamSpecification called, role = source)")
+ return m_mixer->fillInStreamSpecification(connection, side);
+ } else {
+ DEBUG_AUDIO_STREAM("(MediaObjectAudioNode" << int(this) << "fillInStreamSpecification called, role = sink)")
+ return (m_connection2->updateStreamSpecification() && m_connection1->updateStreamSpecification());
+ }
+}
+
+bool MediaObjectAudioNode::setStreamSpecification(AudioConnection *connection, ConnectionSide side)
+{
+ if (side == Source){
+ DEBUG_AUDIO_STREAM("(MediaObjectAudioNode" << int(this) << "setStreamSpecification called, role = source)")
+ return m_mixer->setStreamSpecification(connection, side);
+ }
+ return true;
+}
+
+void MediaObjectAudioNode::setMute(bool mute)
+{
+ m_mute = mute;
+ m_mixer->setVolume(m_mute ? 0 : m_volume1, m_connection1->m_sinkInputBus);
+ m_mixer->setVolume(m_mute ? 0 : m_volume2, m_connection2->m_sinkInputBus);
+}
+
+void MediaObjectAudioNode::updateVolume()
+{
+ if (m_mute)
+ return;
+
+ QuickTimeVideoPlayer *player1 = static_cast<QuickTimeAudioPlayer *>(m_connection1->m_sourceAudioNode)->videoPlayer();
+ QuickTimeVideoPlayer *player2 = static_cast<QuickTimeAudioPlayer *>(m_connection2->m_sourceAudioNode)->videoPlayer();
+ if (player1)
+ player1->setRelativeVolume(m_volume1);
+ if (player2)
+ player2->setRelativeVolume(m_volume2);
+
+ m_mixer->setVolume(m_volume1, m_connection1->m_sinkInputBus);
+ m_mixer->setVolume(m_volume2, m_connection2->m_sinkInputBus);
+}
+
+void MediaObjectAudioNode::startCrossFade(qint64 duration)
+{
+ m_fadeDuration = duration;
+
+ // Swap:
+ AudioConnection *tmp = m_connection1;
+ m_connection1 = m_connection2;
+ m_connection2 = tmp;
+
+ // Init volume:
+ if (m_fadeDuration > 0){
+ m_volume1 = 0;
+ m_volume2 = 1;
+ } else {
+ m_volume1 = 1;
+ m_volume2 = 0;
+ }
+ updateVolume();
+}
+
+float MediaObjectAudioNode::applyCurve(float volume)
+{
+ float newValue = 0;
+ if (volume > 0)
+ newValue = float(0.5f * (2 + log10(volume)));
+ return newValue;
+}
+
+void MediaObjectAudioNode::updateCrossFade(qint64 currentTime)
+{
+ // Assume that currentTime starts at 0 and progress.
+ if (m_fadeDuration > 0){
+ float volume = float(currentTime) / float(m_fadeDuration);
+ if (volume >= 1){
+ volume = 1;
+ m_fadeDuration = 0;
+ }
+ m_volume1 = applyCurve(volume);
+ m_volume2 = 1 - volume;
+ updateVolume();
+ }
+}
+
+bool MediaObjectAudioNode::isCrossFading()
+{
+ return (m_fadeDuration > 0);
+}
+
+void MediaObjectAudioNode::cancelCrossFade()
+{
+ m_fadeDuration = 0;
+ m_volume1 = 1;
+ m_volume2 = 0;
+ updateVolume();
+}
+
+void MediaObjectAudioNode::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()){
+ case MediaNodeEvent::AudioGraphAboutToBeDeleted:
+ m_connection1->invalidate();
+ m_connection2->invalidate();
+ break;
+ case MediaNodeEvent::AudioGraphCannotPlay:
+ case MediaNodeEvent::AudioGraphInitialized:
+ updateVolume();
+ break;
+ default:
+ break;
+ }
+
+ m_player1->mediaNodeEvent(event);
+ m_player2->mediaNodeEvent(event);
+ m_mixer->mediaNodeEvent(event);
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/quicktimeaudioplayer.h b/src/3rdparty/phonon/qt7/quicktimeaudioplayer.h
new file mode 100644
index 0000000..25ddb5e
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimeaudioplayer.h
@@ -0,0 +1,112 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_QUICKTIMEAUDIOPLAYER_H
+#define Phonon_QT7_QUICKTIMEAUDIOPLAYER_H
+
+#include "backendheader.h"
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ #include <QuickTime/QuickTime.h>
+ #undef check // avoid name clash;
+#endif
+
+#include <phonon/mediasource.h>
+#include <Carbon/Carbon.h>
+#include <QtCore/QString>
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioGraph;
+ class MediaNodeEvent;
+ class QuickTimeVideoPlayer;
+
+ class QuickTimeAudioPlayer : public AudioNode
+ {
+ public:
+ enum State {Playing, Paused, NoMedia, NoState};
+
+ QuickTimeAudioPlayer();
+ virtual ~QuickTimeAudioPlayer();
+
+ void play();
+ void pause();
+ void seek(quint64 milliseconds);
+ void enableAudio(bool enable);
+ bool audioEnabled();
+ void flush();
+
+ void setVideoPlayer(QuickTimeVideoPlayer *videoPlayer);
+ void unsetVideoPlayer();
+
+ bool hasAudio();
+ bool isPlaying();
+ void scheduleAudioToGraph();
+ long regularTaskFrequency();
+ quint64 currentTime();
+ QString currentTimeString();
+ QuickTimeVideoPlayer *videoPlayer();
+
+ ComponentDescription getAudioNodeDescription() const;
+ void initializeAudioUnit();
+ bool fillInStreamSpecification(AudioConnection *connection, ConnectionSide side);
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+ static bool soundPlayerIsAwailable();
+
+ private:
+ void initSoundExtraction();
+ void newGraphNotification();
+ void allocateSoundSlices();
+ void scheduleSoundSlices();
+
+ State m_state;
+ QuickTimeVideoPlayer *m_videoPlayer;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ MovieAudioExtractionRef m_audioExtractionRef;
+#endif
+
+ ScheduledAudioSlice *m_sliceList;
+ AudioChannelLayout *m_audioChannelLayout;
+ UInt32 m_audioChannelLayoutSize;
+ AudioStreamBasicDescription m_audioStreamDescription;
+
+ bool m_discrete;
+ bool m_playerUnitStarted;
+ bool m_audioExtractionComplete;
+ bool m_audioEnabled;
+ bool m_audioUnitIsReset;
+
+ long m_samplesRemaining;
+ int m_sliceCount;
+ int m_maxExtractionPacketCount;
+
+ Float64 m_sampleTimeStamp;
+ quint64 m_startTime;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_QUICKTIMEAUDIOPLAYER_H
diff --git a/src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm b/src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm
new file mode 100644
index 0000000..aefec02
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm
@@ -0,0 +1,493 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#import <QTKit/QTMovie.h>
+
+#include "quicktimeaudioplayer.h"
+#include "quicktimevideoplayer.h"
+#include "audiograph.h"
+#include "medianodeevent.h"
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+QuickTimeAudioPlayer::QuickTimeAudioPlayer() : AudioNode(0, 1)
+{
+ m_state = NoMedia;
+ m_videoPlayer = 0;
+ m_audioChannelLayout = 0;
+ m_sliceList = 0;
+ m_sliceCount = 30;
+ m_maxExtractionPacketCount = 4096;
+ m_audioExtractionComplete = false;
+ m_audioEnabled = true;
+ m_samplesRemaining = -1;
+ m_startTime = 0;
+ m_sampleTimeStamp = 0;
+ m_audioUnitIsReset = true;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ m_audioExtractionRef = 0;
+#endif
+}
+
+QuickTimeAudioPlayer::~QuickTimeAudioPlayer()
+{
+ unsetVideoPlayer();
+}
+
+void QuickTimeAudioPlayer::unsetVideoPlayer()
+{
+ if (m_audioUnit){
+ OSStatus err = AudioUnitReset(m_audioUnit, kAudioUnitScope_Global, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not reset audio player unit when unsetting movie", FATAL_ERROR)
+ }
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_audioExtractionRef && m_videoPlayer && m_videoPlayer->hasMovie())
+ MovieAudioExtractionEnd(m_audioExtractionRef);
+ m_audioExtractionRef = 0;
+#endif
+
+ if (m_audioChannelLayout){
+ free(m_audioChannelLayout);
+ m_audioChannelLayout = 0;
+ }
+
+ if (m_sliceList){
+ for (int i=0; i<m_sliceCount; i++)
+ free(m_sliceList[i].mBufferList);
+ free(m_sliceList);
+ m_sliceList = 0;
+ }
+
+ m_videoPlayer = 0;
+ m_audioExtractionComplete = false;
+ m_samplesRemaining = -1;
+ m_sampleTimeStamp = 0;
+ m_state = NoMedia;
+}
+
+void QuickTimeAudioPlayer::enableAudio(bool enable)
+{
+ // Remember to seek after enabling audio.
+ if (enable == m_audioEnabled)
+ return;
+
+ m_audioEnabled = enable;
+ if (!enable)
+ flush();
+}
+
+bool QuickTimeAudioPlayer::audioEnabled()
+{
+ return m_audioEnabled;
+}
+
+void QuickTimeAudioPlayer::setVideoPlayer(QuickTimeVideoPlayer *videoPlayer)
+{
+ unsetVideoPlayer();
+ if (videoPlayer && videoPlayer->hasMovie()){
+ m_videoPlayer = videoPlayer;
+ initSoundExtraction();
+ allocateSoundSlices();
+ m_state = Paused;
+ seek(0);
+ }
+}
+
+QuickTimeVideoPlayer *QuickTimeAudioPlayer::videoPlayer()
+{
+ return m_videoPlayer;
+}
+
+void QuickTimeAudioPlayer::scheduleAudioToGraph()
+{
+ if (!m_videoPlayer || !m_audioEnabled || m_audioExtractionComplete || m_state != Playing)
+ return;
+
+ // Schedule audio slices, and detect if everything went OK.
+ // If not, flag the need for another audio system, but let
+ // the end app know about it:
+ gClearError();
+ scheduleSoundSlices();
+ if (gGetErrorType() != NO_ERROR){
+ gClearError();
+ if (m_audioGraph)
+ m_audioGraph->setStatusCannotPlay();
+ }
+}
+
+void QuickTimeAudioPlayer::flush()
+{
+ // Empty scheduled audio data, so playback
+ // will stop. Call seek to refill data again.
+ if (m_audioUnit){
+ m_startTime = currentTime();
+ OSStatus err = AudioUnitReset(m_audioUnit, kAudioUnitScope_Global, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not reset audio player unit on pause", FATAL_ERROR)
+ m_audioUnitIsReset = true;
+ }
+}
+
+void QuickTimeAudioPlayer::pause()
+{
+ m_state = Paused;
+ flush();
+}
+
+void QuickTimeAudioPlayer::play()
+{
+ m_state = Playing;
+ if (!m_audioEnabled)
+ return;
+ if (m_audioUnitIsReset)
+ seek(m_startTime);
+ else
+ scheduleAudioToGraph();
+}
+
+bool QuickTimeAudioPlayer::isPlaying()
+{
+ return m_videoPlayer && m_state == Playing;
+}
+
+void QuickTimeAudioPlayer::seek(quint64 milliseconds)
+{
+ if (!m_videoPlayer || !m_videoPlayer->hasMovie())
+ return;
+ if (milliseconds > m_videoPlayer->duration())
+ milliseconds = m_videoPlayer->duration();
+ if (!m_audioUnitIsReset && milliseconds == currentTime())
+ return;
+
+ m_startTime = milliseconds;
+
+ // Since the graph may be running (advancing time), there is
+ // no point in seeking if were not going to play immidiatly:
+ if (m_state != Playing)
+ return;
+ if (!m_audioUnit)
+ return;
+ if (!m_audioEnabled || !m_videoPlayer->isSeekable())
+ return;
+
+ // Reset (and stop playing):
+ OSStatus err;
+ if (!m_audioUnitIsReset){
+ err = AudioUnitReset(m_audioUnit, kAudioUnitScope_Global, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not reset audio player unit before seek", FATAL_ERROR)
+ }
+ m_sampleTimeStamp = 0;
+ for (int i = 0; i < m_sliceCount; i++)
+ m_sliceList[i].mFlags = kScheduledAudioSliceFlag_Complete;
+
+ // Start to play again immidiatly:
+ AudioTimeStamp timeStamp;
+ memset(&timeStamp, 0, sizeof(timeStamp));
+ timeStamp.mFlags = kAudioTimeStampSampleTimeValid;
+ timeStamp.mSampleTime = -1;
+ err = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_ScheduleStartTimeStamp, kAudioUnitScope_Global,
+ 0, &timeStamp, sizeof(timeStamp));
+ BACKEND_ASSERT2(err == noErr, "Could not set schedule start time stamp on audio player unit", FATAL_ERROR)
+
+ // Seek back to 'now' in the movie:
+ TimeRecord timeRec;
+ timeRec.scale = m_videoPlayer->timeScale();
+ timeRec.base = 0;
+ timeRec.value.hi = 0;
+ timeRec.value.lo = (milliseconds / 1000.0f) * timeRec.scale;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ err = MovieAudioExtractionSetProperty(m_audioExtractionRef,
+ kQTPropertyClass_MovieAudioExtraction_Movie,
+ kQTMovieAudioExtractionMoviePropertyID_CurrentTime,
+ sizeof(TimeRecord), &timeRec);
+ BACKEND_ASSERT2(err == noErr, "Could not set current time on audio player unit", FATAL_ERROR)
+#endif
+
+ float durationLeftSec = float(m_videoPlayer->duration() - milliseconds) / 1000.0f;
+ m_samplesRemaining = (durationLeftSec > 0) ? (durationLeftSec * m_audioStreamDescription.mSampleRate) : -1;
+ m_audioExtractionComplete = false;
+ m_audioUnitIsReset = false;
+ scheduleAudioToGraph();
+
+}
+
+quint64 QuickTimeAudioPlayer::currentTime()
+{
+ if (!m_audioUnit){
+ if (m_videoPlayer)
+ return m_videoPlayer->currentTime();
+ else
+ return m_startTime;
+ }
+
+ Float64 currentUnitTime = getTimeInSamples(kAudioUnitProperty_CurrentPlayTime);
+ if (currentUnitTime == -1)
+ currentUnitTime = 0;
+
+ quint64 cTime = quint64(m_startTime +
+ float(currentUnitTime / float(m_audioStreamDescription.mSampleRate)) * 1000.0f);
+ return (m_videoPlayer && cTime > m_videoPlayer->duration()) ? m_videoPlayer->duration() : cTime;
+}
+
+QString QuickTimeAudioPlayer::currentTimeString()
+{
+ return QuickTimeVideoPlayer::timeToString(currentTime());
+}
+
+bool QuickTimeAudioPlayer::hasAudio()
+{
+ if (!m_videoPlayer)
+ return false;
+
+ return m_videoPlayer->hasAudio();
+}
+
+bool QuickTimeAudioPlayer::soundPlayerIsAwailable()
+{
+ QuickTimeAudioPlayer player;
+ ComponentDescription d = player.getAudioNodeDescription();
+ return FindNextComponent(0, &d);
+}
+
+ComponentDescription QuickTimeAudioPlayer::getAudioNodeDescription() const
+{
+ ComponentDescription description;
+ description.componentType = kAudioUnitType_Generator;
+ description.componentSubType = kAudioUnitSubType_ScheduledSoundPlayer;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+ return description;
+}
+
+void QuickTimeAudioPlayer::initializeAudioUnit()
+{
+}
+
+bool QuickTimeAudioPlayer::fillInStreamSpecification(AudioConnection *connection, ConnectionSide side)
+{
+ if (!m_videoPlayer){
+ if (side == Source)
+ DEBUG_AUDIO_STREAM("QuickTimeAudioPlayer" << int(this) << "is source, but has no movie to use for stream spec fill.")
+ return true;
+ }
+
+ if (side == Source){
+ DEBUG_AUDIO_STREAM("QuickTimeAudioPlayer" << int(this) << "is source, and fills in stream spec from movie.")
+ connection->m_sourceStreamDescription = m_audioStreamDescription;
+ connection->m_sourceChannelLayout = (AudioChannelLayout *) malloc(m_audioChannelLayoutSize);
+ memcpy(connection->m_sourceChannelLayout, m_audioChannelLayout, m_audioChannelLayoutSize);
+ connection->m_sourceChannelLayoutSize = m_audioChannelLayoutSize;
+ connection->m_hasSourceSpecification = true;
+ }
+ return true;
+}
+
+long QuickTimeAudioPlayer::regularTaskFrequency(){
+ if (!m_audioEnabled || !m_audioUnit || (m_audioGraph && m_audioGraph->graphCannotPlay()))
+ return INT_MAX;
+
+ // Calculate how much audio in
+ // milliseconds our slices can hold:
+ int packetNeedPerSecond = m_audioStreamDescription.mSampleRate / m_maxExtractionPacketCount;
+ long bufferTimeLengthSec = float(m_sliceCount) / float(packetNeedPerSecond);
+ // Make sure we also get some time to fill the
+ // buffer, so divide the time by two:
+ return (bufferTimeLengthSec * (1000 / 2));
+}
+
+void QuickTimeAudioPlayer::initSoundExtraction()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+ // Initilize the extraction:
+ OSStatus err = noErr;
+ err = MovieAudioExtractionBegin([m_videoPlayer->qtMovie() quickTimeMovie], 0, &m_audioExtractionRef);
+ BACKEND_ASSERT2(err == noErr, "Could not start audio extraction on audio player unit", FATAL_ERROR)
+ m_discrete = false;
+#if 0
+ // Extract all channels as descrete:
+ err = MovieAudioExtractionSetProperty(audioExtractionRef,
+ kQTPropertyClass_MovieAudioExtraction_Movie,
+ kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete,
+ sizeof (discrete),
+ &discrete);
+ BACKEND_ASSERT2(err == noErr, "Could not set channels discrete on audio player unit", FATAL_ERROR)
+#endif
+
+ // Get the size of the audio channel layout (may include offset):
+ err = MovieAudioExtractionGetPropertyInfo(m_audioExtractionRef,
+ kQTPropertyClass_MovieAudioExtraction_Audio,
+ kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
+ 0, &m_audioChannelLayoutSize, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not get channel layout size from audio extraction", FATAL_ERROR)
+
+ // Allocate memory for the layout
+ m_audioChannelLayout = (AudioChannelLayout *) calloc(1, m_audioChannelLayoutSize);
+ BACKEND_ASSERT2(m_audioChannelLayout, "Could not allocate memory for channel layout on audio player unit", FATAL_ERROR)
+
+ // Get the layout:
+ err = MovieAudioExtractionGetProperty(m_audioExtractionRef,
+ kQTPropertyClass_MovieAudioExtraction_Audio,
+ kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
+ m_audioChannelLayoutSize, m_audioChannelLayout, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not get channel layout from audio extraction", FATAL_ERROR)
+
+ // Get audio stream description:
+ err = MovieAudioExtractionGetProperty(m_audioExtractionRef,
+ kQTPropertyClass_MovieAudioExtraction_Audio,
+ kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
+ sizeof(m_audioStreamDescription), &m_audioStreamDescription, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not get audio stream description from audio extraction", FATAL_ERROR)
+
+#endif // QUICKTIME_C_API_AVAILABLE
+}
+
+void QuickTimeAudioPlayer::allocateSoundSlices()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+ // m_sliceList will contain a specified number of ScheduledAudioSlice-s that each can
+ // carry audio from extraction, and be scheduled for playback at an audio unit.
+ // Each ScheduledAudioSlice will contain several audio buffers, one for each sound channel.
+ // Each buffer will carry (at most) a specified number of sound packets, and each packet can
+ // contain one or more frames.
+
+ // Create a list of ScheduledAudioSlices:
+ m_sliceList = (ScheduledAudioSlice *) calloc(m_sliceCount, sizeof(ScheduledAudioSlice));
+ BACKEND_ASSERT2(m_sliceList, "Could not allocate memory for audio slices", FATAL_ERROR)
+ bzero(m_sliceList, m_sliceCount * sizeof(ScheduledAudioSlice));
+
+ // Calculate the size of the different structures needed:
+ int packetsBufferSize = m_maxExtractionPacketCount * m_audioStreamDescription.mBytesPerPacket;
+ int channels = m_audioStreamDescription.mChannelsPerFrame;
+ int audioBufferListSize = int(sizeof(AudioBufferList) + (channels-1) * sizeof(AudioBuffer));
+ int mallocSize = audioBufferListSize + (packetsBufferSize * m_audioStreamDescription.mChannelsPerFrame);
+
+ // Round off to Altivec sizes:
+ packetsBufferSize = int(((packetsBufferSize + 15) / 16) * 16);
+ audioBufferListSize = int(((audioBufferListSize + 15) / 16) * 16);
+
+ for (int sliceIndex = 0; sliceIndex < m_sliceCount; ++sliceIndex){
+ // Create the memory chunk for this audio slice:
+ AudioBufferList *audioBufferList = (AudioBufferList*) calloc(1, mallocSize);
+ BACKEND_ASSERT2(audioBufferList, "Could not allocate memory for audio buffer list", FATAL_ERROR)
+
+ // The AudioBufferList contains an AudioBuffer for each channel in the audio stream:
+ audioBufferList->mNumberBuffers = m_audioStreamDescription.mChannelsPerFrame;
+ for (uint i = 0; i < audioBufferList->mNumberBuffers; ++i){
+ audioBufferList->mBuffers[i].mNumberChannels = 1;
+ audioBufferList->mBuffers[i].mData = (char *) audioBufferList + audioBufferListSize + (i * packetsBufferSize);
+ audioBufferList->mBuffers[i].mDataByteSize = packetsBufferSize;
+ }
+
+ m_sliceList[sliceIndex].mBufferList = audioBufferList;
+ m_sliceList[sliceIndex].mNumberFrames = m_maxExtractionPacketCount;
+ m_sliceList[sliceIndex].mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
+ m_sliceList[sliceIndex].mCompletionProcUserData = 0;
+ m_sliceList[sliceIndex].mCompletionProc = 0;
+ m_sliceList[sliceIndex].mFlags = kScheduledAudioSliceFlag_Complete;
+ m_sliceList[sliceIndex].mReserved = 0;
+ }
+
+#endif // QUICKTIME_C_API_AVAILABLE
+}
+
+void QuickTimeAudioPlayer::scheduleSoundSlices()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+ PhononAutoReleasePool pool;
+ // For each completed (or never used) slice, fill and schedule it.
+ for (int sliceIndex = 0; sliceIndex < m_sliceCount; ++sliceIndex){
+ if (m_sliceList[sliceIndex].mFlags & kScheduledAudioSliceFlag_Complete){
+ if (m_samplesRemaining == 0)
+ m_audioExtractionComplete = true;
+
+ if (!m_audioExtractionComplete){
+ // Determine how many samples to read:
+ int samplesCount = m_samplesRemaining;
+ if ((samplesCount > m_maxExtractionPacketCount) || (samplesCount == -1))
+ samplesCount = m_maxExtractionPacketCount;
+ m_sliceList[sliceIndex].mTimeStamp.mSampleTime = m_sampleTimeStamp;
+
+ // Reset buffer sizes:
+ int byteSize = samplesCount * m_audioStreamDescription.mBytesPerPacket;
+ for (uint i = 0; i < m_sliceList[sliceIndex].mBufferList->mNumberBuffers; ++i)
+ m_sliceList[sliceIndex].mBufferList->mBuffers[i].mDataByteSize = byteSize;
+
+ // Do the extraction:
+ UInt32 flags = 0;
+ UInt32 samplesRead = samplesCount;
+ OSStatus err = MovieAudioExtractionFillBuffer(
+ m_audioExtractionRef, &samplesRead, m_sliceList[sliceIndex].mBufferList, &flags);
+ BACKEND_ASSERT2(err == noErr, "Could not fill audio buffers from audio extraction", FATAL_ERROR)
+ m_audioExtractionComplete = (flags & kQTMovieAudioExtractionComplete);
+
+ // Play the slice:
+ if (samplesRead != 0 && m_audioUnit != 0){
+ m_sliceList[sliceIndex].mNumberFrames = samplesRead;
+ err = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_ScheduleAudioSlice, kAudioUnitScope_Global,
+ 0, &m_sliceList[sliceIndex], sizeof(ScheduledAudioSlice));
+ BACKEND_ASSERT2(err == noErr, "Could not schedule audio buffers on audio unit", FATAL_ERROR)
+ } else
+ m_sliceList[sliceIndex].mFlags = kScheduledAudioSliceFlag_Complete;
+
+ // Move the window:
+ m_sampleTimeStamp += samplesRead;
+ if (m_samplesRemaining != -1)
+ m_samplesRemaining -= samplesRead;
+ }
+ }
+ }
+
+#endif // QUICKTIME_C_API_AVAILABLE
+}
+
+void QuickTimeAudioPlayer::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()){
+ case MediaNodeEvent::AudioGraphAboutToBeDeleted:
+ case MediaNodeEvent::AboutToRestartAudioStream:
+ case MediaNodeEvent::StartConnectionChange:
+ m_startTime = currentTime();
+ break;
+ case MediaNodeEvent::AudioGraphInitialized:
+ case MediaNodeEvent::RestartAudioStreamRequest:
+ case MediaNodeEvent::EndConnectionChange:
+ if (m_state == Playing)
+ seek(m_startTime);
+ break;
+ default:
+ break;
+ }
+}
+
+}}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/qt7/quicktimemetadata.h b/src/3rdparty/phonon/qt7/quicktimemetadata.h
new file mode 100644
index 0000000..d524183
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimemetadata.h
@@ -0,0 +1,67 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_QUICKTIMEMETADATA_H
+#define Phonon_QT7_QUICKTIMEMETADATA_H
+
+#include "backendheader.h"
+#include <phonon/mediasource.h>
+#include <Carbon/Carbon.h>
+#include <QtCore/QString>
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ #include <QuickTime/QuickTime.h>
+ #undef check // avoid name clash;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeVideoPlayer;
+ class QuickTimeMetaData
+ {
+ public:
+ QuickTimeMetaData();
+ virtual ~QuickTimeMetaData();
+
+ void setVideo(QuickTimeVideoPlayer *videoPlayer);
+ QMultiMap<QString, QString> metaData();
+
+ private:
+ QMultiMap<QString, QString> m_metaData;
+ bool m_movieChanged;
+ QuickTimeVideoPlayer *m_videoPlayer;
+ void readMetaData();
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QString stripCopyRightSymbol(const QString &key);
+ QString convertQuickTimeKeyToUserKey(const QString &key);
+ OSStatus readMetaValue(QTMetaDataRef, QTMetaDataItem, QTPropertyClass, QTPropertyID, QTPropertyValuePtr *, ByteCount *);
+ UInt32 getMetaType(QTMetaDataRef metaDataRef, QTMetaDataItem item);
+ QString getMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, SInt32 id);
+ void readFormattedData(QTMetaDataRef metaDataRef, OSType format, QMultiMap<QString, QString> &result);
+#endif // QUICKTIME_C_API_AVAILABLE
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_QUICKTIMEMETADATA_H
diff --git a/src/3rdparty/phonon/qt7/quicktimemetadata.mm b/src/3rdparty/phonon/qt7/quicktimemetadata.mm
new file mode 100644
index 0000000..4ae3e2c
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimemetadata.mm
@@ -0,0 +1,187 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#import <QTKit/QTMovie.h>
+
+#include "quicktimemetadata.h"
+#include "quicktimevideoplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+QuickTimeMetaData::QuickTimeMetaData()
+{
+ m_videoPlayer = 0;
+ m_movieChanged = false;
+}
+
+QuickTimeMetaData::~QuickTimeMetaData()
+{
+}
+
+void QuickTimeMetaData::setVideo(QuickTimeVideoPlayer *videoPlayer)
+{
+ m_videoPlayer = videoPlayer;
+ m_movieChanged = true;
+ m_metaData.clear();
+}
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+QString QuickTimeMetaData::stripCopyRightSymbol(const QString &key)
+{
+ return key.right(key.length()-1);
+}
+
+QString QuickTimeMetaData::convertQuickTimeKeyToUserKey(const QString &key)
+{
+ if (key == QLatin1String("com.apple.quicktime.displayname"))
+ return QLatin1String("nam");
+ else if (key == QLatin1String("com.apple.quicktime.album"))
+ return QLatin1String("alb");
+ else if (key == QLatin1String("com.apple.quicktime.artist"))
+ return QLatin1String("ART");
+ else
+ return QLatin1String("???");
+}
+
+OSStatus QuickTimeMetaData::readMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, QTPropertyClass propClass,
+ QTPropertyID id, QTPropertyValuePtr *value, ByteCount *size)
+{
+ QTPropertyValueType type;
+ ByteCount propSize;
+ UInt32 propFlags;
+ OSStatus err = QTMetaDataGetItemPropertyInfo(metaDataRef, item, propClass, id, &type, &propSize, &propFlags);
+ BACKEND_ASSERT3(err == noErr, "Could not read meta data value size", NORMAL_ERROR, err)
+
+ *value = malloc(propSize);
+
+ err = QTMetaDataGetItemProperty(metaDataRef, item, propClass, id, propSize, *value, size);
+ BACKEND_ASSERT3(err == noErr, "Could not read meta data value", NORMAL_ERROR, err)
+
+ if (type == 'code' || type == 'itsk' || type == 'itlk') {
+ // convert from native endian to big endian
+ OSTypePtr pType = (OSTypePtr)*value;
+ *pType = EndianU32_NtoB(*pType);
+ }
+
+ return err;
+}
+
+UInt32 QuickTimeMetaData::getMetaType(QTMetaDataRef metaDataRef, QTMetaDataItem item)
+{
+ QTPropertyValuePtr value = 0;
+ ByteCount ignore = 0;
+ OSStatus err = readMetaValue(
+ metaDataRef, item, kPropertyClass_MetaDataItem, kQTMetaDataItemPropertyID_DataType, &value, &ignore);
+ BACKEND_ASSERT3(err == noErr, "Could not read meta data type", NORMAL_ERROR, 0)
+ UInt32 type = *((UInt32 *) value);
+ if (value)
+ free(value);
+ return type;
+}
+
+QString QuickTimeMetaData::getMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, SInt32 id)
+{
+ QTPropertyValuePtr value = 0;
+ ByteCount size = 0;
+ OSStatus err = readMetaValue(metaDataRef, item, kPropertyClass_MetaDataItem, id, &value, &size);
+ BACKEND_ASSERT3(err == noErr, "Could not read meta data item", NORMAL_ERROR, QString())
+ BACKEND_ASSERT3(value != 0, "Could not read meta data item", NORMAL_ERROR, QString())
+
+ QString string;
+ UInt32 dataType = getMetaType(metaDataRef, item);
+ switch (dataType){
+ case kQTMetaDataTypeUTF8:
+ case kQTMetaDataTypeMacEncodedText:
+ string = PhononCFString::toQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF8, false));
+ break;
+ case kQTMetaDataTypeUTF16BE:
+ string = PhononCFString::toQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF16BE, false));
+ break;
+ default:
+ break;
+ }
+
+ if (value)
+ free(value);
+ return string;
+}
+
+void QuickTimeMetaData::readFormattedData(QTMetaDataRef metaDataRef, OSType format, QMultiMap<QString, QString> &result)
+{
+ QTMetaDataItem item = kQTMetaDataItemUninitialized;
+ OSStatus err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item);
+ while (err == noErr){
+ QString key = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Key);
+ if (format == kQTMetaDataStorageFormatQuickTime)
+ key = convertQuickTimeKeyToUserKey(key);
+ else
+ key = stripCopyRightSymbol(key);
+
+ if (!result.contains(key)){
+ QString val = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Value);
+ result.insert(key, val);
+ }
+ err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item);
+ }
+}
+
+#endif // QUICKTIME_C_API_AVAILABLE
+
+void QuickTimeMetaData::readMetaData()
+{
+ if (!m_videoPlayer)
+ return;
+ QMultiMap<QString, QString> metaMap;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QTMetaDataRef metaDataRef;
+ OSStatus err = QTCopyMovieMetaData([m_videoPlayer->qtMovie() quickTimeMovie], &metaDataRef);
+ BACKEND_ASSERT2(err == noErr, "Could not read QuickTime meta data", NORMAL_ERROR)
+
+ readFormattedData(metaDataRef, kQTMetaDataStorageFormatUserData, metaMap);
+ readFormattedData(metaDataRef, kQTMetaDataStorageFormatQuickTime, metaMap);
+ readFormattedData(metaDataRef, kQTMetaDataStorageFormatiTunes, metaMap);
+#else
+ NSString *name = [m_videoPlayer->qtMovie() attributeForKey:@"QTMovieDisplayNameAttribute"];
+ metaMap.insert(QLatin1String("nam"), QString::fromUtf8([name UTF8String]));
+#endif // QUICKTIME_C_API_AVAILABLE
+
+ m_metaData.insert(QLatin1String("ARTIST"), metaMap.value(QLatin1String("ART")));
+ m_metaData.insert(QLatin1String("ALBUM"), metaMap.value(QLatin1String("alb")));
+ m_metaData.insert(QLatin1String("TITLE"), metaMap.value(QLatin1String("nam")));
+ m_metaData.insert(QLatin1String("DATE"), metaMap.value(QLatin1String("day")));
+ m_metaData.insert(QLatin1String("GENRE"), metaMap.value(QLatin1String("gnre")));
+ m_metaData.insert(QLatin1String("TRACKNUMBER"), metaMap.value(QLatin1String("trk")));
+ m_metaData.insert(QLatin1String("DESCRIPTION"), metaMap.value(QLatin1String("des")));
+}
+
+QMultiMap<QString, QString> QuickTimeMetaData::metaData()
+{
+ if (m_videoPlayer && m_videoPlayer->hasMovie() && m_movieChanged)
+ readMetaData();
+ return m_metaData;
+}
+
+}}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/quicktimestreamreader.h b/src/3rdparty/phonon/qt7/quicktimestreamreader.h
new file mode 100644
index 0000000..0e7590c
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimestreamreader.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_QUICKTIMESTREAMREADER_H
+#define Phonon_QT7_QUICKTIMESTREAMREADER_H
+
+#include <phonon/mediasource.h>
+#include <phonon/streaminterface.h>
+#include <QtCore/QReadWriteLock>
+
+#ifndef QT_MAC_USE_COCOA
+#include <QuickTime/Movies.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeStreamReader : public QObject, Phonon::StreamInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::StreamInterface)
+
+ public:
+ QuickTimeStreamReader(const Phonon::MediaSource &source);
+ ~QuickTimeStreamReader();
+
+ int readData(long offset, long size, void *data);
+ bool readAllData();
+ QByteArray *pointerToData();
+ void writeData(const QByteArray &data);
+ void endOfData();
+ void setStreamSize(qint64 newSize);
+ qint64 streamSize() const;
+ void setStreamSeekable(bool s);
+ bool streamSeekable() const;
+ void setCurrentPos(qint64 pos);
+ qint64 currentPos() const;
+ int currentBufferSize() const;
+#ifndef QT_MAC_USE_COCOA
+ Movie movieRef();
+#endif
+
+ QByteArray m_buffer;
+ mutable QReadWriteLock m_lock;
+ bool m_seekable;
+ qint64 m_pos;
+ qint64 m_size;
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_QUICKTIMESTREAMREADER_H
diff --git a/src/3rdparty/phonon/qt7/quicktimestreamreader.mm b/src/3rdparty/phonon/qt7/quicktimestreamreader.mm
new file mode 100644
index 0000000..7131616
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimestreamreader.mm
@@ -0,0 +1,137 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backendheader.h"
+#include "quicktimestreamreader.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+QuickTimeStreamReader::QuickTimeStreamReader(const Phonon::MediaSource &source)
+{
+ connectToSource(source);
+}
+
+QuickTimeStreamReader::~QuickTimeStreamReader()
+{
+}
+
+bool QuickTimeStreamReader::readAllData()
+{
+ int oldSize = m_buffer.size();
+ while (m_buffer.size() < m_size){
+ needData();
+ if (oldSize == currentBufferSize())
+ BACKEND_ASSERT3(oldSize != currentBufferSize(),
+ "Could not create new movie from IO stream. Not enough free memory to preload the whole movie.",
+ FATAL_ERROR, false)
+ oldSize = m_buffer.size();
+ }
+ return true;
+}
+
+QByteArray *QuickTimeStreamReader::pointerToData()
+{
+ return &m_buffer;
+}
+
+int QuickTimeStreamReader::readData(long offset, long size, void *data)
+{
+// QReadLocker readLocker(&m_lock);
+ if (streamSize() != 1 && offset + size > streamSize()){
+ size = streamSize() - offset;
+ }
+
+ if (currentPos() - currentBufferSize() != offset)
+ setCurrentPos(offset);
+
+ int oldSize = currentBufferSize();
+ while (currentBufferSize() < int(size)) {
+ needData();
+ if (oldSize == currentBufferSize())
+ break;
+ oldSize = currentBufferSize();
+ }
+
+ int bytesRead = qMin(currentBufferSize(), int(size));
+// QWriteLocker writeLocker(&m_lock);
+ qMemCopy(data, m_buffer.data(), bytesRead);
+ m_buffer = m_buffer.mid(bytesRead);
+
+ return bytesRead;
+}
+
+void QuickTimeStreamReader::writeData(const QByteArray &data)
+{
+ QWriteLocker locker(&m_lock);
+ m_pos += data.size();
+ m_buffer += data;
+}
+
+void QuickTimeStreamReader::endOfData()
+{
+}
+
+void QuickTimeStreamReader::setStreamSize(qint64 newSize)
+{
+ m_size = newSize;
+}
+
+qint64 QuickTimeStreamReader::streamSize() const
+{
+ return m_size;
+}
+
+void QuickTimeStreamReader::setStreamSeekable(bool s)
+{
+ m_seekable = s;
+}
+
+bool QuickTimeStreamReader::streamSeekable() const
+{
+ return m_seekable;
+}
+
+void QuickTimeStreamReader::setCurrentPos(qint64 pos)
+{
+ QWriteLocker locker(&m_lock);
+ m_pos = pos;
+ seekStream(pos);
+ m_buffer.clear();
+}
+
+qint64 QuickTimeStreamReader::currentPos() const
+{
+ return m_pos;
+}
+
+int QuickTimeStreamReader::currentBufferSize() const
+{
+ QReadLocker locker(&m_lock);
+ return m_buffer.size();
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_quicktimestreamreader.cpp"
+
diff --git a/src/3rdparty/phonon/qt7/quicktimevideoplayer.h b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h
new file mode 100644
index 0000000..0b3aec2
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h
@@ -0,0 +1,167 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_QUICKTIMEVIDEOPLAYER_H
+#define Phonon_QT7_QUICKTIMEVIDEOPLAYER_H
+
+#include "backendheader.h"
+
+#import <QTKit/QTDataReference.h>
+#import <QTKit/QTMovie.h>
+
+#include <phonon/mediasource.h>
+#include <Carbon/Carbon.h>
+#include <QtCore/QString>
+#include <QtOpenGL/QGLPixelBuffer>
+#include "videoframe.h"
+
+QT_BEGIN_NAMESPACE
+
+class QGLContext;
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeStreamReader;
+ class VideoRenderWidgetQTMovieView;
+
+ class QuickTimeVideoPlayer : QObject
+ {
+ public:
+ enum StateEnum {
+ Playing = 0x1,
+ Paused = 0x2,
+ NoMedia = 0x4,
+ };
+ Q_DECLARE_FLAGS(State, StateEnum);
+
+ QuickTimeVideoPlayer();
+ virtual ~QuickTimeVideoPlayer();
+
+ void setMediaSource(const MediaSource &source);
+ MediaSource mediaSource() const;
+ void unsetVideo();
+
+ void play();
+ void pause();
+ void seek(quint64 milliseconds);
+
+ bool videoFrameChanged();
+ CVOpenGLTextureRef currentFrameAsCVTexture();
+ GLuint currentFrameAsGLTexture();
+ void *currentFrameAsCIImage();
+ QImage currentFrameAsQImage();
+ QRect videoRect() const;
+
+ quint64 duration() const;
+ quint64 currentTime() const;
+ long timeScale() const;
+ QString currentTimeString();
+
+ void setColors(qreal brightness = 0, qreal contrast = 1, qreal hue = 0, qreal saturation = 1);
+ void setMasterVolume(float volume);
+ void setRelativeVolume(float volume);
+ void setVolume(float masterVolume, float relativeVolume);
+ void setMute(bool mute);
+ void enableAudio(bool enable);
+ bool audioEnabled();
+ bool setAudioDevice(int id);
+ void setPlaybackRate(float rate);
+ QTMovie *qtMovie() const;
+
+ float playbackRate() const;
+ float prefferedPlaybackRate() const;
+
+ QuickTimeVideoPlayer::State state() const;
+
+ bool hasAudio() const;
+ bool hasVideo() const;
+ bool hasMovie() const;
+ bool canPlayMedia() const;
+ bool isPlaying() const;
+ bool isSeekable() const;
+ bool isDrmProtected() const;
+ bool isDrmAuthorized() const;
+
+ bool preRollMovie(qint64 startTime = 0);
+ float percentageLoaded();
+ quint64 timeLoaded();
+
+ static QString timeToString(quint64 ms);
+
+ // Help functions when drawing to more that one widget in cocoa 64:
+ void *m_primaryRenderingTarget;
+ void setPrimaryRenderingTarget(NSObject *target);
+
+ void *primaryRenderingCIImage();
+ void setPrimaryRenderingCIImage(void *ciImage);
+
+ private:
+ QTMovie *m_QTMovie;
+ State m_state;
+ QGLPixelBuffer *m_QImagePixelBuffer;
+
+ bool m_playbackRateSat;
+ bool m_isDrmProtected;
+ bool m_isDrmAuthorized;
+ bool m_mute;
+ bool m_audioEnabled;
+ bool m_hasVideo;
+ float m_masterVolume;
+ float m_relativeVolume;
+ float m_playbackRate;
+ quint64 m_currentTime;
+ MediaSource m_mediaSource;
+ void *m_primaryRenderingCIImage;
+ qreal m_brightness;
+ qreal m_contrast;
+ qreal m_hue;
+ qreal m_saturation;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QTVisualContextRef m_visualContext;
+#endif
+ VideoFrame m_currentFrame;
+ QuickTimeStreamReader *m_streamReader;
+
+ void createVisualContext();
+ void openMovieFromCurrentMediaSource();
+ void openMovieFromDataRef(QTDataReference *dataRef);
+ void openMovieFromFile();
+ void openMovieFromUrl();
+ void openMovieFromStream();
+ void openMovieFromData(QByteArray *data, char *fileType);
+ void openMovieFromDataGuessType(QByteArray *data);
+ QString mediaSourcePath();
+ bool codecExistsAccordingToSuffix(const QString &fileName);
+
+ void setError(NSError *error);
+ bool errorOccured();
+ void readProtection();
+ void checkIfVideoAwailable();
+ bool movieNotLoaded();
+ void waitStatePlayable();
+ };
+
+ Q_DECLARE_OPERATORS_FOR_FLAGS(QuickTimeVideoPlayer::State);
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_QUICKTIMEVIDEOPLAYER_H
diff --git a/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
new file mode 100644
index 0000000..3f76132
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
@@ -0,0 +1,955 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "quicktimevideoplayer.h"
+#include "mediaobject.h"
+#include "videowidget.h"
+#include "audiodevice.h"
+#include "quicktimestreamreader.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QEventLoop>
+#include <QtCore/QFileInfo>
+#include <QtCore/QUrl>
+#include <QtOpenGL/QGLContext>
+
+#import <QTKit/QTTrack.h>
+#import <QTKit/QTMedia.h>
+#import <QuartzCore/CIContext.h>
+#import <QuartzCore/CIFilter.h>
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ #include <QuickTime/QuickTime.h>
+ #undef check // avoid name clash;
+ #include <AGL/agl.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+// Defined in videowidget.cpp:
+QGLWidget *PhononSharedQGLWidget();
+
+QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0)
+{
+ m_state = NoMedia;
+ m_mediaSource = MediaSource();
+ m_QTMovie = 0;
+ m_streamReader = 0;
+ m_playbackRate = 1.0f;
+ m_masterVolume = 1.0f;
+ m_relativeVolume = 1.0f;
+ m_currentTime = 0;
+ m_mute = false;
+ m_audioEnabled = false;
+ m_hasVideo = false;
+ m_playbackRateSat = false;
+ m_isDrmProtected = false;
+ m_isDrmAuthorized = true;
+ m_primaryRenderingTarget = 0;
+ m_primaryRenderingCIImage = 0;
+ m_QImagePixelBuffer = 0;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ OSStatus err = EnterMovies();
+ BACKEND_ASSERT2(err == noErr, "Could not initialize QuickTime", FATAL_ERROR)
+ createVisualContext();
+#endif
+}
+
+QuickTimeVideoPlayer::~QuickTimeVideoPlayer()
+{
+ unsetVideo();
+ [(NSObject*)m_primaryRenderingTarget release];
+ m_primaryRenderingTarget = 0;
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_visualContext)
+ CFRelease(m_visualContext);
+#endif
+}
+
+void QuickTimeVideoPlayer::createVisualContext()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ PhononSharedQGLWidget()->makeCurrent();
+
+ PhononAutoReleasePool pool;
+ CGLContextObj cglContext = CGLGetCurrentContext();
+ NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat];
+ CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>([nsglPixelFormat CGLPixelFormatObj]);
+ BACKEND_ASSERT2(cglContext, "Could not get current CoreVideo GL context (OpenGL)", FATAL_ERROR)
+ BACKEND_ASSERT2(cglPixelFormat, "Could not get current CoreVideo pixel format (OpenGL)", FATAL_ERROR)
+
+ CFTypeRef keys[] = { kQTVisualContextWorkingColorSpaceKey };
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CFDictionaryRef textureContextAttributes = CFDictionaryCreate(kCFAllocatorDefault,
+ (const void **)keys,
+ (const void **)&colorSpace, 1,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ OSStatus err = QTOpenGLTextureContextCreate(kCFAllocatorDefault, cglContext,
+ cglPixelFormat, textureContextAttributes, &m_visualContext);
+ CFRelease(textureContextAttributes);
+ BACKEND_ASSERT2(err == noErr, "Could not create visual context (OpenGL)", FATAL_ERROR)
+#endif // QUICKTIME_C_API_AVAILABLE
+}
+
+bool QuickTimeVideoPlayer::videoFrameChanged()
+{
+ if (!m_QTMovie || !m_hasVideo)
+ return false;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_primaryRenderingTarget)
+ return true;
+ if (!m_visualContext)
+ return false;
+
+ QTVisualContextTask(m_visualContext);
+ return QTVisualContextIsNewImageAvailable(m_visualContext, 0);
+
+#elif defined(QT_MAC_USE_COCOA)
+ return true;
+
+#else
+ return false;
+#endif
+}
+
+CVOpenGLTextureRef QuickTimeVideoPlayer::currentFrameAsCVTexture()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (!m_visualContext)
+ return 0;
+ CVOpenGLTextureRef texture = 0;
+ OSStatus err = QTVisualContextCopyImageForTime(m_visualContext, 0, 0, &texture);
+ BACKEND_ASSERT3(err == noErr, "Could not copy image for time in QuickTime player", FATAL_ERROR, 0)
+ return texture;
+
+#else
+ return 0;
+#endif
+}
+
+QImage QuickTimeVideoPlayer::currentFrameAsQImage()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QGLContext *prevContext = const_cast<QGLContext *>(QGLContext::currentContext());
+ CVOpenGLTextureRef texture = currentFrameAsCVTexture();
+ GLenum target = CVOpenGLTextureGetTarget(texture);
+ GLfloat lowerLeft[2], lowerRight[2], upperRight[2], upperLeft[2];
+
+ if (!m_QImagePixelBuffer){
+ m_QImagePixelBuffer = new QGLPixelBuffer(videoRect().size(), QGLFormat::defaultFormat(), PhononSharedQGLWidget());
+ m_QImagePixelBuffer->makeCurrent();
+ glEnable(target);
+ glDisable(GL_BLEND);
+ glDisable(GL_CULL_FACE);
+ } else {
+ m_QImagePixelBuffer->makeCurrent();
+ }
+
+ CVOpenGLTextureGetCleanTexCoords(texture, upperLeft, upperRight, lowerRight, lowerLeft);
+ glBindTexture(target, CVOpenGLTextureGetName(texture));
+ glBegin(GL_QUADS);
+ glTexCoord2f(lowerLeft[0], lowerLeft[1]);
+ glVertex2i(-1, 1);
+ glTexCoord2f(lowerRight[0], lowerRight[1]);
+ glVertex2i(1, 1);
+ glTexCoord2f(upperRight[0], upperRight[1]);
+ glVertex2i(1, -1);
+ glTexCoord2f(upperLeft[0], upperLeft[1]);
+ glVertex2i(-1, -1);
+ glEnd();
+
+ QImage image = m_QImagePixelBuffer->toImage();
+ CVOpenGLTextureRelease(texture);
+ // Because of QuickTime, m_QImagePixelBuffer->doneCurrent() will fail.
+ // So we store, and restore, the context our selves:
+ prevContext->makeCurrent();
+ return image;
+#else
+ CIImage *img = (CIImage *)currentFrameAsCIImage();
+ if (!img)
+ return QImage();
+
+ NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
+ CGRect bounds = [img extent];
+ QImage qImg([bitmap bitmapData], bounds.size.width, bounds.size.height, QImage::Format_ARGB32);
+ QImage swapped = qImg.rgbSwapped();
+ [bitmap release];
+ [img release];
+ return swapped;
+#endif
+}
+
+void QuickTimeVideoPlayer::setPrimaryRenderingCIImage(void *ciImage)
+{
+ [(CIImage *)m_primaryRenderingCIImage release];
+ m_primaryRenderingCIImage = ciImage;
+ [(CIImage *)m_primaryRenderingCIImage retain];
+}
+
+void QuickTimeVideoPlayer::setPrimaryRenderingTarget(NSObject *target)
+{
+ [(NSObject*)m_primaryRenderingTarget release];
+ m_primaryRenderingTarget = target;
+ [(NSObject*)m_primaryRenderingTarget retain];
+}
+
+void *QuickTimeVideoPlayer::primaryRenderingCIImage()
+{
+ return m_primaryRenderingCIImage;
+}
+
+void *QuickTimeVideoPlayer::currentFrameAsCIImage()
+{
+ if (!m_QTMovie)
+ return 0;
+
+#if defined(QT_MAC_USE_COCOA)
+ if (m_primaryRenderingCIImage){
+ CIImage *img = (CIImage *)m_primaryRenderingCIImage;
+ if (m_brightness || m_contrast || m_saturation){
+ CIFilter *colorFilter = [CIFilter filterWithName:@"CIColorControls"];
+ [colorFilter setValue:[NSNumber numberWithFloat:m_brightness] forKey:@"inputBrightness"];
+ [colorFilter setValue:[NSNumber numberWithFloat:(m_contrast < 1) ? m_contrast : 1 + ((m_contrast-1)*3)] forKey:@"inputContrast"];
+ [colorFilter setValue:[NSNumber numberWithFloat:m_saturation] forKey:@"inputSaturation"];
+ [colorFilter setValue:img forKey:@"inputImage"];
+ img = [colorFilter valueForKey:@"outputImage"];
+ }
+ if (m_hue){
+ CIFilter *colorFilter = [CIFilter filterWithName:@"CIHueAdjust"];
+ [colorFilter setValue:[NSNumber numberWithFloat:(m_hue * 3.14)] forKey:@"inputAngle"];
+ [colorFilter setValue:img forKey:@"inputImage"];
+ img = [colorFilter valueForKey:@"outputImage"];
+ }
+ return [img retain];
+ }
+#endif
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ CVOpenGLTextureRef cvImg = currentFrameAsCVTexture();
+ CIImage *img = [[CIImage alloc] initWithCVImageBuffer:cvImg];
+ CVOpenGLTextureRelease(cvImg);
+ return img;
+#else
+ return 0;
+#endif
+}
+
+GLuint QuickTimeVideoPlayer::currentFrameAsGLTexture()
+{
+ CIImage *img = (CIImage *)currentFrameAsCIImage();
+ if (!img)
+ return 0;
+
+ NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
+ GLuint texName = 0;
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap pixelsWide]);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glGenTextures(1, &texName);
+ glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texName);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ int samplesPerPixel = [bitmap samplesPerPixel];
+ if (![bitmap isPlanar] && (samplesPerPixel == 3 || samplesPerPixel == 4)){
+ glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0,
+ samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
+ [bitmap pixelsWide], [bitmap pixelsHigh],
+ 0, samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
+ GL_UNSIGNED_BYTE, [bitmap bitmapData]);
+ } else {
+ // Handle other bitmap formats.
+ }
+
+ [bitmap release];
+ [img release];
+ return texName;
+}
+
+void QuickTimeVideoPlayer::setMasterVolume(float volume)
+{
+ setVolume(volume, m_relativeVolume);
+}
+
+void QuickTimeVideoPlayer::setRelativeVolume(float volume)
+{
+ setVolume(m_masterVolume, volume);
+}
+
+void QuickTimeVideoPlayer::setVolume(float masterVolume, float relativeVolume)
+{
+ m_masterVolume = masterVolume;
+ m_relativeVolume = relativeVolume;
+ if (!m_QTMovie || !m_audioEnabled || m_mute)
+ return;
+ [m_QTMovie setVolume:(m_masterVolume * m_relativeVolume)];
+}
+
+void QuickTimeVideoPlayer::setMute(bool mute)
+{
+ m_mute = mute;
+ if (!m_QTMovie || m_state != Playing || !m_audioEnabled)
+ return;
+
+ // Work-around bug that happends if you set/unset mute
+ // before movie is playing, and audio is not played
+ // through graph. Then audio is delayed.
+ [m_QTMovie setMuted:mute];
+ [m_QTMovie setVolume:(mute ? 0 : m_masterVolume * m_relativeVolume)];
+}
+
+void QuickTimeVideoPlayer::enableAudio(bool enable)
+{
+ m_audioEnabled = enable;
+ if (!m_QTMovie || m_state != Playing)
+ return;
+
+ // Work-around bug that happends if you set/unset mute
+ // before movie is playing, and audio is not played
+ // through graph. Then audio is delayed.
+ [m_QTMovie setMuted:(!enable || m_mute)];
+ [m_QTMovie setVolume:((!enable || m_mute) ? 0 : m_masterVolume * m_relativeVolume)];
+}
+
+bool QuickTimeVideoPlayer::audioEnabled()
+{
+ return m_audioEnabled;
+}
+
+bool QuickTimeVideoPlayer::setAudioDevice(int id)
+{
+ if (!m_QTMovie)
+ return false;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ // The following code will not work for some media codecs that
+ // typically mingle audio/video frames (e.g mpeg).
+ CFStringRef idString = PhononCFString::toCFStringRef(AudioDevice::deviceUID(id));
+ QTAudioContextRef context;
+ QTAudioContextCreateForAudioDevice(kCFAllocatorDefault, idString, 0, &context);
+ OSStatus err = SetMovieAudioContext([m_QTMovie quickTimeMovie], context);
+ CFRelease(context);
+ if (err != noErr)
+ return false;
+ return true;
+#else
+ Q_UNUSED(id);
+ return false;
+#endif
+}
+
+void QuickTimeVideoPlayer::setColors(qreal brightness, qreal contrast, qreal hue, qreal saturation)
+{
+ if (!m_QTMovie)
+ return;
+
+ // 0 is default value for the colors
+ // in phonon, so adjust scale:
+ contrast += 1;
+ saturation += 1;
+
+ m_brightness = brightness;
+ m_contrast = contrast;
+ m_hue = hue;
+ m_saturation = saturation;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ Float32 value;
+ value = brightness;
+ SetMovieVisualBrightness([m_QTMovie quickTimeMovie], value, 0);
+ value = contrast;
+ SetMovieVisualContrast([m_QTMovie quickTimeMovie], value, 0);
+ value = hue;
+ SetMovieVisualHue([m_QTMovie quickTimeMovie], value, 0);
+ value = saturation;
+ SetMovieVisualSaturation([m_QTMovie quickTimeMovie], value, 0);
+#endif
+}
+
+QRect QuickTimeVideoPlayer::videoRect() const
+{
+ if (!m_QTMovie)
+ return QRect();
+
+ PhononAutoReleasePool pool;
+ NSSize size = [[m_QTMovie attributeForKey:@"QTMovieCurrentSizeAttribute"] sizeValue];
+ return QRect(0, 0, size.width, size.height);
+}
+
+void QuickTimeVideoPlayer::unsetVideo()
+{
+ if (!m_QTMovie)
+ return;
+
+ [m_QTMovie release];
+ m_QTMovie = 0;
+ delete m_streamReader;
+ m_streamReader = 0;
+ m_currentTime = 0;
+ m_state = NoMedia;
+ m_isDrmProtected = false;
+ m_isDrmAuthorized = true;
+ m_mediaSource = MediaSource();
+ [(CIImage *)m_primaryRenderingCIImage release];
+ m_primaryRenderingCIImage = 0;
+ delete m_QImagePixelBuffer;
+ m_QImagePixelBuffer = 0;
+}
+
+QuickTimeVideoPlayer::State QuickTimeVideoPlayer::state() const
+{
+ return m_state;
+}
+
+quint64 QuickTimeVideoPlayer::timeLoaded()
+{
+ if (!m_QTMovie)
+ return 0;
+#ifdef QUICKTIME_C_API_AVAILABLE
+ TimeValue value;
+ GetMaxLoadedTimeInMovie([m_QTMovie quickTimeMovie], &value);
+ quint64 loaded = static_cast<quint64>(float(value) / float(GetMovieTimeScale([m_QTMovie quickTimeMovie])) * 1000.0f);
+ return (loaded == INT_MAX) ? 0 : loaded;
+#else
+ return 0;
+#endif
+}
+
+float QuickTimeVideoPlayer::percentageLoaded()
+{
+ if (!m_QTMovie || !isSeekable())
+ return 0;
+#ifdef QUICKTIME_C_API_AVAILABLE
+ TimeValue loaded;
+ GetMaxLoadedTimeInMovie([m_QTMovie quickTimeMovie], &loaded);
+ float duration = GetMovieDuration([m_QTMovie quickTimeMovie]);
+ return duration ? float(loaded) / duration : 0;
+#else
+ return 0;
+#endif
+}
+
+void QuickTimeVideoPlayer::waitStatePlayable()
+{
+#if defined(QT_MAC_USE_COCOA)
+ long state = [[m_QTMovie attributeForKey:@"QTMovieLoadStateAttribute"] longValue];
+ while (state != QTMovieLoadStateError && state < QTMovieLoadStatePlayable)
+ state = [[m_QTMovie attributeForKey:@"QTMovieLoadStateAttribute"] longValue];
+#elif defined(QUICKTIME_C_API_AVAILABLE)
+ long state = GetMovieLoadState([m_QTMovie quickTimeMovie]);
+ while (state != kMovieLoadStateError && state < kMovieLoadStatePlayable){
+ MoviesTask(0, 0);
+ state = GetMovieLoadState([m_QTMovie quickTimeMovie]);
+ }
+#endif
+}
+
+bool QuickTimeVideoPlayer::movieNotLoaded()
+{
+ if (!m_QTMovie)
+ return true;
+
+#if defined(QT_MAC_USE_COCOA)
+ long state = [[m_QTMovie attributeForKey:@"QTMovieLoadStateAttribute"] longValue];
+ return state == QTMovieLoadStateError;
+#elif defined(QUICKTIME_C_API_AVAILABLE)
+ long state = GetMovieLoadState([m_QTMovie quickTimeMovie]);
+ return state == kMovieLoadStateError;
+#endif
+}
+
+void QuickTimeVideoPlayer::setError(NSError *error)
+{
+ if (!error)
+ return;
+ QString desc = QString::fromUtf8([[error localizedDescription] UTF8String]);
+ if (desc == "The file is not a movie file.")
+ desc = QLatin1String("Could not decode media source.");
+ else if (desc == "A necessary data reference could not be resolved."){
+ if (codecExistsAccordingToSuffix(mediaSourcePath()))
+ desc = QLatin1String("Could not locate media source.");
+ else
+ desc = QLatin1String("Could not decode media source.");
+ } else if (desc == "You do not have sufficient permissions for this operation.")
+ desc = QLatin1String("Could not open media source.");
+ SET_ERROR(desc, FATAL_ERROR)
+}
+
+bool QuickTimeVideoPlayer::errorOccured()
+{
+ if (gGetErrorType() != NO_ERROR){
+ return true;
+ } else if (movieNotLoaded()){
+ SET_ERROR("Could not open media source.", FATAL_ERROR)
+ return true;
+ }
+ return false;
+}
+
+bool QuickTimeVideoPlayer::codecExistsAccordingToSuffix(const QString &fileName)
+{
+ PhononAutoReleasePool pool;
+ NSArray *fileTypes = [QTMovie movieFileTypes:QTIncludeAllTypes];
+ for (uint i=0; i<[fileTypes count]; ++i){
+ NSString *type = [fileTypes objectAtIndex:i];
+ QString formattedType = QString::fromUtf8([type UTF8String]);
+ formattedType.remove('\'').remove('.');
+ if (fileName.endsWith(QChar('.') + formattedType, Qt::CaseInsensitive))
+ return true;
+ }
+ return false;
+}
+
+void QuickTimeVideoPlayer::setMediaSource(const MediaSource &mediaSource)
+{
+ PhononAutoReleasePool pool;
+ unsetVideo();
+ m_mediaSource = mediaSource;
+ if (mediaSource.type() == MediaSource::Empty || mediaSource.type() == MediaSource::Invalid){
+ m_state = NoMedia;
+ return;
+ }
+ openMovieFromCurrentMediaSource();
+ if (errorOccured()){
+ unsetVideo();
+ return;
+ }
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_visualContext)
+ SetMovieVisualContext([m_QTMovie quickTimeMovie], m_visualContext);
+#endif
+
+ waitStatePlayable();
+ if (errorOccured()){
+ unsetVideo();
+ return;
+ }
+
+ readProtection();
+ preRollMovie();
+ if (errorOccured()){
+ unsetVideo();
+ return;
+ }
+
+ if (!m_playbackRateSat)
+ m_playbackRate = prefferedPlaybackRate();
+ checkIfVideoAwailable();
+ enableAudio(m_audioEnabled);
+ setMute(m_mute);
+ setVolume(m_masterVolume, m_relativeVolume);
+ pause();
+}
+
+void QuickTimeVideoPlayer::openMovieFromCurrentMediaSource()
+{
+ switch (m_mediaSource.type()){
+ case MediaSource::LocalFile:
+ openMovieFromFile();
+ break;
+ case MediaSource::Url:
+ openMovieFromUrl();
+ break;
+ case MediaSource::Disc:
+ CASE_UNSUPPORTED("Could not open media source.", FATAL_ERROR)
+ break;
+ case MediaSource::Stream:
+ openMovieFromStream();
+ break;
+ case MediaSource::Empty:
+ case MediaSource::Invalid:
+ break;
+ }
+}
+
+QString QuickTimeVideoPlayer::mediaSourcePath()
+{
+ switch (m_mediaSource.type()){
+ case MediaSource::LocalFile:{
+ QFileInfo fileInfo(m_mediaSource.fileName());
+ return fileInfo.isSymLink() ? fileInfo.symLinkTarget() : fileInfo.canonicalFilePath();
+ break;}
+ case MediaSource::Url:
+ return m_mediaSource.url().toEncoded();
+ break;
+ default:
+ break;
+ }
+ return QString();
+}
+
+void QuickTimeVideoPlayer::openMovieFromDataRef(QTDataReference *dataRef)
+{
+ PhononAutoReleasePool pool;
+ NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys:
+ dataRef, QTMovieDataReferenceAttribute,
+ [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute,
+ [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute,
+ [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute,
+ [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute,
+ nil];
+
+ NSError *err = 0;
+ m_QTMovie = [[QTMovie movieWithAttributes:attr error:&err] retain];
+ if (err){
+ [m_QTMovie release];
+ m_QTMovie = 0;
+ setError(err);
+ }
+}
+
+void QuickTimeVideoPlayer::openMovieFromData(QByteArray *data, char *fileType)
+{
+ PhononAutoReleasePool pool;
+ NSString *type = [NSString stringWithUTF8String:fileType];
+ NSData *nsData = [NSData dataWithBytesNoCopy:data->data() length:data->size() freeWhenDone:NO];
+ QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToData:nsData name:type MIMEType:@""];
+ openMovieFromDataRef(dataRef);
+}
+
+void QuickTimeVideoPlayer::openMovieFromDataGuessType(QByteArray *data)
+{
+ // It turns out to be better to just try the standard file types rather
+ // than using e.g [QTMovie movieFileTypes:QTIncludeCommonTypes]. Some
+ // codecs *think* they can decode the stream, and crash...
+#define TryOpenMovieWithCodec(type) gClearError(); \
+ openMovieFromData(data, "."type); \
+ if (m_QTMovie) return;
+
+ TryOpenMovieWithCodec("avi");
+ TryOpenMovieWithCodec("mp4");
+ TryOpenMovieWithCodec("m4p");
+ TryOpenMovieWithCodec("m1s");
+ TryOpenMovieWithCodec("mp3");
+ TryOpenMovieWithCodec("mpeg");
+ TryOpenMovieWithCodec("mov");
+ TryOpenMovieWithCodec("ogg");
+ TryOpenMovieWithCodec("wav");
+ TryOpenMovieWithCodec("wmv");
+#undef TryOpenMovieWithCodec(type)
+}
+
+void QuickTimeVideoPlayer::openMovieFromFile()
+{
+ NSString *nsFilename = (NSString *)PhononCFString::toCFStringRef(mediaSourcePath());
+ QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToFile:nsFilename];
+ openMovieFromDataRef(dataRef);
+}
+
+void QuickTimeVideoPlayer::openMovieFromUrl()
+{
+ PhononAutoReleasePool pool;
+ NSString *urlString = (NSString *)PhononCFString::toCFStringRef(mediaSourcePath());
+ NSURL *url = [NSURL URLWithString: urlString];
+ QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToURL:url];
+ openMovieFromDataRef(dataRef);
+}
+
+void QuickTimeVideoPlayer::openMovieFromStream()
+{
+ m_streamReader = new QuickTimeStreamReader(m_mediaSource);
+ if (!m_streamReader->readAllData())
+ return;
+ openMovieFromDataGuessType(m_streamReader->pointerToData());
+}
+
+MediaSource QuickTimeVideoPlayer::mediaSource() const
+{
+ return m_mediaSource;
+}
+
+QTMovie *QuickTimeVideoPlayer::qtMovie() const
+{
+ return m_QTMovie;
+}
+
+void QuickTimeVideoPlayer::setPlaybackRate(float rate)
+{
+ PhononAutoReleasePool pool;
+ m_playbackRateSat = true;
+ m_playbackRate = rate;
+ if (m_QTMovie)
+ [m_QTMovie setRate:m_playbackRate];
+}
+
+float QuickTimeVideoPlayer::playbackRate() const
+{
+ return m_playbackRate;
+}
+
+quint64 QuickTimeVideoPlayer::currentTime() const
+{
+ if (!m_QTMovie || m_state == Paused)
+ return m_currentTime;
+
+ PhononAutoReleasePool pool;
+ QTTime qtTime = [m_QTMovie currentTime];
+ quint64 t = static_cast<quint64>(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f);
+ const_cast<QuickTimeVideoPlayer *>(this)->m_currentTime = t;
+ return m_currentTime;
+}
+
+long QuickTimeVideoPlayer::timeScale() const
+{
+ if (!m_QTMovie)
+ return 0;
+
+ PhononAutoReleasePool pool;
+ return [[m_QTMovie attributeForKey:@"QTMovieTimeScaleAttribute"] longValue];
+}
+
+QString QuickTimeVideoPlayer::timeToString(quint64 ms)
+{
+ int sec = ms/1000;
+ int min = sec/60;
+ int hour = min/60;
+ return QString(QLatin1String("%1:%2:%3:%4")).arg(hour%60).arg(min%60).arg(sec%60).arg(ms%1000);
+}
+
+QString QuickTimeVideoPlayer::currentTimeString()
+{
+ return timeToString(currentTime());
+}
+
+quint64 QuickTimeVideoPlayer::duration() const
+{
+ if (!m_QTMovie)
+ return 0;
+
+ PhononAutoReleasePool pool;
+ QTTime qtTime = [m_QTMovie duration];
+ return static_cast<quint64>(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f);
+}
+
+void QuickTimeVideoPlayer::play()
+{
+ if (!canPlayMedia())
+ return;
+
+ PhononAutoReleasePool pool;
+ m_state = Playing;
+ enableAudio(m_audioEnabled);
+ setMute(m_mute);
+ [m_QTMovie setRate:m_playbackRate];
+}
+
+void QuickTimeVideoPlayer::pause()
+{
+ if (!canPlayMedia())
+ return;
+
+ PhononAutoReleasePool pool;
+ currentTime();
+ m_state = Paused;
+
+ if (isSeekable())
+ [m_QTMovie setRate:0];
+ else // pretend to be paused:
+ [m_QTMovie setMuted:0];
+}
+
+void QuickTimeVideoPlayer::seek(quint64 milliseconds)
+{
+ if (!canPlayMedia() || !isSeekable() || milliseconds == currentTime())
+ return;
+ if (milliseconds > duration())
+ milliseconds = duration();
+
+ PhononAutoReleasePool pool;
+ QTTime newQTTime = [m_QTMovie currentTime];
+ newQTTime.timeValue = (milliseconds / 1000.0f) * newQTTime.timeScale;
+ [m_QTMovie setCurrentTime:newQTTime];
+
+ // The movie might not have been able to seek
+ // to the exact point we told it to. So set
+ // the current time according to what the movie says:
+ newQTTime = [m_QTMovie currentTime];
+ m_currentTime = static_cast<quint64>
+ (float(newQTTime.timeValue) / float(newQTTime.timeScale) * 1000.0f);
+
+ if (m_state == Paused){
+ // We need (for reasons unknown) to task
+ // the movie twize to make sure that
+ // a subsequent call to frameAsCvTexture
+ // returns the correct frame:
+#ifdef QUICKTIME_C_API_AVAILABLE
+ MoviesTask(0, 0);
+ MoviesTask(0, 0);
+#elif defined(QT_MAC_USE_COCOA)
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
+#endif
+ }
+}
+
+bool QuickTimeVideoPlayer::canPlayMedia() const
+{
+ if (!m_QTMovie)
+ return false;
+ return m_isDrmAuthorized;
+}
+
+bool QuickTimeVideoPlayer::isPlaying() const
+{
+ return m_state == Playing;
+}
+
+bool QuickTimeVideoPlayer::isSeekable() const
+{
+ return canPlayMedia() && (duration()-1) != INT_MAX;
+}
+
+float QuickTimeVideoPlayer::prefferedPlaybackRate() const
+{
+ if (!m_QTMovie)
+ return 0;
+
+ PhononAutoReleasePool pool;
+ return [[m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue];
+}
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+void MoviePrePrerollCompleteCallBack(Movie /*theMovie*/, OSErr /*thePrerollErr*/, void * /*userData*/)
+{
+ // QuickTimeVideoPlayer *player = static_cast<QuickTimeVideoPlayer *>(userData);
+}
+#endif
+
+bool QuickTimeVideoPlayer::preRollMovie(qint64 startTime)
+{
+ if (!canPlayMedia())
+ return false;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (PrePrerollMovie([m_QTMovie quickTimeMovie], startTime, FloatToFixed(m_playbackRate),
+ 0 /*MoviePrePrerollCompleteCallBack*/, this) != noErr) // No callback means wait (synch)
+ return false;
+
+ if (PrerollMovie([m_QTMovie quickTimeMovie], startTime, FloatToFixed(m_playbackRate)) != noErr)
+ return false;
+
+ return true;
+#else
+ Q_UNUSED(startTime);
+ return false;
+#endif
+}
+
+bool QuickTimeVideoPlayer::hasAudio() const
+{
+ if (!m_QTMovie)
+ return false;
+
+ PhononAutoReleasePool pool;
+ return [[m_QTMovie attributeForKey:@"QTMovieHasAudioAttribute"] boolValue] == YES;
+}
+
+bool QuickTimeVideoPlayer::hasVideo() const
+{
+ return m_hasVideo;
+}
+
+bool QuickTimeVideoPlayer::hasMovie() const
+{
+ return m_QTMovie != 0;
+}
+
+void QuickTimeVideoPlayer::checkIfVideoAwailable()
+{
+ PhononAutoReleasePool pool;
+ m_hasVideo = [[m_QTMovie attributeForKey:@"QTMovieHasVideoAttribute"] boolValue] == YES;
+}
+
+bool QuickTimeVideoPlayer::isDrmProtected() const
+{
+ return m_isDrmProtected;
+}
+
+bool QuickTimeVideoPlayer::isDrmAuthorized() const
+{
+ return m_isDrmAuthorized;
+}
+/*
+void QuickTimeVideoPlayer::movieCodecIsMPEG()
+{
+ NSArray *tracks = [m_QTMovie tracks];
+ for (QTTrack *track in tracks)
+ if ([[track media] hasCharacteristic:QTMediaTypeMPEG])
+ return true;
+ return false;
+}
+*/
+
+static void QtGetTrackProtection(QTTrack *track, bool &isDrmProtected, bool &isDrmAuthorized)
+{
+ isDrmProtected = false;
+ isDrmAuthorized = true;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QTMedia *media = [track media];
+ MediaHandler mediaHandler = GetMediaHandler([media quickTimeMedia]);
+ if (mediaHandler){
+ // Regardless, skip message boxes pointing to iTunes regarding DRM:
+ Boolean boolFalse = false;
+ QTSetComponentProperty(mediaHandler,
+ kQTPropertyClass_DRM, kQTDRMPropertyID_InteractWithUser,
+ sizeof(boolFalse), &boolFalse);
+
+ // Check track:
+ Boolean value;
+ OSStatus err = QTGetComponentProperty(mediaHandler,
+ kQTPropertyClass_DRM, kQTDRMPropertyID_IsProtected,
+ sizeof(value), &value, 0);
+ isDrmProtected = (err == noErr) ? bool(value) : false;
+ err = QTGetComponentProperty(mediaHandler,
+ kQTPropertyClass_DRM, kQTDRMPropertyID_IsAuthorized,
+ sizeof(value), &value, 0);
+ isDrmAuthorized = (err == noErr) ? bool(value) : true;
+ }
+#else
+ Q_UNUSED(track);
+#endif // QUICKTIME_C_API_AVAILABLE
+}
+
+void QuickTimeVideoPlayer::readProtection()
+{
+ m_isDrmProtected = false;
+ m_isDrmAuthorized = true;
+
+ NSArray *tracks = [m_QTMovie tracks];
+ for (uint i=0; i<[tracks count]; ++i){
+ QTTrack *track = [tracks objectAtIndex:i];
+ bool isDrmProtected = false;
+ bool isDrmAuthorized = true;
+ QtGetTrackProtection(track, isDrmProtected, isDrmAuthorized);
+ if (isDrmProtected)
+ m_isDrmProtected = true;
+ if (!isDrmAuthorized)
+ m_isDrmAuthorized = false;
+ }
+}
+
+}}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/videoeffect.h b/src/3rdparty/phonon/qt7/videoeffect.h
new file mode 100644
index 0000000..9189a6a
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videoeffect.h
@@ -0,0 +1,63 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_VIDEOEFFECT_H
+#define Phonon_QT7_VIDEOEFFECT_H
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <phonon/effectinterface.h>
+#include "medianode.h"
+#include "videoframe.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class EffectParameter;
+
+namespace QT7
+{
+ class MediaNodeEvent;
+
+ class VideoEffect : public MediaNode, public Phonon::EffectInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::EffectInterface)
+
+ public:
+ VideoEffect(int effectId, QObject *parent);
+ virtual ~VideoEffect();
+
+ QList<EffectParameter> parameters() const;
+ QVariant parameterValue(const EffectParameter &) const;
+ void setParameterValue(const EffectParameter &, const QVariant &newValue);
+
+ void updateVideo(VideoFrame &frame);
+
+ protected:
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+ private:
+ int effectId;
+ void *ciFilter;
+ QString filterName;
+ };
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_VIDEOEFFECT_H
diff --git a/src/3rdparty/phonon/qt7/videoeffect.mm b/src/3rdparty/phonon/qt7/videoeffect.mm
new file mode 100644
index 0000000..c33a919
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videoeffect.mm
@@ -0,0 +1,76 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "videoeffect.h"
+#include "backendheader.h"
+#include "objc_help.h"
+#include <phonon/effect.h>
+#include <phonon/effectparameter.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+VideoEffect::VideoEffect(int effectId, QObject *parent) : MediaNode(VideoSink | VideoSource, 0, parent), effectId(effectId)
+{
+ ciFilter = objc_createCiFilter(effectId);
+ if (ciFilter)
+ filterName = objc_getCiFilterInfo()->filterDisplayNames[effectId];
+}
+
+VideoEffect::~VideoEffect()
+{
+ if (ciFilter)
+ objc_releaseCiFilter(ciFilter);
+}
+
+QList<EffectParameter> VideoEffect::parameters() const
+{
+ IMPLEMENTED;
+ return objc_getCiFilterParameterInfo(ciFilter).parameters;
+}
+
+QVariant VideoEffect::parameterValue(const EffectParameter &parameter) const
+{
+ IMPLEMENTED;
+ return objc_getCiFilterParameter(ciFilter, parameter.id());
+}
+
+void VideoEffect::setParameterValue(const EffectParameter &parameter, const QVariant &newValue)
+{
+ IMPLEMENTED;
+ objc_setCiFilterParameter(ciFilter, parameter.id(), newValue);
+}
+
+void VideoEffect::mediaNodeEvent(const MediaNodeEvent */*event*/)
+{
+}
+
+void VideoEffect::updateVideo(VideoFrame &frame){
+ frame.applyCoreImageFilter(ciFilter);
+ MediaNode::updateVideo(frame);
+}
+
+}}
+
+QT_END_NAMESPACE
+
+#include "moc_videoeffect.cpp"
+
diff --git a/src/3rdparty/phonon/qt7/videoframe.h b/src/3rdparty/phonon/qt7/videoframe.h
new file mode 100644
index 0000000..5069607
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videoframe.h
@@ -0,0 +1,98 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_VIDEOFRAME_H
+#define Phonon_QT7_VIDEOFRAME_H
+
+#import <QuartzCore/CVOpenGLTexture.h>
+#import <AppKit/NSImage.h>
+#undef check // avoid name clash;
+
+#include <QtCore/QRect>
+#include <QtGui/QPainter>
+#include <QtGui/QImage>
+
+QT_BEGIN_NAMESPACE
+
+class QGLContext;
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeVideoPlayer;
+ class QNSBitmapImage;
+
+ class VideoFrame
+ {
+ public:
+ VideoFrame();
+ VideoFrame(QuickTimeVideoPlayer *videoPlayer);
+ VideoFrame(const VideoFrame& frame);
+ void operator=(const VideoFrame& frame);
+ ~VideoFrame();
+
+
+ CVOpenGLTextureRef cachedCVTexture() const;
+ void *cachedCIImage() const;
+ GLuint glTextureRef() const;
+
+ void drawQImage(QPainter *p, const QRect &rect) const;
+ void drawCIImage(const CGRect &rect, float opacity = 1.0f) const;
+ void drawCIImage(const QRect &rect, float opacity = 1.0f) const;
+ void drawCVTexture(const QRect &rect, float opacity = 1.0f) const;
+ void drawGLTexture(const QRect &rect, float opacity = 1.0f) const;
+
+ void applyCoreImageFilter(void *filter);
+ void setColors(qreal brightness, qreal contrast, qreal hue, qreal saturation);
+ bool hasColorAdjustments();
+ void setBaseOpacity(qreal opacity);
+ void setBackgroundFrame(const VideoFrame &frame);
+
+ bool isEmpty();
+ QRect frameRect() const;
+ QuickTimeVideoPlayer *videoPlayer();
+
+ void retain() const;
+ void release() const;
+
+ static CGRect QRectToCGRect(const QRect & qrect);
+
+ private:
+ CVOpenGLTextureRef m_cachedCVTextureRef;
+ void *m_cachedCIImage;
+ QImage m_cachedQImage;
+ NSBitmapImageRep *m_cachedNSBitmap;
+
+ QuickTimeVideoPlayer *m_videoPlayer;
+ VideoFrame *m_backgroundFrame;
+
+ qreal m_brightness;
+ qreal m_contrast;
+ qreal m_hue;
+ qreal m_saturation;
+ qreal m_opacity;
+
+ void initMembers();
+ void copyMembers(const VideoFrame& frame);
+ void invalidateImage() const;
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_VIDEOFRAME_H
diff --git a/src/3rdparty/phonon/qt7/videoframe.mm b/src/3rdparty/phonon/qt7/videoframe.mm
new file mode 100644
index 0000000..92a3cd5
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videoframe.mm
@@ -0,0 +1,378 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "videoframe.h"
+#include "quicktimevideoplayer.h"
+#import <QuartzCore/CIFilter.h>
+#import <QuartzCore/CIContext.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+ VideoFrame::VideoFrame()
+ {
+ initMembers();
+ }
+
+ VideoFrame::VideoFrame(QuickTimeVideoPlayer *videoPlayer)
+ {
+ initMembers();
+ m_videoPlayer = videoPlayer;
+ }
+
+ VideoFrame::VideoFrame(const VideoFrame& frame)
+ {
+ copyMembers(frame);
+ retain();
+ }
+
+ void VideoFrame::operator=(const VideoFrame& frame)
+ {
+ if (this == &frame)
+ return;
+
+ release();
+ copyMembers(frame);
+ retain();
+ }
+
+ void VideoFrame::initMembers()
+ {
+ m_cachedCVTextureRef = 0;
+ m_cachedCIImage = 0;
+ m_cachedNSBitmap = 0;
+ m_videoPlayer = 0;
+ m_brightness = 0;
+ m_contrast = 0;
+ m_hue = 0;
+ m_saturation = 0;
+ m_opacity = 1;
+ m_backgroundFrame = 0;
+ }
+
+ void VideoFrame::copyMembers(const VideoFrame& frame)
+ {
+ m_cachedCVTextureRef = frame.m_cachedCVTextureRef;
+ m_cachedCIImage = frame.m_cachedCIImage;
+ m_cachedQImage = frame.m_cachedQImage;
+ m_cachedNSBitmap = frame.m_cachedNSBitmap;
+ m_videoPlayer = frame.m_videoPlayer;
+ m_brightness = frame.m_brightness;
+ m_contrast = frame.m_contrast;
+ m_hue = frame.m_hue;
+ m_saturation = frame.m_saturation;
+ m_opacity = frame.m_opacity;
+ m_backgroundFrame = frame.m_backgroundFrame;
+ }
+
+ VideoFrame::~VideoFrame()
+ {
+ release();
+ }
+
+ QuickTimeVideoPlayer *VideoFrame::videoPlayer()
+ {
+ return m_videoPlayer;
+ }
+
+ void VideoFrame::setBackgroundFrame(const VideoFrame &frame)
+ {
+ m_backgroundFrame = new VideoFrame(frame);
+ }
+
+ QRect VideoFrame::frameRect() const
+ {
+ return m_videoPlayer->videoRect();
+ }
+
+ CVOpenGLTextureRef VideoFrame::cachedCVTexture() const
+ {
+ if (!m_cachedCVTextureRef && m_videoPlayer){
+ m_videoPlayer->setColors(m_brightness, m_contrast, m_hue, m_saturation);
+ (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = m_videoPlayer->currentFrameAsCVTexture();
+ }
+ return m_cachedCVTextureRef;
+ }
+
+ void *VideoFrame::cachedCIImage() const
+ {
+ if (!m_cachedCIImage && m_videoPlayer){
+ m_videoPlayer->setColors(m_brightness, m_contrast, m_hue, m_saturation);
+ (const_cast<VideoFrame *>(this))->m_cachedCIImage = m_videoPlayer->currentFrameAsCIImage();
+ }
+ return m_cachedCIImage;
+ }
+
+ GLuint VideoFrame::glTextureRef() const
+ {
+ return CVOpenGLTextureGetName(cachedCVTexture());
+ }
+
+ void VideoFrame::setColors(qreal brightness, qreal contrast, qreal hue, qreal saturation)
+ {
+ if (m_backgroundFrame)
+ m_backgroundFrame->setColors(brightness, contrast, hue, saturation);
+ if (m_brightness == brightness
+ && m_contrast == contrast
+ && m_hue == hue
+ && m_saturation == saturation)
+ return;
+
+ m_brightness = brightness;
+ m_contrast = contrast;
+ m_hue = hue;
+ m_saturation = saturation;
+
+ invalidateImage();
+ }
+
+ CGRect VideoFrame::QRectToCGRect(const QRect & qrect)
+ {
+ CGRect cgrect;
+ cgrect.origin.x = qrect.x();
+ cgrect.origin.y = qrect.y() + qrect.height();
+ cgrect.size.width = qrect.width();
+ cgrect.size.height = -qrect.height();
+ return cgrect;
+ }
+
+ bool VideoFrame::hasColorAdjustments()
+ {
+ return (m_brightness || m_contrast || m_saturation || m_hue);
+ }
+
+ void VideoFrame::setBaseOpacity(qreal opacity)
+ {
+ m_opacity = opacity;
+ }
+
+ void VideoFrame::drawQImage(QPainter *p, const QRect &rect) const
+ {
+ if (!m_videoPlayer)
+ return;
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_cachedQImage.isNull()){
+ m_videoPlayer->setColors(m_brightness, m_contrast, m_hue, m_saturation);
+ (const_cast<VideoFrame *>(this))->m_cachedQImage = m_videoPlayer->currentFrameAsQImage();
+ }
+#else
+ // Since cocoa-64 doesn't give us OpenGL textures directly, the process of converting
+ // CIImges into QImages takes time. We could still call m_videoPlayer->currentFrameAsQImage(),
+ // but because of bitmap memory management issues, and the fact that we need to swap red and
+ // blue, we can optimize the process a bit here since we are going to draw immidiatly:
+ CIImage *img = (CIImage*)cachedCIImage();
+ if (!img)
+ return;
+
+ if (!m_cachedNSBitmap){
+ (const_cast<VideoFrame *>(this))->m_cachedNSBitmap =
+ [[NSBitmapImageRep alloc] initWithCIImage:img];
+ CGRect bounds = [img extent];
+ int w = bounds.size.width;
+ int h = bounds.size.height;
+ (const_cast<VideoFrame *>(this))->m_cachedQImage =
+ QImage([m_cachedNSBitmap bitmapData], w, h, QImage::Format_ARGB32);
+ // Swap red and blue (same as QImage::rgbSwapped, but without copy)
+ for (int i=0; i<h; ++i) {
+ uint *p = (uint*) m_cachedQImage.scanLine(i);
+ uint *end = p + w;
+ while (p < end) {
+ *p = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
+ p++;
+ }
+ }
+ }
+#endif
+ p->drawImage(rect, m_cachedQImage);
+ }
+
+ void VideoFrame::drawCIImage(const QRect &rect, float opacity) const
+ {
+ drawCIImage(QRectToCGRect(rect), opacity);
+ }
+
+ void VideoFrame::drawCIImage(const CGRect &rect, float opacity) const
+ {
+ Q_UNUSED(opacity);
+ CIImage *img = (CIImage *) cachedCIImage();
+ if (!img)
+ return;
+
+ CIContext* ciContext = [[NSGraphicsContext currentContext] CIContext];
+ [ciContext drawImage:img inRect:rect fromRect:[img extent]];
+ }
+
+ void VideoFrame::drawCVTexture(const QRect &rect, float opacity) const
+ {
+ if (!m_videoPlayer)
+ return;
+ if (m_backgroundFrame)
+ m_backgroundFrame->drawCVTexture(rect, opacity);
+
+ CVOpenGLTextureRef texRef = cachedCVTexture();
+ if (!texRef)
+ return;
+
+ glPushMatrix();
+ glDisable(GL_CULL_FACE);
+ GLenum target = CVOpenGLTextureGetTarget(texRef);
+ glEnable(target);
+
+ opacity *= m_opacity;
+ if (opacity < 1){
+ glEnable(GL_BLEND);
+ glColor4f(1, 1, 1, opacity);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glColor3f(1, 1, 1);
+ glDisable(GL_BLEND);
+ }
+
+ glBindTexture(target, CVOpenGLTextureGetName(texRef));
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ GLfloat lowerLeft[2], lowerRight[2], upperRight[2], upperLeft[2];
+ CVOpenGLTextureGetCleanTexCoords(texRef, lowerLeft, lowerRight, upperRight, upperLeft);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(lowerLeft[0], lowerLeft[1]);
+ glVertex2i(rect.topLeft().x(), rect.topLeft().y());
+ glTexCoord2f(lowerRight[0], lowerRight[1]);
+ glVertex2i(rect.topRight().x() + 1, rect.topRight().y());
+ glTexCoord2f(upperRight[0], upperRight[1]);
+ glVertex2i(rect.bottomRight().x() + 1, rect.bottomRight().y() + 1);
+ glTexCoord2f(upperLeft[0], upperLeft[1]);
+ glVertex2i(rect.bottomLeft().x(), rect.bottomLeft().y() + 1);
+ glEnd();
+ glPopMatrix();
+ }
+
+ void VideoFrame::drawGLTexture(const QRect &rect, float opacity) const
+ {
+ if (!m_videoPlayer)
+ return;
+ if (m_backgroundFrame)
+ m_backgroundFrame->drawGLTexture(rect, opacity);
+
+ GLuint texture = m_videoPlayer->currentFrameAsGLTexture();
+ if (!texture)
+ return;
+
+ glPushMatrix();
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_RECTANGLE_EXT);
+
+ opacity *= m_opacity;
+ if (opacity < 1){
+ glEnable(GL_BLEND);
+ glColor4f(1, 1, 1, opacity);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glColor3f(1, 1, 1);
+ glDisable(GL_BLEND);
+ }
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture);
+ glTexParameterf(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ QRect videoRect = m_videoPlayer->videoRect();
+ GLfloat lowerLeft[2], lowerRight[2], upperRight[2], upperLeft[2];
+ lowerLeft[0] = 0;
+ lowerLeft[1] = videoRect.height();
+ lowerRight[0] = videoRect.width();
+ lowerRight[1] = videoRect.height();
+ upperRight[0] = videoRect.width();
+ upperRight[1] = 0;
+ upperLeft[0] = 0;
+ upperLeft[1] = 0;
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(lowerLeft[0], lowerLeft[1]);
+ glVertex2i(rect.topLeft().x(), rect.topLeft().y());
+ glTexCoord2f(lowerRight[0], lowerRight[1]);
+ glVertex2i(rect.topRight().x() + 1, rect.topRight().y());
+ glTexCoord2f(upperRight[0], upperRight[1]);
+ glVertex2i(rect.bottomRight().x() + 1, rect.bottomRight().y() + 1);
+ glTexCoord2f(upperLeft[0], upperLeft[1]);
+ glVertex2i(rect.bottomLeft().x(), rect.bottomLeft().y() + 1);
+ glEnd();
+ glPopMatrix();
+
+
+ // FOR NOW. FREE THE TEXTURE:
+ glDeleteTextures(1, &texture);
+ }
+
+ bool VideoFrame::isEmpty()
+ {
+ return (m_videoPlayer == 0);
+ }
+
+ void VideoFrame::invalidateImage() const
+ {
+ if (m_cachedCVTextureRef){
+ CVOpenGLTextureRelease(m_cachedCVTextureRef);
+ (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0;
+ }
+ if (m_cachedCIImage){
+ [(CIImage *) m_cachedCIImage release];
+ (const_cast<VideoFrame *>(this))->m_cachedCIImage = 0;
+ }
+ if (m_cachedNSBitmap){
+ [m_cachedNSBitmap release];
+ (const_cast<VideoFrame *>(this))->m_cachedNSBitmap = 0;
+ }
+ (const_cast<VideoFrame *>(this))-> m_cachedQImage = QImage();
+ }
+
+ void VideoFrame::retain() const
+ {
+ if (m_cachedCVTextureRef)
+ CVOpenGLTextureRetain(m_cachedCVTextureRef);
+ if (m_cachedCIImage)
+ [(CIImage *) m_cachedCIImage retain];
+ if (m_backgroundFrame)
+ m_backgroundFrame->retain();
+ if (m_cachedNSBitmap)
+ [m_cachedNSBitmap retain];
+ }
+
+ void VideoFrame::release() const
+ {
+ if (m_cachedCVTextureRef)
+ CVOpenGLTextureRelease(m_cachedCVTextureRef);
+ if (m_cachedCIImage)
+ [(CIImage *) m_cachedCIImage release];
+ if (m_backgroundFrame)
+ m_backgroundFrame->release();
+ if (m_cachedNSBitmap)
+ [m_cachedNSBitmap release];
+
+ (const_cast<VideoFrame *>(this))->m_backgroundFrame = 0;
+ (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0;
+ (const_cast<VideoFrame *>(this))->m_cachedCIImage = 0;
+ (const_cast<VideoFrame *>(this))->m_cachedNSBitmap = 0;
+ }
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/videowidget.h b/src/3rdparty/phonon/qt7/videowidget.h
new file mode 100644
index 0000000..8d084ec
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videowidget.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_VIDEOWIDGET_H
+#define Phonon_QT7_VIDEOWIDGET_H
+
+#include <QtGui/QPaintEngine>
+#include <phonon/videowidgetinterface.h>
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class MediaNodeEvent;
+ class VideoRenderWidget;
+
+ class VideoWidget : public MediaNode, public Phonon::VideoWidgetInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::VideoWidgetInterface)
+
+ public:
+ VideoWidget(QObject *parent);
+ virtual ~VideoWidget();
+
+ Phonon::VideoWidget::AspectRatio aspectRatio() const;
+ void setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio);
+ qreal brightness() const;
+ void setBrightness(qreal);
+ Phonon::VideoWidget::ScaleMode scaleMode() const;
+ void setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode);
+ qreal contrast() const;
+ void setContrast(qreal);
+ qreal hue() const;
+ void setHue(qreal);
+ qreal saturation() const;
+ void setSaturation(qreal);
+
+ QWidget *widget();
+
+ void updateVideo(VideoFrame &frame);
+
+ protected:
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+ private:
+ VideoRenderWidget *m_videoRenderWidget;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_VIDEOWIDGET_H
diff --git a/src/3rdparty/phonon/qt7/videowidget.mm b/src/3rdparty/phonon/qt7/videowidget.mm
new file mode 100644
index 0000000..0600268
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videowidget.mm
@@ -0,0 +1,885 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 or 3 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <QtCore/qglobal.h>
+#ifdef QT_MAC_USE_COCOA
+#import <QTKit/QTMovieLayer.h>
+#endif
+
+#include "videowidget.h"
+#include "backendheader.h"
+#include "quicktimevideoplayer.h"
+#include "medianode.h"
+#include "medianodeevent.h"
+#include "mediaobject.h"
+
+#include <QtOpenGL/QGLWidget>
+#include <QtCore/QTime>
+#include <QtCore/QEvent>
+#include <QtCore/QCoreApplication>
+
+#import <AppKit/NSImage.h>
+#import <QTKit/QTMovieView.h>
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef QT_MAC_USE_COCOA // Rendering to a QTMovieView can only be done in Cocoa
+
+#define VIDEO_TRANSPARENT(m) -(void)m:(NSEvent *)e{[[self superview] m:e];}
+
+@interface SharedQTMovieView : QTMovieView
+{
+@private
+ Phonon::QT7::QuickTimeVideoPlayer *m_player;
+ QList<QWidget *> *m_parents;
+ QWidget *m_window;
+ QRect *m_drawRect;
+ bool m_newImageReady;
+ bool m_usingWindow;
+}
+
+- (SharedQTMovieView *) init;
+- (void) registerParent:(QWidget *)parent;
+- (void) unregisterParent:(QWidget *)parent;
+- (void) setDrawRect:(QRect &)rect;
+- (void) drawVideoFrame:(Phonon::QT7::VideoFrame &)frame forWidget:(QWidget *)widget shareImages:(bool)share;
+- (void) useOffscreenWindow:(bool)offscreen;
+- (void) applyDrawRectOnSelf;
+@end
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation SharedQTMovieView
+
+- (SharedQTMovieView *) init
+{
+ self = [super initWithFrame:NSZeroRect];
+ if (self){
+ [self setControllerVisible:NO];
+ m_parents = new QList<QWidget *>();
+ m_drawRect = new QRect(0, 0, 1, 1);
+ [self applyDrawRectOnSelf];
+ m_usingWindow = false;
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+ Phonon::QT7::PhononAutoReleasePool pool;
+ delete m_window;
+ delete m_drawRect;
+ delete m_parents;
+ [super dealloc];
+}
+
+- (void) applyDrawRectOnSelf
+{
+ NSRect nsrect;
+ nsrect.origin.x = m_drawRect->x();
+ nsrect.origin.y = m_drawRect->y();
+ nsrect.size.width = m_drawRect->width();
+ nsrect.size.height = m_drawRect->height();
+ [self setFrame:nsrect];
+}
+
+- (void) setDrawRect:(QRect &)rect
+{
+ *m_drawRect = rect;
+ if (!m_usingWindow)
+ [self applyDrawRectOnSelf];
+}
+
+- (void) waitForFrame
+{
+ if (m_usingWindow){
+ QTMovie *movie = [self movie];
+ if (movie){
+ // CIImages are expected, but not received.
+ // Try to wait a couple of seconds for them:
+ m_newImageReady = false;
+ float rate = [movie rate];
+ if (!rate)
+ [movie setRate:1];
+ QTime t; t.start();
+ while (!m_newImageReady && t.elapsed() < 2000)
+ ;
+ [movie setRate:rate];
+ }
+ }
+}
+
+- (void) useOffscreenWindow:(bool)offscreen
+{
+ if (offscreen == m_usingWindow)
+ return;
+ if (offscreen){
+ if (!m_window){
+ m_window = new QWidget;
+ m_window->setWindowOpacity(0.0);
+ m_window->show();
+ m_window->hide();
+ }
+ m_usingWindow = true;
+ [self setDelegate:self];
+ [self waitForFrame];
+ foreach(QWidget *w, *m_parents)
+ w->repaint();
+ qApp->processEvents();
+ [self removeFromSuperview];
+ [(NSView *)m_window->winId() addSubview:self];
+ } else if (!m_parents->isEmpty()){
+ m_usingWindow = false;
+ [self removeFromSuperview];
+ [(NSView*)m_parents->first()->winId() addSubview:self];
+ [self setDelegate:0];
+ [self setDrawRect:*m_drawRect];
+ }
+}
+
+- (void) drawVideoFrame:(Phonon::QT7::VideoFrame &)frame forWidget:(QWidget *)widget shareImages:(bool)share;
+{
+ // Detect if the video that produces the frame has changed:
+ Phonon::QT7::QuickTimeVideoPlayer *player = frame.videoPlayer();
+ if (player && player->qtMovie() != [self movie]){
+ m_player = player;
+ [self setMovie:player->qtMovie()];
+ [self waitForFrame];
+ }
+
+ [self useOffscreenWindow:(share || m_parents->size() > 1)];
+ if (m_usingWindow)
+ widget->update();
+}
+
+// Override this method so that the movie doesn't stop if
+// the window becomes invisible
+- (void)viewWillMoveToWindow:(NSWindow *)newWindow
+{
+ Q_UNUSED(newWindow);
+}
+
+- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img
+{
+ // This method is called from QTMovieView just
+ // before the image will be drawn.
+ Q_UNUSED(view);
+ m_player->setPrimaryRenderingCIImage(img);
+ m_newImageReady = true;
+ return img;
+}
+
+- (void) registerParent:(QWidget *)parent
+{
+ if (m_parents->contains(parent))
+ return;
+ m_parents->append(parent);
+ if (m_parents->size() == 1){
+ Phonon::QT7::PhononAutoReleasePool pool;
+ m_usingWindow = true;
+ [self applyDrawRectOnSelf];
+ [self useOffscreenWindow:NO];
+ }
+}
+
+- (void) unregisterParent:(QWidget *)parent
+{
+ m_parents->removeAll(parent);
+ if (m_parents->size() == 1)
+ [self applyDrawRectOnSelf];
+}
+
+VIDEO_TRANSPARENT(mouseDown);
+VIDEO_TRANSPARENT(mouseDragged);
+VIDEO_TRANSPARENT(mouseUp);
+VIDEO_TRANSPARENT(mouseMoved);
+VIDEO_TRANSPARENT(mouseEntered);
+VIDEO_TRANSPARENT(mouseExited);
+VIDEO_TRANSPARENT(rightMouseDown);
+VIDEO_TRANSPARENT(rightMouseDragged);
+VIDEO_TRANSPARENT(rightMouseUp);
+VIDEO_TRANSPARENT(otherMouseDown);
+VIDEO_TRANSPARENT(otherMouseDragged);
+VIDEO_TRANSPARENT(otherMouseUp);
+VIDEO_TRANSPARENT(keyDown);
+VIDEO_TRANSPARENT(keyUp);
+VIDEO_TRANSPARENT(scrollWheel)
+
+@end
+
+#endif // QT_MAC_USE_COCOA
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+class IVideoRenderDrawWidget
+{
+public:
+ virtual ~IVideoRenderDrawWidget(){}
+ virtual void setVideoFrame(VideoFrame &) = 0;
+ virtual void setDrawFrameRect(const QRect &) = 0;
+ virtual void updateVideoOutputCount(int){}
+ virtual void setMovieIsPaused(bool){}
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+QGLWidget *PhononSharedQGLWidget(){
+ static QGLWidget *glWidget = 0;
+ if (!glWidget)
+ glWidget = new QGLWidget();
+ return glWidget;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class RenderOpenGL : public QGLWidget, public IVideoRenderDrawWidget
+{
+public:
+ VideoFrame m_currentFrame;
+ QRect m_drawFrameRect;
+
+ RenderOpenGL(QWidget *parent, const QGLFormat &format, const QSize &size) : QGLWidget(format, parent, PhononSharedQGLWidget())
+ {
+ resize(size);
+ setAutoFillBackground(false);
+ show();
+ }
+
+ void initializeGL()
+ {
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ void resizeGL(int w, int h)
+ {
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glViewport(0, 0, GLsizei(w), GLsizei(h));
+ glOrtho(0, GLsizei(w), 0, GLsizei(h), -1, 1);
+ updateGL();
+ }
+
+ void paintGL()
+ {
+ glClear(GL_COLOR_BUFFER_BIT);
+ m_currentFrame.drawCVTexture(m_drawFrameRect);
+ }
+
+ void setVideoFrame(VideoFrame &frame)
+ {
+ m_currentFrame = frame;
+ makeCurrent();
+ paintGL();
+ swapBuffers();
+ }
+
+ void setDrawFrameRect(const QRect &rect)
+ {
+ m_drawFrameRect = rect;
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class RenderQTMovieView : public QWidget, public IVideoRenderDrawWidget
+{
+public:
+#if defined(QT_MAC_USE_COCOA)
+ QRect m_drawRect;
+ VideoFrame m_videoFrame;
+ SharedQTMovieView *m_currentView;
+ bool m_setDrawRectPending;
+ bool m_share;
+
+ RenderQTMovieView(bool share, QWidget *parent, const QSize &size=QSize()) : QWidget(parent), m_currentView(0)
+ {
+ m_setDrawRectPending = true;
+ m_share = share;
+ setAutoFillBackground(false);
+ if (share){
+ // In 'share' mode, this widget will only make sure
+ // that CIIImages are produced, and not actually
+ // draw anything:
+ hide();
+ } else {
+ resize(size);
+ show();
+ }
+ }
+
+ ~RenderQTMovieView()
+ {
+ [m_currentView unregisterParent:this];
+ }
+
+ void showEvent(QShowEvent *)
+ {
+ if (m_share)
+ return;
+ [m_currentView registerParent:this];
+ }
+
+ void hideEvent(QHideEvent *)
+ {
+ if (m_share)
+ return;
+ [m_currentView unregisterParent:this];
+ }
+
+ void paintEvent(QPaintEvent *)
+ {
+ if (m_share)
+ return;
+ QPainter p(this);
+ p.fillRect(rect(), Qt::black);
+ m_videoFrame.drawCIImage(m_drawRect);
+ }
+
+ void updateVideoOutputCount(int count)
+ {
+ Q_UNUSED(count);
+ }
+
+ void setMovieIsPaused(bool paused)
+ {
+ Q_UNUSED(paused);
+ }
+
+ void setVideoFrame(VideoFrame &frame)
+ {
+ m_videoFrame = frame;
+
+ if (!m_videoFrame.isEmpty()){
+ Phonon::QT7::QuickTimeVideoPlayer *player = m_videoFrame.videoPlayer();
+ if (!player->m_primaryRenderingTarget){
+ // First movie view. Create the shared resource:
+ SharedQTMovieView *view = [[[SharedQTMovieView alloc] init] autorelease];
+ player->setPrimaryRenderingTarget(view);
+ }
+
+ SharedQTMovieView *view = static_cast<SharedQTMovieView *>(player->m_primaryRenderingTarget);
+ if (!m_share && view != m_currentView){
+ [m_currentView unregisterParent:this];
+ m_currentView = view;
+ [m_currentView registerParent:this];
+ }
+
+ [view drawVideoFrame:m_videoFrame forWidget:this shareImages:m_share || m_videoFrame.hasColorAdjustments()];
+
+ if (m_setDrawRectPending){
+ m_setDrawRectPending = false;
+ [view setDrawRect:m_drawRect];
+ }
+ }
+ }
+
+ void setDrawFrameRect(const QRect &rect)
+ {
+ m_drawRect = rect;
+ Phonon::QT7::QuickTimeVideoPlayer *player = m_videoFrame.videoPlayer();
+ if (player && player->m_primaryRenderingTarget){
+ SharedQTMovieView *view = static_cast<SharedQTMovieView *>(player->m_primaryRenderingTarget);
+ [view setDrawRect:m_drawRect];
+ } else
+ m_setDrawRectPending = true;
+ }
+
+#else // QT_MAC_USE_COCOA == false
+ RenderQTMovieView(bool, QWidget *, const QSize& = QSize()){}
+ void setVideoFrame(VideoFrame &){}
+ void setDrawFrameRect(const QRect &){}
+#endif
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class RenderQTMovieLayer : public QWidget, public IVideoRenderDrawWidget
+{
+public:
+#ifdef QT_MAC_USE_COCOA
+ QTMovieLayer *m_movieLayer;
+
+ RenderQTMovieLayer(QWidget *parent, const QSize&) : QWidget(parent)
+ {
+ PhononAutoReleasePool pool;
+ setAutoFillBackground(false);
+ m_movieLayer = 0;
+ [(NSView *)winId() setWantsLayer:YES];
+ }
+
+ void setVideoFrame(VideoFrame &frame)
+ {
+ QuickTimeVideoPlayer *player = frame.videoPlayer();
+ if (!player || player->qtMovie() == [m_movieLayer movie])
+ return;
+
+ if (m_movieLayer)
+ [m_movieLayer setMovie:player->qtMovie()];
+ else {
+ m_movieLayer = [QTMovieLayer layerWithMovie:player->qtMovie()];
+ [(NSView *)winId() setLayer:m_movieLayer];
+ }
+ }
+
+ void setDrawFrameRect(const QRect &rect)
+ {
+ CGRect frame = m_movieLayer.frame;
+ frame.origin.x = rect.x();
+ frame.origin.y = rect.y();
+ frame.size.width = rect.width();
+ frame.size.height = rect.height();
+ m_movieLayer.frame = frame;
+ }
+
+#else // QT_MAC_USE_COCOA == false
+ RenderQTMovieLayer(QWidget *, const QSize&){}
+ void setVideoFrame(VideoFrame &){}
+ void setDrawFrameRect(const QRect &){}
+#endif
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class VideoRenderWidget : public QWidget
+{
+public:
+ enum RenderSystem { RS_NoRendering = 0,
+ RS_QGLWidget = 1,
+ RS_QPainter = 2,
+ RS_CIImage = 3,
+ RS_CVTexture = 4,
+ RS_QImage = 5,
+ RS_QTMovieView = 6,
+ RS_QTMovieLayer = 7
+ } m_renderSystem;
+
+ VideoFrame m_currentFrame;
+ QRect m_movieFrameRect;
+ QRect m_drawFrameRect;
+ Phonon::VideoWidget::ScaleMode m_scaleMode;
+ Phonon::VideoWidget::AspectRatio m_aspect;
+ IVideoRenderDrawWidget *m_renderDrawWidget;
+
+ qreal m_brightness;
+ qreal m_contrast;
+ qreal m_hue;
+ qreal m_saturation;
+ qreal m_opacity;
+
+ VideoRenderWidget() : QWidget(0),
+ m_scaleMode(Phonon::VideoWidget::FitInView), m_aspect(Phonon::VideoWidget::AspectRatioAuto)
+ {
+ PhononAutoReleasePool pool;
+ m_brightness = 0;
+ m_contrast = 0;
+ m_hue = 0;
+ m_saturation = 0;
+ m_opacity = 1;
+ m_renderDrawWidget = 0;
+ m_renderSystem = RS_NoRendering;
+
+ setAutoFillBackground(false);
+ updateDrawFrameRect();
+ }
+
+ RenderSystem selectBestRenderSystem(){
+ if (!isVisible())
+ return RS_NoRendering;
+ else if (window() && window()->testAttribute(Qt::WA_DontShowOnScreen))
+ return RS_QPainter;
+ else {
+#ifdef QUICKTIME_C_API_AVAILABLE
+ return RS_QGLWidget;
+#else
+ return RS_QTMovieView;
+#endif
+ }
+ }
+
+ void setRenderSystem(RenderSystem renderSystem){
+ PhononAutoReleasePool pool;
+ static QString userSystem = qgetenv("PHONON_RENDER_SYSTEM");
+ if (!userSystem.isEmpty())
+ renderSystem = RenderSystem(userSystem.toInt());
+
+ if (m_renderSystem == renderSystem)
+ return;
+
+ m_renderSystem = renderSystem;
+ if (m_renderDrawWidget){
+ delete m_renderDrawWidget;
+ m_renderDrawWidget = 0;
+ }
+
+ switch (m_renderSystem){
+ case RS_QGLWidget:{
+ QGLFormat format = QGLFormat::defaultFormat();
+ format.setSwapInterval(1); // Vertical sync (avoid tearing)
+ m_renderDrawWidget = new RenderOpenGL(this, format, size());
+ break;}
+ case RS_QTMovieView:{
+ m_renderDrawWidget = new RenderQTMovieView(false, this, size());
+ break;}
+ case RS_QTMovieLayer:{
+ m_renderDrawWidget = new RenderQTMovieLayer(this, size());
+ break;}
+ case RS_QPainter:
+ case RS_CIImage:
+ case RS_CVTexture:
+ case RS_QImage:
+#ifndef QUICKTIME_C_API_AVAILABLE
+ // On cocoa-64, let QTMovieView produce
+ // video frames for us:
+ m_renderDrawWidget = new RenderQTMovieView(true, this);
+#endif
+ break;
+ case RS_NoRendering:
+ break;
+ }
+
+ if (m_renderDrawWidget){
+ m_renderDrawWidget->setVideoFrame(m_currentFrame);
+ m_renderDrawWidget->setDrawFrameRect(m_drawFrameRect);
+ }
+ }
+
+ QSize sizeHint() const
+ {
+ return m_movieFrameRect.size();
+ }
+
+ bool event(QEvent *event)
+ {
+ switch (event->type()){
+ // Try to detect if one of this objects
+ // anchestors might have changed:
+ case QEvent::Resize:{
+ PhononAutoReleasePool pool;
+ updateDrawFrameRect();
+ if (m_renderDrawWidget)
+ dynamic_cast<QWidget *>(m_renderDrawWidget)->resize(size());
+ break; }
+ case QEvent::Paint:{
+ PhononAutoReleasePool pool;
+ float opacity = parentWidget() ? parentWidget()->windowOpacity() : 1;
+ switch (m_renderSystem){
+ case RS_QPainter:{
+ QPainter p(this);
+ p.fillRect(rect(), Qt::black);
+ if (p.paintEngine()->type() == QPaintEngine::OpenGL)
+ m_currentFrame.drawCVTexture(m_drawFrameRect, opacity);
+ else
+ m_currentFrame.drawQImage(&p, m_drawFrameRect);
+ break; }
+ case RS_CIImage:
+ m_currentFrame.drawCIImage(m_drawFrameRect, opacity);
+ break;
+ case RS_CVTexture:
+ m_currentFrame.drawCVTexture(m_drawFrameRect, opacity);
+ break;
+ case RS_QImage:{
+ QPainter p(this);
+ p.fillRect(rect(), Qt::black);
+ m_currentFrame.drawQImage(&p, m_drawFrameRect);
+ break; }
+ case RS_QGLWidget:
+ case RS_QTMovieView:
+ case RS_QTMovieLayer:
+ // draw in separate widget
+ break;
+ case RS_NoRendering:
+ QPainter p(this);
+ p.fillRect(rect(), Qt::black);
+ break;
+ }
+ break; }
+ default:
+ break;
+ }
+
+ return QWidget::event(event);
+ }
+
+ void setVideoFrame(VideoFrame &frame)
+ {
+ PhononAutoReleasePool pool;
+ m_currentFrame = frame;
+ m_currentFrame.setColors(m_brightness, m_contrast, m_hue, m_saturation);
+
+ if (m_renderDrawWidget)
+ m_renderDrawWidget->setVideoFrame(m_currentFrame);
+
+ setRenderSystem(selectBestRenderSystem());
+ switch (m_renderSystem){
+ case RS_QGLWidget:
+ case RS_QTMovieView:
+ case RS_QTMovieLayer:
+ case RS_NoRendering:
+ break;
+ case RS_CIImage:
+ case RS_CVTexture:
+ case RS_QImage:
+ case RS_QPainter:
+ repaint();
+ break;
+ }
+ }
+
+ void updateVideoFrame()
+ {
+ setVideoFrame(m_currentFrame);
+ }
+
+ void setMovieRect(const QRect &mrect)
+ {
+ if (mrect == m_movieFrameRect)
+ return;
+ m_movieFrameRect = mrect;
+ updateDrawFrameRect();
+ updateGeometry();
+ if (isVisible())
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
+ }
+
+ void setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ m_scaleMode = scaleMode;
+ updateDrawFrameRect();
+ updateVideoFrame();
+ repaint();
+ }
+
+ void setAspectRatio(Phonon::VideoWidget::AspectRatio aspect)
+ {
+ m_aspect = aspect;
+ updateDrawFrameRect();
+ updateVideoFrame();
+ repaint();
+ }
+
+ void updateVideoOutputCount(int count)
+ {
+ if (m_renderDrawWidget)
+ m_renderDrawWidget->updateVideoOutputCount(count);
+ }
+
+ void setMovieIsPaused(bool paused)
+ {
+ if (m_renderDrawWidget)
+ m_renderDrawWidget->setMovieIsPaused(paused);
+ }
+
+ void updateDrawFrameRect()
+ {
+ if (m_movieFrameRect.width() <= 0 || m_movieFrameRect.height() <= 0)
+ m_movieFrameRect = QRect(0, 0, 640, 480);
+
+ // Set m_drawFrameRect to be the size of the smallest possible
+ // rect conforming to the aspect and containing the whole frame:
+ switch(m_aspect){
+ case Phonon::VideoWidget::AspectRatioWidget:
+ m_drawFrameRect = rect();
+ break;
+ case Phonon::VideoWidget::AspectRatio4_3:
+ m_drawFrameRect = scaleToAspect(m_movieFrameRect, 4, 3);
+ break;
+ case Phonon::VideoWidget::AspectRatio16_9:
+ m_drawFrameRect = scaleToAspect(m_movieFrameRect, 16, 9);
+ break;
+ case Phonon::VideoWidget::AspectRatioAuto:
+ default:
+ m_drawFrameRect = m_movieFrameRect;
+ break;
+ }
+
+ // Scale m_drawFrameRect to fill the widget
+ // without breaking aspect:
+ int widgetWidth = rect().width();
+ int widgetHeight = rect().height();
+ int frameWidth = widgetWidth;
+ int frameHeight = m_drawFrameRect.height() * float(widgetWidth) / float(m_drawFrameRect.width());
+
+ switch(m_scaleMode){
+ case Phonon::VideoWidget::ScaleAndCrop:
+ if (frameHeight < widgetHeight){
+ frameWidth *= float(widgetHeight) / float(frameHeight);
+ frameHeight = widgetHeight;
+ }
+ break;
+ case Phonon::VideoWidget::FitInView:
+ default:
+ if (frameHeight > widgetHeight){
+ frameWidth *= float(widgetHeight) / float(frameHeight);
+ frameHeight = widgetHeight;
+ }
+ break;
+ }
+
+ m_drawFrameRect.setSize(QSize(frameWidth, frameHeight));
+ m_drawFrameRect.moveTo((widgetWidth - frameWidth) / 2.0f, (widgetHeight - frameHeight) / 2.0f);
+
+ if (m_renderDrawWidget)
+ m_renderDrawWidget->setDrawFrameRect(m_drawFrameRect);
+ }
+
+ QRect scaleToAspect(QRect srcRect, int w, int h)
+ {
+ int width = srcRect.width();
+ int height = srcRect.width() * (float(h) / float(w));
+ if (height > srcRect.height()){
+ height = srcRect.height();
+ width = srcRect.height() * (float(w) / float(h));
+ }
+ return QRect(0, 0, width, height);
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+VideoWidget::VideoWidget(QObject *parent) : MediaNode(VideoSink, parent)
+{
+ m_videoRenderWidget = new VideoRenderWidget();
+}
+
+VideoWidget::~VideoWidget()
+{
+ delete m_videoRenderWidget;
+}
+
+QWidget *VideoWidget::widget()
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget;
+}
+
+Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_aspect;
+}
+
+void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspect)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->setAspectRatio(aspect);
+}
+
+Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_scaleMode;
+}
+
+void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->setScaleMode(scaleMode);
+}
+
+qreal VideoWidget::brightness() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_brightness;
+}
+
+void VideoWidget::setBrightness(qreal value)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->m_brightness = value;
+ if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
+ m_videoRenderWidget->updateVideoFrame();
+}
+
+qreal VideoWidget::contrast() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_contrast;
+}
+
+void VideoWidget::setContrast(qreal value)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->m_contrast = value;
+ if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
+ m_videoRenderWidget->updateVideoFrame();
+}
+
+qreal VideoWidget::hue() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_hue;
+}
+
+void VideoWidget::setHue(qreal value)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->m_hue = value;
+ if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
+ m_videoRenderWidget->updateVideoFrame();
+}
+
+qreal VideoWidget::saturation() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_saturation;
+}
+
+void VideoWidget::setSaturation(qreal value)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->m_saturation = value;
+ if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
+ m_videoRenderWidget->updateVideoFrame();
+}
+
+void VideoWidget::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()){
+ case MediaNodeEvent::VideoFrameSizeChanged:
+ m_videoRenderWidget->setMovieRect(*static_cast<QRect *>(event->data()));
+ break;
+ case MediaNodeEvent::VideoOutputCountChanged:
+ m_videoRenderWidget->updateVideoOutputCount(*static_cast<int *>(event->data()));
+ break;
+ case MediaNodeEvent::MediaPlaying:
+ m_videoRenderWidget->setMovieIsPaused(!(*static_cast<bool *>(event->data())));
+ break;
+ default:
+ break;
+ }
+}
+
+void VideoWidget::updateVideo(VideoFrame &frame){
+ PhononAutoReleasePool pool;
+ m_videoRenderWidget->setVideoFrame(frame);
+ MediaNode::updateVideo(frame);
+}
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_videowidget.cpp"