| 1 | /*  This file is part of the KDE project.
 | 
|---|
| 2 | 
 | 
|---|
| 3 | Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
 | 
|---|
| 4 | 
 | 
|---|
| 5 | This library is free software: you can redistribute it and/or modify
 | 
|---|
| 6 | it under the terms of the GNU Lesser General Public License as published by
 | 
|---|
| 7 | the Free Software Foundation, either version 2.1 or 3 of the License.
 | 
|---|
| 8 | 
 | 
|---|
| 9 | This library is distributed in the hope that it will be useful,
 | 
|---|
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 12 | GNU Lesser General Public License for more details.
 | 
|---|
| 13 | 
 | 
|---|
| 14 | You should have received a copy of the GNU Lesser General Public License
 | 
|---|
| 15 | along with this library.  If not, see <http://www.gnu.org/licenses/>.
 | 
|---|
| 16 | 
 | 
|---|
| 17 | */
 | 
|---|
| 18 | 
 | 
|---|
| 19 | #include "mediaobject.h"
 | 
|---|
| 20 | 
 | 
|---|
| 21 | #include "mmf_medianode.h"
 | 
|---|
| 22 | 
 | 
|---|
| 23 | QT_BEGIN_NAMESPACE
 | 
|---|
| 24 | 
 | 
|---|
| 25 | using namespace Phonon;
 | 
|---|
| 26 | using namespace Phonon::MMF;
 | 
|---|
| 27 | 
 | 
|---|
| 28 | /*! \class MMF::MediaNode
 | 
|---|
| 29 |   \internal
 | 
|---|
| 30 | */
 | 
|---|
| 31 | 
 | 
|---|
| 32 | MMF::MediaNode::MediaNode(QObject *parent)
 | 
|---|
| 33 |     :   QObject(parent)
 | 
|---|
| 34 |     ,   m_mediaObject(qobject_cast<MediaObject *>(this))
 | 
|---|
| 35 |     ,   m_input(0)
 | 
|---|
| 36 | {
 | 
|---|
| 37 | 
 | 
|---|
| 38 | }
 | 
|---|
| 39 | 
 | 
|---|
| 40 | MMF::MediaNode::~MediaNode()
 | 
|---|
| 41 | {
 | 
|---|
| 42 |     // Phonon framework ensures nodes are disconnected before being destroyed.
 | 
|---|
| 43 |     Q_ASSERT_X(!m_mediaObject, Q_FUNC_INFO,
 | 
|---|
| 44 |         "Media node not disconnected before destruction");
 | 
|---|
| 45 | }
 | 
|---|
| 46 | 
 | 
|---|
| 47 | bool MMF::MediaNode::connectOutput(MediaNode *output)
 | 
|---|
| 48 | {
 | 
|---|
| 49 |     Q_ASSERT_X(output, Q_FUNC_INFO, "Null output pointer");
 | 
|---|
| 50 | 
 | 
|---|
| 51 |     bool connected = false;
 | 
|---|
| 52 | 
 | 
|---|
| 53 |     // Check that this connection will not result in a graph which
 | 
|---|
| 54 |     // containing more than one MediaObject
 | 
|---|
| 55 |     const bool mediaObjectMisMatch =
 | 
|---|
| 56 |             m_mediaObject
 | 
|---|
| 57 |         &&  output->m_mediaObject
 | 
|---|
| 58 |         &&  m_mediaObject != output->m_mediaObject;
 | 
|---|
| 59 | 
 | 
|---|
| 60 |     const bool canConnect =
 | 
|---|
| 61 |             !output->isMediaObject()
 | 
|---|
| 62 |         &&  !output->m_input
 | 
|---|
| 63 |         &&  !m_outputs.contains(output);
 | 
|---|
| 64 | 
 | 
|---|
| 65 |     if (canConnect && !mediaObjectMisMatch) {
 | 
|---|
| 66 |         output->m_input = this;
 | 
|---|
| 67 |         m_outputs += output;
 | 
|---|
| 68 |         updateMediaObject();
 | 
|---|
| 69 |         connected = true;
 | 
|---|
| 70 |     }
 | 
|---|
| 71 | 
 | 
|---|
| 72 |     return connected;
 | 
|---|
| 73 | }
 | 
|---|
| 74 | 
 | 
|---|
| 75 | bool MMF::MediaNode::disconnectOutput(MediaNode *output)
 | 
