QtGStreamer  1.2.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
bus.cpp
1 /*
2  Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
3 
4  This library is free software; you can redistribute it and/or modify
5  it under the terms of the GNU Lesser General Public License as published
6  by the Free Software Foundation; either version 2.1 of the License, or
7  (at your option) any later version.
8 
9  This program 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 program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "bus.h"
18 #include "message.h"
19 #include "../QGlib/Signal"
20 #include <gst/gst.h>
21 #include <QtCore/QObject>
22 #include <QtCore/QTimerEvent>
23 #include <QtCore/QHash>
24 #include <QtCore/QBasicTimer>
25 
26 namespace QGst {
27 namespace Private {
28 
29 class BusWatch : public QObject
30 {
31 public:
32  BusWatch(GstBus *bus)
33  : QObject(), m_bus(bus)
34  {
35  m_timer.start(50, this);
36  }
37 
38  void stop()
39  {
40  m_timer.stop();
41  }
42 
43 private:
44  virtual void timerEvent(QTimerEvent *event)
45  {
46  if (event->timerId() == m_timer.timerId()) {
47  dispatch();
48  } else {
49  QObject::timerEvent(event);
50  }
51  }
52 
53  void dispatch()
54  {
55  GstMessage *message;
56  gst_object_ref(m_bus);
57  while((message = gst_bus_pop(m_bus)) != NULL) {
58  MessagePtr msg = MessagePtr::wrap(message, false);
59  QGlib::Quark detail = gst_message_type_to_quark(static_cast<GstMessageType>(msg->type()));
60  QGlib::emitWithDetail<void>(m_bus, "message", detail, msg);
61  }
62  gst_object_unref(m_bus);
63  }
64 
65  GstBus *m_bus;
66  QBasicTimer m_timer;
67 };
68 
69 class BusWatchManager
70 {
71 public:
72  void addWatch(GstBus *bus)
73  {
74  if (m_watches.contains(bus)) {
75  m_watches[bus].second++; //reference count
76  } else {
77  m_watches.insert(bus, qMakePair(new BusWatch(bus), uint(1)));
78  g_object_weak_ref(G_OBJECT(bus), &BusWatchManager::onBusDestroyed, this);
79  }
80  }
81 
82  void removeWatch(GstBus *bus)
83  {
84  if (m_watches.contains(bus) && --m_watches[bus].second == 0) {
85  m_watches[bus].first->stop();
86  m_watches[bus].first->deleteLater();
87  m_watches.remove(bus);
88  g_object_weak_unref(G_OBJECT(bus), &BusWatchManager::onBusDestroyed, this);
89  }
90  }
91 
92 private:
93  static void onBusDestroyed(gpointer selfPtr, GObject *busPtr)
94  {
95  BusWatchManager *self = static_cast<BusWatchManager*>(selfPtr);
96  GstBus *bus = reinterpret_cast<GstBus*>(busPtr);
97 
98  //we cannot call removeWatch() here because g_object_weak_unref will complain
99  self->m_watches[bus].first->stop();
100  self->m_watches[bus].first->deleteLater();
101  self->m_watches.remove(bus);
102  }
103 
104  QHash< GstBus*, QPair<BusWatch*, uint> > m_watches;
105 };
106 
107 Q_GLOBAL_STATIC(Private::BusWatchManager, s_watchManager)
108 
109 } //namespace Private
110 
111 
112 //static
114 {
115  GstBus *bus = gst_bus_new();
116  if (bus) {
117  gst_object_ref_sink(bus);
118  }
119  return BusPtr::wrap(bus, false);
120 }
121 
123 {
124  return gst_bus_have_pending(object<GstBus>());
125 }
126 
128 {
129  return MessagePtr::wrap(gst_bus_peek(object<GstBus>()), false);
130 }
131 
133 {
134  return MessagePtr::wrap(gst_bus_timed_pop(object<GstBus>(), timeout), false);
135 }
136 
137 MessagePtr Bus::pop(MessageType type, ClockTime timeout)
138 {
139  return MessagePtr::wrap(gst_bus_timed_pop_filtered(object<GstBus>(), timeout,
140  static_cast<GstMessageType>(type)), false);
141 }
142 
143 bool Bus::post(const MessagePtr & message)
144 {
145  return gst_bus_post(object<GstBus>(), gst_message_copy(message));
146 }
147 
148 void Bus::setFlushing(bool flush)
149 {
150  gst_bus_set_flushing(object<GstBus>(), flush);
151 }
152 
154 {
155  Private::s_watchManager()->addWatch(object<GstBus>());
156 }
157 
159 {
160  Private::s_watchManager()->removeWatch(object<GstBus>());
161 }
162 
164 {
165  gst_bus_enable_sync_message_emission(object<GstBus>());
166 }
167 
169 {
170  gst_bus_disable_sync_message_emission(object<GstBus>());
171 }
172 
173 } //namespace QGst
static RefPointer< T > wrap(typename T::CType *nativePtr, bool increaseRef=true)
Definition: refpointer.h:326
bool hasPendingMessages() const
Definition: bus.cpp:122
Smart pointer class for working with wrapper classes that support reference counting.
Definition: global.h:56
A datatype to hold a time, measured in nanoseconds.
Definition: clocktime.h:37
void enableSyncMessageEmission()
Definition: bus.cpp:163
void setFlushing(bool flush)
Definition: bus.cpp:148
void addSignalWatch()
Definition: bus.cpp:153
static BusPtr create()
Definition: bus.cpp:113
void disableSyncMessageEmission()
Definition: bus.cpp:168
MessagePtr pop(ClockTime timeout=0)
Definition: bus.cpp:132
void removeSignalWatch()
Definition: bus.cpp:158
bool post(const MessagePtr &message)
Definition: bus.cpp:143
MessagePtr peek() const
Definition: bus.cpp:127
Wrapper class for GQuark.
Definition: quark.h:42