summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/phonon/qt7/medianode.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/phonon/qt7/medianode.mm')
-rw-r--r--src/3rdparty/phonon/qt7/medianode.mm261
1 files changed, 261 insertions, 0 deletions
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"
+