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.
tellico/src/translators/amcimporter.cpp

295 lines
8.6 KiB

/***************************************************************************
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"