/* This file is part of the KDE project Copyright (C) 2007-2008 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "abstractmediastream2.h" #include "abstractmediastream2_p.h" #include "mediaobjectinterface.h" #include "mediaobject_p.h" #include "phononnamespace_p.h" #include #include namespace Phonon { bool AbstractMediaStream2::event(QEvent *e) { if (e->type() == QEvent::ThreadChange) { Q_D(AbstractMediaStream2); if (d->eventDispatcher) { pWarning() << "Do not call moveToThread on an AbstractMediaStream2 object when it is in use."; QObject::disconnect(d->eventDispatcher, SIGNAL(awake()), this, SLOT(_k_handleStreamEvent())); d->eventDispatcher = 0; } } return AbstractMediaStream::event(e); } void AbstractMediaStream2Private::dataReady() { Q_Q(AbstractMediaStream2); if (!eventDispatcher) { eventDispatcher = QAbstractEventDispatcher::instance(q->thread()); if (!eventDispatcher) { pError() << "AbstractMediaStream2 needs to run in a thread with QEventLoop"; return; } else { QObject::connect(eventDispatcher, SIGNAL(awake()), q, SLOT(_k_handleStreamEvent()), Qt::DirectConnection); } } eventDispatcher->wakeUp(); } void AbstractMediaStream2Private::_k_handleStreamEvent() { Q_ASSERT(streamEventQueue); Q_Q(AbstractMediaStream2); StreamEventQueue::Command c; while (streamEventQueue->nextCommandForFrontend(&c)) { switch (c.command) { case StreamEventQueue::SetStreamSize: case StreamEventQueue::SetSeekable: case StreamEventQueue::Write: case StreamEventQueue::EndOfData: case StreamEventQueue::SeekDone: case StreamEventQueue::ResetDone: case StreamEventQueue::ConnectDone: pFatal("AbstractMediaStream2 received wrong Command"); break; case StreamEventQueue::NeedData: q->needData(qvariant_cast(c.data)); break; case StreamEventQueue::EnoughData: q->enoughData(); break; case StreamEventQueue::Seek: q->seekStream(qvariant_cast(c.data)); break; case StreamEventQueue::Reset: q->reset(); break; case StreamEventQueue::Connect: if (firstConnect) { firstConnect = false; streamEventQueue->sendToBackend(StreamEventQueue::ConnectDone); streamEventQueue->sendToBackend(StreamEventQueue::SetSeekable, streamSeekable); if (streamSize != 0) { streamEventQueue->sendToBackend(StreamEventQueue::SetStreamSize, streamSize); } } else { ++connectReset; q->reset(); } break; } } } AbstractMediaStream2::AbstractMediaStream2(QObject *parent) : AbstractMediaStream(*new AbstractMediaStream2Private, parent) { } AbstractMediaStream2::AbstractMediaStream2(AbstractMediaStream2Private &dd, QObject *parent) : AbstractMediaStream(dd, parent) { } void AbstractMediaStream2Private::setStreamSize(qint64 newSize) { streamSize = newSize; streamEventQueue->sendToBackend(StreamEventQueue::SetStreamSize, newSize); } void AbstractMediaStream2Private::setStreamSeekable(bool s) { streamSeekable = s; streamEventQueue->sendToBackend(StreamEventQueue::SetSeekable, s); } void AbstractMediaStream2Private::writeData(const QByteArray &data) { streamEventQueue->sendToBackend(StreamEventQueue::Write, data); } void AbstractMediaStream2Private::endOfData() { streamEventQueue->sendToBackend(StreamEventQueue::EndOfData); } void AbstractMediaStream2::resetDone() { Q_D(AbstractMediaStream2); if (d->connectReset > 0) { --d->connectReset; d->streamEventQueue->sendToBackend(StreamEventQueue::ConnectDone); } else { d->streamEventQueue->sendToBackend(StreamEventQueue::ResetDone); } d->streamEventQueue->sendToBackend(StreamEventQueue::SetSeekable, d->streamSeekable); if (d->streamSize != 0) { d->streamEventQueue->sendToBackend(StreamEventQueue::SetStreamSize, d->streamSize); } } void AbstractMediaStream2::seekStreamDone() { d_func()->streamEventQueue->sendToBackend(StreamEventQueue::SeekDone); } AbstractMediaStream2Private::AbstractMediaStream2Private() : streamEventQueue(new StreamEventQueue), eventDispatcher(0), connectReset(0), firstConnect(true) { streamEventQueue->ref(); streamEventQueue->setFrontendCommandHandler(this); } AbstractMediaStream2Private::~AbstractMediaStream2Private() { // setFrontendCommandHandler blocks internally until a handler that might be called right now is // done. That means AbstractMediaStream2Private::dataReady will either not run again or it will // be done before this object and our q object are deleted. streamEventQueue->setFrontendCommandHandler(0); streamEventQueue->deref(); streamEventQueue = 0; // if eventDispatcher->wakeUp() was called and we are now still connected to its awake() signal // then the QObject will be deleted until execution reaches the event loop again and // _k_handleStreamEvent will not get called } } // namespace Phonon #include "moc_abstractmediastream2.cpp" // vim: sw=4 sts=4 et tw=100