summaryrefslogtreecommitdiffstats
path: root/juk/filehandle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'juk/filehandle.cpp')
-rw-r--r--juk/filehandle.cpp298
1 files changed, 298 insertions, 0 deletions
diff --git a/juk/filehandle.cpp b/juk/filehandle.cpp
new file mode 100644
index 00000000..583cfc0d
--- /dev/null
+++ b/juk/filehandle.cpp
@@ -0,0 +1,298 @@
+/***************************************************************************
+ begin : Sun Feb 29 2004
+ copyright : (C) 2004 by Scott Wheeler
+ email : wheeler@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 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include <kdebug.h>
+
+#include <qfileinfo.h>
+
+#include "filehandle.h"
+#include "filehandleproperties.h"
+#include "tag.h"
+#include "cache.h"
+#include "coverinfo.h"
+
+AddProperty(Title, tag()->title())
+AddProperty(Artist, tag()->artist())
+AddProperty(Album, tag()->album())
+AddProperty(Genre, tag()->genre())
+AddNumberProperty(Track, tag()->track())
+AddNumberProperty(Year, tag()->year())
+AddProperty(Comment, tag()->comment())
+AddNumberProperty(Seconds, tag()->seconds())
+AddNumberProperty(Bitrate, tag()->bitrate())
+AddProperty(Path, absFilePath())
+AddNumberProperty(Size, fileInfo().size())
+AddProperty(Extension, fileInfo().extension(false))
+
+static QString resolveSymLinks(const QFileInfo &file) // static
+{
+ char real[PATH_MAX];
+
+ if(file.exists() && realpath(QFile::encodeName(file.absFilePath()).data(), real))
+ return QFile::decodeName(real);
+ else
+ return file.filePath();
+}
+
+/**
+ * A simple reference counter -- pasted from TagLib.
+ */
+
+class RefCounter
+{
+public:
+ RefCounter() : refCount(1) {}
+ void ref() { refCount++; }
+ bool deref() { return ! --refCount ; }
+ int count() const { return refCount; }
+private:
+ uint refCount;
+};
+
+class FileHandle::FileHandlePrivate : public RefCounter
+{
+public:
+ FileHandlePrivate() :
+ tag(0),
+ coverInfo(0) {}
+
+ ~FileHandlePrivate()
+ {
+ delete tag;
+ delete coverInfo;
+ }
+
+ mutable Tag *tag;
+ mutable CoverInfo *coverInfo;
+ mutable QString absFilePath;
+ QFileInfo fileInfo;
+ QDateTime modificationTime;
+ QDateTime lastModified;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// public methods
+////////////////////////////////////////////////////////////////////////////////
+
+FileHandle::FileHandle()
+{
+ static FileHandlePrivate nullPrivate;
+ d = &nullPrivate;
+ d->ref();
+}
+
+FileHandle::FileHandle(const FileHandle &f) :
+ d(f.d)
+{
+ if(!d) {
+ kdDebug(65432) << "The source FileHandle was not initialized." << endl;
+ d = null().d;
+ }
+ d->ref();
+}
+
+FileHandle::FileHandle(const QFileInfo &info, const QString &path) :
+ d(0)
+{
+ setup(info, path);
+}
+
+FileHandle::FileHandle(const QString &path) :
+ d(0)
+{
+ setup(QFileInfo(path), path);
+}
+
+FileHandle::FileHandle(const QString &path, CacheDataStream &s)
+{
+ d = new FileHandlePrivate;
+ d->fileInfo = QFileInfo(path);
+ d->absFilePath = path;
+ read(s);
+ Cache::instance()->insert(*this);
+}
+
+FileHandle::~FileHandle()
+{
+ if(d->deref())
+ delete d;
+}
+
+void FileHandle::refresh()
+{
+ d->fileInfo.refresh();
+ delete d->tag;
+ d->tag = new Tag(d->absFilePath);
+}
+
+void FileHandle::setFile(const QString &path)
+{
+ if(!d || isNull())
+ setup(QFileInfo(path), path);
+ else {
+ d->absFilePath = resolveSymLinks(path);
+ d->fileInfo.setFile(path);
+ d->tag->setFileName(d->absFilePath);
+ }
+}
+
+Tag *FileHandle::tag() const
+{
+ if(!d->tag)
+ d->tag = new Tag(d->absFilePath);
+
+ return d->tag;
+}
+
+CoverInfo *FileHandle::coverInfo() const
+{
+ if(!d->coverInfo)
+ d->coverInfo = new CoverInfo(*this);
+
+ return d->coverInfo;
+}
+
+QString FileHandle::absFilePath() const
+{
+ if(d->absFilePath.isNull())
+ d->absFilePath = resolveSymLinks(d->fileInfo.absFilePath());
+ return d->absFilePath;
+}
+
+const QFileInfo &FileHandle::fileInfo() const
+{
+ return d->fileInfo;
+}
+
+bool FileHandle::isNull() const
+{
+ return *this == null();
+}
+
+bool FileHandle::current() const
+{
+ return (d->modificationTime.isValid() &&
+ lastModified().isValid() &&
+ d->modificationTime >= lastModified());
+}
+
+const QDateTime &FileHandle::lastModified() const
+{
+ if(d->lastModified.isNull())
+ d->lastModified = d->fileInfo.lastModified();
+
+ return d->lastModified;
+}
+
+void FileHandle::read(CacheDataStream &s)
+{
+ switch(s.cacheVersion()) {
+ case 1:
+ default:
+ if(!d->tag)
+ d->tag = new Tag(d->absFilePath, true);
+
+ s >> *(d->tag);
+ s >> d->modificationTime;
+ break;
+ }
+}
+
+FileHandle &FileHandle::operator=(const FileHandle &f)
+{
+ if(&f == this)
+ return *this;
+
+ if(d->deref())
+ delete d;
+
+ d = f.d;
+ d->ref();
+
+ return *this;
+}
+
+bool FileHandle::operator==(const FileHandle &f) const
+{
+ return d == f.d;
+}
+
+bool FileHandle::operator!=(const FileHandle &f) const
+{
+ return d != f.d;
+}
+
+QStringList FileHandle::properties() // static
+{
+ return FileHandleProperties::properties();
+}
+
+QString FileHandle::property(const QString &name) const
+{
+ return FileHandleProperties::property(*this, name.latin1());
+}
+
+const FileHandle &FileHandle::null() // static
+{
+ static FileHandle f;
+ return f;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private methods
+////////////////////////////////////////////////////////////////////////////////
+
+void FileHandle::setup(const QFileInfo &info, const QString &path)
+{
+ if(d && !isNull())
+ return;
+
+ QString fileName = path.isNull() ? info.absFilePath() : path;
+
+ FileHandle cached = Cache::instance()->value(resolveSymLinks(fileName));
+
+ if(cached != null()) {
+ d = cached.d;
+ d->ref();
+ }
+ else {
+ d = new FileHandlePrivate;
+ d->fileInfo = info;
+ d->absFilePath = resolveSymLinks(fileName);
+ d->modificationTime = info.lastModified();
+ Cache::instance()->insert(*this);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// related functions
+////////////////////////////////////////////////////////////////////////////////
+
+QDataStream &operator<<(QDataStream &s, const FileHandle &f)
+{
+ s << *(f.tag())
+ << f.lastModified();
+
+ return s;
+}
+
+CacheDataStream &operator>>(CacheDataStream &s, FileHandle &f)
+{
+ f.read(s);
+ return s;
+}