QtGStreamer  0.10.2
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
bus.cpp
00001 /*
00002     Copyright (C) 2010  George Kiagiadakis <kiagiadakis.george@gmail.com>
00003 
00004     This library is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU Lesser General Public License as published
00006     by the Free Software Foundation; either version 2.1 of the License, or
00007     (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU Lesser General Public License for more details.
00013 
00014     You should have received a copy of the GNU Lesser General Public License
00015     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 */
00017 #include "bus.h"
00018 #include "message.h"
00019 #include "../QGlib/signal.h"
00020 #include <gst/gst.h>
00021 #include <QtCore/QObject>
00022 #include <QtCore/QTimerEvent>
00023 #include <QtCore/QHash>
00024 #include <QtCore/QBasicTimer>
00025 
00026 namespace QGst {
00027 namespace Private {
00028 
00029 class BusWatch : public QObject
00030 {
00031 public:
00032     BusWatch(GstBus *bus)
00033         : QObject(), m_bus(bus)
00034     {
00035         m_timer.start(50, this);
00036     }
00037 
00038     void stop()
00039     {
00040         m_timer.stop();
00041     }
00042 
00043 private:
00044     virtual void timerEvent(QTimerEvent *event)
00045     {
00046         if (event->timerId() == m_timer.timerId()) {
00047             dispatch();
00048         } else {
00049             QObject::timerEvent(event);
00050         }
00051     }
00052 
00053     void dispatch()
00054     {
00055         GstMessage *message;
00056         gst_object_ref(m_bus);
00057         while((message = gst_bus_pop(m_bus)) != NULL) {
00058             MessagePtr msg = MessagePtr::wrap(message, false);
00059             QGlib::Quark detail = gst_message_type_to_quark(static_cast<GstMessageType>(msg->type()));
00060             QGlib::emitWithDetail<void>(m_bus, "message", detail, msg);
00061         }
00062         gst_object_unref(m_bus);
00063     }
00064 
00065     GstBus *m_bus;
00066     QBasicTimer m_timer;
00067 };
00068 
00069 class BusWatchManager
00070 {
00071 public:
00072     void addWatch(GstBus *bus)
00073     {
00074         if (m_watches.contains(bus)) {
00075             m_watches[bus].second++; //reference count
00076         } else {
00077             m_watches.insert(bus, qMakePair(new BusWatch(bus), uint(1)));
00078             g_object_weak_ref(G_OBJECT(bus), &BusWatchManager::onBusDestroyed, this);
00079         }
00080     }
00081 
00082     void removeWatch(GstBus *bus)
00083     {
00084         if (m_watches.contains(bus) && --m_watches[bus].second == 0) {
00085             m_watches[bus].first->stop();
00086             m_watches[bus].first->deleteLater();
00087             m_watches.remove(bus);
00088             g_object_weak_unref(G_OBJECT(bus), &BusWatchManager::onBusDestroyed, this);
00089         }
00090     }
00091 
00092 private:
00093     static void onBusDestroyed(gpointer selfPtr, GObject *busPtr)
00094     {
00095         BusWatchManager *self = static_cast<BusWatchManager*>(selfPtr);
00096         GstBus *bus = reinterpret_cast<GstBus*>(busPtr);
00097 
00098         //we cannot call removeWatch() here because g_object_weak_unref will complain
00099         self->m_watches[bus].first->stop();
00100         self->m_watches[bus].first->deleteLater();
00101         self->m_watches.remove(bus);
00102     }
00103 
00104     QHash< GstBus*, QPair<BusWatch*, uint> > m_watches;
00105 };
00106 
00107 Q_GLOBAL_STATIC(Private::BusWatchManager, s_watchManager)
00108 
00109 } //namespace Private
00110 
00111 
00112 //static
00113 BusPtr Bus::create()
00114 {
00115     GstBus *bus = gst_bus_new();
00116     if (bus) {
00117         gst_object_ref_sink(bus);
00118     }
00119     return BusPtr::wrap(bus, false);
00120 }
00121 
00122 bool Bus::hasPendingMessages() const
00123 {
00124     return gst_bus_have_pending(object<GstBus>());
00125 }
00126 
00127 MessagePtr Bus::peek() const
00128 {
00129     return MessagePtr::wrap(gst_bus_peek(object<GstBus>()), false);
00130 }
00131 
00132 MessagePtr Bus::pop(ClockTime timeout)
00133 {
00134     return MessagePtr::wrap(gst_bus_timed_pop(object<GstBus>(), timeout), false);
00135 }
00136 
00137 MessagePtr Bus::pop(MessageType type, ClockTime timeout)
00138 {
00139     return MessagePtr::wrap(gst_bus_timed_pop_filtered(object<GstBus>(), timeout,
00140                                                        static_cast<GstMessageType>(type)), false);
00141 }
00142 
00143 bool Bus::post(const MessagePtr & message)
00144 {
00145     return gst_bus_post(object<GstBus>(), gst_message_copy(message));
00146 }
00147 
00148 void Bus::setFlushing(bool flush)
00149 {
00150     gst_bus_set_flushing(object<GstBus>(), flush);
00151 }
00152 
00153 void Bus::addSignalWatch()
00154 {
00155     Private::s_watchManager()->addWatch(object<GstBus>());
00156 }
00157 
00158 void Bus::removeSignalWatch()
00159 {
00160     Private::s_watchManager()->removeWatch(object<GstBus>());
00161 }
00162 
00163 void Bus::enableSyncMessageEmission()
00164 {
00165     gst_bus_enable_sync_message_emission(object<GstBus>());
00166 }
00167 
00168 void Bus::disableSyncMessageEmission()
00169 {
00170     gst_bus_disable_sync_message_emission(object<GstBus>());
00171 }
00172 
00173 } //namespace QGst