diff --git a/src/Lib/Ass/AssFactory.cc b/src/Lib/Ass/AssFactory.cc index 7bd08bfe0792fd013662a72a85b931b5a8b4dd47..354c50d8ce4b7fca4b3bfb6d68924c93cfb3fd32 100644 --- a/src/Lib/Ass/AssFactory.cc +++ b/src/Lib/Ass/AssFactory.cc @@ -6,22 +6,19 @@ using namespace Vivy::Ass; bool AssFactory::initFromStorage() noexcept { - QTextStream in(&diskStorage); QString currentSection{}; quint64 lineIndex = 0; QStringList stylesContent{}; QStringList eventsContent{}; - while (!in.atEnd()) { - const QString line = in.readLine().trimmed(); - - // Dectect comment + auto processLine = [&](const QString line) { + // Detect comment if (line.startsWith(";") || line.isEmpty()) { lineIndex++; - continue; + return; } - // Dectect sections + // Detect sections else if (line.startsWith("[") && line.endsWith("]")) { currentSection = line.mid(1, line.size() - 2); logDebug() << "Parsing section " << VIVY_LOG_QUOTED(currentSection); @@ -57,7 +54,23 @@ AssFactory::initFromStorage() noexcept } lineIndex++; - } + }; + + if (internalAss.isArray()) { + QJsonArray arr = internalAss.toArray(); + auto i = arr.constBegin(); + while (i != arr.constEnd()) { + processLine(i->toString()); + ++i; + } + } else if (diskStorage.exists()) { + QTextStream in(&diskStorage); + + while (!in.atEnd()) { + processLine(in.readLine().trimmed()); + } + } else + return false; // Construct the styles and the lines try { @@ -109,23 +122,24 @@ AssFactory::checkValidity() const noexcept AssFactory::AssFactory(const QString &fileName) : diskStorage(fileName) + , internalAss() { if (!diskStorage.open(QIODevice::ReadOnly | QIODevice::Text)) throw std::runtime_error("failed to open file for reading"); - if (!initFromStorage()) - throw std::runtime_error("failed to init ass factory from file"); - - if (!checkValidity()) - throw std::runtime_error("the loaded ass is invalid"); + init(); } AssFactory::AssFactory(const QJsonValue &internal) : diskStorage("") + , internalAss(internal) { - if (!diskStorage.open(QIODevice::ReadOnly | QIODevice::Text)) - throw std::runtime_error("failed to open file for reading"); + init(); +} +void +AssFactory::init() +{ if (!initFromStorage()) throw std::runtime_error("failed to init ass factory from file"); @@ -155,6 +169,32 @@ AssFactory::getInfoSection() const noexcept return assInfo; } +QStringList +AssFactory::getAssHeaderAsText() const noexcept +{ + QStringList ret = QStringList("[" + sectionScriptInfo + "]"); + + auto it = assInfo.constBegin(); + while (it != assInfo.constEnd()) { + ret += it.key() + ": " + it.value().toString(); + ++it; + } + + // TODO: add styles as text + ret.append(""); + ret.append("[" + sectionStyles + "]"); + //ret.append("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"); + for (int i = 0; i < assStyles.size(); ++i) { + ret.append(assStyles.at(i)->getRawText()); + } + + ret.append(""); + ret.append("[" + sectionEvents + "]"); + //ret.append("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"); + + return ret; +} + StyleWeakPtr AssFactory::getStyle(const QString &name) const noexcept { diff --git a/src/Lib/Ass/AssFactory.hh b/src/Lib/Ass/AssFactory.hh index 544806afe3c7b608ca4ad65dd254b438abc970a7..9e0c49c513a95ec82cb91b5b0256e893e1c67f1d 100644 --- a/src/Lib/Ass/AssFactory.hh +++ b/src/Lib/Ass/AssFactory.hh @@ -23,6 +23,8 @@ public: private: QFile diskStorage; + QJsonValue internalAss; + SectionContent assInfo{}; QVector<LinePtr> assLines{}; QVector<StylePtr> assStyles{}; @@ -44,6 +46,8 @@ private: bool initFromStorage() noexcept; bool checkValidity() const noexcept; + void init(); + public: explicit AssFactory(const QString &); explicit AssFactory(const QJsonValue &); @@ -53,6 +57,7 @@ public: StyleWeakPtr getStyle(const QString &) const noexcept; SectionContent getInfoSection() const noexcept; + QStringList getAssHeaderAsText() const noexcept; void getStyles(QVector<StylePtr> &) const noexcept; void getLines(QVector<LinePtr> &) const noexcept; }; diff --git a/src/Lib/Ass/Line.cc b/src/Lib/Ass/Line.cc index 5188678d6740670cc6ff68299fd5a5b8d6f1553f..af9448cb6ca28372faf56104ff0fad8025d07471 100644 --- a/src/Lib/Ass/Line.cc +++ b/src/Lib/Ass/Line.cc @@ -180,7 +180,10 @@ Line::getContentAsText() const noexcept QString Line::getLineAsText() const noexcept { - return QString::asprintf("%s: %d,%s,%s,", "Dialogue", layer, "0:00:00.00", "0:00:00.00") + + // FIXME: asprintf bad, use QString("%x").arg()? + return QString::asprintf("%s: %d,%s,%s,", "Dialogue", layer, + Utils::Time::fromUInt(start).toString().toStdString().c_str(), + Utils::Time::fromUInt(end).toString().toStdString().c_str()) + styleProperties.name + QString::asprintf(",%s,%d,%d,%d,%s,", "", styleProperties.marginL, styleProperties.marginR, styleProperties.marginV, "karaoke") + diff --git a/src/Lib/Ass/Style.cc b/src/Lib/Ass/Style.cc index 0a78af9537991cd7d4f8d123ea79b3034967bcc8..c6114cfc31a49dd72e66771bb9200aab4e299dc2 100644 --- a/src/Lib/Ass/Style.cc +++ b/src/Lib/Ass/Style.cc @@ -196,3 +196,21 @@ Style::getProperties() const noexcept ret.setObject(object); return ret; } + +#define PRINT_STYLE_BOOL(b) b ? -1 : 0 +QString +Style::getRawText() const noexcept +{ + // FIXME: asprintf bad, use QString("%x").arg()? + return QString::asprintf( + "Style: %s,%s,%d,%s,%s,%s,%s,%d,%d,%d,%d,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%d,%d,%d,%d,%d", + styleName.toStdString().c_str(), fontName.toStdString().c_str(), fontSize, + Color::toString(primaryColor).toStdString().c_str(), + Color::toString(secondaryColor).toStdString().c_str(), + Color::toString(outlineColor).toStdString().c_str(), + Color::toString(backColor).toStdString().c_str(), PRINT_STYLE_BOOL(bold), + PRINT_STYLE_BOOL(italic), PRINT_STYLE_BOOL(underline), PRINT_STYLE_BOOL(strikeOut), + double(scaleX), double(scaleY), double(spacing), double(angle), double(borderStyle), + double(outline), double(shadow), alignment, marginL, marginR, marginV, encoding); +} +#undef PRINT_STYLE_BOOL diff --git a/src/Lib/Ass/Style.hh b/src/Lib/Ass/Style.hh index 6712368c054861e3f03368a3f27c4002f7166da6..d4b3bfb62c679466988af0831261edd8da927535 100644 --- a/src/Lib/Ass/Style.hh +++ b/src/Lib/Ass/Style.hh @@ -47,5 +47,6 @@ public: QString getElementName() const noexcept; QJsonDocument getProperties() const noexcept; + QString getRawText() const noexcept; }; } diff --git a/src/Lib/Ass/StyleProperties.hh b/src/Lib/Ass/StyleProperties.hh index d01680a297640f9f2bbdbbd42a5884ea59584264..0efc92abddef11e533d97b18790a50866a00e944 100644 --- a/src/Lib/Ass/StyleProperties.hh +++ b/src/Lib/Ass/StyleProperties.hh @@ -8,7 +8,7 @@ namespace Vivy::Ass // Overrides some properties of the Style of an Ass::Line, Ass::Char, Ass::Syl struct StyleProperties final { - QString name{}; + QString name{ "Default" }; // Colors QColor primaryColor{ Color::defaultValue }, secondaryColor{ Color::defaultValue }, diff --git a/src/Lib/Document/CRTPSubDocument.hh b/src/Lib/Document/CRTPSubDocument.hh index a32869f9ecf4daff7b710c399bd120b038c7fa68..96a2607b12abe7a5299250fe90b955aa9ba75629 100644 --- a/src/Lib/Document/CRTPSubDocument.hh +++ b/src/Lib/Document/CRTPSubDocument.hh @@ -140,6 +140,8 @@ public: } catch (const std::runtime_error &e) { ret->logDebug() << "Failed to init ASS subdocument from internal: " << e.what(); ret.reset(); + // FIXME: currently terminate, but should be changed to stop the loading of the document + throw e; } return ret; diff --git a/src/Lib/Document/CRTPSubDocument/AssSubDocument.cc b/src/Lib/Document/CRTPSubDocument/AssSubDocument.cc index a1266bf8ce4ea84107e564bb268d85ab9b106fb8..96366e4a6ac7b2d7b0a4ddea82b3eb9323014f37 100644 --- a/src/Lib/Document/CRTPSubDocument/AssSubDocument.cc +++ b/src/Lib/Document/CRTPSubDocument/AssSubDocument.cc @@ -80,6 +80,10 @@ AssSubDocument::getInternalAss() noexcept { QJsonArray ret; + QStringList info = assFactory->getAssHeaderAsText(); + for (int i = 0; i < info.size(); ++i) + ret.append(info.at(i)); + for (int i = 0; i < lines.size(); i++) { ret.append(lines[i]->getLineAsText()); } diff --git a/src/Lib/Utils.cc b/src/Lib/Utils.cc index 5bfeaab70b7818aa03d88bf61f8e7204c7989e2a..408a13a9d0edb749fffcd470e016b64d27d6a6f0 100644 --- a/src/Lib/Utils.cc +++ b/src/Lib/Utils.cc @@ -146,6 +146,25 @@ Utils::Time::fromString(const QString &str) throw std::runtime_error("The string is not of the format `H:MM:SS.cs`"); } +Utils::Time +Utils::Time::fromUInt(const quint64 &t) +{ + quint64 rem = t; + Time ret; + + ret.hour = rem / (100 * 60 * 60); + rem = rem % (100 * 60 * 60); + + ret.minute = rem / (100 * 60); + rem = rem % (100 * 60); + + ret.second = rem / (100); + + ret.centisecond = rem % 100; + + return ret; +} + quint64 Utils::Time::toUInt() const noexcept { @@ -156,8 +175,10 @@ Utils::Time::toUInt() const noexcept QString Utils::Time::toString() const noexcept { - return QString::number(hour) + ":" + QString::number(minute) + ":" + QString::number(second) + - "." + QString::number(centisecond); + return QString("%1").arg(hour, 2, 10, QChar('0')) + ":" + + QString("%1").arg(minute, 2, 10, QChar('0')) + ":" + + QString("%1").arg(second, 2, 10, QChar('0')) + "." + + QString("%1").arg(centisecond, 2, 10, QChar('0')); } QString diff --git a/src/Lib/Utils.hh b/src/Lib/Utils.hh index 097b16ad332a0335926063f990090d6372ae40ff..d80030d0aae5ea7e1043a540ab64c297de89b429 100644 --- a/src/Lib/Utils.hh +++ b/src/Lib/Utils.hh @@ -217,6 +217,7 @@ struct Time final { quint64 centisecond; static Time fromString(const QString &); + static Time fromUInt(const quint64 &); QString toString() const noexcept; quint64 toUInt() const noexcept;