foreach (QObject *object, objects) { MediaNode *sourceNode = qobject_cast<MediaNode *>(object); MediaObject *media = sourceNode->root(); if (media) { media->saveState(); return true; } }
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); }
/** * Propagates an event down the graph * sender is responsible for deleting the event */ void MediaNode::notify(const MediaNodeEvent *event) { Q_ASSERT(event); mediaNodeEvent(event); for (int i=0; i<m_audioSinkList.size(); ++i) { MediaNode *node = qobject_cast<MediaNode*>(m_audioSinkList[i]); node->notify(event); } for (int i=0; i<m_videoSinkList.size(); ++i) { MediaNode *node = qobject_cast<MediaNode*>(m_videoSinkList[i]); node->notify(event); } }
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); }
bool MediaNode::connectNode(QObject *obj) { MediaNode *sink = qobject_cast<MediaNode*>(obj); bool success = false; if (sink) { if (!sink->isValid()) { m_backend->logMessage(QString("Trying to link to an invalid node (%0)").arg(sink->name()), Backend::Warning); return false; } if (sink->root()) { m_backend->logMessage("Trying to link a node that is already linked to a different mediasource ", Backend::Warning); return false; } if ((m_description & AudioSource) && (sink->m_description & AudioSink)) { m_audioSinkList << obj; MediaNodeEvent event(MediaNodeEvent::AudioSinkAdded, sink); root()->mediaNodeEvent(&event); success = true; } if ((m_description & VideoSource) && (sink->m_description & VideoSink)) { m_videoSinkList << obj; MediaNodeEvent event(MediaNodeEvent::VideoSinkAdded, sink); root()->mediaNodeEvent(&event); success = true; } // If we have a root source, and we are connected // try to link the gstreamer elements if (success && root()) { MediaNodeEvent mediaObjectConnected(MediaNodeEvent::MediaObjectConnected, root()); notify(&mediaObjectConnected); root()->buildGraph(); } } return success; }
/** * Disconnects children recursively */ bool MediaNode::breakGraph() { for (int i=0; i<m_audioSinkList.size(); ++i) { MediaNode *node = qobject_cast<MediaNode*>(m_audioSinkList[i]); if (!node || !node->breakGraph()) return false; node->setRoot(0); } for (int i=0; i <m_videoSinkList.size(); ++i) { MediaNode *node = qobject_cast<MediaNode*>(m_videoSinkList[i]); if (!node || !node->breakGraph()) return false; node->setRoot(0); } unlink(); return true; }
bool MediaNode::disconnectNode(QObject *obj) { MediaNode *sink = qobject_cast<MediaNode*>(obj); if (root()) { // Disconnecting elements while playing or paused seems to cause // potential deadlock. Hence we force the pipeline into ready state // before any nodes are disconnected. gst_element_set_state(root()->pipeline(), GST_STATE_READY); Q_ASSERT(sink->root()); //sink has to have a root since it is onnected if (sink->description() & (AudioSink)) { GstPad *sinkPad = gst_element_get_pad(sink->audioElement(), "sink"); // Release requested src pad from tee GstPad *requestedPad = gst_pad_get_peer(sinkPad); if (requestedPad) { gst_element_release_request_pad(m_audioTee, requestedPad); gst_object_unref(requestedPad); } if (GST_ELEMENT_PARENT(sink->audioElement())) gst_bin_remove(GST_BIN(root()->audioGraph()), sink->audioElement()); gst_object_unref(sinkPad); } if (sink->description() & (VideoSink)) { GstPad *sinkPad = gst_element_get_pad(sink->videoElement(), "sink"); // Release requested src pad from tee GstPad *requestedPad = gst_pad_get_peer(sinkPad); if (requestedPad) { gst_element_release_request_pad(m_videoTee, requestedPad); gst_object_unref(requestedPad); } if (GST_ELEMENT_PARENT(sink->videoElement())) gst_bin_remove(GST_BIN(root()->videoGraph()), sink->videoElement()); gst_object_unref(sinkPad); } sink->breakGraph(); sink->setRoot(0); } m_videoSinkList.removeAll(obj); m_audioSinkList.removeAll(obj); if (sink->m_description & AudioSink) { // Remove sink from graph MediaNodeEvent event(MediaNodeEvent::AudioSinkRemoved, sink); mediaNodeEvent(&event); return true; } if ((m_description & VideoSource) && (sink->m_description & VideoSink)) { // Remove sink from graph MediaNodeEvent event(MediaNodeEvent::VideoSinkRemoved, sink); mediaNodeEvent(&event); return true; } return false; }