summaryrefslogtreecommitdiffstats
path: root/kdemm/factory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdemm/factory.cpp')
-rw-r--r--kdemm/factory.cpp296
1 files changed, 296 insertions, 0 deletions
diff --git a/kdemm/factory.cpp b/kdemm/factory.cpp
new file mode 100644
index 000000000..1994b8e5e
--- /dev/null
+++ b/kdemm/factory.cpp
@@ -0,0 +1,296 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Matthias Kretz <kretz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include "factory.h"
+#include "backend.h"
+#include "player.h"
+#include "videoplayer.h"
+#include "channel.h"
+
+#include <ktrader.h>
+#include <kservice.h>
+#include <klibloader.h>
+#include <kmessagebox.h>
+#include <tqfile.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <kdebug.h>
+
+namespace KDE
+{
+namespace Multimedia
+{
+class Factory::Private
+{
+ public:
+ Private()
+ : backend( 0 )
+ {
+ createBackend();
+ }
+
+ void createBackend()
+ {
+ KTrader::OfferList offers = KTrader::self()->query( "KDEMultimediaBackend", "Type == 'Service'" );
+ KTrader::OfferListIterator it = offers.begin();
+ KTrader::OfferListIterator end = offers.end();
+ TQStringList errormsg;
+ for( ; it != end; ++it )
+ {
+ KService::Ptr ptr = *it;
+ KLibFactory * factory = KLibLoader::self()->factory( TQFile::encodeName( ptr->library() ) );
+ if( factory )
+ {
+ backend = ( Backend* )factory->create( 0, "Multimedia Backend", "KDE::Multimedia::Backend" );
+ if( 0 == backend )
+ {
+ TQString e = i18n( "create method returned 0" );
+ errormsg.append( e );
+ kdDebug( 600 ) << "Error getting backend from factory for " <<
+ ptr->name() << ":\n" << e << endl;
+ }
+ else
+ {
+ service = ptr;
+ kdDebug( 600 ) << "using backend: " << ptr->name() << endl;
+ break;
+ }
+ }
+ else
+ {
+ TQString e = KLibLoader::self()->lastErrorMessage();
+ errormsg.append( e );
+ kdDebug( 600 ) << "Error getting factory for " << ptr->name() <<
+ ":\n" << e << endl;
+ }
+ }
+#if 0
+ if( 0 == backend )
+ {
+ if( offers.size() == 0 )
+ KMessageBox::error( 0, i18n( "Unable to find a Multimedia Backend" ) );
+ else
+ {
+ TQString details = "<qt><table>";
+ TQStringList::Iterator eit = errormsg.begin();
+ TQStringList::Iterator eend = errormsg.end();
+ KTrader::OfferListIterator oit = offers.begin();
+ KTrader::OfferListIterator oend = offers.end();
+ for( ; eit != eend || oit != oend; ++eit, ++oit )
+ details += TQString( "<tr><td><b>%1</b></td><td>%2</td></tr>" )
+ .arg( ( *oit )->name() ).arg( *eit );
+ details += "</table></qt>";
+
+ KMessageBox::detailedError( 0,
+ i18n( "Unable to use any of the available Multimedia Backends" ), details );
+ }
+ }
+#endif
+ }
+
+ Backend * backend;
+ KService::Ptr service;
+
+ TQValueList<void*> objects;
+};
+
+Factory * Factory::m_self = 0;
+
+Factory * Factory::self()
+{
+ if( ! m_self )
+ m_self = new Factory();
+ return m_self;
+}
+
+Factory::Factory()
+ : DCOPObject( "KDEMMFactory" )
+ , d( new Private )
+{
+ connectDCOPSignal( 0, 0, "kdemmBackendChanged()", "kdemmBackendChanged()", false);
+}
+
+Factory::~Factory()
+{
+ delete d;
+}
+
+void Factory::kdemmBackendChanged()
+{
+ if( d->backend )
+ {
+ // wouw, if we want to switch on the fly we have to exchange the
+ // (Video)Player and Channel classes without the API user noticing. That
+ // would mean to implement a kind of smartwrapper:
+ // Player: Interface that accesses Player_skel which is abstract and is
+ // implemented by the Backend. The API user would only get access to the
+ // Player class and if you want to switch the backend you can delete the
+ // Player_skel object and put another implementation in its place.
+ //
+ // Now we tell the kdemm using app to help us. With the first signal we
+ // tell 'em to delete all the (Video)Players and Channels and with the
+ // second to recreate them all again.
+ emit deleteYourObjects();
+ if( d->objects.size() > 0 )
+ {
+ kdWarning( 600 ) << "we were asked to change the backend but the application did\n"
+ "not free all references to objects created by the factory. Therefor we can not\n"
+ "change the backend without crashing. Now we have to wait for a restart to make\n"
+ "backendswitching possible." << endl;
+ // in case there were objects deleted give 'em a chance to recreate
+ // them now
+ emit recreateObjects();
+ return;
+ }
+ delete d->backend;
+ d->backend = 0;
+ }
+ d->createBackend();
+ emit recreateObjects();
+}
+
+void Factory::objectDestroyed( TQObject * obj )
+{
+ kdDebug( 600 ) << k_funcinfo << obj << endl;
+ void * p = ( void* )obj;
+ d->objects.remove( p );
+}
+
+Player * Factory::createPlayer()
+{
+ if( d->backend )
+ {
+ Player * p = d->backend->createPlayer();
+ connect( p, TQT_SIGNAL( destroyed( TQObject* ) ), TQT_SLOT( objectDestroyed( TQObject* ) ) );
+ d->objects.append( p );
+ return p;
+ }
+ else
+ return 0;
+}
+
+VideoPlayer * Factory::createVideoPlayer()
+{
+ if( d->backend )
+ {
+ VideoPlayer * vp = d->backend->createVideoPlayer();
+ connect( vp, TQT_SIGNAL( destroyed( TQObject* ) ), TQT_SLOT( objectDestroyed( TQObject* ) ) );
+ d->objects.append( vp );
+ return vp;
+ }
+ else
+ return 0;
+}
+
+bool Factory::playSoundEvent(const KURL & url)
+{
+ if( d->backend )
+ return d->backend->playSoundEvent(url);
+ else
+ return false;
+}
+
+Channel * Factory::createChannel( const TQString & title, const TQString & channeltype,
+ Channel::Direction direction )
+{
+ if( d->backend )
+ {
+ Channel * c = d->backend->createChannel( title, channeltype, direction );
+ connect( c, TQT_SIGNAL( destroyed( TQObject* ) ), TQT_SLOT( objectDestroyed( TQObject* ) ) );
+ d->objects.append( c );
+ return c;
+ }
+ else
+ return 0;
+}
+
+TQStringList Factory::availableChannels( Channel::Direction direction ) const
+{
+ if( d->backend )
+ return d->backend->availableChannels( direction );
+ else
+ return TQStringList();
+}
+
+TQStringList Factory::playableMimeTypes() const
+{
+ if( d->backend )
+ return d->backend->playableMimeTypes();
+ else
+ return TQStringList();
+}
+
+bool Factory::isMimeTypePlayable( const TQString & type ) const
+{
+ if( d->backend )
+ {
+ KMimeType::Ptr mimetype = KMimeType::mimeType( type );
+ TQStringList mimetypes = playableMimeTypes();
+ for( TQStringList::ConstIterator i=mimetypes.begin(); i!=mimetypes.end(); i++ )
+ if( mimetype->is( *i ) )
+ return true;
+ }
+ return false;
+}
+
+TQString Factory::backendName() const
+{
+ if( d->service )
+ return d->service->name();
+ else
+ return TQString::null;
+}
+
+TQString Factory::backendComment() const
+{
+ if( d->service )
+ return d->service->comment();
+ else
+ return TQString::null;
+}
+
+TQString Factory::backendVersion() const
+{
+ if( d->service )
+ return d->service->property( "X-KDE-MMBackendInfo-Version" ).toString();
+ else
+ return TQString::null;
+}
+
+TQString Factory::backendIcon() const
+{
+ if( d->service )
+ return d->service->icon();
+ else
+ return TQString::null;
+}
+
+TQString Factory::backendWebsite() const
+{
+ if( d->service )
+ return d->service->property( "X-KDE-MMBackendInfo-Website" ).toString();
+ else
+ return TQString::null;
+}
+
+}} //namespaces
+
+#include "factory.moc"
+
+// vim: sw=4 ts=4 noet