Phonon

abstractmediastream2.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2007-2008 Matthias Kretz <kretz@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) version 3, or any
8 later version accepted by the membership of KDE e.V. (or its
9 successor approved by the membership of KDE e.V.), Nokia Corporation
10 (or its successors, if any) and the KDE Free Qt Foundation, which shall
11 act as a proxy defined in Section 6 of version 3 of the license.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library. If not, see <http://www.gnu.org/licenses/>.
20
21*/
22
23#include "abstractmediastream2.h"
24#include "abstractmediastream2_p.h"
25#include "mediaobjectinterface.h"
26#include "mediaobject_p.h"
27#include "phononnamespace_p.h"
28
29#include <QAbstractEventDispatcher>
30#include <QEvent>
31
32namespace Phonon
33{
34
35bool AbstractMediaStream2::event(QEvent *e)
36{
37 if (e->type() == QEvent::ThreadChange) {
39 if (d->eventDispatcher) {
40 pWarning() << "Do not call moveToThread on an AbstractMediaStream2 object when it is in use.";
41 QObject::disconnect(d->eventDispatcher, SIGNAL(awake()), this, SLOT(_k_handleStreamEvent()));
42 d->eventDispatcher = 0;
43 }
44 }
46}
47
48void AbstractMediaStream2Private::dataReady()
49{
50 Q_Q(AbstractMediaStream2);
51 if (!eventDispatcher) {
52 eventDispatcher = QAbstractEventDispatcher::instance(q->thread());
53 if (!eventDispatcher) {
54 pError() << "AbstractMediaStream2 needs to run in a thread with QEventLoop";
55 return;
56 } else {
57 QObject::connect(eventDispatcher, SIGNAL(awake()), q, SLOT(_k_handleStreamEvent()), Qt::DirectConnection);
58 }
59 }
60 eventDispatcher->wakeUp();
61}
62
63void AbstractMediaStream2Private::_k_handleStreamEvent()
64{
65 Q_ASSERT(streamEventQueue);
66 Q_Q(AbstractMediaStream2);
67 StreamEventQueue::Command c;
68 while (streamEventQueue->nextCommandForFrontend(&c)) {
69 switch (c.command) {
70 case StreamEventQueue::SetStreamSize:
71 case StreamEventQueue::SetSeekable:
72 case StreamEventQueue::Write:
73 case StreamEventQueue::EndOfData:
74 case StreamEventQueue::SeekDone:
75 case StreamEventQueue::ResetDone:
76 case StreamEventQueue::ConnectDone:
77 pFatal("AbstractMediaStream2 received wrong Command");
78 break;
79 case StreamEventQueue::NeedData:
80 q->needData(qvariant_cast<quint32>(c.data));
81 break;
82 case StreamEventQueue::EnoughData:
83 q->enoughData();
84 break;
85 case StreamEventQueue::Seek:
86 q->seekStream(qvariant_cast<quint64>(c.data));
87 break;
88 case StreamEventQueue::Reset:
89 q->reset();
90 break;
91 case StreamEventQueue::Connect:
92 if (firstConnect) {
93 firstConnect = false;
94 streamEventQueue->sendToBackend(StreamEventQueue::ConnectDone);
95 streamEventQueue->sendToBackend(StreamEventQueue::SetSeekable, streamSeekable);
96 if (streamSize != 0) {
97 streamEventQueue->sendToBackend(StreamEventQueue::SetStreamSize, streamSize);
98 }
99 } else {
100 ++connectReset;
101 q->reset();
102 }
103 break;
104 }
105 }
106}
107
109 : AbstractMediaStream(*new AbstractMediaStream2Private, parent)
110{
111}
112
113AbstractMediaStream2::AbstractMediaStream2(AbstractMediaStream2Private &dd, QObject *parent)
114 : AbstractMediaStream(dd, parent)
115{
116}
117
118void AbstractMediaStream2Private::setStreamSize(qint64 newSize)
119{
120 streamSize = newSize;
121 streamEventQueue->sendToBackend(StreamEventQueue::SetStreamSize, newSize);
122}
123
124void AbstractMediaStream2Private::setStreamSeekable(bool s)
125{
126 streamSeekable = s;
127 streamEventQueue->sendToBackend(StreamEventQueue::SetSeekable, s);
128}
129
130void AbstractMediaStream2Private::writeData(const QByteArray &data)
131{
132 streamEventQueue->sendToBackend(StreamEventQueue::Write, data);
133}
134
135void AbstractMediaStream2Private::endOfData()
136{
137 streamEventQueue->sendToBackend(StreamEventQueue::EndOfData);
138}
139
140void AbstractMediaStream2::resetDone()
141{
143 if (d->connectReset > 0) {
144 --d->connectReset;
145 d->streamEventQueue->sendToBackend(StreamEventQueue::ConnectDone);
146 } else {
147 d->streamEventQueue->sendToBackend(StreamEventQueue::ResetDone);
148 }
149 d->streamEventQueue->sendToBackend(StreamEventQueue::SetSeekable, d->streamSeekable);
150 if (d->streamSize != 0) {
151 d->streamEventQueue->sendToBackend(StreamEventQueue::SetStreamSize, d->streamSize);
152 }
153}
154
155void AbstractMediaStream2::seekStreamDone()
156{
157 d_func()->streamEventQueue->sendToBackend(StreamEventQueue::SeekDone);
158}
159
160AbstractMediaStream2Private::AbstractMediaStream2Private()
161 : streamEventQueue(new StreamEventQueue),
162 eventDispatcher(0),
163 connectReset(0),
164 firstConnect(true)
165{
166 streamEventQueue->ref();
167 streamEventQueue->setFrontendCommandHandler(this);
168}
169
170AbstractMediaStream2Private::~AbstractMediaStream2Private()
171{
172 // setFrontendCommandHandler blocks internally until a handler that might be called right now is
173 // done. That means AbstractMediaStream2Private::dataReady will either not run again or it will
174 // be done before this object and our q object are deleted.
175 streamEventQueue->setFrontendCommandHandler(0);
176 streamEventQueue->deref();
177 streamEventQueue = 0;
178 // if eventDispatcher->wakeUp() was called and we are now still connected to its awake() signal
179 // then the QObject will be deleted until execution reaches the event loop again and
180 // _k_handleStreamEvent will not get called
181}
182
183} // namespace Phonon
184
185#include "moc_abstractmediastream2.cpp"
186
187// vim: sw=4 sts=4 et tw=100
AbstractMediaStream2(QObject *parent=0)
Constructs an AbstractMediaStream2 object with a parent.
Base class for custom media data streams.
QAbstractEventDispatcher * instance(QThread *thread)
Type type() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
virtual bool event(QEvent *e)
T qobject_cast(QObject *object)
DirectConnection
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 24 2024 11:53:28 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.