|---|
| 76 | {
 | 
|---|
| 77 |     Q_ASSERT_X(output, Q_FUNC_INFO, "Null output pointer");
 | 
|---|
| 78 | 
 | 
|---|
| 79 |     bool disconnected = false;
 | 
|---|
| 80 | 
 | 
|---|
| 81 |     if (m_outputs.contains(output) && this == output->m_input) {
 | 
|---|
| 82 |         output->m_input = 0;
 | 
|---|
| 83 |         const bool removed = m_outputs.removeOne(output);
 | 
|---|
| 84 |         Q_ASSERT_X(removed, Q_FUNC_INFO, "Output removal failed");
 | 
|---|
| 85 | 
 | 
|---|
| 86 |         Q_ASSERT_X(!m_outputs.contains(output), Q_FUNC_INFO,
 | 
|---|
| 87 |             "Output list contains duplicate entries");
 | 
|---|
| 88 | 
 | 
|---|
| 89 |         // Perform traversal across each of the two graphs separately
 | 
|---|
| 90 |         updateMediaObject();
 | 
|---|
| 91 |         output->updateMediaObject();
 | 
|---|
| 92 | 
 | 
|---|
| 93 |         disconnected = true;
 | 
|---|
| 94 |     }
 | 
|---|
| 95 | 
 | 
|---|
| 96 |     return disconnected;
 | 
|---|
| 97 | }
 | 
|---|
| 98 | 
 | 
|---|
| 99 | bool MMF::MediaNode::isMediaObject() const
 | 
|---|
| 100 | {
 | 
|---|
| 101 |     return (qobject_cast<const MediaObject *>(this) != 0);
 | 
|---|
| 102 | }
 | 
|---|
| 103 | 
 | 
|---|
| 104 | void MMF::MediaNode::updateMediaObject()
 | 
|---|
| 105 | {
 | 
|---|
| 106 |     QList<MediaNode *> nodes;
 | 
|---|
| 107 |     MediaObject *mediaObject = 0;
 | 
|---|
| 108 | 
 | 
|---|
| 109 |     // Traverse the graph, collecting a list of nodes, and locating
 | 
|---|
| 110 |     // the MediaObject node, if present
 | 
|---|
| 111 |     visit(nodes, mediaObject);
 | 
|---|
| 112 | 
 | 
|---|
| 113 |     MediaNode *node = 0;
 | 
|---|
| 114 |     foreach(node, nodes)
 | 
|---|
| 115 |         node->setMediaObject(mediaObject);
 | 
|---|
| 116 | }
 | 
|---|
| 117 | 
 | 
|---|
| 118 | void MMF::MediaNode::setMediaObject(MediaObject *mediaObject)
 | 
|---|
| 119 | {
 | 
|---|
| 120 |     if(!isMediaObject() && m_mediaObject != mediaObject) {
 | 
|---|
| 121 |         if (!mediaObject)
 | 
|---|
| 122 |             disconnectMediaObject(m_mediaObject);
 | 
|---|
| 123 |         else {
 | 
|---|
| 124 |             Q_ASSERT_X(!m_mediaObject, Q_FUNC_INFO, "MediaObject already set");
 | 
|---|
| 125 |             connectMediaObject(mediaObject);
 | 
|---|
| 126 |         }
 | 
|---|
| 127 |         m_mediaObject = mediaObject;
 | 
|---|
| 128 |     }
 | 
|---|
| 129 | }
 | 
|---|
| 130 | 
 | 
|---|
| 131 | void MMF::MediaNode::visit(QList<MediaNode *>& visited, MediaObject*& mediaObject)
 | 
|---|
| 132 | {
 | 
|---|
| 133 |     if (isMediaObject()) {
 | 
|---|
| 134 |         // There can never be more than one MediaObject per graph, due to the
 | 
|---|
| 135 |         // mediaObjectMisMatch test in connectOutput().
 | 
|---|
| 136 |         Q_ASSERT_X(!mediaObject, Q_FUNC_INFO, "MediaObject already found");
 | 
|---|
| 137 |         mediaObject = static_cast<MediaObject *>(this);
 | 
|---|
| 138 |     }
 | 
|---|
| 139 | 
 | 
|---|
| 140 |     visited += this;
 | 
|---|
| 141 | 
 | 
|---|
| 142 |     if (m_input && !visited.contains(m_input))
 | 
|---|
| 143 |         m_input->visit(visited, mediaObject);
 | 
|---|
| 144 | 
 | 
|---|
| 145 |     MediaNode *output = 0;
 | 
|---|
| 146 |     foreach (output, m_outputs)
 | 
|---|
| 147 |         if (!visited.contains(output))
 | 
|---|
| 148 |             output->visit(visited, mediaObject);
 | 
|---|
| 149 | }
 | 
|---|
| 150 | 
 | 
|---|
| 151 | QT_END_NAMESPACE
 | 
|---|
| 152 | 
 | 
|---|