Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:zwabel
extragear-multimedia
amarok.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File amarok.diff of Package extragear-multimedia
Index: amarok/src/EngineController.h =================================================================== --- amarok/src/EngineController.h (Revision 861484) +++ amarok/src/EngineController.h (Arbeitskopie) @@ -23,6 +23,7 @@ #include <Phonon/Path> #include <Phonon/MediaSource> //Needed for the slot +#include <Phonon/AbstractMediaStream> class QTimer; @@ -38,6 +39,8 @@ class AMAROK_EXPORT EngineController : public QObject, public EngineSubject { Q_OBJECT + KUrl m_overrideUrl; + QPointer<Phonon::AbstractMediaStream> m_overrideWithStream; public: typedef QMap<QString, bool> ExtensionCache; @@ -88,6 +91,9 @@ Error = -1 }; + ///When @param url is played, and the stream pointer is still valid, it is played through this stream. + void overrideUrl(KUrl url, QPointer<Phonon::AbstractMediaStream> stream); + public slots: void play(); void play( const Meta::TrackPtr&, uint offset = 0 ); @@ -131,8 +137,10 @@ private: static EngineController* s_instance; + public: EngineController(); ~EngineController(); + private: static ExtensionCache s_extensionCache; Index: amarok/src/browsers/servicebrowser/lastfm/meta/LastFmMeta.cpp =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/meta/LastFmMeta.cpp (Revision 861484) +++ amarok/src/browsers/servicebrowser/lastfm/meta/LastFmMeta.cpp (Arbeitskopie) @@ -40,6 +40,7 @@ #include <KSharedPtr> #include <KStandardDirs> +#include <StreamHandler/StreamHandler.h> namespace LastFm { @@ -410,6 +411,7 @@ if( The::lastFmService()->scrobbler() ) The::lastFmService()->scrobbler()->love(); } + StreamHandler::self()->loving(this); } void Index: amarok/src/browsers/servicebrowser/lastfm/AudioController.cpp =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/AudioController.cpp (Revision 861484) +++ amarok/src/browsers/servicebrowser/lastfm/AudioController.cpp (Arbeitskopie) @@ -16,6 +16,7 @@ #include "EngineController.h" #include "LastFmService.h" #include "RadioAdapter.h" +#include "StreamHandler/StreamHandler.h" #include <KLocale> @@ -162,6 +163,7 @@ AudioController::playTrack( const TrackInfo &track ) { LastFm::TrackPtr lfmTrack = The::lastFmService()->radio()->currentTrack(); + StreamHandler::self()->handleTrack(track, lfmTrack.data()); if( lfmTrack ) { if( !m_currentTrackInfo.isEmpty() ) Index: amarok/src/browsers/servicebrowser/lastfm/LastFmServiceCollection.h =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/LastFmServiceCollection.h (Revision 861484) +++ amarok/src/browsers/servicebrowser/lastfm/LastFmServiceCollection.h (Arbeitskopie) @@ -27,7 +27,7 @@ class LastFmServiceCollection : public ServiceCollection { - Q_OBJECT + Q_OBJECT; public: LastFmServiceCollection( const QString& userName ); virtual ~LastFmServiceCollection(); @@ -40,11 +40,17 @@ virtual QueryMaker* queryMaker(); +Q_SIGNALS: + void reset(); private slots: + void slotAddPlayedSong( QString file ); + void slotRemovePlayedSong( QString file ); + void slotAddNeighboursLoved( WeightedStringList list ); void slotAddNeighboursPersonal( WeightedStringList list ); void slotAddFriendsLoved( QStringList list ); void slotAddFriendsPersonal( QStringList list ); + void slotRecentlyLovedTrackResult( Request* ); void slotRecentTrackResult( Request* ); Index: amarok/src/browsers/servicebrowser/lastfm/CMakeLists.txt =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/CMakeLists.txt (Revision 861484) +++ amarok/src/browsers/servicebrowser/lastfm/CMakeLists.txt (Arbeitskopie) @@ -36,6 +36,10 @@ RadioAdapter.cpp ScrobblerAdapter.cpp + StreamHandler/StreamHandler.cpp + StreamHandler/kiomediastream.cpp + StreamHandler/SavingStream.cpp + meta/LastFmMeta.cpp meta/LastFmStreamInfoCapability.cpp @@ -106,6 +110,7 @@ ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${KDE4_THREADWEAVER_LIBRARIES} + phonon ) if (APPLE) target_link_libraries(amarok_service_lastfm /System/Library/Frameworks/SystemConfiguration.framework) @@ -125,7 +130,7 @@ kde4_add_plugin( kcm_amarok_service_lastfm ${kcm_amarok_service_lastfm_PART_SRCS} ) - target_link_libraries( kcm_amarok_service_lastfm amaroklib ${KDE4_KDEUI_LIBS} ${KDE4_KUTILS_LIBS} ) + target_link_libraries( kcm_amarok_service_lastfm amaroklib ${KDE4_KDEUI_LIBS} ${KDE4_KUTILS_LIBS} phonon ) install(TARGETS kcm_amarok_service_lastfm DESTINATION ${PLUGIN_INSTALL_DIR}) Index: amarok/src/browsers/servicebrowser/lastfm/StreamHandler/kiomediastream.cpp =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/StreamHandler/kiomediastream.cpp (Revision 0) +++ amarok/src/browsers/servicebrowser/lastfm/StreamHandler/kiomediastream.cpp (Revision 0) @@ -0,0 +1,277 @@ +/* This file is part of the KDE project + Copyright (C) 2007 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 "kiomediastream.h" +#include "kiomediastream_p.h" +#include <kdebug.h> +#include <kprotocolmanager.h> +#include <kio/filejob.h> +#include <kio/job.h> +#include <klocale.h> + +namespace Phonon +{ + +KioMediaStream::KioMediaStream(const QUrl &url, QObject *parent) + : AbstractMediaStream(parent), d_ptr(new KioMediaStreamPrivate(this, url)) +{ + kDebug(600); + reset(); +} + +void KioMediaStream::reset() +{ + kDebug(600); + Q_D(KioMediaStream); + if (d->kiojob) { + d->kiojob->disconnect(this); + d->kiojob->kill(); + + d->endOfDataSent = false; + d->seeking = false; + d->reading = false; + d->open = false; + d->seekPosition = 0; + } + + if (KProtocolManager::supportsOpening(d->url)) { + d->kiojob = KIO::open(d->url, QIODevice::ReadOnly); + Q_ASSERT(d->kiojob); + d->open = false; + setStreamSeekable(true); + connect(d->kiojob, SIGNAL(open(KIO::Job *)), this, SLOT(_k_bytestreamFileJobOpen(KIO::Job *))); + connect(d->kiojob, SIGNAL(position(KIO::Job *, KIO::filesize_t)), + this, SLOT(_k_bytestreamSeekDone(KIO::Job *, KIO::filesize_t))); + } else { + d->kiojob = KIO::get(d->url, KIO::NoReload, KIO::HideProgressInfo); + Q_ASSERT(d->kiojob); + setStreamSeekable(false); + connect(d->kiojob, SIGNAL(totalSize(KJob *, qulonglong)), + this, SLOT(_k_bytestreamTotalSize(KJob *,qulonglong))); + d->kiojob->suspend(); + } + + gotNewJob(); + + d->kiojob->addMetaData("UserAgent", QLatin1String("KDE Phonon")); + connect(d->kiojob, SIGNAL(data(KIO::Job *,const QByteArray &)), + this, SLOT(_k_bytestreamData(KIO::Job *,const QByteArray &))); + connect(d->kiojob, SIGNAL(result(KJob *)), this, SLOT(_k_bytestreamResult(KJob *))); +} + +void KioMediaStream::gotNewJob() +{ +} + +void KioMediaStream::haveResult(bool success) +{ +} + +KioMediaStream::~KioMediaStream() +{ + kDebug(600); + Q_D(KioMediaStream); + if (d->kiojob) { + d->kiojob->disconnect(this); + KIO::FileJob *filejob = qobject_cast<KIO::FileJob *>(d->kiojob); + if (filejob) { + filejob->close(); + } + d->kiojob->kill(); + } + delete d_ptr; +} + +void KioMediaStream::needData() +{ + Q_D(KioMediaStream); + if (!d->kiojob) { + // no job => job is finished and endOfData was already sent + return; + } + KIO::FileJob *filejob = qobject_cast<KIO::FileJob *>(d->kiojob); + if (filejob) { + // while d->seeking the backend won't get any data + if (d->seeking || !d->open) { + d->reading = true; + } else if (!d->reading) { + d->reading = true; + QMetaObject::invokeMethod(this, "_k_read", Qt::QueuedConnection); + //filejob->read(32768); + } + } else { + // KIO::TransferJob + d->kiojob->resume(); + } +} + +void KioMediaStream::enoughData() +{ + Q_D(KioMediaStream); + //kDebug(600); + // Don't suspend when using a FileJob. The FileJob is controlled by calls to + // FileJob::read() + if (d->kiojob && !qobject_cast<KIO::FileJob *>(d->kiojob) && !d->kiojob->isSuspended()) { + d->kiojob->suspend(); + } else { + d->reading = false; + } +} + +void KioMediaStream::seekStream(qint64 position) +{ + Q_D(KioMediaStream); + if (!d->kiojob || d->endOfDataSent) { + // no job => job is finished and endOfData was already sent + kDebug(600) << "no job/job finished -> recreate it"; + reset(); + } + Q_ASSERT(d->kiojob); + kDebug(600) << position << " = " << qulonglong(position); + d->seeking = true; + d->seekPosition = position; + if (d->open) { + KIO::FileJob *filejob = qobject_cast<KIO::FileJob *>(d->kiojob); + filejob->seek(position); + } +} + +void KioMediaStreamPrivate::_k_bytestreamData(KIO::Job *, const QByteArray &data) +{ + Q_Q(KioMediaStream); + Q_ASSERT(kiojob); + if (q->streamSize() == 0) { + q->setStreamSize(-1); + } + if (seeking) { + // seek doesn't block, so don't send data to the backend until it signals us + // that the seek is done + kDebug(600) << "seeking: do nothing"; + return; + } + + if (data.isEmpty()) { + reading = false; + if (!endOfDataSent) { + kDebug(600) << "empty data: stopping the stream"; + endOfDataSent = true; + q->endOfData(); + } + return; + } + + //kDebug(600) << "calling writeData on the Backend ByteStream " << data.size(); + q->writeData(data); + if (reading) { + Q_ASSERT(qobject_cast<KIO::FileJob *>(kiojob)); + QMetaObject::invokeMethod(q, "_k_read", Qt::QueuedConnection); + } +} + +void KioMediaStreamPrivate::_k_bytestreamResult(KJob *job) +{ + Q_Q(KioMediaStream); + Q_ASSERT(kiojob == job); + if (job->error()) { + QString kioErrorString = job->errorString(); + kDebug(600) << "KIO Job error: " << kioErrorString; + QObject::disconnect(kiojob, SIGNAL(data(KIO::Job *,const QByteArray &)), + q, SLOT(_k_bytestreamData(KIO::Job *,const QByteArray &))); + QObject::disconnect(kiojob, SIGNAL(result(KJob *)), + q, SLOT(_k_bytestreamResult(KJob *))); + KIO::FileJob *filejob = qobject_cast<KIO::FileJob *>(kiojob); + if (filejob) { + QObject::disconnect(kiojob, SIGNAL(open(KIO::Job *)), + q, SLOT(_k_bytestreamFileJobOpen(KIO::Job *))); + QObject::disconnect(kiojob, SIGNAL(position(KIO::Job *, KIO::filesize_t)), + q, SLOT(_k_bytestreamSeekDone(KIO::Job *, KIO::filesize_t))); + } else { + QObject::disconnect(kiojob, SIGNAL(totalSize(KJob *, qulonglong)), + q, SLOT(_k_bytestreamTotalSize(KJob *,qulonglong))); + } + // go to ErrorState - NormalError + kWarning() << "ERROR IN STREAM" << kioErrorString; + q->error(NormalError, kioErrorString); + } else if (seeking) { + open = false; + kiojob = 0; + endOfDataSent = false; + reading = false; + q->reset(); + return; + } + open = false; + kiojob = 0; + kDebug(600) << "KIO Job is done (will delete itself) and d->kiojob reset to 0"; + endOfDataSent = true; + q->endOfData(); + q->haveResult(job->error() == 0); + + reading = false; +} + +void KioMediaStreamPrivate::_k_bytestreamTotalSize(KJob *, qulonglong size) +{ + Q_Q(KioMediaStream); + kDebug(600) << size; + q->setStreamSize(size > 0 ? size : -1); +} + +void KioMediaStreamPrivate::_k_bytestreamFileJobOpen(KIO::Job *) +{ + Q_Q(KioMediaStream); + Q_ASSERT(kiojob); + open = true; + endOfDataSent = false; + KIO::FileJob *filejob = static_cast<KIO::FileJob *>(kiojob); + kDebug(600) << filejob->size(); + q->setStreamSize(filejob->size() > 0 ? filejob->size() : -1); + + if (seeking) { + filejob->seek(seekPosition); + } else if (reading) { + //filejob->read(32768); + QMetaObject::invokeMethod(q, "_k_read", Qt::QueuedConnection); + } +} + +void KioMediaStreamPrivate::_k_bytestreamSeekDone(KIO::Job *, KIO::filesize_t offset) +{ + Q_ASSERT(kiojob); + kDebug(600) << offset; + seeking = false; + endOfDataSent = false; + if (reading) { + Q_Q(KioMediaStream); + Q_ASSERT(qobject_cast<KIO::FileJob *>(kiojob)); + QMetaObject::invokeMethod(q, "_k_read", Qt::QueuedConnection); + } +} + +void KioMediaStreamPrivate::_k_read() +{ + KIO::FileJob *filejob = qobject_cast<KIO::FileJob *>(kiojob); + Q_ASSERT(filejob); + filejob->read(32768); +} + +} // namespace Phonon + +#include "kiomediastream.moc" +// vim: sw=4 sts=4 et tw=100 Index: amarok/src/browsers/servicebrowser/lastfm/StreamHandler/StreamHandler.h =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/StreamHandler/StreamHandler.h (Revision 0) +++ amarok/src/browsers/servicebrowser/lastfm/StreamHandler/StreamHandler.h (Revision 0) @@ -0,0 +1,47 @@ +#ifndef STREAMHANDLER_H +#define STREAMHANDLER_H + +#include <QObject> +#include <QDir> +#include <QList> +#include <QString> +#include <KUrl> + +class TrackInfo; +namespace Phonon { +class KioMediaStream; +} +namespace LastFm { +class Track; +} + +class StreamHandler : public QObject{ + Q_OBJECT + public: + static StreamHandler* self(); + StreamHandler(); + ~StreamHandler(); + + void handleTrack(const TrackInfo& track, LastFm::Track* lfmTrack); + + //Returns a list of all currently stored played songs + QList<QString> recentlyPlayed() const; + public: + void loving(LastFm::Track* track); + Q_SIGNALS: + void downloaded(QString file); + void deleted(QString file); + + private Q_SLOTS: + void slotDownloaded(KUrl url, QString file); + private: + //Returns an empty path on error + QDir directory() const; + QDir lovingDirectory() const; + void closeStreams(); + void limitFileCount(); + QList<Phonon::KioMediaStream*> m_openStreams; + KUrl m_loving; +}; + +#endif Index: amarok/src/browsers/servicebrowser/lastfm/StreamHandler/kiomediastream_p.h =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/StreamHandler/kiomediastream_p.h (Revision 0) +++ amarok/src/browsers/servicebrowser/lastfm/StreamHandler/kiomediastream_p.h (Revision 0) @@ -0,0 +1,79 @@ +/* This file is part of the KDE project + Copyright (C) 2007 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 KIOMEDIASTREAM_P_H +#define KIOMEDIASTREAM_P_H + +#include "kiomediastream.h" +#include <kurl.h> +#include <kio/jobclasses.h> +#include <QPointer> + +namespace Phonon +{ + +class KioMediaStreamPrivate +{ + Q_DECLARE_PUBLIC(KioMediaStream) + public: + KioMediaStreamPrivate(KioMediaStream* stream, const KUrl &u) + : url(u), + endOfDataSent(false), + seeking(false), + reading(false), + open(false), + seekPosition(0), + kiojob(0), + q_ptr(stream) + { + } + + ~KioMediaStreamPrivate() + { + if (kiojob) { + kiojob->kill(); + kiojob = 0; + } + } + + void _k_bytestreamNeedData(); + void _k_bytestreamEnoughData(); + void _k_bytestreamData(KIO::Job *, const QByteArray &); + void _k_bytestreamResult(KJob *); + void _k_bytestreamTotalSize(KJob *, qulonglong); + void _k_bytestreamSeekStream(qint64); + void _k_bytestreamFileJobOpen(KIO::Job *); + void _k_bytestreamSeekDone(KIO::Job *, KIO::filesize_t); + void _k_read(); + + KUrl url; + bool endOfDataSent; + bool seeking; + bool reading; + bool open; + qint64 seekPosition; + KIO::SimpleJob *kiojob; + QPointer<KioMediaStream> q_ptr; + //QPointer<KioMediaStream> safe_ptr; +}; + +} // namespace Phonon + +#endif // KIOMEDIASTREAM_P_H +// vim: sw=4 sts=4 et tw=100 Index: amarok/src/browsers/servicebrowser/lastfm/StreamHandler/kiomediastream.h =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/StreamHandler/kiomediastream.h (Revision 0) +++ amarok/src/browsers/servicebrowser/lastfm/StreamHandler/kiomediastream.h (Revision 0) @@ -0,0 +1,60 @@ +/* This file is part of the KDE project + Copyright (C) 2007 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 PHONON_KIOMEDIASTREAM_H +#define PHONON_KIOMEDIASTREAM_H + +#include <Phonon/AbstractMediaStream> + +class QUrl; + +namespace Phonon +{ + +class KioMediaStreamPrivate; + +class KioMediaStream : public AbstractMediaStream +{ + Q_OBJECT + Q_DECLARE_PRIVATE(KioMediaStream) + public: + explicit KioMediaStream(const QUrl &url, QObject *parent = 0); + ~KioMediaStream(); + + protected: + void reset(); + void needData(); + void enoughData(); + void seekStream(qint64); + KioMediaStreamPrivate* d_ptr; + + virtual void gotNewJob(); + virtual void haveResult(bool success); + + private: + Q_PRIVATE_SLOT(d_func(), void _k_bytestreamData(KIO::Job *, const QByteArray &)) + Q_PRIVATE_SLOT(d_func(), void _k_bytestreamResult(KJob *)) + Q_PRIVATE_SLOT(d_func(), void _k_bytestreamTotalSize(KJob *, qulonglong)) + Q_PRIVATE_SLOT(d_func(), void _k_bytestreamFileJobOpen(KIO::Job *)) + Q_PRIVATE_SLOT(d_func(), void _k_bytestreamSeekDone(KIO::Job *, KIO::filesize_t)) + Q_PRIVATE_SLOT(d_func(), void _k_read()) +}; + +} // namespace Phonon +#endif // PHONON_KIOMEDIASTREAM_H Index: amarok/src/browsers/servicebrowser/lastfm/StreamHandler/SavingStream.cpp =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/StreamHandler/SavingStream.cpp (Revision 0) +++ amarok/src/browsers/servicebrowser/lastfm/StreamHandler/SavingStream.cpp (Revision 0) @@ -0,0 +1,66 @@ +#include "SavingStream.h" +#include <QFile> +#include <taglib/fileref.h> +#include <taglib/tag.h> +#include <kdebug.h> +#include "kiomediastream_p.h" +#include <meta/MetaUtility.h> + +SavingStream::SavingStream(const QString& targetFile, const TrackInfo& track, QObject* parent) : Phonon::KioMediaStream(QUrl(track.path()), parent), m_trackInfo(track), m_targetFile(targetFile), m_file(0), m_ready(false) { + kWarning() << "storing" << track.toString() << "from" << track.path() << "to" << targetFile; + m_file = new QFile(targetFile); + m_file->open(QIODevice::WriteOnly); +} + +SavingStream::~SavingStream() { + if(m_file) { + m_file->close(); + } + if(!m_ready) { + kWarning() << m_trackInfo.toString() << "not ready, deleting it"; + QFile::remove(m_targetFile); + } + delete m_file; +} + +bool SavingStream::success() const { + return m_ready; +} + +void SavingStream::gotNewJob() { + connect(d_ptr->kiojob, SIGNAL(data(KIO::Job *,const QByteArray &)), + this, SLOT(data(KIO::Job *,const QByteArray &))); +} + +void SavingStream::haveResult(bool success) +{ + if(m_file) { + m_file->close(); + } + + delete m_file; + m_file = 0; + + m_ready = success; + if(!m_ready) + kWarning() << "download failed" << m_trackInfo.path() << m_targetFile; + + QVariantMap data; + data.insert(Meta::Field::ARTIST, m_trackInfo.artist()); + data.insert(Meta::Field::TRACKNUMBER, m_trackInfo.trackNr()); + data.insert(Meta::Field::TITLE, m_trackInfo.track()); + data.insert(Meta::Field::ALBUM, m_trackInfo.album()); + + data.insert(Meta::Field::COMMENT, QString("This is a private recording made from a last.fm stream, do not distribute it.")); + + Meta::Field::writeFields(m_targetFile, data); + + if(m_ready) + emit downloaded(KUrl(m_trackInfo.path()), m_targetFile); +} + +void SavingStream::data(KIO::Job *,const QByteArray & data) { + if(m_file && m_file->isOpen()) + m_file->write(data); +} + Index: amarok/src/browsers/servicebrowser/lastfm/StreamHandler/SavingStream.h =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/StreamHandler/SavingStream.h (Revision 0) +++ amarok/src/browsers/servicebrowser/lastfm/StreamHandler/SavingStream.h (Revision 0) @@ -0,0 +1,36 @@ +#ifndef SAVINGSTREAM_H +#define SAVINGSTREAM_H + +#include "kiomediastream.h" +#include "libUnicorn/TrackInfo.h" +#include <kio/job.h> +#include <QFile> +#include <QString> + +class QFile; +class TrackInfo; + + +class SavingStream : public Phonon::KioMediaStream { + Q_OBJECT; + public: + SavingStream(const QString& targetFile, const TrackInfo& track, QObject* parent); + ~SavingStream(); + bool success() const; + + Q_SIGNALS: + void downloaded(KUrl url, QString file); + protected: + virtual void gotNewJob(); + void haveResult(bool success); + private Q_SLOTS: + void data(KIO::Job *,const QByteArray &); + private: + bool m_ready; + QFile* m_file; + QString m_targetFile; + TrackInfo m_trackInfo; +}; + +#endif + Index: amarok/src/browsers/servicebrowser/lastfm/StreamHandler/StreamHandler.cpp =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/StreamHandler/StreamHandler.cpp (Revision 0) +++ amarok/src/browsers/servicebrowser/lastfm/StreamHandler/StreamHandler.cpp (Revision 0) @@ -0,0 +1,148 @@ +#include "StreamHandler.h" +#include "libUnicorn/TrackInfo.h" +#include <kdebug.h> +#include <QDir> +#include "meta/LastFmMeta.h" +#include <QDateTime> +#include <QFileInfo> +#include "kiomediastream.h" +#include "EngineController.h" +#include "SavingStream.h" + +const int maxSongs = 200; + +StreamHandler::StreamHandler() { +} + +StreamHandler::~StreamHandler() { + closeStreams(); +} + +StreamHandler* StreamHandler::self() { + static StreamHandler* ret = new StreamHandler(); + return ret; +} + +QDir StreamHandler::directory() const { + QString dirName = ".lastfm_rip"; + + QDir targetDirectory = QDir::home(); + if(!targetDirectory.exists(dirName)) { + kWarning() << "creating rip directory" << dirName; + targetDirectory.mkdir(dirName); + } + if(!targetDirectory.cd(dirName)) { + kWarning() << "could not enter directory" << targetDirectory.path() + "/" + dirName; + return QDir(); + } + return targetDirectory; +} + +QDir StreamHandler::lovingDirectory() const { + QString dirName = ".lastfm_loved"; + + QDir targetDirectory = QDir::home(); + if(!targetDirectory.exists(dirName)) { + kWarning() << "creating rip directory" << dirName; + targetDirectory.mkdir(dirName); + } + if(!targetDirectory.cd(dirName)) { + kWarning() << "could not enter directory" << targetDirectory.path() + "/" + dirName; + return QDir(); + } + return targetDirectory; +} + +void StreamHandler::handleTrack(const TrackInfo& track, LastFm::Track* lfmTrack) { + kWarning() << "handling track" << track.toString() << "from" << track.path(); + closeStreams(); + QString target = track.artist() + " - " + track.track() + ".mp3"; + target.replace(":", "_"); + + QDir dir(directory()); + if(dir.path().isEmpty()) + return; + + KUrl u(dir.path()); + u.addPath(target); + target = u.path(); + + if(QFile::exists(target)) { + kWarning() << "File already exists:" << target; + return; + } + + m_openStreams << new SavingStream(target, track, 0); + connect(m_openStreams.back(), SIGNAL(downloaded(KUrl, QString)), this, SLOT(slotDownloaded(KUrl, QString))); + The::engineController()->overrideUrl( KUrl(track.path()), m_openStreams.back()); +} + +void StreamHandler::closeStreams() { + foreach(Phonon::KioMediaStream* stream, m_openStreams) + delete stream; + m_openStreams.clear(); +} + +void StreamHandler::limitFileCount() { + QDir dir(directory()); + dir.setFilter(QDir::NoDotAndDotDot); + dir.setSorting(QDir::Time); + QList<QString> ret; + QList<QFileInfo> infoList = dir.entryInfoList(); + + if(infoList.size() <= maxSongs) + return; + + kWarning() << "there is" << infoList.size() << "songs in" << dir.path() << ", limiting them to" << maxSongs; + + int deleteCount = infoList.size() - maxSongs; + for(int a = 0; a < deleteCount; ++a) { + kWarning() << "removing" << infoList[a].absoluteFilePath(); + QFile::remove( infoList[a].absoluteFilePath() ); + emit deleted(infoList[a].absoluteFilePath()); + } +} + +QStringList absoluteFileNamesInDir(QDir dir) { + dir.setSorting(QDir::Time); + + QList<QString> ret; + QList<QFileInfo> infos = dir.entryInfoList(); + + kWarning() << "got" << infos.size() << "recently played songs in directory" << dir.path(); + foreach(QFileInfo info, infos) + if(!info.fileName().startsWith(".")) + ret << info.absoluteFilePath(); + + return ret; +} + +QList<QString> StreamHandler::recentlyPlayed() const { + return absoluteFileNamesInDir(lovingDirectory()) + absoluteFileNamesInDir(directory()); +} + +void StreamHandler::slotDownloaded(KUrl url, QString file) { + if(!m_loving.isEmpty()) { + if(m_loving == url) { + QDir lovingDir = lovingDirectory(); + if(!lovingDir.path().isEmpty()) { + QFileInfo fi(file); + QString newFile = lovingDir.absoluteFilePath(fi.fileName()); + QFile::rename(file, newFile); + file = newFile; + } + }else{ + kWarning() << "loved track" << m_loving << "but downloaded" << url; + } + m_loving = KUrl(); + } + + emit downloaded(file); +} + +void StreamHandler::loving(LastFm::Track* track) { + m_loving = track->playableUrl(); + kWarning() << "loving" << m_loving; +} + +#include "StreamHandler.moc" Index: amarok/src/browsers/servicebrowser/lastfm/LastFmServiceCollection.cpp =================================================================== --- amarok/src/browsers/servicebrowser/lastfm/LastFmServiceCollection.cpp (Revision 861484) +++ amarok/src/browsers/servicebrowser/lastfm/LastFmServiceCollection.cpp (Arbeitskopie) @@ -18,10 +18,15 @@ #include "LastFmServiceQueryMaker.h" #include "meta/LastFmMeta.h" #include "ServiceMetaBase.h" +#include "StreamHandler/StreamHandler.h" + +#include <QFileInfo> +#include <QDateTime> // libunicorn includes #include "libUnicorn/WebService/Request.h" #include "WebService.h" +#include "meta/file/File.h" #include "support/MemoryQueryMaker.h" @@ -33,11 +38,11 @@ m_userName = userName; - Meta::ServiceGenre * userStreams = new Meta::ServiceGenre( i18n( "%1's Streams", userName ) ); + Meta::ServiceGenre * userStreams = new Meta::ServiceGenre( userName +"'s Streams" ); Meta::GenrePtr userStreamsPtr( userStreams ); addGenre( userStreamsPtr ); - Meta::ServiceGenre * globalTags = new Meta::ServiceGenre( i18n( "Global Tags" ) ); + Meta::ServiceGenre * globalTags = new Meta::ServiceGenre( "Global Tags" ); Meta::GenrePtr globalTagsPtr( globalTags ); addGenre( globalTagsPtr ); @@ -107,13 +112,46 @@ connect( rlt, SIGNAL( result( Request* ) ), SLOT( slotRecentlyLovedTrackResult( Request* ) ) ); rlt->start(); - RecentTracksRequest *rt = new RecentTracksRequest; - connect( rt, SIGNAL( result( Request* ) ), SLOT( slotRecentTrackResult( Request* ) ) ); - rt->start(); + foreach(QString file, StreamHandler::self()->recentlyPlayed()) + slotAddPlayedSong( file ); + connect(StreamHandler::self(), SIGNAL(downloaded(QString)), this, SLOT(slotAddPlayedSong(QString))); + connect(StreamHandler::self(), SIGNAL(deleted(QString)), this, SLOT(slotRemovePlayedSong(QString))); +// RecentTracksRequest *rt = new RecentTracksRequest; +// connect( rt, SIGNAL( result( Request* ) ), SLOT( slotRecentTrackResult( Request* ) ) ); +// rt->start(); //TODO Automatically add simmilar artist streams for the users favorite artists. } +class RecentTrack : public MetaFile::Track { +public: + RecentTrack( const KUrl &url ) : MetaFile::Track(url) { + m_dateString = QFileInfo(url.path()).lastModified().toString(Qt::ISODate); + } + + virtual QString prettyName() const { + return playableUrl().fileName(); + } + + virtual QString sortableName() const { + return m_dateString; + } + QString m_dateString; +}; + +void LastFmServiceCollection::slotAddPlayedSong( QString file ) +{ + KUrl url(file); + kDebug() << "adding recently played" << file; + Meta::TrackPtr track( new RecentTrack( url ) ); + m_recentlyPlayed->addTrack(track); + addTrack(track); ///@todo wofür? +} + +void LastFmServiceCollection::slotRemovePlayedSong( QString file ) +{ + emit reset(); +} LastFmServiceCollection::~LastFmServiceCollection() { Index: amarok/src/meta/MetaUtility.cpp =================================================================== --- amarok/src/meta/MetaUtility.cpp (Revision 861484) +++ amarok/src/meta/MetaUtility.cpp (Arbeitskopie) @@ -181,7 +181,8 @@ #endif TagLib::FileRef f = TagLib::FileRef( encodedName, true, TagLib::AudioProperties::Fast ); - return writeFields( f, changes ); + writeFields( f, changes ); + f.save(); } void @@ -190,7 +191,7 @@ DEBUG_BLOCK if( fileref.isNull() || changes.isEmpty() ) return; - debug() << "CHANGES: " << changes; + DEBUG_LINE_INFO TagLib::Tag *tag = fileref.tag(); if( !tag ) Index: amarok/src/App.cpp =================================================================== --- amarok/src/App.cpp (Revision 861484) +++ amarok/src/App.cpp (Arbeitskopie) @@ -83,7 +83,7 @@ extern void setupEventHandler_mac(long); #endif -#define AMAROK_CAPTION "Amarok 2 beta" +#define AMAROK_CAPTION "Amarok 2 beta special" AMAROK_EXPORT KAboutData aboutData( "amarok", 0, ki18n( "Amarok" ), APP_VERSION, Index: amarok/src/EngineController.cpp =================================================================== --- amarok/src/EngineController.cpp (Revision 856877) +++ amarok/src/EngineController.cpp (Arbeitskopie) @@ -43,6 +43,12 @@ #include <QFile> #include <QTimer> +void EngineController::overrideUrl(KUrl url, QPointer<Phonon::AbstractMediaStream> stream) +{ + kDebug() << "setting override stream for" << url; + m_overrideUrl = url; + m_overrideWithStream = stream; +} EngineController::ExtensionCache EngineController::s_extensionCache; @@ -59,11 +65,15 @@ return &privateSelf->self; } +void EngineController::destroy() { +} + EngineController::EngineController() : m_media( 0 ) , m_audio( 0 ) , m_playWhenFetched(true) , m_fadeoutTimer( new QTimer( this ) ) + , m_mutex( QMutex::Recursive ) { DEBUG_BLOCK @@ -291,7 +301,12 @@ slotStopFadeout(); debug() << "URL: " << url.url(); - m_media->setCurrentSource( url ); + if(url == m_overrideUrl && m_overrideWithStream) { + kDebug() << "using overridden stream"; + m_media->setCurrentSource( m_overrideWithStream.data() ); + }else{ + m_media->setCurrentSource( url ); + } m_nextTrack.clear(); m_nextUrl.clear(); @@ -542,11 +557,16 @@ EngineController::slotAboutToFinish() { // For some reason, phonon emits this when it's done buffering. + kDebug() << "state:" << m_media->state() << "current:" << m_media->currentTime() << "remaining:" << m_media->remainingTime() << "error:" << m_media->errorType(); +// if( /*m_media->state() == Phonon::BufferingState && */!m_media->currentTime()) if( m_media->state() == Phonon::BufferingState ) return; DEBUG_BLOCK +// m_media->stop(); //To reset the time to zero + kDebug() << "current time after stop:" << m_media->currentTime(); + if( m_multi ) { m_mutex.lock(); @@ -563,7 +583,7 @@ { DEBUG_BLOCK - if( m_currentTrack ) + if( m_currentTrack && (m_nextTrack || m_nextUrl.isEmpty()) ) { emit trackFinished(); m_currentTrack->finishedPlaying( 1.0 ); Index: amarok/src/CMakeLists.txt =================================================================== --- amarok/src/CMakeLists.txt (Revision 861484) +++ amarok/src/CMakeLists.txt (Arbeitskopie) @@ -544,6 +544,7 @@ ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${QT_QTSCRIPT_LIBRARY} + ${QT_QT3SUPPORT_LIBRARY} ${QT_QTWEBKIT_LIBRARY} ${KDE4_PHONON_LIBRARY} ${KDE4_SOLID_LIBRARY}
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor