You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
6.7 KiB
299 lines
6.7 KiB
15 years ago
|
/***************************************************************************
|
||
|
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;
|
||
|
}
|