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
/***************************************************************************
|
|
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 <tqfileinfo.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 TQString resolveSymLinks(const TQFileInfo &file) // static
|
|
{
|
|
char real[PATH_MAX];
|
|
|
|
if(file.exists() && realpath(TQFile::encodeName(file.absFilePath()).data(), real))
|
|
return TQFile::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 TQString absFilePath;
|
|
TQFileInfo fileInfo;
|
|
TQDateTime modificationTime;
|
|
TQDateTime 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 TQFileInfo &info, const TQString &path) :
|
|
d(0)
|
|
{
|
|
setup(info, path);
|
|
}
|
|
|
|
FileHandle::FileHandle(const TQString &path) :
|
|
d(0)
|
|
{
|
|
setup(TQFileInfo(path), path);
|
|
}
|
|
|
|
FileHandle::FileHandle(const TQString &path, CacheDataStream &s)
|
|
{
|
|
d = new FileHandlePrivate;
|
|
d->fileInfo = TQFileInfo(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 TQString &path)
|
|
{
|
|
if(!d || isNull())
|
|
setup(TQFileInfo(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;
|
|
}
|
|
|
|
TQString FileHandle::absFilePath() const
|
|
{
|
|
if(d->absFilePath.isNull())
|
|
d->absFilePath = resolveSymLinks(d->fileInfo.absFilePath());
|
|
return d->absFilePath;
|
|
}
|
|
|
|
const TQFileInfo &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 TQDateTime &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;
|
|
}
|
|
|
|
TQStringList FileHandle::properties() // static
|
|
{
|
|
return FileHandleProperties::properties();
|
|
}
|
|
|
|
TQString FileHandle::property(const TQString &name) const
|
|
{
|
|
return FileHandleProperties::property(*this, name.latin1());
|
|
}
|
|
|
|
const FileHandle &FileHandle::null() // static
|
|
{
|
|
static FileHandle f;
|
|
return f;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// private methods
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FileHandle::setup(const TQFileInfo &info, const TQString &path)
|
|
{
|
|
if(d && !isNull())
|
|
return;
|
|
|
|
TQString 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
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TQDataStream &operator<<(TQDataStream &s, const FileHandle &f)
|
|
{
|
|
s << *(f.tag())
|
|
<< f.lastModified();
|
|
|
|
return s;
|
|
}
|
|
|
|
CacheDataStream &operator>>(CacheDataStream &s, FileHandle &f)
|
|
{
|
|
f.read(s);
|
|
return s;
|
|
}
|