00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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++;
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
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 }
00110
00111
00112
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 }