|
|
|
/***************************************************************************
|
|
|
|
copyright : (C) 2006 by Robby Stephenson
|
|
|
|
email : robby@periapsis.org
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of version 2 of the GNU General Public License as *
|
|
|
|
* published by the Free Software Foundation; *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
// The information about the AMC file format was taken from the source code for
|
|
|
|
// GCfilms, (GPL) (c) 2005 Tian
|
|
|
|
// Monotheka, (GPL) (c) 2004, 2005 Michael Dominic K.
|
|
|
|
// 2005 Aurelien Mino
|
|
|
|
|
|
|
|
#include "amcimporter.h"
|
|
|
|
#include "../collections/videocollection.h"
|
|
|
|
#include "../imagefactory.h"
|
|
|
|
#include "../latin1literal.h"
|
|
|
|
#include "../progressmanager.h"
|
|
|
|
#include "../tellico_debug.h"
|
|
|
|
|
|
|
|
#include <kapplication.h>
|
|
|
|
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqimage.h>
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
static const TQCString AMC_FILE_ID = " AMC_X.Y Ant Movie Catalog 3.5.x www.buypin.com www.antp.be ";
|
|
|
|
}
|
|
|
|
|
|
|
|
using Tellico::Import::AMCImporter;
|
|
|
|
|
|
|
|
AMCImporter::AMCImporter(const KURL& url_) : DataImporter(url_), m_coll(0), m_cancelled(false) {
|
|
|
|
}
|
|
|
|
|
|
|
|
AMCImporter::~AMCImporter() {
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AMCImporter::canImport(int type) const {
|
|
|
|
return type == Data::Collection::Video;
|
|
|
|
}
|
|
|
|
|
|
|
|
Tellico::Data::CollPtr AMCImporter::collection() {
|
|
|
|
if(m_coll) {
|
|
|
|
return m_coll;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!fileRef().open()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQIODevice* f = fileRef().file();
|
|
|
|
m_ds.setDevice(f);
|
|
|
|
// AMC is always little-endian? can't confirm
|
|
|
|
m_ds.setByteOrder(TQDataStream::LittleEndian);
|
|
|
|
|
|
|
|
const uint l = AMC_FILE_ID.length();
|
|
|
|
TQMemArray<char> buffer(l+1);
|
|
|
|
m_ds.readRawBytes(buffer.data(), l);
|
|
|
|
TQString version = TQString::fromLocal8Bit(buffer, l);
|
|
|
|
TQRegExp versionRx(TQString::fromLatin1(".+AMC_(\\d+)\\.(\\d+).+"));
|
|
|
|
if(version.find(versionRx) == -1) {
|
|
|
|
myDebug() << "AMCImporter::collection() - no file id match" << endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ProgressItem& item = ProgressManager::self()->newProgressItem(this, progressLabel(), true);
|
|
|
|
item.setTotalSteps(f->size());
|
|
|
|
connect(&item, TQT_SIGNAL(signalCancelled(ProgressItem*)), TQT_SLOT(slotCancel()));
|
|
|
|
ProgressItem::Done done(this);
|
|
|
|
|
|
|
|
m_coll = new Data::VideoCollection(true);
|
|
|
|
|
|
|
|
m_majVersion = versionRx.cap(1).toInt();
|
|
|
|
m_minVersion = versionRx.cap(2).toInt();
|
|
|
|
// myDebug() << m_majVersion << "::" << m_minVersion << endl;
|
|
|
|
|
|
|
|
readString(); // name
|
|
|
|
readString(); // email
|
|
|
|
if(m_majVersion <= 3 && m_minVersion < 5) {
|
|
|
|
readString(); // icq
|
|
|
|
}
|
|
|
|
readString(); // webpage
|
|
|
|
readString(); // description
|
|
|
|
|
|
|
|
const bool showProgress = options() & ImportProgress;
|
|
|
|
|
|
|
|
while(!m_cancelled && !f->atEnd()) {
|
|
|
|
readEntry();
|
|
|
|
if(showProgress) {
|
|
|
|
ProgressManager::self()->setProgress(this, f->at());
|
|
|
|
kapp->processEvents();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_coll;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AMCImporter::readBool() {
|
|
|
|
TQ_UINT8 b;
|
|
|
|
m_ds >> b;
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQ_UINT32 AMCImporter::readInt() {
|
|
|
|
TQ_UINT32 i;
|
|
|
|
m_ds >> i;
|
|
|
|
if(i >= UINT_MAX) {
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString AMCImporter::readString() {
|
|
|
|
// The serialization format is a length specifier first, then l bytes of data
|
|
|
|
uint l = readInt();
|
|
|
|
if(l == 0) {
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
TQMemArray<char> buffer(l+1);
|
|
|
|
m_ds.readRawBytes(buffer.data(), l);
|
|
|
|
TQString s = TQString::fromLocal8Bit(buffer, l);
|
|
|
|
// myDebug() << "string: " << s << endl;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString AMCImporter::readImage(const TQString& format_) {
|
|
|
|
uint l = readInt();
|
|
|
|
if(l == 0) {
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
TQMemArray<char> buffer(l+1);
|
|
|
|
m_ds.readRawBytes(buffer.data(), l);
|
|
|
|
TQByteArray bytes;
|
|
|
|
bytes.setRawData(buffer.data(), l);
|
|
|
|
TQImage img(bytes);
|
|
|
|
bytes.resetRawData(buffer.data(), l);
|
|
|
|
if(img.isNull()) {
|
|
|
|
myDebug() << "AMCImporter::readImage() - null image" << endl;
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
TQString format = TQString::fromLatin1("PNG");
|
|
|
|
if(format_ == Latin1Literal(".jpg")) {
|
|
|
|
format = TQString::fromLatin1("JPEG");
|
|
|
|
} else if(format_ == Latin1Literal(".gif")) {
|
|
|
|
format = TQString::fromLatin1("GIF");
|
|
|
|
}
|
|
|
|
return ImageFactory::addImage(img, format);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AMCImporter::readEntry() {
|
|
|
|
Data::EntryPtr e = new Data::Entry(m_coll);
|
|
|
|
|
|
|
|
int id = readInt();
|
|
|
|
if(id > 0) {
|
|
|
|
e->setId(id);
|
|
|
|
}
|
|
|
|
readInt(); // add date
|
|
|
|
|
|
|
|
int rating = readInt();
|
|
|
|
if(m_majVersion >= 3 && m_minVersion >= 5) {
|
|
|
|
rating /= 10;
|
|
|
|
}
|
|
|
|
e->setField(TQString::fromLatin1("rating"), TQString::number(rating));
|
|
|
|
int year = readInt();
|
|
|
|
if(year > 0) {
|
|
|
|
e->setField(TQString::fromLatin1("year"), TQString::number(year));
|
|
|
|
}
|
|
|
|
int time = readInt();
|
|
|
|
if(time > 0) {
|
|
|
|
e->setField(TQString::fromLatin1("running-time"), TQString::number(time));
|
|
|
|
}
|
|
|
|
|
|
|
|
readInt(); // video bitrate
|
|
|
|
readInt(); // audio bitrate
|
|
|
|
readInt(); // number of files
|
|
|
|
readBool(); // checked
|
|
|
|
readString(); // media label
|
|
|
|
e->setField(TQString::fromLatin1("medium"), readString());
|
|
|
|
readString(); // source
|
|
|
|
readString(); // borrower
|
|
|
|
TQString s = readString(); // title
|
|
|
|
if(!s.isEmpty()) {
|
|
|
|
e->setField(TQString::fromLatin1("title"), s);
|
|
|
|
}
|
|
|
|
TQString s2 = readString(); // translated title
|
|
|
|
if(s.isEmpty()) {
|
|
|
|
e->setField(TQString::fromLatin1("title"), s2);
|
|
|
|
}
|
|
|
|
|
|
|
|
e->setField(TQString::fromLatin1("director"), readString());
|
|
|
|
s = readString();
|
|
|
|
TQRegExp roleRx(TQString::fromLatin1("(.+) \\(([^(]+)\\)"));
|
|
|
|
roleRx.setMinimal(true);
|
|
|
|
if(s.find(roleRx) > -1) {
|
|
|
|
TQString role = roleRx.cap(2).lower();
|
|
|
|
if(role == Latin1Literal("story") || role == Latin1Literal("written by")) {
|
|
|
|
e->setField(TQString::fromLatin1("writer"), roleRx.cap(1));
|
|
|
|
} else {
|
|
|
|
e->setField(TQString::fromLatin1("producer"), s);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
e->setField(TQString::fromLatin1("producer"), s);
|
|
|
|
}
|
|
|
|
e->setField(TQString::fromLatin1("nationality"), readString());
|
|
|
|
e->setField(TQString::fromLatin1("genre"), readString().replace(TQString::fromLatin1(", "), TQString::fromLatin1("; ")));
|
|
|
|
|
|
|
|
e->setField(TQString::fromLatin1("cast"), parseCast(readString()).join(TQString::fromLatin1("; ")));
|
|
|
|
|
|
|
|
readString(); // url
|
|
|
|
e->setField(TQString::fromLatin1("plot"), readString());
|
|
|
|
e->setField(TQString::fromLatin1("comments"), readString());
|
|
|
|
s = readString(); // video format
|
|
|
|
TQRegExp regionRx(TQString::fromLatin1("Region \\d"));
|
|
|
|
if(s.find(regionRx) > -1) {
|
|
|
|
e->setField(TQString::fromLatin1("region"), regionRx.cap(0));
|
|
|
|
}
|
|
|
|
e->setField(TQString::fromLatin1("audio-track"), readString()); // audio format
|
|
|
|
readString(); // resolution
|
|
|
|
readString(); // frame rate
|
|
|
|
e->setField(TQString::fromLatin1("language"), readString()); // audio language
|
|
|
|
e->setField(TQString::fromLatin1("subtitle"), readString()); // subtitle
|
|
|
|
readString(); // file size
|
|
|
|
s = readString(); // picture extension
|
|
|
|
s = readImage(s); // picture
|
|
|
|
if(!s.isEmpty()) {
|
|
|
|
e->setField(TQString::fromLatin1("cover"), s);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_coll->addEntries(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList AMCImporter::parseCast(const TQString& text_) {
|
|
|
|
TQStringList cast;
|
|
|
|
int nPar = 0;
|
|
|
|
TQRegExp castRx(TQString::fromLatin1("[,()]"));
|
|
|
|
TQString person, role;
|
|
|
|
int oldPos = 0;
|
|
|
|
for(int pos = text_.find(castRx); pos > -1; pos = text_.find(castRx, pos+1)) {
|
|
|
|
if(text_.at(pos) == ',' && nPar%2 == 0) {
|
|
|
|
// we're done with this one
|
|
|
|
person += text_.mid(oldPos, pos-oldPos).stripWhiteSpace();
|
|
|
|
TQString all = person;
|
|
|
|
if(!role.isEmpty()) {
|
|
|
|
if(role.startsWith(TQString::fromLatin1("as "))) {
|
|
|
|
role = role.mid(3);
|
|
|
|
}
|
|
|
|
all += "::" + role;
|
|
|
|
}
|
|
|
|
cast << all;
|
|
|
|
person.truncate(0);
|
|
|
|
role.truncate(0);
|
|
|
|
oldPos = pos+1; // add one to go past comma
|
|
|
|
} else if(text_.at(pos) == '(') {
|
|
|
|
if(nPar == 0) {
|
|
|
|
person = text_.mid(oldPos, pos-oldPos).stripWhiteSpace();
|
|
|
|
oldPos = pos+1; // add one to go past parenthesis
|
|
|
|
}
|
|
|
|
++nPar;
|
|
|
|
} else if(text_.at(pos) == ')') {
|
|
|
|
--nPar;
|
|
|
|
if(nPar == 0) {
|
|
|
|
role = text_.mid(oldPos, pos-oldPos).stripWhiteSpace();
|
|
|
|
oldPos = pos+1; // add one to go past parenthesis
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// grab the last one
|
|
|
|
if(nPar%2 == 0) {
|
|
|
|
int pos = text_.length();
|
|
|
|
person += text_.mid(oldPos, pos-oldPos).stripWhiteSpace();
|
|
|
|
TQString all = person;
|
|
|
|
if(!role.isEmpty()) {
|
|
|
|
if(role.startsWith(TQString::fromLatin1("as "))) {
|
|
|
|
role = role.mid(3);
|
|
|
|
}
|
|
|
|
all += "::" + role;
|
|
|
|
}
|
|
|
|
cast << all;
|
|
|
|
}
|
|
|
|
return cast;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AMCImporter::slotCancel() {
|
|
|
|
m_cancelled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "amcimporter.moc"
|