diff options
Diffstat (limited to 'src/3rdparty/phonon/qt7/medianode.mm')
-rw-r--r-- | src/3rdparty/phonon/qt7/medianode.mm | 261 |
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" + |