diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | ce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch) | |
tree | 5ac38a06f3dde268dc7927dc155896926aaf7012 /arts/kde | |
download | tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'arts/kde')
43 files changed, 5132 insertions, 0 deletions
diff --git a/arts/kde/Makefile.am b/arts/kde/Makefile.am new file mode 100644 index 000000000..5a933ba68 --- /dev/null +++ b/arts/kde/Makefile.am @@ -0,0 +1,40 @@ +INCLUDES = -I$(top_builddir)/arts/kde \ + -I$(top_srcdir) -I$(includedir)/arts $(all_includes) + +lib_LTLIBRARIES = libartskde.la +libartskde_la_SOURCES = artskde.cc kioinputstream_impl.cpp kplayobject.cc \ + kplayobjectfactory.cc kartsfloatwatch.cpp kartsdispatcher.cc \ + kaudiorecordstream.cpp kaudioplaystream.cpp \ + kartsserver.cpp kdatarequest_impl.cpp kaudioconverter.cc \ + kvideowidget.cpp kplayobjectcreator.cc \ + kaudiomanagerplay.cpp +libartskde_la_LIBADD = $(LIB_KIO) -lqtmcop -lsoundserver_idl +libartskde_la_LDFLAGS = $(all_libraries) -no-undefined -version-info 3:0:2 +libartskde_la_METASOURCES = AUTO +libartskde_la_COMPILE_FIRST = artskde.h + +artskdeincludedir = $(includedir)/arts +artskdeinclude_HEADERS = kplayobject.h kplayobjectfactory.h kartsfloatwatch.h \ + artskde.h kartsdispatcher.h \ + kaudiorecordstream.h kaudioplaystream.h \ + kartsserver.h kvideowidget.h kaudiomanagerplay.h +noinst_HEADERS = kplayobjectcreator.h kplayobjectfactory_p.h + +artskde.mcoptype: artskde.h +artskde.mcopclass: artskde.h +MCOPINC = -I$(srcdir) +artskde.cc artskde.h: $(top_srcdir)/arts/kde/artskde.idl $(MCOPIDL) + $(MCOPIDL) -I$(includedir)/arts -t $(MCOPINC) $(top_srcdir)/arts/kde/artskde.idl + +DISTCLEANFILES = artskde.cc artskde.h artskde.mcoptype artskde.mcopclass + +check_PROGRAMS = kiotest kiotestslow kconverttest +kiotest_SOURCES = kiotest.cc +kiotestslow_SOURCES = kiotestslow.cc +kconverttest_SOURCES = kconverttest.cc + +kiotest_LDADD = libartskde.la -lqtmcop -lkmedia2 -lsoundserver_idl +kiotestslow_LDADD = $(kiotest_LDADD) +kconverttest_LDADD = $(kiotest_LDADD) + +# vim: ts=8 noet diff --git a/arts/kde/README b/arts/kde/README new file mode 100644 index 000000000..2d34f08fd --- /dev/null +++ b/arts/kde/README @@ -0,0 +1,51 @@ +libartskde Introduction +----------------------- + +1. What is libartskde? +libartskde is a simple KDE->aRts wrapper +that allows the developer to use KDE +technology to access aRts. +ie. no need to deal with std::string's anymore +etc.. you can just use QString's or KURL's +to play sound + +2. How to use it to play sounds? +<snip> +1 KArtsDispatcher dispatcher; +2 KArtsServer server; + +3 KURL file = "file:/home/nikoz/test.mp3"; + +4 KPlayObjectFactory factory(server.server()); +5 KPlayObject *playobj = factory.createPlayObject(file, true); + +6 playobj->play(); +<snap> + +Line: +1 Sets up the a KArtsDispatcher +2 Starts a new SoundServerV2 in the running artsd process + +3 Simple test URL to demonstrate the use with KURL + +4 Creates a KPlayObjectFactory, parameter: our SoundServerV2 +5 Gets a KPlayObject from the factory, containing an Arts::PlayObject + created in our running artsd process + Parameters: + KURL url + (specifies the url to be played) + bool createBUS + (specifies wheter to create a Synth_BUS_UPLINK or not, "false" is only interesting if you want to use EffectsStacks etc..., see Noatun) +6 Play the file + +That's it, with 6 LOC a "full" media player :) + +To make the example above compile you will also have to add these #includes: +#include <arts/kartsserver.h> +#include <arts/kartsdispatcher.h> +#include <arts/kplayobject.h> +#include <arts/kplayobjectfactory.h> + +Enjoy... +Nikolas Zimmermann +<wildfox@kde.org> diff --git a/arts/kde/artskde.idl b/arts/kde/artskde.idl new file mode 100644 index 000000000..f31b49ed4 --- /dev/null +++ b/arts/kde/artskde.idl @@ -0,0 +1,41 @@ +#include <kmedia2.idl> + +module Arts { + +/* + * notification proxy for floats, used internally! + */ +interface KFloatWatchProxy { + attribute float value; +}; + +/* + * used for deliviering MCOP data to the playobjects + */ +interface KIOInputStream : InputStream { + boolean openURL(string url); + + attribute long bufferPackets; + + long packetSize(); +}; + +/* + * used for piping raw data to KAudioConverter from the POs + */ +interface KDataRequest : SynthModule { + void goOn(); + + default in audio stream left, right; +}; + +/* + * TESTING ONLY + */ + +interface KIOTestSlow : SynthModule { + async in byte stream data; + + attribute InputStream inputStream; +}; +}; diff --git a/arts/kde/kartsdispatcher.cc b/arts/kde/kartsdispatcher.cc new file mode 100644 index 000000000..e6136ce12 --- /dev/null +++ b/arts/kde/kartsdispatcher.cc @@ -0,0 +1,60 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include <qiomanager.h> +#include <dispatcher.h> + +#include <kdebug.h> + +#include "kartsdispatcher.moc" + +int KArtsDispatcher::m_refCount = 0; +Arts::Dispatcher *KArtsDispatcher::artsDispatcher = 0; +Arts::QIOManager *KArtsDispatcher::artsQIOManager = 0; + +KArtsDispatcher::KArtsDispatcher(QObject *parent, const char *name) + : QObject(parent, name) +{ + m_refCount++; + if(artsDispatcher == 0) + { + if (!Arts::Dispatcher::the()) // only if no Arts::Dispatcher is created yet + { + artsQIOManager = new Arts::QIOManager(); + artsDispatcher = new Arts::Dispatcher(artsQIOManager); + } + else + kdWarning(400) << "An Arts::Dispatcher() instance exists already while trying to instantiate KArtsDispatcher!" << endl; + } +} + +KArtsDispatcher::~KArtsDispatcher() +{ + m_refCount--; + if(m_refCount == 0) + { + delete KArtsDispatcher::artsDispatcher; + artsDispatcher = 0; + + delete KArtsDispatcher::artsQIOManager; + artsQIOManager = 0; + } +} diff --git a/arts/kde/kartsdispatcher.h b/arts/kde/kartsdispatcher.h new file mode 100644 index 000000000..db2792a97 --- /dev/null +++ b/arts/kde/kartsdispatcher.h @@ -0,0 +1,87 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#ifndef KARTSDISPATCHER_H +#define KARTSDISPATCHER_H + +#include <qobject.h> + +#include <kdelibs_export.h> + +namespace Arts +{ + class QIOManager; + class Dispatcher; +} + +/** + * KArtsDispatcher ensures that an instance of Arts::Dispatcher using an + * Arts::QIOManager exists. When the last KArtsDispatcher is deleted, the + * Arts::Dispatcher is released as well. + * + * Using KArtsDispatcher is especially useful in setups where another plugin + * might also already use an Arts::Dispatcher, for instance in konqueror. + * + * \code + * { + * // old code + * Arts::QIOManager qiomanager; + * Arts::Dispatcher dispatcher(&qiomanager); + * + * Arts::SoundServer server = Arts::Reference("global:Arts_SoundServer"); + * server.play("/usr/share/sounds/pop.wav"); + * } + * \endcode + * + * \code + * { + * // new code + * KArtsDispatcher dispatcher; + * + * Arts::SoundServer server = Arts::Reference("global:Arts_SoundServer"); + * server.play("/usr/share/sounds/pop.wav"); + * } + * \endcode + */ +class KDE_EXPORT KArtsDispatcher : public QObject +{ +Q_OBJECT +public: + /** + * Constructor. + * + * @param parent the parent Qt object + * @param name the Qt object name of this object + */ + KArtsDispatcher(QObject *parent = 0, const char *name = 0); + + /** + * Destructor + */ + ~KArtsDispatcher(); + +private: + static int m_refCount; + static Arts::Dispatcher *artsDispatcher; + static Arts::QIOManager *artsQIOManager; +}; + +#endif diff --git a/arts/kde/kartsfloatwatch.cpp b/arts/kde/kartsfloatwatch.cpp new file mode 100644 index 000000000..d26d76718 --- /dev/null +++ b/arts/kde/kartsfloatwatch.cpp @@ -0,0 +1,64 @@ + /* + + Copyright (C) 2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "artskde.h" +#include "kartsfloatwatch.moc" +#include "connect.h" + +using namespace Arts; + +class KArtsFloatWatchPrivate { +public: + KFloatWatchProxy proxy; +}; + +namespace Arts { + +class KFloatWatchProxy_impl : public KFloatWatchProxy_skel { +protected: + KArtsFloatWatch *watch; +public: + KFloatWatchProxy_impl(KArtsFloatWatch *watch) : watch(watch) { }; + + float value() { return 0.0; /* dummy */ } + void value(float newValue) { watch->change(newValue); } +}; + +} + +KArtsFloatWatch::KArtsFloatWatch(Arts::Object object, const char *stream, + QObject *parent, const char *name) : QObject(parent, name) +{ + d = new KArtsFloatWatchPrivate(); + d->proxy = KFloatWatchProxy::_from_base(new KFloatWatchProxy_impl(this)); + Arts::connect(object, stream, d->proxy, "value"); +} + +KArtsFloatWatch::~KArtsFloatWatch() +{ + delete d; +} + +void KArtsFloatWatch::change(float newValue) +{ + emit valueChanged(newValue); +} diff --git a/arts/kde/kartsfloatwatch.h b/arts/kde/kartsfloatwatch.h new file mode 100644 index 000000000..6c23327ea --- /dev/null +++ b/arts/kde/kartsfloatwatch.h @@ -0,0 +1,82 @@ + /* + + Copyright (C) 2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "common.h" +#include <qobject.h> + +class KArtsFloatWatchPrivate; +namespace Arts { class KFloatWatchProxy_impl; } + +/** + * KArtsFloatWatch offers an easy way to watch aRts streams via Qt signals. + * For instance, if you have an object of the following type: + * + * \code + * interface StereoVolumeControl : StereoEffect { + * attribute float scaleFactor; + * readonly attribute float currentVolumeLeft; + * readonly attribute float currentVolumeRight; + * }; + * \endcode + * + * and you want to get notified when scaleFactor changes, you could do it + * like this: + * + * \code + * StereoVolumeControl stereoVolumeControl = ...; + * KArtsFloatWatch *w = new KArtsFloatWatch(stereoVolumeControl, "scaleFactor_changed", this); + * connect(w, SIGNAL(valueChanged(float)), this, SLOT(setValue(float))); + * \endcode + */ +class KArtsFloatWatch : public QObject { + Q_OBJECT +private: + KArtsFloatWatchPrivate *d; + friend class Arts::KFloatWatchProxy_impl; + + /** + * called by the proxy (internal) + */ + void change(float newValue); + +public: + /** + * Constructor. + * + * @param object the aRts object that should be watched + * @param stream the aRts stream that should be watched + * @param parent the parent Qt object + * @param name the Qt object name of this object + */ + KArtsFloatWatch(Arts::Object object, const char *stream, QObject *parent = 0, const char *name = 0); + + /** + * Destructor + */ + ~KArtsFloatWatch(); + +signals: + /** + * this signal will be emitted with values of the aRts stream + */ + void valueChanged(float newValue); +}; diff --git a/arts/kde/kartsserver.cpp b/arts/kde/kartsserver.cpp new file mode 100644 index 000000000..9b4739928 --- /dev/null +++ b/arts/kde/kartsserver.cpp @@ -0,0 +1,111 @@ +// Copyright (c) 2000-2001 Charles Samuels <charles@kde.org> +// Neil Stevens <neil@qualityassistant.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIAB\ILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include <flowsystem.h> +#include <ksimpleconfig.h> +#include <kprocess.h> +#include <kstandarddirs.h> +#include <qdir.h> +#include <qfile.h> +#include "kartsserver.h" + +struct KArtsServer::Data +{ + Arts::SoundServerV2 server; +}; + +KArtsServer::KArtsServer(QObject *parent, const char *name) + : QObject(parent, name) + , d(new Data) +{ + d->server = Arts::SoundServerV2::null(); +} + +KArtsServer::~KArtsServer(void) +{ + d->server = Arts::SoundServerV2::null(); + delete d; +} + +Arts::SoundServerV2 KArtsServer::server(void) +{ + bool error = d->server.error(); + if( d->server.isNull() || error ) + { + d->server = Arts::Reference("global:Arts_SoundServerV2"); + if( error && !d->server.isNull() && !d->server.error() ) + emit restartedServer(); + } + + if(!d->server.isNull() && !d->server.error()) + return d->server; + + // aRts seems not to be running, let's try to run it + // First, let's read the configuration as in kcmarts + KConfig config("kcmartsrc", false /*bReadOnly*/, false /*bUseKDEGlobals*/); + KProcess proc; + + config.setGroup("Arts"); + + bool rt = config.readBoolEntry("StartRealtime", false); + bool x11Comm = config.readBoolEntry("X11GlobalComm", false); + + // put the value of x11Comm into .mcoprc + KSimpleConfig X11CommConfig(QDir::homeDirPath()+"/.mcoprc"); + + if(x11Comm) + X11CommConfig.writeEntry("GlobalComm", "Arts::X11GlobalComm"); + else + X11CommConfig.writeEntry("GlobalComm", "Arts::TmpGlobalComm"); + + X11CommConfig.sync(); + + proc << QFile::encodeName(KStandardDirs::findExe(QString::fromLatin1("kdeinit_wrapper"))); + + if(rt) + proc << QFile::encodeName(KStandardDirs::findExe(QString::fromLatin1("artswrapper"))); + else + proc << QFile::encodeName(KStandardDirs::findExe(QString::fromLatin1("artsd"))); + + proc << QStringList::split( " ", config.readEntry( "Arguments", "-F 10 -S 4096 -s 60 -m artsmessage -l 3 -f" ) ); + + if(proc.start(KProcess::Block) && proc.normalExit()) + { + // We could have a race-condition here. + // The correct way to do it is to make artsd fork-and-exit + // after starting to listen to connections (and running artsd + // directly instead of using kdeinit), but this is better + // than nothing. + int time = 0; + do + { + sleep(1); + d->server = Arts::Reference("global:Arts_SoundServerV2"); + } while(++time < 5 && (d->server.isNull())); + + emit restartedServer(); + } + // TODO else what? + + return d->server; +} + +// vim: sw=4 ts=4 noet +#include "kartsserver.moc" diff --git a/arts/kde/kartsserver.h b/arts/kde/kartsserver.h new file mode 100644 index 000000000..8456e25ea --- /dev/null +++ b/arts/kde/kartsserver.h @@ -0,0 +1,75 @@ +// Copyright (c) 2000-2001 Charles Samuels <charles@kde.org> +// Neil Stevens <neil@qualityassistant.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIAB\ILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef KARTSSERVER_H +#define KARTSSERVER_H + +#include "kmedia2.h" +#include <qobject.h> +#include "soundserver.h" +#include <kdelibs_export.h> + +/** + * KArtsServer is a wrapper to conveniently get a reference to a SoundServer, + * and restart artsd when necessary, using the kcontrol settings. + * + * Of course we'd rather that artsd never crashed, and that all users start + * artsd on KDE startup, but at the very least there will always be third + * party PlayObjects that will crash. So, this is necessary. + */ +class KDE_ARTS_EXPORT KArtsServer : public QObject +{ +Q_OBJECT + +public: + /** + * Create a new KArtsServer. Don't forget to create a KArtsDispatcher + * before using KArtsServer. + */ + KArtsServer(QObject *parent = 0, const char *name = 0); + virtual ~KArtsServer(void); + + /** + * Get a verified reference to the SoundServerV2, (re)starting artsd + * using the kcontrol-specified settings if necessary. + * + * If the soundserver has changed since you called this method the last + * time (meaning artsd was restarted) restartedServer() will be emitted. + */ + Arts::SoundServerV2 server(void); + +signals: + /** + * This is emitted when the soundserver has been restarted (by this + * KArtsServer instance or outside). It is not + * emitted automatically when the soundserver comes up but only after + * your code calls server(). + */ + void restartedServer(void); + +private: + KArtsServer(const KArtsServer &rhs); + KArtsServer &operator=(const KArtsServer &rhs); + + struct Data; + Data *d; +}; + +#endif diff --git a/arts/kde/kaudioconverter.cc b/arts/kde/kaudioconverter.cc new file mode 100644 index 000000000..a5f1e8e43 --- /dev/null +++ b/arts/kde/kaudioconverter.cc @@ -0,0 +1,198 @@ + /* + + Copyright (C) 2002 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "config.h" +#include "artskde.h" +#include "connect.h" +#include "flowsystem.h" +#include "audiosubsys.h" +#include "dynamicrequest.h" +#include "kdatarequest_impl.h" +#include "kioinputstream_impl.h" +#include "kaudioconverter.moc" + +#include <iostream> + +#include <qfile.h> +#include <qtimer.h> + +#include <kurl.h> +#include <kdebug.h> +#include <kmimetype.h> +#include <kapplication.h> + +using namespace std; + +KAudioConverter::KAudioConverter() +{ + m_incoming = 0; + m_started = false; +} + +KAudioConverter::~KAudioConverter() +{ + delete m_incoming; +} + +bool KAudioConverter::setup(int samplingRate) +{ + string backupAudioIO = Arts::AudioSubSystem::the()->audioIO(); + int backupSamplingRate = Arts::AudioSubSystem::the()->samplingRate(); + + Arts::AudioSubSystem::the()->audioIO("null"); + Arts::AudioSubSystem::the()->samplingRate(samplingRate); + + if(!Arts::AudioSubSystem::the()->open()) + { + Arts::AudioSubSystem::the()->audioIO(backupAudioIO); + Arts::AudioSubSystem::the()->samplingRate(backupSamplingRate); + + return false; + } + + return true; +} + +void KAudioConverter::slotMimeType(const QString &mimeType) +{ + m_mimeType = mimeType; + kapp->exit_loop(); +} + +void KAudioConverter::requestPlayObject(const KURL &url) +{ + string queryInterface = "Arts::PlayObject"; + + Arts::KIOInputStream inputStream; + + if(!url.isLocalFile()) + { + Arts::KIOInputStream_impl *inputStreamImpl = new Arts::KIOInputStream_impl(); + inputStream = Arts::KIOInputStream::_from_base(inputStreamImpl); + + QObject::connect(inputStreamImpl, SIGNAL(mimeTypeFound(const QString &)), SLOT(slotMimeType(const QString &))); + + inputStream.openURL(url.url().latin1()); + inputStream.streamStart(); + + // ugly hacks.. :/ + kapp->enter_loop(); + + queryInterface = "Arts::StreamPlayObject"; + } + else + { + KMimeType::Ptr mimetype = KMimeType::findByURL(url); + m_mimeType = mimetype->name(); + } + + Arts::TraderQuery query; + query.supports("Interface", queryInterface); + query.supports("MimeType", string(m_mimeType.latin1())); + + string objectType; + + vector<Arts::TraderOffer> *offers = query.query(); + if(!offers->empty()) + objectType = offers->front().interfaceName(); // first offer + + delete offers; + + if(objectType.empty()) + { + m_incoming = 0; + return; + } + + if(!url.isLocalFile()) + { + Arts::StreamPlayObject result = Arts::SubClass(objectType); + result.streamMedia(inputStream); + result._node()->start(); + + m_incoming = new KPlayObject(result, true); + } + else + { + Arts::PlayObject result = Arts::SubClass(objectType); + + if(result.loadMedia(string(QFile::encodeName(url.path())))) + { + result._node()->start(); + m_incoming = new KPlayObject(result, false); + } + else + m_incoming = 0; + } +} + +void KAudioConverter::start() +{ + if(m_started || !m_incoming) + return; + + m_started = true; + + emit rawStreamStart(); + + m_incoming->play(); + + Arts::KDataRequest_impl *requestImpl = new Arts::KDataRequest_impl(); + m_request = Arts::KDataRequest::_from_base(requestImpl); + + Arts::connect(m_incoming->object(), "left", m_request, "left"); + Arts::connect(m_incoming->object(), "right", m_request, "right"); + + QObject::connect(requestImpl, SIGNAL(newBlockSize(long)), SIGNAL(newBlockSize(long))); + QObject::connect(requestImpl, SIGNAL(newBlockPointer(long)), SIGNAL(newBlockPointer(long))); + QObject::connect(requestImpl, SIGNAL(newData()), SIGNAL(newData())); + + // Special mpeglib case + // TODO: needed at all?? + usleep(100000); + if(m_incoming->object()._base()->_isCompatibleWith("DecoderBaseObject")) + if(!Arts::DynamicRequest(m_incoming->object()).method("_set_blocking").param(true).invoke()) + cerr << "mpeglib, and blocking attribute can't be changed?" << endl; + + m_request.start(); + + // TODO: Maybe do this async, using QTimer::singleShot + // But jowenn i think jowenn is right -> this would + // lead to problems in slotNewData() when accessing the data + // (could already be overwritten...) + while(m_incoming->state() != Arts::posIdle) + m_request.goOn(); + + stop(); +} + +void KAudioConverter::stop() +{ + if(!m_started || !m_incoming) + return; + + m_incoming->halt(); + m_request.streamEnd(); + + m_started = false; + + emit rawStreamFinished(); +} diff --git a/arts/kde/kaudioconverter.h b/arts/kde/kaudioconverter.h new file mode 100644 index 000000000..6235739d8 --- /dev/null +++ b/arts/kde/kaudioconverter.h @@ -0,0 +1,65 @@ + /* + + Copyright (C) 2002 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#ifndef KAUDIOCONVERTER_H +#define KAUDIOCONVERTER_H + +#include <qobject.h> +#include "artskde.h" +#include "kplayobject.h" + +class KURL; +class QString; + +class KAudioConverter : public QObject +{ +Q_OBJECT +public: + KAudioConverter(); + ~KAudioConverter(); + + bool setup(int samplingRate); + void requestPlayObject(const KURL &url); + + void start(); + void stop(); + +signals: + void rawStreamStart(); + + void newBlockSize(long blockSize); + void newBlockPointer(long blockPointer); + void newData(); + + void rawStreamFinished(); + +private slots: + void slotMimeType(const QString &mimeType); + +private: + Arts::KDataRequest m_request; + KPlayObject *m_incoming; + QString m_mimeType; + + bool m_started; +}; + +#endif diff --git a/arts/kde/kaudiomanagerplay.cpp b/arts/kde/kaudiomanagerplay.cpp new file mode 100644 index 000000000..12b817a87 --- /dev/null +++ b/arts/kde/kaudiomanagerplay.cpp @@ -0,0 +1,90 @@ +/* This file is part of the KDE project + Copyright (C) 2003 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "kaudiomanagerplay.h" +#include "kartsserver.h" + +#include <soundserver.h> +#include <string> + +KAudioManagerPlay::KAudioManagerPlay( KArtsServer * server, const QString & title ) +{ + d = new PrivateData; + d->amanPlay = Arts::DynamicCast( server->server().createObject( "Arts::Synth_AMAN_PLAY" ) ); + d->started = false; + setTitle( title ); +} + +KAudioManagerPlay::~KAudioManagerPlay() +{ + stop(); + delete d; +} + +Arts::Synth_AMAN_PLAY KAudioManagerPlay::amanPlay() +{ + return d->amanPlay; +} + +bool KAudioManagerPlay::isNull() const +{ + if( !this ) + return true; + return d->amanPlay.isNull(); +} + +void KAudioManagerPlay::setTitle( const QString & title ) +{ + d->amanPlay.title( std::string( title.local8Bit() ) ); +} + +QString KAudioManagerPlay::title() +{ + return QString::fromLocal8Bit( d->amanPlay.title().c_str() ); +} + +void KAudioManagerPlay::setAutoRestoreID( const QString & autoRestoreID ) +{ + d->amanPlay.autoRestoreID( std::string( autoRestoreID.local8Bit() ) ); +} + +QString KAudioManagerPlay::autoRestoreID() +{ + return QString::fromLocal8Bit( d->amanPlay.autoRestoreID().c_str() ); +} + +void KAudioManagerPlay::start() +{ + if( d->started ) + return; + + d->started = true; + d->amanPlay.start(); +} + +void KAudioManagerPlay::stop() +{ + if( !d->started ) + return; + + d->started = false; + d->amanPlay.stop(); +} + +// vim: sw=4 ts=4 diff --git a/arts/kde/kaudiomanagerplay.h b/arts/kde/kaudiomanagerplay.h new file mode 100644 index 000000000..6bf332130 --- /dev/null +++ b/arts/kde/kaudiomanagerplay.h @@ -0,0 +1,84 @@ +/* This file is part of the KDE project + Copyright (C) 2003 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef KAUDIOMANAGERPLAY_H +#define KAUDIOMANAGERPLAY_H + +#include <artsflow.h> +#include <qstring.h> +#include <kdelibs_export.h> + +class KArtsServer; +class QString; + +/** + * KDE Wrapper for Arts::Synth_AMAN_PLAY. Use this class to create an entry in + * the AudioManager - that's the list you see when opening the AudioManager view + * in artscontrol. + * + * @author Matthias Kretz <kretz@kde.org> + * @since 3.2 + */ +class KDE_ARTS_EXPORT KAudioManagerPlay +{ + public: + KAudioManagerPlay( KArtsServer * server, const QString & title = QString::null ); + ~KAudioManagerPlay(); + + /** + * Returns the internal Arts::Synth_AMAN_PLAY + */ + Arts::Synth_AMAN_PLAY amanPlay(); + + /** + * return true if this == 0 or amanPlay().isNull() + * + * in essence, ((KDE::PlayObject*)0)->isNull() will not + * crash + **/ + bool isNull() const; + + /** + * Set the name of the output in the AudioManager + */ + void setTitle( const QString & title ); + + /** + * returns the name of the output as it appears in the AudioManager + */ + QString title(); + + void setAutoRestoreID( const QString & autoRestoreID ); + QString autoRestoreID(); + + void start(); + void stop(); + + private: + struct PrivateData { + Arts::Synth_AMAN_PLAY amanPlay; + bool started; + }; + PrivateData* d; +}; + + +#endif // KAUDIOMANAGERPLAY_H + +// vim: sw=4 ts=4 diff --git a/arts/kde/kaudioplaystream.cpp b/arts/kde/kaudioplaystream.cpp new file mode 100644 index 000000000..200128ffc --- /dev/null +++ b/arts/kde/kaudioplaystream.cpp @@ -0,0 +1,210 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Arnold Krille <arnold@arnoldarts.de> + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "kaudioplaystream.h" +#include "kaudioplaystream_p.h" + +#include <kartsserver.h> +#include <kaudiomanagerplay.h> + +#include <artsflow.h> +#include <soundserver.h> + +#include <kglobal.h> +#include <kdebug.h> + +#include <qstring.h> +//#include <qptrqueue.h> +//#include <qcstring.h> //QByteArray + +#include <string.h> // for strncpy + +//#include <assert.h> + +KAudioPlayStreamPrivate::KAudioPlayStreamPrivate( KArtsServer* server, const QString title, QObject* p, const char* n ) + : QObject( p,n ) + , _server( server ) + , _play( new KAudioManagerPlay( _server, title ) ) + , _effectrack( Arts::StereoEffectStack::null() ) + , _polling( true ), _attached( false ), _effects( true ) +{ +kdDebug( 400 ) << k_funcinfo << endl; + initaRts(); +} + +KAudioPlayStreamPrivate::~KAudioPlayStreamPrivate() +{ + kdDebug( 400 ) << k_funcinfo << endl; + _play->stop(); + if ( _effects ) _effectrack.stop(); + _bs2a.stop(); +} + +void KAudioPlayStreamPrivate::initaRts() { + kdDebug( 400 ) << k_funcinfo << endl; + + _effectrack = Arts::DynamicCast( _server->server().createObject( "Arts::StereoEffectStack" ) ); + if ( _effectrack.isNull() ) + { + kdWarning( 400 ) << "Couldn't create EffectStack!" << endl; + _effects = false; + } + + _bs2a = Arts::DynamicCast( _server->server().createObject( "Arts::ByteStreamToAudio" ) ); + if ( _bs2a.isNull() ) + kdFatal( 400 ) << "Couldn't create ByteStreamToAudio" << endl; + + if ( _effects ) + { + Arts::connect( _effectrack, _play->amanPlay() ); + Arts::connect( _bs2a, _effectrack ); + } else { + Arts::connect( _bs2a, _play->amanPlay() ); + } + + _play->start(); + if ( _effects ) _effectrack.start(); +} + +KAudioPlayStream::KAudioPlayStream( KArtsServer* server, const QString title, QObject* p, const char* n ) + : QObject( p,n ) + , d( new KAudioPlayStreamPrivate( server, title, this ) ) +{ + kdDebug( 400 ) << k_funcinfo << endl; +} +KAudioPlayStream::~KAudioPlayStream() +{ + kdDebug( 400 ) << k_funcinfo << endl; +} + +void KAudioPlayStream::setPolling( bool n ) { d->_polling = n; } +bool KAudioPlayStream::polling() const { return d->_polling; } + +bool KAudioPlayStream::running() const { return d->_attached; } + +Arts::StereoEffectStack KAudioPlayStream::effectStack() const { + return d->_effectrack; +} + +void KAudioPlayStream::start( int samplingRate, int bits, int channels ) +{ + kdDebug( 400 ) << k_funcinfo << "samplingRate: " << samplingRate << " bits: " << bits << " channels: " << channels << endl; + if ( !d->_attached ) + { + d->_bs2a.samplingRate( samplingRate ); + d->_bs2a.channels( channels ); + d->_bs2a.bits( bits ); + + d->_sender = new KByteSoundProducer( this, d->_server->server().minStreamBufferTime(), samplingRate, bits, channels, "PS" ); + d->_artssender = Arts::ByteSoundProducerV2::_from_base( d->_sender ); + Arts::connect( d->_artssender, "outdata", d->_bs2a, "indata" ); + + d->_bs2a.start(); + d->_artssender.start(); + +// // Needed? + Arts::Dispatcher::the()->ioManager()->processOneEvent( false ); + + d->_attached = true; + emit running( d->_attached ); + } +} +void KAudioPlayStream::stop() +{ + kdDebug( 400 ) << k_funcinfo << endl; + if ( d->_attached ) + { + d->_attached = false; + + d->_bs2a.stop(); + d->_artssender.stop(); + + // Shortly stop the play so we dont get clicks and artefacts + d->_play->stop(); + d->_play->start(); + + Arts::disconnect( d->_artssender, d->_bs2a ); + d->_artssender = Arts::ByteSoundProducerV2::null(); + d->_sender = 0; + + emit running( d->_attached ); + } +} + +void KAudioPlayStream::write( QByteArray& ) +{ +} + +void KAudioPlayStream::fillData( Arts::DataPacket<Arts::mcopbyte> *packet ) +{ + //kdDebug( 400 ) << k_funcinfo << "packet->size=" << packet->size << endl; + if ( d->_polling ) + { + QByteArray bytearray( packet->size ); + bytearray.setRawData( ( char* )packet->contents, packet->size ); + bytearray.fill( 0 ); + emit requestData( bytearray ); + bytearray.resetRawData( ( char* )packet->contents, packet->size ); + + //for ( int i=0; i<10; i++ ) + // kdDebug() << packet->contents[ i ] << " : " << bytearray.data()[ i ] << endl; + } else { + /// TODO: Implement a queue and fetching from it... + } +} + +// * * * KByteSoundProducer * * * + +KByteSoundProducer::KByteSoundProducer( KAudioPlayStream* impl, float minBufferTime, int rate, int bits, int channels, const char * title ) + : _samplingRate( rate ) + , _channels( channels ) + , _bits( bits ) + , _packets( 7 ) + , _title( title ) + , _impl( impl ) +{ + // Calculate packet count (packetsize is fixed to packetCapacity = 4096 + float streamBufferTime; + do { + _packets++; + streamBufferTime = ( float )( _packets * packetCapacity * 1000 ) + / ( float )( _samplingRate * _channels * 2 ); + } while ( streamBufferTime < minBufferTime ); + //kdDebug( 400 ) << k_funcinfo << "_packets:" << _packets << " packetCapacity:" << packetCapacity << endl; +} + +KByteSoundProducer::~KByteSoundProducer() +{ +} + +void KByteSoundProducer::streamStart() { outdata.setPull( _packets, packetCapacity ); } +void KByteSoundProducer::streamEnd() { outdata.endPull(); } + +void KByteSoundProducer::request_outdata( Arts::DataPacket<Arts::mcopbyte> *packet ) +{ + if ( _impl->running() ) { + _impl->fillData( packet ); + packet->send(); + } +} + +// vim: sw=4 ts=4 tw=80 + +#include "kaudioplaystream.moc" +#include "kaudioplaystream_p.moc" diff --git a/arts/kde/kaudioplaystream.h b/arts/kde/kaudioplaystream.h new file mode 100644 index 000000000..8f34cc8c9 --- /dev/null +++ b/arts/kde/kaudioplaystream.h @@ -0,0 +1,127 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Arnold Krille <arnold@arnoldarts.de> + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef KAUDIOPLAYSTREAM_H +#define KAUDIOPLAYSTREAM_H + +#include <qobject.h> + +#include <qcstring.h> +#include <stdsynthmodule.h> + +#include <kdelibs_export.h> + +class KArtsServer; +namespace Arts { class StereoEffectStack; } + +class KAudioPlayStreamPrivate; + +/** + * @brief A wrapper around ByteSoundProducer/ByteStreamToAudio/Synth_AMAN_PLAY. + * + * @author Arnold Krille <arnold@arnoldarts.de> + * @since 3.2 +*/ + +class KDE_ARTS_EXPORT KAudioPlayStream : public QObject { + Q_OBJECT +public: + /** + * Creates a KAudioPlayStream on server with a title. You should pass the KArtsServer also + * as parent to be sure this object is deleted before the server is. + * + * @param server The server where it should play to. + * @param title The title that is shown in the AudioManager. + * @param parent You will propably want to pass the server as parent to so this stream gets deleted before the server disappears. + * @param name The name of the stream. + */ + KAudioPlayStream( KArtsServer* server, const QString title, QObject* parent=0, const char* name=0 ); + /** + * Destructs the KAudioPlayStream. + */ + ~KAudioPlayStream(); + + /** + * Controls wether this Stream should poll the data from you via the signal requestData() + * or you use write() to fill the inputbuffer. + * + * Default is true + */ + void setPolling( bool ); + /** + * Returns the polling state. + * @see setPolling + */ + bool polling() const; + + /** + * @return wether this stream is running ("on air") or not. + */ + bool running() const; + + /** + * @return The Arts::StereoEffectStack right before the Synth_AMAN_PLAY. + */ + Arts::StereoEffectStack effectStack() const; +public slots: + /** + * Start the stream. + * @param samplingRate how many samples per second ( typically 11000/22050/44100/48000 ) + * @param bits how many bits per sample ( 8 / 16 ) + * @param channels how many channels ( 1 or 2 ) + */ + void start( int samplingRate, int bits, int channels ); + /** + * Stops the stream. + */ + void stop(); + + /** + * Write data into the inputbuffer. + * If you ignore the signal noData() it will play 0 ( silence ). + */ + void write( QByteArray& data ); +signals: + /** + * This signal is emitted when audio should be played. + * You have to fill the array with data. + */ + void requestData( QByteArray& ); + + /** + * Is emitted when the state changes. + */ + void running( bool ); + + /** + * Is emitted if the inputbuffer runs dry and polling os off. + */ + void noData(); +public: + /** + * @internal + */ + void fillData( Arts::DataPacket<Arts::mcopbyte> *packet ); +private: + KAudioPlayStreamPrivate* d; +}; + +#endif // KAUDIOPLAYSTREAM_H + +// vim: sw=4 ts=4 tw=80 diff --git a/arts/kde/kaudioplaystream_p.h b/arts/kde/kaudioplaystream_p.h new file mode 100644 index 000000000..a7e5cc4e7 --- /dev/null +++ b/arts/kde/kaudioplaystream_p.h @@ -0,0 +1,84 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Arnold Krille <arnold@arnoldarts.de> + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef KAUDIOPLAYSTREAM_P_H +#define KAUDIOPLAYSTREAM_P_H + +#include <soundserver.h> +#include <stdsynthmodule.h> + +#include <qobject.h> + +class KArtsServer; +class KAudioManagerPlay; +namespace Arts { + class Synth_AMAN_PLAY; + class StereoEffectStack; + class ByteStreamToAudio; +} + +class KAudioPlayStream; +class KByteSoundProducer; + +class KAudioPlayStreamPrivate : public QObject { + Q_OBJECT +public: + KAudioPlayStreamPrivate( KArtsServer*, const QString title, QObject*, const char* =0 ); + ~KAudioPlayStreamPrivate(); + + KArtsServer* _server; + KAudioManagerPlay* _play; + Arts::StereoEffectStack _effectrack; + Arts::ByteStreamToAudio _bs2a; + KByteSoundProducer* _sender; + Arts::ByteSoundProducerV2 _artssender; + bool _polling, _attached, _effects; + +public slots: + void initaRts(); +}; + +class KByteSoundProducer : virtual public Arts::ByteSoundProducerV2_skel + , virtual public Arts::StdSynthModule +{ +public: + KByteSoundProducer( KAudioPlayStream*, float minBufferTime, int rate, int bits, int channels, const char * title ); + ~KByteSoundProducer(); + + long samplingRate() { return _samplingRate; } + long channels() { return _channels; } + long bits() { return _bits; } + std::string title() { return _title; } + + void streamStart(); + void streamEnd(); + +protected: + void request_outdata( Arts::DataPacket<Arts::mcopbyte> *packet ); + +private: + long _samplingRate, _channels, _bits, _packets; + std::string _title; + enum { packetCapacity = 4096 }; + KAudioPlayStream* _impl; +}; + +#endif // KAUDIOPLAYSTREAM_P_H + +// vim: sw=4 ts=4 diff --git a/arts/kde/kaudiorecordstream.cpp b/arts/kde/kaudiorecordstream.cpp new file mode 100644 index 000000000..53788e296 --- /dev/null +++ b/arts/kde/kaudiorecordstream.cpp @@ -0,0 +1,269 @@ + /* + + Copyright (C) 2001, 2002 Matthias Kretz + kretz@kde.org + 2003 Arnold Krille + arnold@arnoldarts.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "kaudiorecordstream.h" +#include "kaudiorecordstream_p.h" +#include "kartsserver.h" + +#include <artsflow.h> +#include <soundserver.h> + +#include <kglobal.h> +#include <kdebug.h> + +#include <qstring.h> +#include <qptrqueue.h> +#include <qcstring.h> //QByteArray + +#include <assert.h> + +struct KAudioRecordStream::Data +{ + Arts::Synth_AMAN_RECORD in; + Arts::AudioToByteStream convert; + Arts::StereoEffectStack effectStack; + Arts::ByteSoundReceiver receiver; + KByteSoundReceiver * receiver_base; + KArtsServer * kserver; + bool attached; + bool blocking; + bool polling; + unsigned int pos; + QPtrQueue<QByteArray> inqueue; + QString title; +}; + +KAudioRecordStream::KAudioRecordStream( KArtsServer * kserver, const QString & title, QObject * parent, const char * name ) + : QObject( parent, name ) + , d( new Data ) +{ + d->kserver = kserver; + d->attached = false; + d->blocking = true; + d->polling = false; + d->pos = 0; + d->inqueue.setAutoDelete( true ); + d->title = title; + + connect( d->kserver, SIGNAL( restartedServer() ), SLOT( slotRestartedServer() ) ); + + d->in = Arts::DynamicCast( d->kserver->server().createObject( "Arts::Synth_AMAN_RECORD" ) ); + d->effectStack = Arts::DynamicCast( d->kserver->server().createObject( "Arts::StereoEffectStack" ) ); + d->convert = Arts::DynamicCast( d->kserver->server().createObject( "Arts::AudioToByteStream" ) ); + if( d->in.isNull() ) + kdFatal( 400 ) << "couldn't create a Synth_AMAN_RECORD on the aRts server\n"; + if( d->effectStack.isNull() ) + kdFatal( 400 ) << "couldn't create a StereoEffectStack on the aRts server\n"; + if( d->convert.isNull() ) + kdFatal( 400 ) << "couldn't create a AudioToByteStream on the aRts server\n"; + + d->in.title( ( const char * ) d->title.local8Bit() ); + Arts::connect( d->in, d->effectStack ); + d->in.start(); + d->effectStack.start(); +} + +KAudioRecordStream::~KAudioRecordStream() +{ + d->receiver = Arts::ByteSoundReceiver::null(); + // don't delete receiver_base because aRts takes care of that (in the line + // above) + d->receiver_base = 0; + delete d; +} + +int KAudioRecordStream::read( char * buffer, int size ) +{ + kdDebug( 400 ) << k_funcinfo << endl; + unsigned int remaining = size; + while( remaining ) + { + if( d->blocking ) + while( d->inqueue.isEmpty() ) + Arts::Dispatcher::the()->ioManager()->processOneEvent( true ); + else + { + if( d->inqueue.isEmpty() ) + Arts::Dispatcher::the()->ioManager()->processOneEvent( false ); + if( d->inqueue.isEmpty() ) + return size - remaining; + } + QByteArray * data = d->inqueue.head(); + unsigned int tocopy = kMin( remaining, data->size() - d->pos ); + memcpy( buffer, data->data() + d->pos, tocopy ); + d->pos += tocopy; + buffer += tocopy; + remaining -= tocopy; + if( d->pos == data->size() ) + { + d->inqueue.remove(); + d->pos = 0; + } + } + return size; +} + +void KAudioRecordStream::setBlockingIO( bool blocking ) +{ + d->blocking = blocking; +} + +bool KAudioRecordStream::blockingIO() const +{ + return d->blocking; +} + +void KAudioRecordStream::usePolling( bool polling ) +{ + d->polling = polling; + if( ! polling ) + flush(); +} + +bool KAudioRecordStream::polling() const +{ + return d->polling; +} + +Arts::StereoEffectStack KAudioRecordStream::effectStack() const +{ + return d->effectStack; +} + +bool KAudioRecordStream::running() const +{ + return d->attached; +} + +void KAudioRecordStream::stop() +{ + kdDebug( 400 ) << k_funcinfo << endl; + if( d->attached ) + { + d->receiver.stop(); + d->convert.stop(); + + Arts::disconnect( d->convert, d->receiver ); + d->receiver = Arts::ByteSoundReceiver::null(); + d->receiver_base = 0; + + Arts::disconnect( d->effectStack, d->convert ); + + d->attached = false; + emit running( false ); + } +} + +void KAudioRecordStream::start( int samplingRate, int bits, int channels ) +{ + kdDebug( 400 ) << k_funcinfo << "samplingRate: " << samplingRate << " bits: " << bits << " channels: " << channels << endl; + if( ! d->attached ) + { + assert( d->kserver ); + + if( ( samplingRate < 500 || samplingRate > 2000000 ) + || ( channels != 1 && channels != 2 ) || ( bits != 8 && bits != 16 ) ) + { + kdWarning( 400 ) << "invalid stream parameters: rate=" << samplingRate << ", " << bits << " bit, " << channels << " channels\n"; + } + else + { + d->convert.samplingRate( samplingRate ); + d->convert.channels( channels ); + d->convert.bits( bits ); + Arts::connect( d->effectStack, d->convert ); + + d->receiver_base = new KByteSoundReceiver( samplingRate, bits, channels, d->title.local8Bit() ); + d->receiver = Arts::ByteSoundReceiver::_from_base( d->receiver_base ); + connect( d->receiver_base, SIGNAL( data( const char *, unsigned int ) ), + SLOT( slotData( const char *, unsigned int ) ) ); + Arts::connect( d->convert, "outdata", d->receiver, "indata" ); + + d->convert.start(); + d->receiver.start(); + + //### needed? + Arts::Dispatcher::the()->ioManager()->processOneEvent( false ); + d->attached = true; + emit running( true ); + } + } +} + +void KAudioRecordStream::flush() +{ + kdDebug( 400 ) << k_funcinfo << endl; + d->inqueue.clear(); +} + +void KAudioRecordStream::slotRestartedServer() { } + +void KAudioRecordStream::slotData( const char * contents, unsigned int size ) +{ + //kdDebug( 400 ) << k_funcinfo << endl; + QByteArray * bytearray = new QByteArray( size ); + // copy the contents to the bytearray + // this has to be deleted later + bytearray->duplicate( contents, size ); + if( d->polling ) + { + kdDebug( 400 ) << "enqueue the data\n"; + d->inqueue.enqueue( bytearray ); + } + else + { + //kdDebug( 400 ) << "emit the data\n"; + emit data( *bytearray ); + //kdDebug( 400 ) << "delete the data\n"; + delete bytearray; + } +} + +//////////////////////////////////////// +// ---*--- KByteSoundReceiver ---*--- // +//////////////////////////////////////// + +KByteSoundReceiver::KByteSoundReceiver( int rate, int bits, int channels, const char * title ) + : _samplingRate( rate ) + , _bits( bits ) + , _channels( channels ) + , _title( title ) +{ +} + +KByteSoundReceiver::~KByteSoundReceiver() +{ +} + +void KByteSoundReceiver::process_indata( Arts::DataPacket<Arts::mcopbyte> * inpacket ) +{ + //kdDebug( 400 ) << k_funcinfo << " size of the packet: " << inpacket->size << endl; + emit data( (char *)inpacket->contents, inpacket->size ); + inpacket->processed(); +} + +// vim:sw=4:ts=4 + +#include "kaudiorecordstream.moc" +#include "kaudiorecordstream_p.moc" diff --git a/arts/kde/kaudiorecordstream.h b/arts/kde/kaudiorecordstream.h new file mode 100644 index 000000000..9f8097676 --- /dev/null +++ b/arts/kde/kaudiorecordstream.h @@ -0,0 +1,165 @@ + /* + + Copyright (C) 2001,2002 Matthias Kretz + kretz@kde.org + 2003 Arnold Krille + arnold@arnoldarts.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#ifndef _KAUDIORECORDSTREAM__H +#define _KAUDIORECORDSTREAM__H + +#include <qobject.h> + +#include <kdelibs_export.h> + +class KArtsServer; +namespace Arts { class StereoEffectStack; } + +/** + * @brief A KDE wrapper around Synth_AMAN_RECORD/AudioToByteStream/ByteSoundReceiver + * + * @author Matthias Kretz <kretz@kde.org> + * @since 3.2 +*/ +class KDE_ARTS_EXPORT KAudioRecordStream : public QObject +{ + Q_OBJECT + + public: + /** + * Construct a KAudioRecordStream + * + * @param server The server where it should record from. + * @param title The title that is shown in the AudioManager. + * @param parent You will propably want to pass the server as parent to so this stream gets deleted before the server disappears. + * @param name The name of the stream. + */ + KAudioRecordStream( KArtsServer * server, const QString & title, QObject * parent = 0, const char * name = 0 ); + + ~KAudioRecordStream(); + + /** + * You can read @p size number of bytes. If blockingIO() is set the method + * will return as soon as it has all your data and could possibly block your + * program. The method returns the number of bytes that are actually in the + * buffer. + * + * @see usePolling() + */ + int read( char *, int size ); + + /** + * If you set blockingIO to true the read method will wait + * until it has enough data to return exactly what you asked for. If + * blockingIO is false you can count on having control back to your + * program soon enough + */ + void setBlockingIO( bool ); + + /** + * read blocking I/O setting + * + * @see setBlockingIO() + */ + bool blockingIO() const; + + /** + * If you want to poll for data using read() set this to true. If + * you'd rather not poll use the data() signal for asynchronous + * I/O. If you set polling to true and don't call read() or + * flush() the inputbuffer will grow endlessly. + * + * The default is false (if you want to use read() set this to true). + */ + void usePolling( bool ); + + /** + * read whether polling is enabled + * + * @see usePolling() + */ + bool polling() const; + + /** + * @return The Effect Stack right after the Synth_AMAN_RECORD. + */ + Arts::StereoEffectStack effectStack() const; + + /** + * @return Wether it is running (recording) or not. + * @since 3.2 + */ + bool running() const; + + public slots: + /** + * Detaches the stream from the soundserver but doesn't remove the Synth_AMAN_RECORD + * so that the entry in the Audiomanager remains. + */ + void stop(); + + /** + * Attach to the soundserver and start getting data to read. This method + * must be called as soon as you want to receive data. In any case you have + * to call start() before read() + * + * @param samplingRate The sampling rate the stream should be resampled to. Use + * a number between 500 and 2000000. + * @param bits The number of bits the stream should have. Only 8 and + * 16 Bits are supported. + * @param channels The number of channels (mono/stereo). Only 1 and 2 are + * supported. + */ + void start( int samplingRate, int bits, int channels ); + + /** + * flush input buffer + */ + void flush(); + + signals: + /** + * Data from the aRts server has arrived. You should copy the data + * because the passed QByteArray will be deleted right after + * returning from your slot(s). + * + * @param data the data from the server + */ + void data( QByteArray & data ); + + /** + * Wether this RecordStream is recording or not. + * @since 3.2 + */ + void running( bool ); + + private slots: + void slotRestartedServer(); + void slotData( const char *, unsigned int ); + + private: + KAudioRecordStream( const KAudioRecordStream & ); + KAudioRecordStream & operator=( const KAudioRecordStream & ); + + struct Data; + Data * d; +}; + +#endif //_KAUDIORECORDSTREAM__H diff --git a/arts/kde/kaudiorecordstream_p.h b/arts/kde/kaudiorecordstream_p.h new file mode 100644 index 000000000..f2899519a --- /dev/null +++ b/arts/kde/kaudiorecordstream_p.h @@ -0,0 +1,62 @@ + /* + + Copyright (C) 2002 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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#ifndef _KAUDIORECORDSTREAM_P__H +#define _KAUDIORECORDSTREAM_P__H + +#include <soundserver.h> +#include <stdsynthmodule.h> + +#include <qobject.h> + +class KByteSoundReceiver : public QObject, + public Arts::ByteSoundReceiver_skel, + public Arts::StdSynthModule +{ + Q_OBJECT + + public: + KByteSoundReceiver( int rate, int bits, int channels, const char * title ); + ~KByteSoundReceiver(); + + long samplingRate() { return _samplingRate; } + long channels() { return _channels; } + long bits() { return _bits; } + std::string title() { return _title; } + + signals: + /** + * new data arrived, the data pointer will be deleted + * after this signal was emitted. So if you want to keep it + * you have to copy it. + */ + void data( const char * data, unsigned int size ); + + protected: + void process_indata(Arts::DataPacket<Arts::mcopbyte> *); + + private: + int _samplingRate, _bits, _channels; + std::string _title; +}; + +#endif // _KAUDIORECORDSTREAM_P__H diff --git a/arts/kde/kconverttest.cc b/arts/kde/kconverttest.cc new file mode 100644 index 000000000..25cb02e4c --- /dev/null +++ b/arts/kde/kconverttest.cc @@ -0,0 +1,96 @@ +#include <stdio.h> + +#include <qfile.h> +#include <qobject.h> + +#include <klocale.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <kapplication.h> + +#include <flowsystem.h> +#include <kplayobject.h> +#include <kartsdispatcher.h> +#include <kplayobjectfactory.h> +#include <kaudioconverter.h> +#include "kconverttest.moc" + +using namespace std; +using namespace Arts; + +static KCmdLineOptions options[] = +{ + { "+[URL]", I18N_NOOP("URL to open"), 0 }, + KCmdLineLastOption +}; + +KConvertTest::KConvertTest() +{ +} + +void KConvertTest::slotRawStreamStart() +{ +// cout << "[START]\n\n" << endl; +} + +void KConvertTest::slotNewBlockSize(long blockSize) +{ + m_blockSize = blockSize; +} + +void KConvertTest::slotNewBlockPointer(long blockPointer) +{ + m_blockPointer = blockPointer; +} + +void KConvertTest::slotNewData() +{ + fwrite((void *) m_blockPointer, 1, m_blockSize, stdout); +} + +void KConvertTest::slotRawStreamFinished() +{ +// cout << "\n\n[END]" << endl; +} + +int main(int argc, char **argv) +{ + KAboutData aboutData("kconverttest", I18N_NOOP("KConvertTest"), I18N_NOOP("0.1"), "", KAboutData::License_GPL, ""); + + KCmdLineArgs::init(argc, argv, &aboutData); + KCmdLineArgs::addCmdLineOptions(options); + KApplication app; + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + KURL url; + + if(args->count()) + url = args->arg(0); + else + exit(1); + + args->clear(); + + KConvertTest *get = new KConvertTest(); + + KArtsDispatcher dispatcher; + KAudioConverter converter; + + // FIXME: crashes + // converter.setup(44100); + converter.requestPlayObject(url); + + QObject::connect(&converter, SIGNAL(rawStreamStart()), get, SLOT(slotRawStreamStart())); + + QObject::connect(&converter, SIGNAL(newBlockSize(long)), get, SLOT(slotNewBlockSize(long))); + QObject::connect(&converter, SIGNAL(newBlockPointer(long)), get, SLOT(slotNewBlockPointer(long))); + QObject::connect(&converter, SIGNAL(newData()), get, SLOT(slotNewData())); + + QObject::connect(&converter, SIGNAL(rawStreamFinished()), get, SLOT(slotRawStreamFinished())); + + converter.start(); + + app.exec(); +} + diff --git a/arts/kde/kconverttest.h b/arts/kde/kconverttest.h new file mode 100644 index 000000000..60847b0aa --- /dev/null +++ b/arts/kde/kconverttest.h @@ -0,0 +1,46 @@ + /* + + Copyright (C) 2002 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#ifndef KCONVERTTEST_H +#define KCONVERTTEST_H + +#include <qobject.h> + +class KConvertTest : public QObject +{ +Q_OBJECT +public: + KConvertTest(); + +public slots: + void slotRawStreamStart(); + + void slotNewBlockSize(long blockSize); + void slotNewBlockPointer(long blockPointer); + void slotNewData(); + + void slotRawStreamFinished(); + +private: + long m_blockSize, m_blockPointer; +}; + +#endif diff --git a/arts/kde/kdatarequest_impl.cpp b/arts/kde/kdatarequest_impl.cpp new file mode 100644 index 000000000..ce8f30f9b --- /dev/null +++ b/arts/kde/kdatarequest_impl.cpp @@ -0,0 +1,80 @@ + /* + + Copyright (C) 2002 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include <kdebug.h> +#include "flowsystem.h" +#include "convert.h" +#include "kdatarequest_impl.moc" + +using namespace Arts; + +KDataRequest_impl::KDataRequest_impl() +{ + m_lastBlockSize = 0; + m_outBlock = 0; +} + +KDataRequest_impl::~KDataRequest_impl() +{ + delete []m_outBlock; +} + +void KDataRequest_impl::streamInit() +{ +} + +void KDataRequest_impl::streamEnd() +{ +} + +void KDataRequest_impl::calculateBlock(unsigned long samples) +{ + long blockSize = samples * 4; + + if(m_lastBlockSize != blockSize) + { + delete []m_outBlock; + emit newBlockSize(blockSize); + + m_outBlock = new unsigned char[blockSize]; // 2 channels, 16 bit + + emit newBlockPointer((long) m_outBlock); + + m_lastBlockSize = blockSize; + } + + convert_stereo_2float_i16le(samples, left, right, m_outBlock); + emit newData(); +} + +/* + * this is the most tricky part here - since we will run in a context + * where no audio hardware will play the "give me more data role", + * we'll have to request things ourselves (requireFlow() tells the + * flowsystem that more signal flow should happen, so that + * calculateBlock will get called + */ +void KDataRequest_impl::goOn() +{ + _node()->requireFlow(); +} + +REGISTER_IMPLEMENTATION(KDataRequest_impl); diff --git a/arts/kde/kdatarequest_impl.h b/arts/kde/kdatarequest_impl.h new file mode 100644 index 000000000..07522f0f1 --- /dev/null +++ b/arts/kde/kdatarequest_impl.h @@ -0,0 +1,59 @@ + /* + + Copyright (C) 2002 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#ifndef KDATAREQUEST_IMPL +#define KDATAREQUEST_IMPL + +#include <qobject.h> +#include "artskde.h" +#include "stdsynthmodule.h" + +namespace Arts +{ + +class KDataRequest_impl : public QObject, virtual public KDataRequest_skel, + virtual public StdSynthModule +{ +Q_OBJECT +public: + KDataRequest_impl(); + ~KDataRequest_impl(); + + void streamInit(); + void streamEnd(); + + void calculateBlock(unsigned long samples); + + void goOn(); + +signals: + void newData(); + void newBlockSize(long blockSize); + void newBlockPointer(long blockPointer); + +private: + long m_lastBlockSize; + unsigned char *m_outBlock; +}; + +} + +#endif diff --git a/arts/kde/kioinputstream_impl.cpp b/arts/kde/kioinputstream_impl.cpp new file mode 100644 index 000000000..b82764931 --- /dev/null +++ b/arts/kde/kioinputstream_impl.cpp @@ -0,0 +1,236 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +/* + * How does it work? + * ----------------- + * + * First the buffer has to be filled. When it reaches a defined size the outdata + * stream has to start pulling packets. If the buffer reaches a size of zero the + * stream has to stop. If the buffer gets to big the job has to be suspended + * until the buffer is small enough again. + */ + +#include <kapplication.h> +#include <kdebug.h> +#include <kio/job.h> +#include <kio/kmimetype.h> +#include <kio/jobclasses.h> +#include <qtimer.h> +#include <qdatastream.h> +#include "artsversion.h" +#include "kioinputstream_impl.moc" + +using namespace Arts; + +const unsigned int KIOInputStream_impl::PACKET_COUNT = 10; + +KIOInputStream_impl::KIOInputStream_impl() : m_packetSize(2048) +{ + m_job = 0; + m_finished = false; + m_firstBuffer = false; + m_packetBuffer = 16; + m_streamStarted = false; + m_streamSuspended = false; + m_streamPulled = false; + m_size = 0; +} + +KIOInputStream_impl::~KIOInputStream_impl() +{ + if(m_job != 0) + m_job->kill(); +} + +void KIOInputStream_impl::streamStart() +{ + // prevent kill/reconnect + if (m_streamStarted) { + kdDebug( 400 ) << "not restarting stream!\n"; + if (m_job->isSuspended()) + m_job->resume(); + return; + } + + kdDebug( 400 ) << "(re)starting stream\n"; + + if(m_job != 0) + m_job->kill(); + m_job = KIO::get(m_url, false, false); + + m_job->addMetaData("accept", "audio/x-mp3, video/mpeg, application/ogg"); + m_job->addMetaData("UserAgent", QString::fromLatin1("aRts/") + QString::fromLatin1(ARTS_VERSION)); + + QObject::connect(m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), + this, SLOT(slotData(KIO::Job *, const QByteArray &))); + QObject::connect(m_job, SIGNAL(result(KIO::Job *)), + this, SLOT(slotResult(KIO::Job *))); + QObject::connect(m_job, SIGNAL(mimetype(KIO::Job *, const QString &)), + this, SLOT(slotScanMimeType(KIO::Job *, const QString &))); + QObject::connect(m_job, SIGNAL(totalSize( KIO::Job *, KIO::filesize_t)), + this, SLOT(slotTotalSize(KIO::Job *, KIO::filesize_t))); + + m_streamStarted = true; +} + +void KIOInputStream_impl::streamEnd() +{ + kdDebug( 400 ) << "streamEnd()\n"; + + if(m_job != 0) + { + QObject::disconnect(m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), + this, SLOT(slotData(KIO::Job *, const QByteArray &))); + QObject::disconnect(m_job, SIGNAL(result(KIO::Job *)), + this, SLOT(slotResult(KIO::Job *))); + QObject::disconnect(m_job, SIGNAL(mimetype(KIO::Job *, const QString &)), + this, SLOT(slotScanMimeType(KIO::Job *, const QString &))); + QObject::disconnect(m_job, SIGNAL(totalSize( KIO::Job *, KIO::filesize_t)), + this, SLOT(slotTotalSize(KIO::Job *, KIO::filesize_t))); + + if ( m_streamPulled ) + outdata.endPull(); + + m_job->kill(); + m_job = 0; + } + + m_streamStarted = false; +} + +bool KIOInputStream_impl::openURL(const std::string& url) +{ + m_url = KURL(url.c_str()); + m_size = 0; + return true; +} + +void KIOInputStream_impl::slotData(KIO::Job *, const QByteArray &data) +{ + if(m_finished) + m_finished = false; + + QDataStream dataStream(m_data, IO_WriteOnly | IO_Append); + dataStream.writeRawBytes(data.data(), data.size()); + //kdDebug( 400 ) << "STREAMING: buffersize = " << m_data.size() << " bytes" << endl; + + processQueue(); +} + +void KIOInputStream_impl::slotResult(KIO::Job *job) +{ + // jobs delete themselves after emitting their result + m_finished = true; + m_streamStarted = false; + m_job = 0; + + if(job->error()) { + // break out of the event loop in case of + // connection error + emit mimeTypeFound("application/x-zerosize"); + job->showErrorDialog(); + } +} + +void KIOInputStream_impl::slotScanMimeType(KIO::Job *, const QString &mimetype) +{ + kdDebug( 400 ) << "got mimetype: " << mimetype << endl; + emit mimeTypeFound(mimetype); +} + +void KIOInputStream_impl::slotTotalSize(KIO::Job *, KIO::filesize_t size) +{ + m_size = size; +} + +bool KIOInputStream_impl::eof() +{ + return (m_finished && m_data.size() == 0); +} + +bool KIOInputStream_impl::seekOk() +{ + return false; +} + +long KIOInputStream_impl::size() +{ + return m_size ? m_size : m_data.size(); +} + +long KIOInputStream_impl::seek(long) +{ + return -1; +} + +void KIOInputStream_impl::processQueue() +{ + if(m_job != 0) + { + if(m_data.size() > (m_packetBuffer * m_packetSize * 2) && !m_job->isSuspended()) + { + kdDebug( 400 ) << "STREAMING: suspend job" << endl; + m_job->suspend(); + } + else if(m_data.size() < (m_packetBuffer * m_packetSize) && m_job->isSuspended()) + { + kdDebug( 400 ) << "STREAMING: resume job" << endl; + m_job->resume(); + } + } + + if (!m_firstBuffer) { + if(m_data.size() < (m_packetBuffer * m_packetSize * 2) ) { + kdDebug( 400 ) << "STREAMING: Buffering in progress... (Needed bytes before it starts to play: " << ((m_packetBuffer * m_packetSize * 2) - m_data.size()) << ")" << endl; + return; + } else { + m_firstBuffer = true; + m_streamPulled = true; + outdata.setPull(PACKET_COUNT, m_packetSize); + } + } +} + +void KIOInputStream_impl::request_outdata(DataPacket<mcopbyte> *packet) +{ + processQueue(); + packet->size = std::min(m_packetSize, m_data.size()); + kdDebug( 400 ) << "STREAMING: Filling one DataPacket with " << packet->size << " bytes of the stream!" << endl; + + if (!m_finished) { + if( (unsigned)packet->size < m_packetSize || ! m_firstBuffer) { + m_firstBuffer = false; + packet->size = 0; + outdata.endPull(); + } + } + + if (packet->size > 0) + { + memcpy(packet->contents, m_data.data(), packet->size); + memmove(m_data.data(), m_data.data() + packet->size, m_data.size() - packet->size); + m_data.resize(m_data.size() - packet->size); + } + packet->send(); +} + +REGISTER_IMPLEMENTATION(KIOInputStream_impl); diff --git a/arts/kde/kioinputstream_impl.h b/arts/kde/kioinputstream_impl.h new file mode 100644 index 000000000..95daac169 --- /dev/null +++ b/arts/kde/kioinputstream_impl.h @@ -0,0 +1,89 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#ifndef KIOINPUTSTREAM_IMPL +#define KIOINPUTSTREAM_IMPL + +#include <qobject.h> +#include <qcstring.h> +#include <kio/jobclasses.h> +#include <kurl.h> +#include "artskde.h" +#include "stdsynthmodule.h" + +namespace Arts { + +class KIOInputStream_impl : public QObject, virtual public KIOInputStream_skel, + virtual public InputStream_skel, + virtual public StdSynthModule +{ +Q_OBJECT +public: + KIOInputStream_impl(); + ~KIOInputStream_impl(); + + void streamStart(); + void streamEnd(); + + bool eof(); + bool seekOk(); + long size(); + long seek(long); + + bool openURL(const std::string& url); + + void processQueue(); + void request_outdata(DataPacket<mcopbyte> *packet); + + long bufferPackets() { return m_packetBuffer; } + void bufferPackets(long i) { m_packetBuffer = i; } + + long packetSize() { return m_packetSize; } + +signals: + void mimeTypeFound(const QString & mimetype); + +private slots: + void slotData(KIO::Job *, const QByteArray &); + void slotResult(KIO::Job *); + void slotScanMimeType(KIO::Job *, const QString &mimetype); + void slotTotalSize(KIO::Job *, KIO::filesize_t size); + +private: + KURL m_url; + KIO::TransferJob *m_job; + QByteArray m_data; + bool m_finished; + bool m_firstBuffer; + bool m_streamStarted; + bool m_streamSuspended; + bool m_streamPulled; + + unsigned int m_packetBuffer; + const unsigned int m_packetSize; + KIO::filesize_t m_size; + + static const unsigned int PACKET_COUNT; +}; + +} + +#endif diff --git a/arts/kde/kiotest.cc b/arts/kde/kiotest.cc new file mode 100644 index 000000000..b5403ce0d --- /dev/null +++ b/arts/kde/kiotest.cc @@ -0,0 +1,54 @@ +#include <stdio.h> +#include <kmedia2.h> +#include <kcmdlineargs.h> +#include <connect.h> +#include <klocale.h> +#include <kapplication.h> +#include <kaboutdata.h> +#include "qiomanager.h" +#include "artskde.h" + +using namespace std; +using namespace Arts; + + +static KCmdLineOptions options[] = +{ + { "+[URL]", I18N_NOOP("URL to open"), 0 }, + KCmdLineLastOption +}; + +int main(int argc, char **argv) +{ + KAboutData aboutData( "kiotest", I18N_NOOP("KIOTest"), I18N_NOOP("0.1"), "", KAboutData::License_GPL, ""); + + KCmdLineArgs::init(argc,argv,&aboutData); + KCmdLineArgs::addCmdLineOptions(options); + KApplication app; + QIOManager qiomanager; + Dispatcher dispatcher(&qiomanager); + KIOInputStream stream; + StdoutWriter writer; + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + if(args->count()) + { + if(!stream.openURL(args->arg(0))) + { + printf("can't open url"); + exit(1); + } + } + else + exit(1); + + args->clear(); + + connect(stream, writer); + + writer.start(); + stream.start(); + + app.exec(); +} diff --git a/arts/kde/kiotestslow.cc b/arts/kde/kiotestslow.cc new file mode 100644 index 000000000..fd5f1e129 --- /dev/null +++ b/arts/kde/kiotestslow.cc @@ -0,0 +1,131 @@ +#include <stdio.h> +#include <kmedia2.h> +#include <kcmdlineargs.h> +#include <connect.h> +#include <klocale.h> +#include <kapplication.h> +#include <kaboutdata.h> +#include <stdsynthmodule.h> +#include "qiomanager.h" +#include "artskde.h" + +using namespace std; +using namespace Arts; + +namespace Arts { +/* simulate slow receiver */ +class KIOTestSlow_impl : public KIOTestSlow_skel, + public TimeNotify, + public StdSynthModule +{ + int pos; + list< DataPacket<mcopbyte>* > q; + InputStream _inputStream; + +public: + InputStream inputStream() { return _inputStream; } + void inputStream(InputStream i) { _inputStream = i; } + + KIOTestSlow_impl() + { + Dispatcher::the()->ioManager()->addTimer(10, this); + pos = 0; + } + void notifyTime() + { + if(!_inputStream.isNull() && _inputStream.eof()) + { + printf("\n[*EOF*] remaining = %d packets\n"); + _inputStream = InputStream::null(); + return; + } + + int TODO = 100; + do { + if(q.empty()) + return; + + DataPacket<mcopbyte> *p = q.front(); + char ch = p->contents[pos++]; + if(p->size == pos) + { + p->processed(); + q.pop_front(); + pos = 0; + } + + if(ch == '\n') + { + long size = 0; + list<DataPacket<mcopbyte>*>::iterator i; + for(i = q.begin(); i != q.end(); i++) + size += (*i)->size; + printf("\n[queued %8ld] ",size-pos); + } + else + putchar(ch); + + } while(TODO-- > 0); + } + void process_data(DataPacket<mcopbyte> *p) + { + if(p->size == 0) + p->processed(); + else + q.push_back(p); + } +}; +REGISTER_IMPLEMENTATION(KIOTestSlow_impl); +}; + +static KCmdLineOptions options[] = +{ + { "+[URL]", I18N_NOOP("URL to open"), 0 }, + KCmdLineLastOption +}; + +#undef USE_FILEINPUTSTREAM + +int main(int argc, char **argv) +{ + KAboutData aboutData( "kiotestslow", I18N_NOOP("KIOTest"), I18N_NOOP("0.1"), "", KAboutData::License_GPL, ""); + + KCmdLineArgs::init(argc,argv,&aboutData); + KCmdLineArgs::addCmdLineOptions(options); + KApplication app; + QIOManager qiomanager; + Dispatcher dispatcher(&qiomanager); +#ifndef USE_FILEINPUTSTREAM + KIOInputStream stream; +#else + FileInputStream stream; +#endif + KIOTestSlow writer; + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + if(args->count()) + { +#ifdef USE_FILEINPUTSTREAM + if(!stream.open(args->arg(0))) +#else + if(!stream.openURL(args->arg(0))) +#endif + { + printf("can't open url"); + exit(1); + } + } + else + exit(1); + + args->clear(); + + writer.inputStream(stream); + connect(stream, writer); + + writer.start(); + stream.start(); + + app.exec(); +} diff --git a/arts/kde/kplayobject.cc b/arts/kde/kplayobject.cc new file mode 100644 index 000000000..af37735cb --- /dev/null +++ b/arts/kde/kplayobject.cc @@ -0,0 +1,303 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "kplayobject.h" +#include "kplayobject.moc" +#include "kplayobjectcreator.h" +#include <kdebug.h> + +KPlayObject::KPlayObject() : QObject() +{ + m_playObject = Arts::PlayObject::null(); + m_isStream = false; +} + +KPlayObject::KPlayObject(Arts::PlayObject playobject, bool isStream) : QObject() +{ + m_playObject = playobject; + m_isStream = isStream; +} + +KPlayObject::~KPlayObject() +{ +} + +void KPlayObject::play() +{ + object().play(); +} + +void KPlayObject::seek(Arts::poTime newTime) +{ + if(!m_isStream) + object().seek(newTime); + else + kdDebug( 400 ) << "Seeking in a Stream? huh?" << endl; +} + +void KPlayObject::pause() +{ + object().pause(); +} + +void KPlayObject::halt() +{ + object().halt(); +} + +QString KPlayObject::description() +{ + return QString::fromLatin1(object().description().c_str()); +} + +Arts::poTime KPlayObject::currentTime() +{ + return object().currentTime(); +} + +Arts::poTime KPlayObject::overallTime() +{ + return object().overallTime(); +} + +Arts::poCapabilities KPlayObject::capabilities() +{ + return object().capabilities(); +} + +QString KPlayObject::mediaName() +{ + return QString::fromLatin1(object().mediaName().c_str()); +} + +Arts::poState KPlayObject::state() +{ + return object().state(); +} + +Arts::PlayObject KPlayObject::object() +{ + return m_playObject; +} + +bool KPlayObject::isNull() +{ + if( !this ) + return true; + return object().isNull(); +} + +void KPlayObject::setObject(Arts::PlayObject playObject) +{ + m_playObject = playObject; +} + +bool KPlayObject::stream() +{ + return m_isStream; +} + +struct KDE::PlayObject::PrivateData +{ + PrivateData() : creator( 0 ), + isProxy( false ), + internalState( Arts::posIdle ) {} + ~PrivateData() { + delete creator; + } + Arts::SoundServerV2 server; + KDE::PlayObjectCreator* creator; + bool createBUS; + bool isProxy; + Arts::poState internalState; + KURL url; +}; + +KDE::PlayObject::PlayObject() : QObject() +{ + m_playObject = Arts::PlayObject::null(); + m_isStream = false; + d = new PrivateData; +} + +KDE::PlayObject::PlayObject(Arts::PlayObject playobject, bool isStream) : QObject() +{ + m_playObject = playobject; + m_isStream = isStream; + d = new PrivateData; + + //very funny! you can't connect to signals before creating + //the object - so nobody will ever receive this signal (mkretz) + // + //emit playObjectCreated(); +} + +KDE::PlayObject::PlayObject( Arts::SoundServerV2 server, const KURL& url, bool isStream, bool createBUS ) : QObject() +{ + kdDebug( 400 ) << "KDE::PlayObject: created as proxy for URL " << url.url()<< endl; + + m_playObject = Arts::PlayObject::null(); + m_isStream = isStream; + d = new PrivateData; + d->server = server; + d->url = url; + d->createBUS = createBUS; + d->isProxy = true; +} + +KDE::PlayObject::~PlayObject() +{ + kdDebug( 400 ) << "KDE::PlayObject: destroyed" << endl; + + delete d; +} + +void KDE::PlayObject::play() +{ + kdDebug( 400 ) << "KDE::PlayObject::play()" << endl; + + if ( object().isNull() ) { + if ( m_isStream ) { + if ( d->creator ) + delete d->creator; + d->creator = new KDE::PlayObjectCreator( d->server ); + d->creator->create( d->url, d->createBUS, this, SLOT( attachPlayObject( Arts::PlayObject ) ) ); + kdDebug( 400 ) << "KDE::PlayObject::play(): creator called" << endl; + d->internalState = Arts::posPlaying; + } + return; + } + object().play(); +} + +void KDE::PlayObject::attachPlayObject( Arts::PlayObject playObject ) +{ + kdDebug( 400 ) << "KDE::PlayObject::attachPlayObject()" << endl; + + m_playObject = playObject; + emit playObjectCreated(); + if ( object().isNull() ) + return; + switch ( d->internalState ) { + case Arts::posIdle: + object().halt(); + break; + case Arts::posPaused: + object().pause(); + break; + case Arts::posPlaying: + object().play (); + break; + } +} + +void KDE::PlayObject::seek(Arts::poTime newTime) +{ + if ( object().isNull() ) + return; + if(!m_isStream) + object().seek(newTime); + else + kdDebug( 400 ) << "Seeking in a Stream? huh?" << endl; +} + +void KDE::PlayObject::pause() +{ + if ( !object().isNull() ) + object().pause(); + d->internalState = Arts::posPaused; +} + +void KDE::PlayObject::halt() +{ + kdDebug( 400 ) << "KDE::PlayObject::halt()" << endl; + if ( !object().isNull() ) + object().halt(); + else if ( d->creator ) { + delete d->creator; + d->creator = 0; + kdDebug( 400 ) << "KDE::PlayObject::halt(): creator destroyed" << endl; + } + d->internalState = Arts::posIdle; +} + +QString KDE::PlayObject::description() +{ + if ( object().isNull() ) + return QString(); + return QString::fromLatin1(object().description().c_str()); +} + +Arts::poTime KDE::PlayObject::currentTime() +{ + if ( object().isNull() ) + return Arts::poTime( 0, 0, -1, "" ); + return object().currentTime(); +} + +Arts::poTime KDE::PlayObject::overallTime() +{ + if ( object().isNull() ) + return Arts::poTime( 0, 0, -1, "" ); + return object().overallTime(); +} + +Arts::poCapabilities KDE::PlayObject::capabilities() +{ + if ( object().isNull() ) + return static_cast<Arts::poCapabilities>( 0 ); + return object().capabilities(); +} + +QString KDE::PlayObject::mediaName() +{ + if ( object().isNull() ) + return QString(); + return QString::fromLatin1(object().mediaName().c_str()); +} + +Arts::poState KDE::PlayObject::state() +{ + if ( object().isNull() ) + return d->internalState; + return object().state(); +} + +Arts::PlayObject KDE::PlayObject::object() +{ + return m_playObject; +} + +bool KDE::PlayObject::isNull() +{ + if ( !this ) + return true; + if ( d->isProxy ) + return false; + return object().isNull(); +} + +bool KDE::PlayObject::stream() +{ + return m_isStream; +} + +// vim: sw=4 ts=4 noet diff --git a/arts/kde/kplayobject.h b/arts/kde/kplayobject.h new file mode 100644 index 000000000..959e46810 --- /dev/null +++ b/arts/kde/kplayobject.h @@ -0,0 +1,306 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#ifndef KPLAYOBJECT_H +#define KPLAYOBJECT_H + +#include "kmedia2.h" +#include "soundserver.h" +#include <kurl.h> +#include <qobject.h> + +class KDE_EXPORT KPlayObject : public QObject +{ +Q_OBJECT +public: + KPlayObject(); + KPlayObject(Arts::PlayObject playobject, bool isStream); + ~KPlayObject(); + + /** + * Sets the internal Arts::PlayObject + * to @a playObject + */ + void setObject(Arts::PlayObject playObject); + + /** + * Returns the internal Arts::PlayObject + */ + Arts::PlayObject object(); + + /** + * return true if both this != 0, and object.isNull() + * + * in essence, ((KPlayObject*)0)->isNull() will not + * crash + **/ + bool isNull(); + + /** + * returns true if the internally playobject + * is used to play a stream + */ + bool stream(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + void play(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + void seek(Arts::poTime newTime); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + void pause(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + + void halt(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + QString description(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + Arts::poTime currentTime(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + Arts::poTime overallTime(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + Arts::poCapabilities capabilities(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + QString mediaName(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + Arts::poState state(); + +private: + Arts::PlayObject m_playObject; + bool m_isStream; +}; + + + +namespace KDE { + +class PlayObjectFactory; + +/** + * This class acts as a general interface to the KDE multimedia framework. + * You basically point the Playobject to an URL and say "play", and it will + * automatically decode and play and / or display the file or stream. + * For non-local media, it will make extensive use of KIOInputStream to + * directly play the content from the remote location without having to + * download it to a temporary local file first. + * + * A KDE::PlayObject is never created directly with new, but only through + * a KDE::PlayObjectFactory. + * + * Basically, it is used like this: + * \code + * KArtsDispatcher dispatcher; + * KArtsServer server; + * KDE::PlayObjectFactory factory( server.server() ); + * KDE::PlayObject* playobj = factory.createPlayObject( someURL, true ); + * playobj->play(); + * \endcode + * + * Internally, the KDE::PlayObject acts as a wrapper for an Arts::PlayObject. + * + * Special care needs to be taken for non-local media. In general, you + * cannot safely figure out the mimetype of the remote media content, by + * looking at the URL alone. You need to download some data to analyze + * the content. Since KDE::PlayObject is only a wrapper for an + * Arts::PlayObject, and an Arts::PlayObject needs to know the mimetype + * of the data it plays in order to pick the correct decoder, one cannot + * directly create an Arts::PlayObject and attach it to a stream. Therefore, + * the following approach is used. + * + * Whenever a the factory creates a KDE::PlayObject for a non-local content, + * it first generates a so called "Proxy" Playobject. This is a + * KDE::PlayObject that does not contain a real Arts::PlayObject yet. + * As soon as you invoke the play() method, a connection to the media + * source is made, and as soon as the mimetype is known, the appropriate + * Arts::PlayObject is created. + * + * This has some side effects that developers need to be aware of: + * Until the real Arts::PlayObject got created, + * - the capabilities() method returns "zero" capabilities, + * - description() and mediaName() will return a null QString, + * - currentTime() and overallTime() will return "zero", + * - despite the fact that isNull() returns "false", object().isNull() + * will return "true". If you need to directly access methods of the + * internal Arts::PlayObject, be sure to use object().isNull() to guard + * your access. + * + * A KDE::PlayObject will emit the signal playObjectCreated() + * as soon as the real internal Arts::PlayObject got created. This is also + * true for local media files. So you can generally connect to this signal + * and act on it if your application needs to know about the real capabilities + * of the Arts::PlayObject. + * + * However, KDE::PlayObject will try to act reasonable on calls to play(), + * halt(), pause() and state(). If you call play() and then pause() + * before the connection to the media source was established, it will + * not start playing once the connection got established. Calling halt() + * will cancel the connection process. KDE::PlayObject will maintain + * an internal state variable, and calling state() will return this + * internal state until the real Arts::PlayObject got created, afterwards + * the state of the Arts::PlayObject will be returned. + */ +class KDE_EXPORT PlayObject : public QObject +{ +Q_OBJECT +public: + ~PlayObject(); + + /** + * Returns the internal Arts::PlayObject + */ + Arts::PlayObject object(); + + /** + * return true if this != 0. + * + * in essence, ((KDE::PlayObject*)0)->isNull() will not + * crash + **/ + bool isNull(); + + /** + * returns "true" if the content to play is delivered as a stream. + */ + bool stream(); + + /** + * causes the PlayObject to start the play back. + */ + void play(); + + /** + * causes the PlayObject to skip to the time @p newTime. + * You don't need to stop or restart the play back after calling seek. + */ + void seek(Arts::poTime newTime); + + /** + * causes the PlayObject to pause play back immediately. It will not + * restart until you call play(). This also works on streams, the + * connection to the media source will be maintained while the + * PlayObject is paused. + */ + void pause(); + + /** + * immediately stops the play back and resets the media to the + * start of the content. If playing from a stream, halt() causes + * the connection to be canceled. + */ + + void halt(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + QString description(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + Arts::poTime currentTime(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + Arts::poTime overallTime(); + + /** + * returns the capabilities of the PlayObject. The return value is + * a binary OR of Arts::capSeek and Arts::capPause, or 0. + */ + Arts::poCapabilities capabilities(); + + /** + * Reimplemented (Arts::PlayObject Wrapper) + */ + QString mediaName(); + + /** + * returns the internal state of the PlayObject. The state can be + * either Arts::posIdle, Arts::posPaused or Arts::posPlaying. A + * PlayObject in state Arts::posIdle is stopped. Once you call + * play(), the state changes to Arts::posPlaying. pause() causes + * the PlayObject to change to Arts::posPaused. + */ + Arts::poState state(); + +signals: + /** + * this signal is emitted as soon as the internal Arts::PlayObject + * is created and ready to play. It is granted that the Arts::PlayObject + * has not started playing, but KDE::PlayObject will call + * object().play() immediately after emitting this signal, so you + * need not do it yourself. + */ + void playObjectCreated(); + +private slots: + void attachPlayObject( Arts::PlayObject ); + +private: + Arts::PlayObject m_playObject; + bool m_isStream; + + struct PrivateData; + PrivateData* d; + + /* private constructors, to prevent instantiation and copying */ + PlayObject(); + PlayObject( const PlayObject& ) : QObject() {}; + PlayObject(Arts::PlayObject playobject, bool isStream); + PlayObject( Arts::SoundServerV2 server, const KURL& url, bool isStream, bool createBUS ); + + friend class KDE::PlayObjectFactory; + +}; + +} + +#endif diff --git a/arts/kde/kplayobjectcreator.cc b/arts/kde/kplayobjectcreator.cc new file mode 100644 index 000000000..26b4308ab --- /dev/null +++ b/arts/kde/kplayobjectcreator.cc @@ -0,0 +1,104 @@ + /* + + Copyright (C) 2002 Matthias Welwarsky <mwelwarsky@web.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include <kio/kmimetype.h> +#include "artskde.h" +#include "kplayobjectcreator.h" +#include "kplayobjectcreator.moc" +#include "kioinputstream_impl.h" + +#include <qfile.h> + +#include <kdebug.h> + +KDE::PlayObjectCreator::PlayObjectCreator(Arts::SoundServerV2 server) +{ + m_server = server; +} + +KDE::PlayObjectCreator::~PlayObjectCreator() +{ +} + +bool KDE::PlayObjectCreator::create(const KURL& url, bool createBUS, const QObject* receiver, const char* slot) +{ + // no need to go any further, and I hate deep indentation + if (m_server.isNull() || url.isEmpty() ) + return false; + + connect( this, SIGNAL( playObjectCreated( Arts::PlayObject ) ), + receiver, slot ); + + // check if the URL is a local file + if (!url.isLocalFile()) + { + m_createBUS = createBUS; + + // This is the RightWay(tm) according to stw + Arts::KIOInputStream_impl* instream_impl = new Arts::KIOInputStream_impl(); + m_instream = Arts::KIOInputStream::_from_base(instream_impl); + + // signal will be called once the ioslave knows the mime-type of the stream + connect(instream_impl, SIGNAL(mimeTypeFound(const QString &)), + this, SLOT(slotMimeType(const QString &))); + + // GO! + m_instream.openURL(url.url().latin1()); + m_instream.streamStart(); + + return true; + } + kdDebug( 400 ) << "stream is local file: " << url.url() << endl; + + // usual stuff if we have a local file + KMimeType::Ptr mimetype = KMimeType::findByURL(url); + emit playObjectCreated ( + m_server.createPlayObjectForURL(std::string(QFile::encodeName(url.path())), + std::string(mimetype->name().latin1()), + createBUS) + ); + return true; +} + +void KDE::PlayObjectCreator::slotMimeType(const QString& mimetype) +{ + + kdDebug( 400 ) << "slotMimeType called: " << mimetype << endl; + + QString mimetype_copy = mimetype; + + if ( mimetype_copy == "application/octet-stream" ) + mimetype_copy = QString("audio/x-mp3"); + + if (mimetype_copy == "application/x-zerosize") + emit playObjectCreated(Arts::PlayObject::null()); + + playObject = m_server.createPlayObjectForStream( + m_instream, + std::string( mimetype_copy.latin1() ), + m_createBUS ); + if ( playObject.isNull() ) { + m_instream.streamEnd(); + emit playObjectCreated( Arts::PlayObject::null() ); + return; + } + emit playObjectCreated( playObject ); +} diff --git a/arts/kde/kplayobjectcreator.h b/arts/kde/kplayobjectcreator.h new file mode 100644 index 000000000..31b0a0b48 --- /dev/null +++ b/arts/kde/kplayobjectcreator.h @@ -0,0 +1,56 @@ + /* + + Copyright (C) 2002 Matthias Welwarsky <mwelwarsky@web.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#ifndef KPLAYOBJECTCREATOR_H +#define KPLAYOBJECTCREATOR_H + +#include <kurl.h> +#include <qobject.h> +#include "soundserver.h" +#include "kioinputstream_impl.h" + +namespace KDE { + +class PlayObjectCreator : public QObject +{ +Q_OBJECT +public: + PlayObjectCreator(Arts::SoundServerV2 server); + ~PlayObjectCreator(); + + bool create(const KURL& url, bool createBUS, const QObject* receiver, const char* slot); + +signals: + void playObjectCreated(Arts::PlayObject playObject); + +private slots: + void slotMimeType(const QString &mimetype); + +private: + Arts::SoundServerV2 m_server; + Arts::KIOInputStream m_instream; + Arts::PlayObject playObject; + bool m_createBUS; +}; + +} +#endif + diff --git a/arts/kde/kplayobjectfactory.cc b/arts/kde/kplayobjectfactory.cc new file mode 100644 index 000000000..ea0218746 --- /dev/null +++ b/arts/kde/kplayobjectfactory.cc @@ -0,0 +1,258 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include <kio/kmimetype.h> +#include "kplayobject.h" +#include "artskde.h" +#include "kplayobjectfactory.h" +#include "kplayobjectfactory_p.h" +#include "kplayobjectcreator.h" +#include "kioinputstream_impl.h" +#include "kartsdispatcher.h" +#include "kartsserver.h" + +#include <qfile.h> +#include <kdebug.h> +#include "kaudiomanagerplay.h" +#include <flowsystem.h> +#include <kio/netaccess.h> + +using namespace std; + +KPlayObjectFactory::KPlayObjectFactory(Arts::SoundServerV2 server) +{ + m_server = server; + m_allowStreaming = true; + m_stream = false; +} + +KPlayObjectFactory::KPlayObjectFactory(KArtsServer* server) +{ + m_server = server->server(); + m_allowStreaming = true; + m_stream = false; +} + +KPlayObjectFactory::~KPlayObjectFactory() +{ +} + +KPlayObject *KPlayObjectFactory::createPlayObject(const KURL& url, bool createBUS) +{ + KMimeType::Ptr mimetype = KMimeType::findByURL(url); + return createPlayObject(url, mimetype->name(), createBUS); +} + + +KPlayObject *KPlayObjectFactory::createPlayObject(const KURL& _url, const QString &mimetype, bool createBUS) +{ + // WHY DOES BROKEN KIO_MEDIA GIVE WRONG URLS? + // I hate it + // I hate it + // It sucks + // kio_media please die + KURL url = KIO::NetAccess::mostLocalURL(_url, 0); + + if(!m_server.isNull()) + { + 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 + return new KPlayObject(m_server.createPlayObjectForURL(string(QFile::encodeName(url.path())), string(mimetype.latin1()), createBUS), false); + } + else + return new KPlayObject(); +} + + + +// + +KDE::PlayObjectFactory::PlayObjectFactory(Arts::SoundServerV2 server) +{ + d = new PrivateData; + d->server = server; + d->amanPlay = 0; + d->helper = 0; + d->allowStreaming = true; + d->isStream = false; +} + +KDE::PlayObjectFactory::PlayObjectFactory(KArtsServer* server) +{ + d = new PrivateData; + d->server = server->server(); + d->amanPlay = 0; + d->helper = 0; + d->allowStreaming = true; + d->isStream = false; +} + +KDE::PlayObjectFactory::~PlayObjectFactory() +{ + delete d->helper; + delete d; +} + +void KDE::PlayObjectFactory::setAudioManagerPlay( KAudioManagerPlay * amanPlay ) +{ + d->amanPlay = amanPlay; + if( ! d->helper ) + d->helper = new POFHelper; +} + +KDE::PlayObject *KDE::PlayObjectFactory::createPlayObject(const KURL& url, bool createBUS) +{ + KMimeType::Ptr mimetype = KMimeType::findByURL(url); + return createPlayObject(url, mimetype->name(), createBUS); +} + +KDE::PlayObject *KDE::PlayObjectFactory::createPlayObject(const KURL& _url, const QString &mimetype, bool createBUS) +{ + // WHY DOES BROKEN KIO_MEDIA GIVE WRONG URLS? + // I hate it + // I hate it + // It sucks + // kio_media please die + KURL url = KIO::NetAccess::mostLocalURL(_url, 0); + + // return a NULL playobject if the server is NULL + if ( d->server.isNull() || url.isEmpty() ) + return new KDE::PlayObject(); + + // if the program wants to use it's own Synth_AMAN_PLAY we don't need a + // bus + if( d->amanPlay && createBUS ) + { + kdWarning( 400 ) << "KDE::PlayObjectFactory was instructed to use a Synth_AMAN_PLAY for output but the program also asked for a Synth_BUS_UPLINK" << endl; + createBUS = false; + } + + // decide if it's a local file. mpeglib provides cdda reading and decoding, so we prefer that over kio_audiocd + if ( url.isLocalFile() || !d->allowStreaming || (url.protocol() == "audiocd" && mimetype == "application/x-cda" && mimeTypes().contains( "application/x-cda" ) ) ) + { + // we rely on the delivered mimetype if it's a local file + d->playObj = new KDE::PlayObject( d->server.createPlayObjectForURL( string( QFile::encodeName( url.path() ) ), string( mimetype.latin1() ), createBUS ), false ); + } + else + { + // if non-local, let the KPlayObject figure out the mimetype itself + // this invokes asynchronous creation automatically + d->playObj = new KDE::PlayObject( d->server, url, true, createBUS ); + } + + if( d->playObj->isNull() ) + { + delete d->playObj; + d->playObj = 0; + return new KDE::PlayObject(); // return a NULL playobject + } + + if( d->amanPlay ) + { + d->helper->po = d->playObj; + d->helper->ap = d->amanPlay; + if( d->playObj->object().isNull() && d->amanPlay ) + QObject::connect( d->playObj, SIGNAL( playObjectCreated() ), d->helper, SLOT( connectAmanPlay() ) ); + else + d->helper->connectAmanPlay(); + } + + return d->playObj; +} + +QStringList KDE::PlayObjectFactory::mimeTypes(void) +{ + KArtsDispatcher dispatcher; // we need such a thing, otherwise we crash + 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; +} + +/* ### KDE4 +void KDE::PlayObjectFactory::connectAmanPlay() +{ + kdDebug( 400 ) << k_funcinfo << endl; + if( d->playObj->object().isNull() ) + return; + + d->amanPlay->start(); + d->playObj->object()._node()->start(); + Arts::connect( d->playObj->object(), "left" , d->amanPlay->amanPlay(), "left" ); + Arts::connect( d->playObj->object(), "right", d->amanPlay->amanPlay(), "right" ); +} +*/ + +void KDE::POFHelper::connectAmanPlay() +{ + kdDebug( 400 ) << k_funcinfo << endl; + if( po->object().isNull() ) + return; + + ap->start(); + po->object()._node()->start(); + Arts::connect( po->object(), "left" , ap->amanPlay(), "left" ); + Arts::connect( po->object(), "right", ap->amanPlay(), "right" ); +} + +#include "kplayobjectfactory_p.moc" + +// vim: sw=4 ts=4 noet diff --git a/arts/kde/kplayobjectfactory.h b/arts/kde/kplayobjectfactory.h new file mode 100644 index 000000000..2f9c096fc --- /dev/null +++ b/arts/kde/kplayobjectfactory.h @@ -0,0 +1,156 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann <wildfox@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 as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#ifndef KPLAYOBJECTFACTORY_H +#define KPLAYOBJECTFACTORY_H + +#include <kurl.h> +#include <kdelibs_export.h> + +#include "soundserver.h" +#include "kplayobject.h" + +class KArtsServer; + +class KDE_EXPORT KPlayObjectFactory +{ +public: + /** + * Constructs a new Factory for creating aRts playobjects on the + * soundserver. + */ + KPlayObjectFactory(Arts::SoundServerV2 server); + + /** + * Convenience constructor to pass a KArtsServer instead of an + * Arts::SoundServerV2. This equivalent to calling + * KPlayObjectFactory( server.server() ). + * + * @since 3.2 + */ + KPlayObjectFactory(KArtsServer* server); + + ~KPlayObjectFactory(); + + KPlayObject *createPlayObject(const KURL& url, bool createBUS); + KPlayObject *createPlayObject(const KURL& url, const QString &mimetype, bool createBUS); + + void setAllowStreaming(bool s) { m_allowStreaming = s; } + bool allowStreaming() { return m_allowStreaming; } + + bool isAStream() { return m_stream; } + +private: + Arts::SoundServerV2 m_server; + bool m_allowStreaming; + bool m_stream; +}; + +class KAudioManagerPlay; + +namespace KDE { + +class POFHelper; + + /** + * This class implements a factory to create KDE::PlayObjects for + * a given URL and mimetype. A detailed description about how to + * use the KDE multimedia framework can be found in the documentation + * for KDE::PlayObject. + */ +class KDE_EXPORT PlayObjectFactory// : public QObject ### for KDE4 make it a QObject to be able to receive signals +{ +public: + /** + * Creates a KDE::PlayObjectFactory. @p server is an + * Arts::SoundServerV2 + */ + PlayObjectFactory(Arts::SoundServerV2 server); + /** + * Convenience constructor to pass a KArtsServer instead of an + * Arts::SoundServerV2. This equivalent to calling + * KDE::PlayObjectFactory( server.server() ). + * + * @since 3.2 + */ + PlayObjectFactory( KArtsServer* server ); + ~PlayObjectFactory(); + + /** + * If this is set the PlayObject doesn't create a Synth_BUS_UPLINK at all + * but always uses the Synth_AMAN_PLAY that you passed. + */ + void setAudioManagerPlay( KAudioManagerPlay * amanplay ); + + /** + * Creates a KDE::PlayObject to play back the file or stream + * @p url points to. Set @p createBUS to "true", if you want the + * PlayObject to be connected to a SYNTH_BUS_UPLINK on creation. + * This is usually the case. You only need to set this to "false" + * if you want to attach your own sound effects to the PlayObject. + * + * You don't need to know the mimetype of the file or stream, it + * will be detected automatically. + */ + KDE::PlayObject *createPlayObject(const KURL& url, bool createBUS); + + /** + * This method also creates a KDE::PlayObject, but does no automatic + * mimetype detection. Use this method with care. + */ + KDE::PlayObject *createPlayObject(const KURL& url, const QString &mimetype, bool createBUS); + + /** + * setAllowStreaming( true ) allows the factory to create a + * streaming PlayObject for a non-local URL. This is also the default. + * Usually, you should not need to set this to false. + */ + void setAllowStreaming(bool s) { d->allowStreaming = s; } + + /** + * returns "true" if the factory is allowed to create streaming + * PlayObjects. + */ + bool allowStreaming() { return d->allowStreaming; } + + /** + * Return the mimetypes that are playable + */ + static QStringList mimeTypes(void); + +/*private slots: ### KDE4 and remove Helper class + void connectAmanPlay();*/ + +private: + struct PrivateData { + Arts::SoundServerV2 server; + KDE::PlayObject* playObj; + KAudioManagerPlay* amanPlay; + POFHelper* helper; + bool allowStreaming; + bool isStream; + }; + PrivateData* d; +}; + +} +#endif +// vim: sw=4 ts=4 noet diff --git a/arts/kde/kplayobjectfactory_p.h b/arts/kde/kplayobjectfactory_p.h new file mode 100644 index 000000000..21ea4c4e9 --- /dev/null +++ b/arts/kde/kplayobjectfactory_p.h @@ -0,0 +1,46 @@ +/* This file is part of the KDE project + Copyright (C) 2003 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef KPLAYOBJECTFACTORY_P_H +#define KPLAYOBJECTFACTORY_P_H + +#include <qobject.h> +#include "kplayobjectfactory.h" + +namespace KDE +{ + +/** + * @internal + */ +class POFHelper : public QObject +{ + friend class PlayObjectFactory; + Q_OBJECT +private slots: + void connectAmanPlay(); +private: + KDE::PlayObject *po; + KAudioManagerPlay *ap; +}; + +} + +#endif // KPLAYOBJECTFACTORY_P_H +// vim: sw=4 ts=4 noet diff --git a/arts/kde/kvideowidget.cpp b/arts/kde/kvideowidget.cpp new file mode 100644 index 000000000..2b0fbd66b --- /dev/null +++ b/arts/kde/kvideowidget.cpp @@ -0,0 +1,446 @@ +/* + This file is part of KDE/aRts (Noatun) - xine integration + Copyright (C) 2002 Ewald Snel <ewald@rambo.its.tudelft.nl> + Copyright (C) 2002 Neil Stevens <neil@qualityassistant.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2 as published by the Free Software Foundation. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <time.h> +#ifdef HAVE_USLEEP +#include <unistd.h> +#endif +#include <qaccel.h> +#include <qcursor.h> + +#if defined Q_WS_X11 && ! defined K_WS_QTONLY +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#else +#define XEvent void +#endif + +#include <kaction.h> +#include <klocale.h> +#include "kvideowidget.h" + + +class KFullscreenVideoWidget : public KVideoWidget +{ +public: + KFullscreenVideoWidget( KVideoWidget *parent = 0, const char *name = 0 ); + +protected: + virtual void windowActivationChange( bool ); + virtual bool x11Event( XEvent *event ); + +private: + KVideoWidget *videoWidget; +}; + +KFullscreenVideoWidget::KFullscreenVideoWidget( KVideoWidget *parent, const char *name ) + : KVideoWidget( 0, name ) +{ + this->videoWidget = parent; + setEraseColor( black ); + setCursor(QCursor(Qt::BlankCursor)); +} + +void KFullscreenVideoWidget::windowActivationChange( bool ) +{ + if (!isActiveWindow()) + { + videoWidget->setWindowed(); + } +} + +bool KFullscreenVideoWidget::x11Event( XEvent *event ) +{ +#if defined Q_WS_X11 && ! defined K_WS_QTONLY + if (event->type == ClientMessage && + event->xclient.message_type == + XInternAtom( qt_xdisplay(), "VPO_RESIZE_NOTIFY", False )) + { + videoWidget->resizeNotify( event->xclient.data.l[0], event->xclient.data.l[1] ); + } +#endif + return false; +} + +KVideoWidget::KVideoWidget( KXMLGUIClient *clientParent, QWidget *parent, const char *name, WFlags f ) + : KXMLGUIClient( clientParent ), + QWidget( parent, name, f ) +{ + init(); + // ??? + QString toolbarName = i18n("Video Toolbar"); + setXML(QString("<!DOCTYPE kpartgui>\n<kpartgui name=\"kvideowidget\" version=\"1\"><MenuBar><Menu name=\"edit\"><Separator/><Action name=\"double_size\"/><Action name=\"normal_size\"/><Action name=\"half_size\"/><Separator/><Action name=\"fullscreen_mode\"/></Menu></MenuBar><Toolbar name=\"VideoToolbar\"><text>Video Toolbar</text><Action name=\"fullscreen_mode\"/></Toolbar></kpartgui>"), true); +} + +KVideoWidget::KVideoWidget( QWidget *parent, const char *name, WFlags f ) + : QWidget( parent, name, f ) +{ + init(); +} + +void KVideoWidget::init(void) +{ + setMinimumSize(0, 0); + setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + setFocusPolicy( ClickFocus ); + + fullscreenWidget = 0; + poVideo = Arts::VideoPlayObject::null(); + videoWidth = 0; + videoHeight = 0; + + // Setup actions + new KToggleAction( i18n("Fullscreen &Mode"), "window_fullscreen", + CTRL+SHIFT+Key_F, this, SLOT(fullscreenActivated()), + actionCollection(), "fullscreen_mode" ); + new KRadioAction( i18n("&Half Size"), ALT+Key_0, + this, SLOT(halfSizeActivated()), + actionCollection(), "half_size" ); + new KRadioAction( i18n("&Normal Size"), ALT+Key_1, + this, SLOT(normalSizeActivated()), + actionCollection(), "normal_size" ); + new KRadioAction( i18n("&Double Size"), ALT+Key_2, + this, SLOT(doubleSizeActivated()), + actionCollection(), "double_size" ); + + ((KToggleAction *)action( "half_size" ))->setExclusiveGroup( "KVideoWidget::zoom" ); + ((KToggleAction *)action( "normal_size" ))->setExclusiveGroup( "KVideoWidget::zoom" ); + ((KToggleAction *)action( "double_size" ))->setExclusiveGroup( "KVideoWidget::zoom" ); + + action("double_size")->setEnabled(false); + action("half_size")->setEnabled(false); + action("normal_size")->setEnabled(false); + action("fullscreen_mode")->setEnabled(false); +} + +KVideoWidget::~KVideoWidget() +{ + if (isEmbedded()) + { + poVideo.x11WindowId( -1 ); + poVideo = Arts::VideoPlayObject::null(); + } + + delete fullscreenWidget; +} + +void KVideoWidget::embed( Arts::VideoPlayObject vpo ) +{ + bool enable; + if (vpo.isNull()) + { + if (isEmbedded()) + { + poVideo.x11WindowId( -1 ); + poVideo = Arts::VideoPlayObject::null(); + } + + setBackgroundMode( PaletteBackground ); + repaint(); + + // Resize GUI + videoWidth = 0; + videoHeight = 0; + + if (isHalfSize() || isNormalSize() || isDoubleSize()) + emit adaptSize( 0, 0 ); + + enable = false; + updateGeometry(); + } + else + { + if (isEmbedded()) + { + poVideo.x11WindowId( -1 ); + } + + poVideo = vpo; + + // Don't reset fullscreen mode for video playlists + if (fullscreenWidget) + { + poVideo.x11WindowId( fullscreenWidget->winId() ); + fullscreenWidget->setBackgroundMode( NoBackground ); + + setEraseColor( black ); + } + else + { + poVideo.x11WindowId( winId() ); + setBackgroundMode( NoBackground ); + } + enable = true; + } + action("double_size")->setEnabled(enable); + action("half_size")->setEnabled(enable); + action("normal_size")->setEnabled(enable); + action("fullscreen_mode")->setEnabled(enable); +} + +QImage KVideoWidget::snapshot( Arts::VideoPlayObject vpo ) +{ +#if defined Q_WS_X11 && ! defined K_WS_QTONLY + Window root; + Pixmap pixmap; + XImage *xImage; + unsigned int width, height, border, depth; + int x, y; + + if (vpo.isNull() || (long)(pixmap = vpo.x11Snapshot()) == -1) + return QImage(); + + // Get 32bit RGBA image data (stored in 1bpp pixmap) + XGetGeometry( qt_xdisplay(), pixmap, &root, &x, &y, &width, &height, &border, &depth ); + + xImage = XGetImage( qt_xdisplay(), pixmap, 0, 0, width, height, 1, XYPixmap ); + + if (xImage == 0) + { + XFreePixmap( qt_xdisplay(), pixmap ); + return QImage(); + } + + // Convert 32bit RGBA image data into Qt image + QImage qImage = QImage( (uchar *)xImage->data, width/32, height, 32, (QRgb *)0, 0, QImage::IgnoreEndian ).copy(); + + // Free X11 resources and return Qt image + XDestroyImage( xImage ); + XFreePixmap( qt_xdisplay(), pixmap ); + + return qImage; +#else + return 0; +#endif +} + +bool KVideoWidget::isEmbedded() +{ + return !poVideo.isNull(); +} + +bool KVideoWidget::isFullscreen() +{ + return ((KToggleAction *)action( "fullscreen_mode" ))->isChecked(); +} + +bool KVideoWidget::isHalfSize() +{ + return ((KToggleAction *)action( "half_size" ))->isChecked(); +} + +bool KVideoWidget::isNormalSize() +{ + return ((KToggleAction *)action( "normal_size" ))->isChecked(); +} + +bool KVideoWidget::isDoubleSize() +{ + return ((KToggleAction *)action( "double_size" ))->isChecked(); +} + +void KVideoWidget::setFullscreen() +{ + if (!isFullscreen()) + { + ((KToggleAction *)action( "fullscreen_mode" ))->setChecked( true ); + fullscreenActivated(); + } +} + +void KVideoWidget::setWindowed() +{ + if (isFullscreen()) + { + ((KToggleAction *)action( "fullscreen_mode" ))->setChecked( false ); + fullscreenActivated(); + } +} + +void KVideoWidget::setHalfSize() +{ + ((KToggleAction *)action( "half_size" ))->setChecked( true ); + halfSizeActivated(); +} + +void KVideoWidget::setNormalSize() +{ + ((KToggleAction *)action( "normal_size" ))->setChecked( true ); + normalSizeActivated(); +} + +void KVideoWidget::setDoubleSize() +{ + ((KToggleAction *)action( "double_size" ))->setChecked( true ); + doubleSizeActivated(); +} + +QSize KVideoWidget::sizeHint() const +{ + return QSize( videoWidth, videoHeight ); +} + +int KVideoWidget::heightForWidth( int w ) const +{ + if(videoWidth == 0) + return 0; + else + return int( double(w)*double(videoHeight)/double(videoWidth) ); +} + +void KVideoWidget::mousePressEvent( QMouseEvent *event ) +{ + QPoint pos = mapToGlobal( event->pos() ); + + emit mouseButtonPressed( event->button(), pos, event->state() ); + + // ### Remove in KDE4 + if ( event->button() == RightButton ) + emit rightButtonPressed( pos ); +} + +void KVideoWidget::mouseDoubleClickEvent( QMouseEvent *event ) +{ + emit mouseButtonDoubleClick( mapToGlobal( event->pos() ), event->state() ); +} + +void KVideoWidget::resizeEvent( QResizeEvent *event ) +{ + QWidget::resizeEvent( event ); + + if (width() > minimumWidth() || height() > minimumHeight()) + { + if (width() == QMAX( (videoWidth / 2), minimumWidth() ) && + height() == QMAX( (videoHeight / 2), minimumHeight() )) + ((KToggleAction *)action( "half_size" ))->setChecked( true ); + else if (width() == QMAX( videoWidth, minimumWidth() ) && + height() == QMAX( videoHeight, minimumHeight() )) + ((KToggleAction *)action( "normal_size" ))->setChecked( true ); + else if (width() == QMAX( (2 * videoWidth), minimumWidth() ) && + height() == QMAX( (2 * videoHeight), minimumHeight() )) + ((KToggleAction *)action( "double_size" ))->setChecked( true ); + else + { + ((KToggleAction *)action( "half_size" ))->setChecked( false ); + ((KToggleAction *)action( "normal_size" ))->setChecked( false ); + ((KToggleAction *)action( "double_size" ))->setChecked( false ); + } + } +} + +void KVideoWidget::resizeNotify( int width, int height ) +{ + if(!isEmbedded()) return; + + videoWidth = width; + videoHeight = height; + + if (isHalfSize()) + emit adaptSize( (videoWidth / 2), (videoHeight / 2) ); + else if (isNormalSize()) + emit adaptSize( videoWidth, videoHeight ); + else if (isDoubleSize()) + emit adaptSize( (2 * videoWidth), (2 * videoHeight) ); + + updateGeometry(); +} + +bool KVideoWidget::x11Event( XEvent *event ) +{ +#if defined Q_WS_X11 && ! defined K_WS_QTONLY + if (event->type == ClientMessage && + event->xclient.message_type == + XInternAtom( qt_xdisplay(), "VPO_RESIZE_NOTIFY", False )) + { + resizeNotify( event->xclient.data.l[0], event->xclient.data.l[1] ); + } +#endif + return false; +} + +void KVideoWidget::fullscreenActivated() +{ + if (isFullscreen() == (fullscreenWidget != 0)) + return; + + if (isFullscreen()) + { + fullscreenWidget = new KFullscreenVideoWidget( this ); + + // Interconnect mouse button signals + connect( fullscreenWidget, SIGNAL(mouseButtonPressed( int, const QPoint &, int )), + this, SIGNAL(mouseButtonPressed( int, const QPoint &, int)) ); + + connect( fullscreenWidget, SIGNAL(mouseButtonDoubleClick( const QPoint &, int )), + this, SIGNAL(mouseButtonDoubleClick( const QPoint &, int )) ); + + // ### Remove in KDE4 + connect( fullscreenWidget, SIGNAL(rightButtonPressed(const QPoint &)), + this, SIGNAL(rightButtonPressed(const QPoint &)) ); + + // Leave fullscreen mode with <Escape> key + QAccel *a = new QAccel( fullscreenWidget ); + a->connectItem( a->insertItem( Key_Escape ), + this, SLOT(setWindowed()) ); + + fullscreenWidget->setFocus(); + fullscreenWidget->showFullScreen(); + + if (isEmbedded()) + { + poVideo.x11WindowId( fullscreenWidget->winId() ); + fullscreenWidget->setBackgroundMode( NoBackground ); + } + } + else + { + if (isEmbedded()) + { + poVideo.x11WindowId( winId() ); + setBackgroundMode( NoBackground ); + } + + delete fullscreenWidget; + fullscreenWidget = 0; + } +} + +void KVideoWidget::halfSizeActivated() +{ + if (isHalfSize()) + { + if(isEmbedded()) emit adaptSize( (videoWidth / 2), (videoHeight / 2) ); + setWindowed(); + } +} + +void KVideoWidget::normalSizeActivated() +{ + if (isNormalSize()) + { + if(isEmbedded()) emit adaptSize( videoWidth, videoHeight ); + setWindowed(); + } +} + +void KVideoWidget::doubleSizeActivated() +{ + if (isDoubleSize()) + { + if(isEmbedded()) emit adaptSize( (2 * videoWidth), (2 * videoHeight) ); + setWindowed(); + } +} + +#include "kvideowidget.moc" diff --git a/arts/kde/kvideowidget.h b/arts/kde/kvideowidget.h new file mode 100644 index 000000000..f314267ca --- /dev/null +++ b/arts/kde/kvideowidget.h @@ -0,0 +1,82 @@ +/* + This file is part of KDE/aRts (Noatun) - xine integration + Copyright (C) 2002 Ewald Snel <ewald@rambo.its.tudelft.nl> + Copyright (C) 2002 Neil Stevens <neil@qualityassistant.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2 as published by the Free Software Foundation. +*/ + +#ifndef ARTSKDE_KVIDEOWIDGET_H +#define ARTSKDE_KVIDEOWIDGET_H + +#include <qevent.h> +#include <qimage.h> +#include <qwidget.h> +#include <kmedia2.h> +#include <kxmlguiclient.h> + + +class KDE_ARTS_EXPORT KVideoWidget : public QWidget, virtual public KXMLGUIClient +{ +Q_OBJECT + +public: + KVideoWidget( KXMLGUIClient *clientParent, QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); + KVideoWidget( QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); + virtual ~KVideoWidget(); + + void embed( Arts::VideoPlayObject vpo ); + static QImage snapshot( Arts::VideoPlayObject vpo ); + + bool isEmbedded(); + bool isFullscreen(); + bool isHalfSize(); + bool isNormalSize(); + bool isDoubleSize(); + + QSize sizeHint() const; + + virtual int heightForWidth ( int w ) const; + +protected: + virtual void mousePressEvent( QMouseEvent *event ); + virtual void mouseDoubleClickEvent( QMouseEvent *event); + virtual void resizeEvent( QResizeEvent *event ); + virtual bool x11Event( XEvent *event ); + +public slots: + void setFullscreen(); + void setWindowed(); + void setHalfSize(); + void setNormalSize(); + void setDoubleSize(); + + void resizeNotify( int width, int height ); + +protected slots: + void fullscreenActivated(); + void halfSizeActivated(); + void normalSizeActivated(); + void doubleSizeActivated(); + +signals: + void adaptSize( int width, int height ); + void mouseButtonPressed( int type, const QPoint &, int state ); + void mouseButtonDoubleClick( const QPoint &, int state ); + /** + * @deprecated + * use mouseButtonPressed( int type, const QPoint & ) instead. + */ + void rightButtonPressed( const QPoint & ); + +private: + void init(void); + QWidget *fullscreenWidget; + int videoWidth; + int videoHeight; + Arts::VideoPlayObject poVideo; +}; + +#endif diff --git a/arts/kde/mcop-dcop/Makefile.am b/arts/kde/mcop-dcop/Makefile.am new file mode 100644 index 000000000..6e2b90eac --- /dev/null +++ b/arts/kde/mcop-dcop/Makefile.am @@ -0,0 +1,20 @@ + +INCLUDES= -I$(includedir)/arts -I$(top_srcdir)/arts/kde $(all_includes) + +bin_PROGRAMS= +lib_LTLIBRARIES = +kdeinit_LTLIBRARIES = kmcop.la + +kmcop_la_SOURCES = mcopdcopobject.cpp kmcop.cpp kmcop.skel +kmcop_la_LIBADD = ../libartskde.la +kmcop_la_LDFLAGS = $(all_libraries) -module -avoid-version +kmcop_la_METASOURCES = AUTO + +noinst_HEADERS = kmcop.h + +kdelnkdir = $(kde_servicesdir) +kdelnk_DATA = kmcop.desktop + +messages: + $(XGETTEXT) kmcop.cpp -o $(podir)/kmcop.pot + diff --git a/arts/kde/mcop-dcop/kmcop.cpp b/arts/kde/mcop-dcop/kmcop.cpp new file mode 100644 index 000000000..22e19dc9d --- /dev/null +++ b/arts/kde/mcop-dcop/kmcop.cpp @@ -0,0 +1,171 @@ +/* + Copyright (c) 2001 Nikolas Zimmermann <wildfox@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <kdebug.h> +#include <kuniqueapplication.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <klocale.h> +#include <dcopclient.h> + +#include <qvaluelist.h> +#include <qcstring.h> + +#include <kartsdispatcher.h> +#include <soundserver.h> +#include <dispatcher.h> +#include <object.h> +#include <core.h> + +#include "mcopdcopobject.h" + +#include "kmcop.moc" + +using namespace Arts; +using namespace std; + +class KMCOPPrivate +{ +public: + MCOPInfo mcopInfo; + QPtrList<MCOPDCOPObject> list; +}; + +int main(int argc, char **argv) +{ + KAboutData aboutdata("kmcop", I18N_NOOP("KMCOP"), + "0.1", I18N_NOOP("KDE MCOP-DCOP Bridge"), + KAboutData::License_GPL, "(C) 2001, Nikolas Zimmermann"); + aboutdata.addAuthor("Nikolas Zimmermann", I18N_NOOP("Author"), "wildfox@kde.org"); + + KCmdLineArgs::init(argc, argv, &aboutdata); + KUniqueApplication::addCmdLineOptions(); + + if(!KUniqueApplication::start()) + { + kdDebug() << "Running kmcop found" << endl; + return 0; + } + + KUniqueApplication app; + app.disableSessionManagement(); + + KArtsDispatcher dispatcher; + + KMCOP notify; + app.dcopClient()->setDefaultObject("arts"); + app.dcopClient()->setDaemonMode(true); + + return app.exec(); +} + +KMCOP::KMCOP() : QObject(), DCOPObject("arts") +{ + d = new KMCOPPrivate(); + d->mcopInfo = Reference("global:Arts_MCOPInfo"); + d->list.setAutoDelete(true); +} + +KMCOP::~KMCOP() +{ + delete d; +} + +int KMCOP::objectCount() +{ + return d->mcopInfo.objectCount(); +} + +QCString KMCOP::correctType(const QCString &str) +{ + if(str == "string") + return "QCString"; + return str; +} + +void KMCOP::addInterfacesHackHackHack() +{ + for(int i = 0; i <= objectCount(); i++) + { + Arts::Object obj = d->mcopInfo.objectForNumber(i); + + if(!obj.isNull()) + { + QCString interfaceName = obj._interfaceName().c_str(); + + if(interfaceName != "Arts::TraderOffer") + { + Arts::InterfaceRepo ifaceRepo = Dispatcher::the()->interfaceRepo(); + + MCOPDCOPObject *interface = new MCOPDCOPObject(interfaceName); + d->list.append(interface); + + InterfaceDef ifaceDef = ifaceRepo.queryInterface(string(interfaceName)); + vector<MethodDef> ifaceMethods = ifaceDef.methods; + + vector<MethodDef>::iterator ifaceMethodsIterator; + for(ifaceMethodsIterator = ifaceMethods.begin(); ifaceMethodsIterator != ifaceMethods.end(); ifaceMethodsIterator++) + { + QCString function, signature; + + MCOPEntryInfo *entry = new MCOPEntryInfo(); + + MethodDef currentMethod = *ifaceMethodsIterator; + vector<ParamDef> currentParameters = currentMethod.signature; + + QCString newType = correctType(QCString(currentMethod.type.c_str())); + + entry->setFunctionType(newType); + entry->setFunctionName(QCString(currentMethod.name.c_str())); + + function = entry->functionType() + QCString(" ") + entry->functionName() + QCString("("); + + signature = QCString("("); + + QCStringList signatureList; + + vector<ParamDef>::iterator methodParametersIterator; + for(methodParametersIterator = currentParameters.begin(); methodParametersIterator != currentParameters.end(); methodParametersIterator++) + { + ParamDef parameter = *methodParametersIterator; + if(methodParametersIterator != currentParameters.begin()) + { + function += QCString(", "); + signature += QCString(","); + } + + QCString correctParameter = correctType(QCString(parameter.type.c_str())); + + function += correctParameter; + signature += correctParameter; + + signatureList.append(QCString(parameter.type.c_str())); + } + + function += QCString(")"); + signature += QCString(")"); + + entry->setSignature(signature); + entry->setSignatureList(signatureList); + + interface->addDynamicFunction(function, entry); + } + } + } + } +} diff --git a/arts/kde/mcop-dcop/kmcop.desktop b/arts/kde/mcop-dcop/kmcop.desktop new file mode 100644 index 000000000..4e6400ef1 --- /dev/null +++ b/arts/kde/mcop-dcop/kmcop.desktop @@ -0,0 +1,90 @@ +[Desktop Entry] +Type=Service +Name=KMCOP +Name[hi]=के-एमकॉप +Name[te]=కెఎంకాప్ +Exec=kmcop +Comment=KDE MCOP-DCOP Bridge +Comment[af]=KDE MCOP-DCOP Brug +Comment[ar]=جسر KDE MCOP-DCOP +Comment[az]=KDE MCOP-DCOP Körpüsü +Comment[be]=Сувязь MCOP/DCOP +Comment[bn]=কে.ডি.ই MCOP-DCOP ব্রিজ +Comment[br]=Pont KDE MCOP-DCOP +Comment[bs]=KDE MCOP-DCOP prelaz +Comment[ca]=Connector MCOP-DCOP per al KDE +Comment[cs]=KDE MCOP-DCOP můstek +Comment[csb]=Mostk KDE MCOP-DCOP +Comment[cy]=Pont MCOP-DCOP KDE +Comment[da]=KDE MCOP-DCOP-bro +Comment[de]=Verbindung zwischen MCOP und DCOP +Comment[el]=Γέφυρα MCOP-DCOP του KDE +Comment[eo]=KDE-ponto inter MCOP-DCOP +Comment[es]=Puente KDE MCOP-DCOP +Comment[et]=KDE MCOP-DCOP sild +Comment[eu]=KDEren MCOP-DCOP zubia +Comment[fa]=پل KDE MCOP-DCOP +Comment[fi]=MCOP-DCOP -silta +Comment[fo]=KDE MCOP-DCOP-brúgv +Comment[fr]=Passerelle MCOP-DCOP pour KDE +Comment[ga]=Droichead KDE idir MCOP agus DCOP +Comment[gl]=Ponte MCOP-DCOP de KDE +Comment[he]=גשר MCOP-DCOP ל־KDE +Comment[hi]=केडीई MCOP-डीकॉप ब्रिज +Comment[hr]=KDE most MCOP-DCOP +Comment[hsb]=KDE MCOP-DCOP-móst +Comment[hu]=KDE MCOP-DCOP összekötőprogram +Comment[id]=Jembatan KDE MCOP-DCOP +Comment[is]=KDE MCOP-DCOP brú +Comment[it]=Ponte MCOP-DCOP per KDE +Comment[ja]=KDE MCOP-DCOP ブリッジ +Comment[ka]=KDE MCOP-DCOP ხიდი +Comment[kk]=KDE MCOP-DCOP көпірі +Comment[ko]=KDE MCOP-DCOP 브릿지 +Comment[lb]=KDE-MCOP-DCOP-Bréck +Comment[lt]=KDE MCOP-DCOP tiltas +Comment[lv]=KDE MCOP-DCOP Tilts +Comment[mk]=KDE MCOP-DCOP Мост +Comment[mn]=KDE-н MCOP ба DCOP хоорондын гүүр +Comment[ms]=Jambatan KDE MCOP-DCOP +Comment[mt]=Pont bejn MCOP u DCOP +Comment[nb]=KDE MCOP-DCOP Bro +Comment[nds]=KDE-Brüch twischen MCOP un DCOP +Comment[ne]=KDE MCOP-DCOP ब्रिज +Comment[nn]=MCOP-DCOP-bru for KDE +Comment[nso]=Leporogo la KDE MCOP-DCOP +Comment[pa]=KDE MCOP-DCOP ਪੁੱਲ +Comment[pl]=Mostek MCOP-DCOP +Comment[pt]=Ponte MCOP-DCOP para o KDE +Comment[pt_BR]=Ligação KDE MCOP-DCOP +Comment[ro]=Punte MCOP-DCOP KDE +Comment[ru]=Мост MCOP-DCOP +Comment[rw]=Iteme MCOP-DCOP KDE +Comment[se]=KDE MCOP-DCOP šaldi +Comment[sk]=Most KDE MCOP-DCOP +Comment[sl]=Premostitelj MCOP-DCOP za KDE +Comment[sq]=Ura e KDE MCOP-DCOP-it +Comment[sr]=KDED MCOP-DCOP мост +Comment[sr@Latn]=KDED MCOP-DCOP most +Comment[ss]=Libhuloho le MCOP-DCOP ku KDE +Comment[sv]=KDE MCOP-DCOP-brygga +Comment[ta]=கேடிஇ MCOP-DCOP பாலம் +Comment[te]=కెడిఈ ఎంసిఓపి-డిసిఓపి వారధి +Comment[tg]=Пайвасти KDE MCOP-DCOP +Comment[th]=ตัวเชื่อม KDE MCOP-DCOP +Comment[tr]=KDE MCOP-DCOP Köprüsü +Comment[tt]=KDE MCOP-DCOP Küpere +Comment[uk]=Міст KDE MCOP-DCOP +Comment[uz]=KDE MCOP-DCOP koʻprigi +Comment[uz@cyrillic]=KDE MCOP-DCOP кўприги +Comment[ven]=KDE MCOP-DCOP Buroho +Comment[vi]=Cầu MCOP-DCOP của KDE +Comment[xh]=KDE MCOP-DCOP Ibhulorho +Comment[zh_CN]=KDE MCOP-DCOP 桥 +Comment[zh_HK]=KDE MCOP-DCOP 橋樑 +Comment[zh_TW]=KDE MCOP-DCOP 橋樑 +Comment[zu]=Ibhulogo le-KDE MCOP-DCOP +Icon=kmcop +ServiceTypes=KMCOP +X-DCOP-ServiceType=Unique +X-KDE-StartupNotify=false diff --git a/arts/kde/mcop-dcop/kmcop.h b/arts/kde/mcop-dcop/kmcop.h new file mode 100644 index 000000000..c81e385ff --- /dev/null +++ b/arts/kde/mcop-dcop/kmcop.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2001 Nikolas Zimmermann <wildfox@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef KMCOP_H +#define KMCOP_H + +#include <qobject.h> + +#include <dcopobject.h> + +class KMCOPPrivate; + +class KMCOP : public QObject, + public DCOPObject +{ +Q_OBJECT +K_DCOP + +public: + KMCOP(); + ~KMCOP(); + +k_dcop: + int objectCount(); + void addInterfacesHackHackHack(); + +private: + QCString correctType(const QCString &str); + KMCOPPrivate *d; +}; + + +#endif + diff --git a/arts/kde/mcop-dcop/mcopdcopobject.cpp b/arts/kde/mcop-dcop/mcopdcopobject.cpp new file mode 100644 index 000000000..f1d1acad5 --- /dev/null +++ b/arts/kde/mcop-dcop/mcopdcopobject.cpp @@ -0,0 +1,152 @@ +/* + Copyright (c) 2001 Nikolas Zimmermann <wildfox@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <kdebug.h> + +#include <core.h> +//#include <object.h> +//#include <reference.h> +#include <dynamicrequest.h> + +#include <qmap.h> +#include <qdatastream.h> + +using namespace std; + +#include "mcopdcoptools.h" +#include "mcopdcopobject.h" + +class MCOPDCOPObjectPrivate +{ +public: + QMap<QCString, MCOPEntryInfo *> dynamicFunctions; +}; + +MCOPDCOPObject::MCOPDCOPObject(QCString name) : DCOPObject(name) +{ + d = new MCOPDCOPObjectPrivate(); +} + +MCOPDCOPObject::~MCOPDCOPObject() +{ + delete d; +} + +QCStringList MCOPDCOPObject::functionsDynamic() +{ + QCStringList returnList; + + QMap<QCString, MCOPEntryInfo *>::iterator it; + for(it = d->dynamicFunctions.begin(); it != d->dynamicFunctions.end(); ++it) + returnList.append(it.key()); + + return returnList; +} + +Arts::Buffer *MCOPDCOPObject::callFunction(MCOPEntryInfo *entry, QCString ifaceName, const QByteArray &data) +{ + Arts::Object workingObject = Arts::SubClass(string(ifaceName)); + Arts::DynamicRequest request(workingObject); + request.method(string(entry->functionName())); + + if(entry->signatureList().size() > 0) + { + QCStringList list = entry->signatureList(); + + QCStringList::iterator it; + for(it = list.begin(); it != list.end(); ++it) + { + QCString param = *it; + + kdDebug() << "PARAM: " << param << endl; + + QDataStream argStream(data, IO_ReadOnly); + + if(param == "long") + request.param(MCOPDCOPTools::getLong(argStream)); + else if(param == "string") + request.param(MCOPDCOPTools::getString(argStream)); + } + } + + Arts::AnyRef result; + if(!request.invoke(result)) + return 0; + + Arts::Buffer *newBuffer = new Arts::Buffer(); + result.write(newBuffer); + + return newBuffer; +} + +bool MCOPDCOPObject::processDynamic(const QCString &fun, const QByteArray &data, QCString &replyType, QByteArray &replyData) +{ + QMap<QCString, MCOPEntryInfo *>::iterator it; + for(it = d->dynamicFunctions.begin(); it != d->dynamicFunctions.end(); ++it) + { + MCOPEntryInfo *entry = it.data(); + + if((entry->functionName() + entry->signature()) == fun) + { + QCString type = entry->functionType(); + + if(type == "void") + { + replyType = type; + + Arts::Buffer *result = callFunction(entry, objId(), data); + + if(result != 0) + delete result; + } + else if(type == "string") + { + replyType = "QCString"; + + QDataStream reply(replyData, IO_WriteOnly); + reply << "fooo!"; + } + else if(type == "long") + { + replyType = type; + + long returnCode = -1; + + Arts::Buffer *result = callFunction(entry, objId(), data); + + if(result != 0) + { + returnCode = result->readLong(); + delete result; + } + + QDataStream reply(replyData, IO_WriteOnly); + reply << returnCode; + } + + return true; + } + } + + return false; +} + +void MCOPDCOPObject::addDynamicFunction(QCString value, MCOPEntryInfo *entry) +{ + d->dynamicFunctions.insert(value, entry); +} diff --git a/arts/kde/mcop-dcop/mcopdcopobject.h b/arts/kde/mcop-dcop/mcopdcopobject.h new file mode 100644 index 000000000..4c7e70cf5 --- /dev/null +++ b/arts/kde/mcop-dcop/mcopdcopobject.h @@ -0,0 +1,89 @@ +/* + Copyright (c) 2001 Nikolas Zimmermann <wildfox@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef MCOPDCOPOBJECT_H +#define MCOPDCOPOBJECT_H + +#include <dcopobject.h> + +#include <qvaluelist.h> +#include <qcstring.h> + +typedef QValueList<QCString> QCStringList; + +class MCOPDCOPObjectPrivate; + +class MCOPEntryInfo +{ +public: + MCOPEntryInfo() + { } + + ~MCOPEntryInfo() + { } + + QCString functionType() + { return m_functionType; } + + QCString functionName() + { return m_functionName; } + + QCString signature() + { return m_signature; } + + QCStringList signatureList() + { return m_signatureList; } + + void setFunctionType(QCString s) + { m_functionType = s; } + + void setFunctionName(QCString s) + { m_functionName = s; } + + void setSignature(QCString s) + { m_signature = s; } + + void setSignatureList(QCStringList s) + { m_signatureList = s; } + +private: + QCString m_functionType, m_functionName, m_signature; + QCStringList m_signatureList; +}; + +class MCOPDCOPObject : public DCOPObject +{ +public: + MCOPDCOPObject(QCString name); + ~MCOPDCOPObject(); + + virtual bool processDynamic(const QCString &fun, const QByteArray &data, QCString &replyType, QByteArray &replyData); + virtual QCStringList functionsDynamic(); + + void addDynamicFunction(QCString value, MCOPEntryInfo *entry); + + Arts::Buffer *callFunction(MCOPEntryInfo *entry, QCString ifaceName, const QByteArray &data); + +private: + MCOPDCOPObjectPrivate *d; +}; + + +#endif + diff --git a/arts/kde/mcop-dcop/mcopdcoptools.h b/arts/kde/mcop-dcop/mcopdcoptools.h new file mode 100644 index 000000000..f1279111c --- /dev/null +++ b/arts/kde/mcop-dcop/mcopdcoptools.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2001 Nikolas Zimmermann <wildfox@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef MCOPDCOPTOOLS_H +#define MCOPDCOPTOOLS_H + +#include <string> + +#include <qdatastream.h> + +class MCOPDCOPTools +{ +public: + static long getLong(QDataStream &stream) + { + long l; + stream << l; + + return l; + } + + static std::string getString(QDataStream &stream) + { + QCString s; + stream << s; + + return std::string(s); + } +}; + +#endif |