[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-multimedia
Subject:    Re: PATCH: proposed changes to KPlayObjectFactory/KPlayObjectCreator
From:       Matthias Welwarsky <matze () stud ! fbi ! fh-darmstadt ! de>
Date:       2002-08-28 11:02:31
[Download RAW message or body]

[Attachment #2 (multipart/mixed)]


On Wednesday 28 August 2002 12:53, Matthias Welwarsky wrote:
> Hi,
>
> to give you some more fan service, I post two patches that implement the
> proposed patches in KPlayObjectFactory/KPlayObjectCreator, including a
> patch to kaboodles Engine so that you can see how the Interface is meant to
> be used.
>
> I know that there's quite some uglyness in this approach, namely that the
> PlayObject is not being created by KPlayObjectCreator::create(), so that
> you cannot immediately call "play" after create(), and I'm open to
> suggestions, but I really don't want to keep the current enter_loop()
> approach that opens the door for many, many bugs due to reentrancy.
>
> regards,
> 	matze

oops, forgot the patch :)


--
Matthias Welwarsky
Fachschaft Informatik FH Darmstadt
Email: matze@stud.fbi.fh-darmstadt.de

"all software sucks equally, but some software is more equal"


[" " (text/x-diff)]

Index: engine.cpp
===================================================================
RCS file: /home/kde/kdemultimedia/kaboodle/engine.cpp,v
retrieving revision 1.31
diff -u -3 -p -u -r1.31 engine.cpp
--- engine.cpp	2002/06/06 10:56:59	1.31
+++ engine.cpp	2002/08/28 10:44:49
@@ -55,6 +55,7 @@ class Kaboodle::Engine::EnginePrivate
 public:
 	EnginePrivate()
 		: playobj(0)
+		, creator(0)
 		, dispatcher()
 		, server()
 	{
@@ -63,12 +64,15 @@ public:
 	~EnginePrivate()
 	{
 		delete playobj;
+		delete creator;
 	}
 
 	KPlayObject *playobj;
+	KPlayObjectCreator *creator;
 	KArtsDispatcher dispatcher;
 	KArtsServer server;
 	KURL file;
+	bool needPlaying;
 };
 
 Kaboodle::Engine::Engine(QObject *parent)
@@ -85,6 +89,8 @@ Kaboodle::Engine::~Engine()
 
 bool Kaboodle::Engine::load(const KURL &file)
 {
+	kdDebug() << "Engine::load " << file.url() << endl;
+
 	if(file.path().length())
 	{
 		d->file = file;
@@ -95,21 +101,65 @@ bool Kaboodle::Engine::load(const KURL &
 
 bool Kaboodle::Engine::reload(void)
 {
+	kdDebug() << "Engine::reload\n";
+
 	// Only You can prevent memory leaks
 	delete d->playobj;
 	d->playobj = 0;
+
+	delete d->creator;
+	d->creator = 0;
 
-	KPlayObjectFactory factory(d->server.server());
-	d->playobj = factory.createPlayObject(d->file, true);
+	d->creator = new KPlayObjectCreator(d->server.server());
+
+	connect(d->creator, SIGNAL(playObjectCreated(KPlayObject*)),
+		this, SLOT(attachPlayObject(KPlayObject*)));
+
+	bool result = d->creator->create(d->file, true);
 	
 	m_needReload = false;
+	d->needPlaying = false;
 
-	return !d->playobj->object().isNull();
+	return result;
+}
+
+void Kaboodle::Engine::attachPlayObject(KPlayObject* playObject)
+{
+	kdDebug() << "Engine::attachPlayObject\n";
+
+	if (d->playobj)
+		delete d->playobj;
+
+	d->playobj = playObject;
+	
+	// check if it's alive
+	if (d->playobj->object().isNull())
+		return;
+
+	// the object just got created, so we assume it's idle;
+	if (d->needPlaying) {
+		d->needPlaying = false;
+		m_needReload = true;
+		d->playobj->play();
+	}
 }
 
 void Kaboodle::Engine::play()
 {
-	if(d->playobj && !d->playobj->object().isNull())
+	kdDebug() << "Engine::play\n";
+
+	if (!d->playobj) {
+		// there is no playobject yet, start to play when
+		// it got created.
+	        d->needPlaying = true;
+		if (m_needReload)
+			reload();
+		return;
+	}
+
+	kdDebug() << "Engine::play " << d->playobj << endl;
+
+	if(!d->playobj->object().isNull())
 	{
 		switch(d->playobj->state())
 		{
@@ -117,7 +167,7 @@ void Kaboodle::Engine::play()
 			if (m_needReload) 
 				reload();
 			m_needReload = true;
-			d->playobj->play();
+			d->needPlaying = true;
 			break;
 		case Arts::posPaused:
 			d->playobj->play();
@@ -125,7 +175,7 @@ void Kaboodle::Engine::play()
 		default:
 			break;
 		}
-	}
+	} 
 }
 
 void Kaboodle::Engine::pause()
@@ -136,6 +186,8 @@ void Kaboodle::Engine::pause()
 
 void Kaboodle::Engine::stop()
 {
+//	kdDebug() << "Engine::stop\n";
+
 	if(d->playobj && !d->playobj->object().isNull())
 	{
 		d->playobj->halt();
@@ -146,6 +198,9 @@ void Kaboodle::Engine::stop()
 // pass time in msecs
 void Kaboodle::Engine::seek(unsigned long msec)
 {
+	if (!seekable())
+		return;
+
 	Arts::poTime t;
 
 	t.ms = (long) msec % 1000;
@@ -196,7 +251,7 @@ KMediaPlayer::Player::State Kaboodle::En
 
 bool Kaboodle::Engine::seekable(void)
 {
-	if(!d->playobj) return false;
+	if(!d->playobj || d->playobj->object().isNull()) return false;
 	return d->playobj->object().capabilities() & Arts::capSeek;
 }
 
@@ -206,3 +261,4 @@ Arts::PlayObject Kaboodle::Engine::playO
 }
 
 #include "engine.moc"
+
Index: engine.h
===================================================================
RCS file: /home/kde/kdemultimedia/kaboodle/engine.h,v
retrieving revision 1.14
diff -u -3 -p -u -r1.14 engine.h
--- engine.h	2002/06/06 10:56:59	1.14
+++ engine.h	2002/08/28 10:44:49
@@ -29,6 +29,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE 
 #include <kmediaplayer/player.h>
 #include <kurl.h>
 
+class KPlayObject;
+
 namespace Arts
 {
 class PlayObject;
@@ -77,6 +79,12 @@ public slots:
 	 * skips to a time
 	 **/
 	void seek(unsigned long msec);
+
+	/**
+	 * attaches a playobject to the engine
+	 * called by the KPlayObjectCreator
+	 **/
+	void attachPlayObject(KPlayObject*);
 
 public:
 	KMediaPlayer::Player::State state();

[" " (text/x-diff)]

Index: kplayobjectfactory.cc
===================================================================
RCS file: /home/kde/kdelibs/arts/kde/kplayobjectfactory.cc,v
retrieving revision 1.18
diff -u -3 -p -u -r1.18 kplayobjectfactory.cc
--- kplayobjectfactory.cc	2002/03/31 20:27:47	1.18
+++ kplayobjectfactory.cc	2002/08/28 10:45:39
@@ -44,104 +44,193 @@ KPlayObjectFactory::~KPlayObjectFactory(
 {
 }
 
-KPlayObject *KPlayObjectFactory::createPlayObject(const KURL& url, bool createBUS)
+KPlayObject *KPlayObjectFactory::createPlayObject(const KURL& url, const QString \
&mimetype, bool createBUS)  {
+	if(!m_server.isNull())
+	{
+		kdDebug() << "createPlayObject: mimetype is " << mimetype << endl;
 
-	// no need to go any further, and I hate deep indentation
-	if (m_server.isNull() || url.isEmpty() )
+		if(mimetype == "application/octet-stream" && m_allowStreaming)
+		{
+			Arts::KIOInputStream instream;
+			instream.openURL(url.url().latin1());
+	    
+			m_stream = true;
+		
+			// TODO: what else than hardcoding audio/x-mp3 ?
+			return new KPlayObject(m_server.createPlayObjectForStream(instream, \
string("audio/x-mp3"), createBUS), true); +		}
+		else if(mimetype == "video/mpeg" && m_allowStreaming)
+		{
+			Arts::KIOInputStream instream;
+			instream.openURL(url.url().latin1());
+
+			m_stream = true;
+
+			return new KPlayObject(m_server.createPlayObjectForStream(instream, \
string("video/mpeg"), createBUS), true); +		}
+		else
+			return new KPlayObject(m_server.createPlayObjectForURL(string(QFile::encodeName(url.path())), \
string(mimetype.latin1()), createBUS), false); +	}
+	else
 		return new KPlayObject();
+}
+
+QStringList KPlayObjectFactory::mimeTypes(void)
+{
+	Arts::TraderQuery query;
+	vector<Arts::TraderOffer> *offers = query.query();
 
+	QStringList results;
+	for(vector<Arts::TraderOffer>::iterator offer = offers->begin();
+	    offer != offers->end(); ++offer)
+	{
+		vector<string> *mimetypes = (*offer).getProperty("MimeType");
+
+		for(vector<string>::iterator mimetype = mimetypes->begin();
+		    mimetype != mimetypes->end(); ++mimetype)
+		{
+			QString name = QString::fromLocal8Bit((*mimetype).c_str()).stripWhiteSpace();
+			if(KMimeType::mimeType(name))
+				results.append(name);
+		}
+
+		delete mimetypes;
+	}
+	delete offers;
+
+	// clean out duplicates
+	results.sort();
+	for(QStringList::iterator result = results.begin(); result != results.end(); )
+	{
+		QStringList::iterator previous = result;
+		++result;
+		if(result != results.end() && *result == *previous)
+		{
+			results.remove(result);
+			result = previous;
+		}
+	}
+
+	return results;
+}
+
+/*
+ * Implementation of KPlayObjectCreator
+ *
+ * the functionality is duplicated from KPlayObjectFactory, but it seems
+ * impossible to extend the existing class while staying binary compatible
+ * (missing d* for example)
+ */
+
+struct KPlayObjectCreator::PrivateData {
+	Arts::SoundServerV2 server;
+	Arts::KIOInputStream instream;
+	bool createBUS;
+};
+
+KPlayObjectCreator::KPlayObjectCreator(Arts::SoundServerV2 server)
+{
+	d = new PrivateData;
+	d->server = server;
+}
+
+KPlayObjectCreator::~KPlayObjectCreator()
+{
+	delete d;
+}
+
+bool KPlayObjectCreator::create(const KURL& url, bool createBUS)
+{
+	// no need to go any further, and I hate deep indentation
+	if (d->server.isNull() || url.isEmpty() )
+		return false;
+
 	// check if streaming is allowed or the URL is a local file
-	if (m_allowStreaming && !url.isLocalFile())
+	if (!url.isLocalFile())
 	{
+		d->createBUS = createBUS;
+
 		// This is the RightWay(tm) according to stw
 		Arts::KIOInputStream_impl* instream_impl = new Arts::KIOInputStream_impl();
-		Arts::KIOInputStream instream = Arts::KIOInputStream::_from_base(instream_impl);
+		d->instream = Arts::KIOInputStream::_from_base(instream_impl);
 
 		// signal will be called once the ioslave knows the mime-type of the stream
 		QObject::connect(instream_impl, SIGNAL(mimeTypeFound(const QString &)),
 				 this, SLOT(slotMimeType(const QString &)));
 
 		// GO!
-		instream.openURL(url.url().latin1());
-		instream.streamStart();
+		d->instream.openURL(url.url().latin1());
+		d->instream.streamStart();
 
-		m_eventLoopEntered = true;
-		// FIXME: need to handle timeouts?
-		// this is UGLY, but I cannot do anything else without changing the interface
-		// the application blocks here, and restarts once slotMimeType() is called.
-		kapp->enter_loop();
-		
-		// wb :D
-		// some error occoured
-		if (m_mimeType == "application/x-zerosize")
-		    return new KPlayObject();
-
-		// ok, now we know the mimetype of the stream
-		m_stream = true;		
-		return new KPlayObject(m_server.createPlayObjectForStream(instream, 
-									  string(m_mimeType.latin1()), 
-									  createBUS), true);
+		return true;
 	}
 	kdDebug() << "stream is local file: " << url.url() << endl;
 
 	// usual stuff if we have a local file
 	KMimeType::Ptr mimetype = KMimeType::findByURL(url);
-	return new KPlayObject(m_server.createPlayObjectForURL(string(QFile::encodeName(url.path())), \
                
-							       string(mimetype->name().latin1()), 
-							       createBUS), 
-			       false);
+	emit playObjectCreated (
+		new KPlayObject(d->server.createPlayObjectForURL(string(QFile::encodeName(url.path())), \
 +								 string(mimetype->name().latin1()), 
+								 createBUS), false)
+		);
+	return true;
 }
 
-void KPlayObjectFactory::slotMimeType(const QString& mimetype)
+void KPlayObjectCreator::slotMimeType(const QString& mimetype)
 {
 
 	kdDebug() << "slotMimeType called: " << mimetype << endl;
 
-	if ( mimetype == "application/octet-stream" )
-	    m_mimeType = "audio/x-mp3";
-	else
-	    m_mimeType = mimetype;
+	QString mimetype_copy = mimetype;
 
-	if (m_eventLoopEntered) {
-		m_eventLoopEntered = false;
-		kapp->exit_loop();
-	}
+	if ( mimetype_copy == "application/octet-stream" )
+	    mimetype_copy = QString("audio/x-mp3");
+
+	if (mimetype_copy == "application/x-zerosize")
+		emit playObjectCreated(new KPlayObject());
+
+	emit playObjectCreated (
+		new KPlayObject(d->server.createPlayObjectForStream(
+			d->instream, string(mimetype_copy.latin1()), d->createBUS), true)
+		);
 }
 
-KPlayObject *KPlayObjectFactory::createPlayObject(const KURL& url, const QString \
&mimetype, bool createBUS) +bool KPlayObjectCreator::create(const KURL& url, const \
QString &mimetype, bool createBUS)  {
-	if(!m_server.isNull())
+	if (d->server.isNull() || url.isEmpty())
+		return false;
+	
+       	kdDebug() << "create: mimetype is " << mimetype << endl;
+	
+	if (url.isLocalFile())
 	{
-		kdDebug() << "createPlayObject: mimetype is " << mimetype << endl;
-
-		if(mimetype == "application/octet-stream" && m_allowStreaming)
-		{
-			Arts::KIOInputStream instream;
-			instream.openURL(url.url().latin1());
-	    
-			m_stream = true;
+		kdDebug() << "url " << url.url() << " is a local file\n";
 		
-			// TODO: what else than hardcoding audio/x-mp3 ?
-			return new KPlayObject(m_server.createPlayObjectForStream(instream, \
                string("audio/x-mp3"), createBUS), true);
-		}
-		else if(mimetype == "video/mpeg" && m_allowStreaming)
-		{
-			Arts::KIOInputStream instream;
-			instream.openURL(url.url().latin1());
-
-			m_stream = true;
-
-			return new KPlayObject(m_server.createPlayObjectForStream(instream, \
                string("video/mpeg"), createBUS), true);
-		}
-		else
-			return new KPlayObject(m_server.createPlayObjectForURL(string(QFile::encodeName(url.path())), \
string(mimetype.latin1()), createBUS), false); +		emit playObjectCreated(
+			new KPlayObject(d->server.createPlayObjectForURL(
+				string(QFile::encodeName(url.path())), 
+				string(mimetype.latin1()), createBUS), 
+					false)
+			);
 	}
 	else
-		return new KPlayObject();
+	{
+		kdDebug() << "url " << url.url() << " is a stream\n";
+		
+		Arts::KIOInputStream instream;
+		instream.openURL(url.url().latin1());
+		emit playObjectCreated(
+			new KPlayObject(d->server.createPlayObjectForStream(
+				instream, 
+				string(mimetype.latin1()), 
+				createBUS), true)
+			);
+	}
+	return true;
 }
 
-QStringList KPlayObjectFactory::mimeTypes(void)
+QStringList KPlayObjectCreator::mimeTypes(void)
 {
 	Arts::TraderQuery query;
 	vector<Arts::TraderOffer> *offers = query.query();
@@ -179,3 +268,21 @@ QStringList KPlayObjectFactory::mimeType
 
 	return results;
 }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: kplayobjectfactory.h
===================================================================
RCS file: /home/kde/kdelibs/arts/kde/kplayobjectfactory.h,v
retrieving revision 1.11
diff -u -3 -p -u -r1.11 kplayobjectfactory.h
--- kplayobjectfactory.h	2002/03/31 20:27:47	1.11
+++ kplayobjectfactory.h	2002/08/28 10:45:39
@@ -27,9 +27,8 @@
 #include "soundserver.h"
 #include "kplayobject.h"
 
-class KPlayObjectFactory : public QObject
+class KPlayObjectFactory
 {
-Q_OBJECT
 public:
 	KPlayObjectFactory(Arts::SoundServerV2 server);
 	~KPlayObjectFactory();
@@ -47,15 +46,41 @@ public:
 	 */
 	static QStringList mimeTypes(void);
 
-private slots:
-	void slotMimeType(const QString &mimetype);
-
 private:
 	Arts::SoundServerV2 m_server;
 	bool m_allowStreaming;
 	bool m_stream;
-	bool m_eventLoopEntered;
-	QString m_mimeType;
+};
+
+
+
+class KPlayObjectCreator : public QObject
+{
+Q_OBJECT
+public:
+	KPlayObjectCreator(Arts::SoundServerV2 server);
+	~KPlayObjectCreator();
+
+	bool create(const KURL& url, bool createBUS);
+	bool create(const KURL& url, const QString &mimetype, bool createBUS);
+
+	/**
+	 * Return the mimetypes that are playable
+	 */
+	static QStringList mimeTypes(void);
+
+signals:
+	void playObjectCreated(KPlayObject* playObject);
+
+private slots:
+	void slotMimeType(const QString &mimetype);
+
+private:
+	struct PrivateData;
+	PrivateData* d;
 };
 
 #endif
+
+
+


[Attachment #7 (application/pgp-signature)]
_______________________________________________
kde-multimedia mailing list
kde-multimedia@mail.kde.org
http://mail.kde.org/mailman/listinfo/kde-multimedia

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic