source: trunk/src/3rdparty/phonon/qt7/medianode.mm

Last change on this file was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 7.7 KB
Line 
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#include "medianode.h"
19#include "audiograph.h"
20#include "audionode.h"
21#include "backendheader.h"
22
23#include "mediaobject.h"
24#include "audiooutput.h"
25#include "quicktimevideoplayer.h"
26
27QT_BEGIN_NAMESPACE
28
29namespace Phonon
30{
31namespace QT7
32{
33
34MediaNode::MediaNode(NodeDescription description, QObject *parent)
35 : QObject(parent), m_audioGraph(0), m_audioNode(0), m_description(description), m_owningMediaObject(0)
36{
37}
38
39MediaNode::MediaNode(NodeDescription description, AudioNode *audioPart, QObject *parent)
40 : QObject(parent), m_audioGraph(0), m_audioNode(audioPart), m_description(description)
41{
42}
43
44void MediaNode::setAudioNode(AudioNode *audioPart)
45{
46 if (m_audioNode)
47 delete m_audioNode;
48 m_audioNode = audioPart;
49}
50
51MediaNode::~MediaNode()
52{
53 delete m_audioNode;
54 qDeleteAll(m_audioSinkList);
55}
56
57AudioConnection *MediaNode::getAudioConnectionToSink(MediaNode *sink)
58{
59 AudioConnection *connection = 0;
60 for (int i=0; i<m_audioSinkList.size(); ++i){
61 if (m_audioSinkList[i]->isBetween(this, sink)){
62 connection = m_audioSinkList[i];
63 break;
64 }
65 }
66 return connection;
67}
68
69bool MediaNode::connectToSink(MediaNode *sink)
70{
71 if ((m_description & AudioSource) && (sink->m_description & AudioSink)){
72 // Check that they don't belong to different graphs. If they do, but
73 // sink is not connected to any source, accept it:
74 if (m_owningMediaObject && sink->m_owningMediaObject
75 && m_owningMediaObject != sink->m_owningMediaObject
76 && !sink->m_audioSourceList.isEmpty()){
77 return false;
78 }
79
80 // Check that the connection doesn't already exists:
81 AudioConnection *connection = getAudioConnectionToSink(sink);
82 if (connection)
83 return true;
84
85 // Check that there are awailable input/output busses:
86 int inputBus = sink->availableAudioInputBus();
87 int outputBus = availableAudioOutputBus();
88 if (inputBus >= sink->m_audioNode->m_maxInputBusses || outputBus >= m_audioNode->m_maxOutputBusses)
89 return false;
90
91 // All OK. Create connection:
92 connection = new AudioConnection(this, outputBus, sink, inputBus);
93 m_audioSinkList << connection;
94 sink->m_audioSourceList << connection;
95
96 if (m_audioNode->m_audioGraph)
97 m_audioNode->m_audioGraph->connectLate(connection);
98
99 MediaNodeEvent event1(MediaNodeEvent::AudioSinkAdded, connection);
100 notify(&event1, false);
101 MediaNodeEvent event2(MediaNodeEvent::AudioSourceAdded, connection);
102 sink->notify(&event2, false);
103 return true;
104 }
105
106 if ((m_description & VideoSource) && (sink->m_description & VideoSink)){
107 // Check that the connection doesn't already exists:
108 if (m_videoSinkList.contains(sink))
109 return true;
110
111 m_videoSinkList << sink;
112 MediaNodeEvent event1(MediaNodeEvent::VideoSinkAdded, sink);
113 notify(&event1, false);
114 MediaNodeEvent event2(MediaNodeEvent::VideoSourceAdded, this);
115 sink->notify(&event2, false);
116 return true;
117 }
118
119 return false;
120}
121
122bool MediaNode::disconnectToSink(MediaNode *sink)
123{
124 if ((m_description & AudioSource) && (sink->m_description & AudioSink)){
125 AudioConnection *connection = getAudioConnectionToSink(sink);
126 if (!connection)
127 return false;
128
129 m_audioSinkList.removeOne(connection);
130 sink->m_audioSourceList.removeOne(connection);
131
132 if (m_audioNode->m_audioGraph)
133 m_audioNode->m_audioGraph->disconnectLate(connection);
134
135 MediaNodeEvent event1(MediaNodeEvent::AudioSinkRemoved, connection);
136 notify(&event1, false);
137 MediaNodeEvent event2(MediaNodeEvent::AudioSourceRemoved, connection);
138 sink->notify(&event2, false);
139
140 delete connection;
141 return true;
142 }
143
144 if ((m_description & VideoSource) && (sink->m_description & VideoSink)){
145 m_videoSinkList.removeOne(sink);
146
147 MediaNodeEvent event1(MediaNodeEvent::VideoSinkRemoved, sink);
148 notify(&event1, false);
149 MediaNodeEvent event2(MediaNodeEvent::VideoSourceRemoved, this);
150 sink->notify(&event2, false);
151 return true;
152 }
153
154 return false;
155}
156
157int MediaNode::availableAudioInputBus()
158{
159 // Scan through all the connection <u>in</u> to this
160 // node, and find an awailable index:
161 int index = -1;
162 bool available = false;
163
164 while (!available){
165 ++index;
166 available = true;
167 for (int i=0; i<m_audioSourceList.size(); ++i){
168 if (m_audioSourceList[i]->m_sinkInputBus == index){
169 available = false;
170 break;
171 }
172 }
173 }
174 return index;
175}
176
177int MediaNode::availableAudioOutputBus()
178{
179 // Scan through all the connection <u>out</u> from this
180 // node, and find an awailable index:
181 int bus = -1;
182 bool available = false;
183
184 while (!available){
185 ++bus;
186 available = true;
187 for (int i=0; i<m_audioSinkList.size(); ++i){
188 if (m_audioSinkList[i]->m_sourceOutputBus == bus){
189 available = false;
190 break;
191 }
192 }
193 }
194 return bus;
195}
196
197void MediaNode::notify(const MediaNodeEvent *event, bool propagate)
198{
199 // Let subclass handle the event first:
200 mediaNodeEvent(event);
201
202 switch(event->type()){
203 case MediaNodeEvent::AudioGraphAboutToBeDeleted:
204 if (m_audioNode){
205 foreach(AudioConnection *connection, m_audioSinkList)
206 connection->invalidate();
207 }
208 break;
209 case MediaNodeEvent::NewAudioGraph:
210 m_audioGraph = static_cast<AudioGraph *>(event->data());
211 break;
212 case MediaNodeEvent::AudioSinkAdded:
213 case MediaNodeEvent::VideoSinkAdded:
214 if (m_owningMediaObject){
215 MediaNodeEvent e1(MediaNodeEvent::SetMediaObject, m_owningMediaObject);
216 sendEventToSinks(&e1);
217 QRect videoRect = m_owningMediaObject->videoPlayer()->videoRect();
218 MediaNodeEvent e2(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
219 sendEventToSinks(&e2);
220 }
221 break;
222 case MediaNodeEvent::SetMediaObject:
223 m_owningMediaObject = static_cast<MediaObject *>(event->data());
224 break;
225 default:
226 break;
227 }
228
229 // Inform the audio node as well:
230 if (m_audioNode)
231 m_audioNode->notify(event);
232
233 // And perhaps the sinks:
234 if (propagate)
235 sendEventToSinks(event);
236}
237
238void MediaNode::sendEventToSinks(const MediaNodeEvent *event)
239{
240 for (int i=0; i<m_audioSinkList.size(); ++i)
241 m_audioSinkList[i]->m_sink->notify(event);
242 for (int i=0; i<m_videoSinkList.size(); ++i)
243 m_videoSinkList[i]->notify(event);
244}
245
246void MediaNode::updateVideo(VideoFrame &frame){
247 for (int i=0; i<m_videoSinkList.size(); ++i)
248 m_videoSinkList[i]->updateVideo(frame);
249}
250
251void MediaNode::mediaNodeEvent(const MediaNodeEvent */*event*/)
252{
253 // Override if needed.
254}
255
256}} //namespace Phonon::QT7
257
258QT_END_NAMESPACE
259
260#include "moc_medianode.cpp"
261
Note: See TracBrowser for help on using the repository browser.