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