src/3rdparty/phonon/qt7/medianode.mm
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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 
       
    27 QT_BEGIN_NAMESPACE
       
    28 
       
    29 namespace Phonon
       
    30 {
       
    31 namespace QT7
       
    32 {
       
    33 
       
    34 MediaNode::MediaNode(NodeDescription description, QObject *parent)
       
    35     : QObject(parent), m_audioGraph(0), m_audioNode(0), m_description(description), m_owningMediaObject(0)
       
    36 {
       
    37 }
       
    38 
       
    39 MediaNode::MediaNode(NodeDescription description, AudioNode *audioPart, QObject *parent)
       
    40     : QObject(parent), m_audioGraph(0), m_audioNode(audioPart), m_description(description)
       
    41 {
       
    42 }
       
    43 
       
    44 void MediaNode::setAudioNode(AudioNode *audioPart)
       
    45 {
       
    46     if (m_audioNode)
       
    47         delete m_audioNode;
       
    48     m_audioNode = audioPart;
       
    49 }
       
    50 
       
    51 MediaNode::~MediaNode()
       
    52 {
       
    53    delete m_audioNode;
       
    54    qDeleteAll(m_audioSinkList);
       
    55 }
       
    56 
       
    57 AudioConnection *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 
       
    69 bool 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 
       
   122 bool 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 
       
   157 int 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 
       
   177 int 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 
       
   197 void 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 
       
   238 void 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 
       
   246 void MediaNode::updateVideo(VideoFrame &frame){
       
   247     for (int i=0; i<m_videoSinkList.size(); ++i)
       
   248         m_videoSinkList[i]->updateVideo(frame);
       
   249 }
       
   250 
       
   251 void MediaNode::mediaNodeEvent(const MediaNodeEvent */*event*/)
       
   252 {
       
   253    // Override if needed.
       
   254 }
       
   255 
       
   256 }} //namespace Phonon::QT7
       
   257 
       
   258 QT_END_NAMESPACE
       
   259 
       
   260 #include "moc_medianode.cpp"
       
   261