/* 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 "mediaobject.h"
#include "mmf_medianode.h"
QT_BEGIN_NAMESPACE
using namespace Phonon;
using namespace Phonon::MMF;
/*! \class MMF::MediaNode
\internal
*/
MMF::MediaNode::MediaNode(QObject *parent)
: QObject(parent)
, m_mediaObject(qobject_cast<MediaObject *>(this))
, m_input(0)
{
}
MMF::MediaNode::~MediaNode()
{
// Phonon framework ensures nodes are disconnected before being destroyed.
Q_ASSERT_X(!m_mediaObject, Q_FUNC_INFO,
"Media node not disconnected before destruction");
}
bool MMF::MediaNode::connectOutput(MediaNode *output)
{
Q_ASSERT_X(output, Q_FUNC_INFO, "Null output pointer");
bool connected = false;
// Check that this connection will not result in a graph which
// containing more than one MediaObject
const bool mediaObjectMisMatch =
m_mediaObject
&& output->m_mediaObject
&& m_mediaObject != output->m_mediaObject;
const bool canConnect =
!output->isMediaObject()
&& !output->m_input
&& !m_outputs.contains(output);
if (canConnect && !mediaObjectMisMatch) {
output->m_input = this;
m_outputs += output;
updateMediaObject();
connected = true;
}
return connected;
}
bool MMF::MediaNode::disconnectOutput(MediaNode *output)
{
Q_ASSERT_X(output, Q_FUNC_INFO, "Null output pointer");
bool disconnected = false;
if (m_outputs.contains(output) && this == output->m_input) {
output->m_input = 0;
const bool removed = m_outputs.removeOne(output);
Q_ASSERT_X(removed, Q_FUNC_INFO, "Output removal failed");
Q_ASSERT_X(!m_outputs.contains(output), Q_FUNC_INFO,
"Output list contains duplicate entries");
// Perform traversal across each of the two graphs separately
updateMediaObject();
output->updateMediaObject();
disconnected = true;
}
return disconnected;
}
bool MMF::MediaNode::isMediaObject() const
{
return (qobject_cast<const MediaObject *>(this) != 0);
}
void MMF::MediaNode::updateMediaObject()
{
QList<MediaNode *> nodes;
MediaObject *mediaObject = 0;
// Traverse the graph, collecting a list of nodes, and locating
// the MediaObject node, if present
visit(nodes, mediaObject);
MediaNode *node = 0;
foreach(node, nodes)
node->setMediaObject(mediaObject);
}
void MMF::MediaNode::setMediaObject(MediaObject *mediaObject)
{
if(!isMediaObject() && m_mediaObject != mediaObject) {
if (!mediaObject)
disconnectMediaObject(m_mediaObject);
else {
Q_ASSERT_X(!m_mediaObject, Q_FUNC_INFO, "MediaObject already set");
connectMediaObject(mediaObject);
}
m_mediaObject = mediaObject;
}
}
void MMF::MediaNode::visit(QList<MediaNode *>& visited, MediaObject*& mediaObject)
{
if (isMediaObject()) {
// There can never be more than one MediaObject per graph, due to the
// mediaObjectMisMatch test in connectOutput().
Q_ASSERT_X(!mediaObject, Q_FUNC_INFO, "MediaObject already found");
mediaObject = static_cast<MediaObject *>(this);
}
visited += this;
if (m_input && !visited.contains(m_input))
m_input->visit(visited, mediaObject);
MediaNode *output = 0;
foreach (output, m_outputs)
if (!visited.contains(output))
output->visit(visited, mediaObject);
}
QT_END_NAMESPACE