290 lines
11 KiB
C++
290 lines
11 KiB
C++
#ifndef TAGEDITOR_NO_JSENGINE
|
|
|
|
#include "./tageditorobject.h"
|
|
#include "./filesystemitem.h"
|
|
#include "./jsincludes.h"
|
|
|
|
#include "../misc/utility.h"
|
|
|
|
#include <tagparser/abstracttrack.h>
|
|
#include <tagparser/exceptions.h>
|
|
#include <tagparser/mediafileinfo.h>
|
|
#include <tagparser/progressfeedback.h>
|
|
#include <tagparser/tag.h>
|
|
#include <tagparser/tagvalue.h>
|
|
|
|
#include <qtutilities/misc/conversion.h>
|
|
|
|
#include <c++utilities/conversion/conversionexception.h>
|
|
|
|
#include <QDir>
|
|
|
|
#include <iostream>
|
|
|
|
using namespace std;
|
|
using namespace CppUtilities;
|
|
using namespace QtUtilities;
|
|
using namespace Utility;
|
|
using namespace TagParser;
|
|
using namespace Utility;
|
|
|
|
namespace RenamingUtility {
|
|
|
|
/// \brief Adds notifications from \a statusProvider to \a notificationsObject.
|
|
TAGEDITOR_JS_VALUE &operator<<(TAGEDITOR_JS_VALUE &diagObject, const Diagnostics &diag)
|
|
{
|
|
quint32 counter = 0;
|
|
for (const auto &msg : diag) {
|
|
TAGEDITOR_JS_VALUE val;
|
|
val.setProperty("msg", QString::fromUtf8(msg.message().data()) TAGEDITOR_JS_READONLY);
|
|
val.setProperty("critical", msg.level() >= DiagLevel::Critical TAGEDITOR_JS_READONLY);
|
|
diagObject.setProperty(counter, val);
|
|
++counter;
|
|
}
|
|
return diagObject;
|
|
}
|
|
|
|
/// \brief Add fields and notifications from \a tag to \a tagObject.
|
|
TAGEDITOR_JS_VALUE &operator<<(TAGEDITOR_JS_VALUE &tagObject, const Tag &tag)
|
|
{
|
|
// add text fields
|
|
static const char *const fieldNames[]
|
|
= { "title", "artist", "albumartist", "album", "year", "comment", "genre", "encoder", "language", "description", nullptr };
|
|
static const KnownField fields[] = { KnownField::Title, KnownField::Artist, KnownField::AlbumArtist, KnownField::Album, KnownField::RecordDate,
|
|
KnownField::Comment, KnownField::Genre, KnownField::Encoder, KnownField::Language, KnownField::Description };
|
|
const char *const *fieldName = fieldNames;
|
|
const KnownField *field = fields;
|
|
for (; *fieldName; ++fieldName, ++field) {
|
|
try {
|
|
tagObject.setProperty(*fieldName, tagValueToQString(tag.value(*field)) TAGEDITOR_JS_READONLY);
|
|
} catch (const ConversionException &) {
|
|
}
|
|
}
|
|
|
|
// add numeric fields
|
|
try {
|
|
tagObject.setProperty("partNumber", tag.value(KnownField::PartNumber).toInteger() TAGEDITOR_JS_READONLY);
|
|
} catch (const ConversionException &) {
|
|
}
|
|
try {
|
|
tagObject.setProperty("totalParts", tag.value(KnownField::TotalParts).toInteger() TAGEDITOR_JS_READONLY);
|
|
} catch (const ConversionException &) {
|
|
}
|
|
PositionInSet pos;
|
|
try {
|
|
pos = tag.value(KnownField::TrackPosition).toPositionInSet();
|
|
} catch (const ConversionException &) {
|
|
}
|
|
tagObject.setProperty("trackPos", pos.position() TAGEDITOR_JS_READONLY);
|
|
tagObject.setProperty("trackTotal", pos.total() TAGEDITOR_JS_READONLY);
|
|
pos = PositionInSet();
|
|
try {
|
|
pos = tag.value(KnownField::DiskPosition).toPositionInSet();
|
|
} catch (const ConversionException &) {
|
|
}
|
|
tagObject.setProperty("diskPos", pos.position() TAGEDITOR_JS_READONLY);
|
|
tagObject.setProperty("diskTotal", pos.total() TAGEDITOR_JS_READONLY);
|
|
|
|
return tagObject;
|
|
}
|
|
|
|
TagEditorObject::TagEditorObject(TAGEDITOR_JS_ENGINE *engine)
|
|
: m_engine(engine)
|
|
, m_currentType(ItemType::Dir)
|
|
, m_action(ActionType::None)
|
|
{
|
|
}
|
|
|
|
void TagEditorObject::setFileInfo(const QFileInfo &file, FileSystemItem *item)
|
|
{
|
|
m_currentPath = file.absoluteFilePath();
|
|
m_currentName = file.fileName();
|
|
m_currentRelativeDirectory = item->relativeDir();
|
|
m_currentType = item->type();
|
|
m_action = ActionType::None;
|
|
m_newName.clear();
|
|
m_newRelativeDirectory.clear();
|
|
}
|
|
|
|
const QString &TagEditorObject::currentPath() const
|
|
{
|
|
return m_currentPath;
|
|
}
|
|
|
|
const QString &TagEditorObject::currentName() const
|
|
{
|
|
return m_currentName;
|
|
}
|
|
|
|
const QString &TagEditorObject::currentRelativeDirectory() const
|
|
{
|
|
return m_currentRelativeDirectory;
|
|
}
|
|
|
|
bool TagEditorObject::isDir() const
|
|
{
|
|
return m_currentType == ItemType::Dir;
|
|
}
|
|
|
|
bool TagEditorObject::isFile() const
|
|
{
|
|
return m_currentType == ItemType::File;
|
|
}
|
|
|
|
const QString &TagEditorObject::newName() const
|
|
{
|
|
return m_newName;
|
|
}
|
|
|
|
const QString &TagEditorObject::newRelativeDirectory() const
|
|
{
|
|
return m_newRelativeDirectory;
|
|
}
|
|
|
|
TAGEDITOR_JS_VALUE TagEditorObject::parseFileInfo(const QString &fileName)
|
|
{
|
|
Diagnostics diag;
|
|
AbortableProgressFeedback progress; // FIXME: actually use the progress object
|
|
MediaFileInfo fileInfo(std::string(toNativeFileName(fileName).data()));
|
|
|
|
// add basic file information
|
|
auto fileInfoObject = m_engine->newObject();
|
|
fileInfoObject.setProperty(QStringLiteral("currentPath"), QString::fromUtf8(fileInfo.path().data()));
|
|
fileInfoObject.setProperty(QStringLiteral("currentPathWithoutExtension"), QString::fromUtf8(fileInfo.pathWithoutExtension().data()));
|
|
fileInfoObject.setProperty(QStringLiteral("currentName"), QString::fromUtf8(fileInfo.fileName(false).data()));
|
|
fileInfoObject.setProperty(QStringLiteral("currentBaseName"), QString::fromUtf8(fileInfo.fileName(true).data()));
|
|
QString suffix = fromNativeFileName(fileInfo.extension().data());
|
|
if (suffix.startsWith('.')) {
|
|
suffix.remove(0, 1);
|
|
}
|
|
fileInfoObject.setProperty(QStringLiteral("currentSuffix"), suffix TAGEDITOR_JS_READONLY);
|
|
|
|
// parse further file information
|
|
bool criticalParseingErrorOccured = false, ioErrorOccured = false;
|
|
try {
|
|
fileInfo.parseEverything(diag, progress);
|
|
} catch (const Failure &) {
|
|
// parsing notifications will be addded anyways
|
|
criticalParseingErrorOccured = true;
|
|
} catch (const std::ios_base::failure &) {
|
|
criticalParseingErrorOccured = true;
|
|
ioErrorOccured = true;
|
|
}
|
|
|
|
// add diag messages
|
|
auto diagObj = m_engine->newArray(static_cast<uint>(diag.size()));
|
|
diagObj << diag;
|
|
criticalParseingErrorOccured |= diag.level() >= DiagLevel::Critical;
|
|
fileInfoObject.setProperty(QStringLiteral("hasCriticalMessages"), criticalParseingErrorOccured);
|
|
fileInfoObject.setProperty(QStringLiteral("ioErrorOccured"), ioErrorOccured);
|
|
fileInfoObject.setProperty(QStringLiteral("diagMessages"), diagObj);
|
|
|
|
// add MIME-type, suitable suffix and technical summary
|
|
fileInfoObject.setProperty(QStringLiteral("mimeType"), qstr(fileInfo.mimeType()) TAGEDITOR_JS_READONLY);
|
|
fileInfoObject.setProperty(QStringLiteral("suitableSuffix"), qstr(fileInfo.containerFormatAbbreviation()) TAGEDITOR_JS_READONLY);
|
|
fileInfoObject.setProperty(QStringLiteral("technicalSummary"), qstr(fileInfo.technicalSummary()) TAGEDITOR_JS_READONLY);
|
|
fileInfoObject.setProperty(QStringLiteral("hasAudioTracks"), fileInfo.hasTracksOfType(MediaType::Audio) TAGEDITOR_JS_READONLY);
|
|
fileInfoObject.setProperty(QStringLiteral("hasVideoTracks"), fileInfo.hasTracksOfType(MediaType::Video) TAGEDITOR_JS_READONLY);
|
|
|
|
// add tag information
|
|
const vector<Tag *> tags = fileInfo.tags();
|
|
auto combinedTagObject = m_engine->newObject();
|
|
auto tagsObject = m_engine->newArray(static_cast<uint>(tags.size()));
|
|
std::uint32_t tagIndex = 0;
|
|
for (auto tagIterator = tags.cbegin(), end = tags.cend(); tagIterator != end; ++tagIterator, ++tagIndex) {
|
|
const Tag &tag = **tagIterator;
|
|
auto tagObject = m_engine->newObject();
|
|
combinedTagObject << tag;
|
|
tagObject << tag;
|
|
tagsObject.setProperty(tagIndex, tagObject TAGEDITOR_JS_READONLY);
|
|
}
|
|
fileInfoObject.setProperty(QStringLiteral("tag"), combinedTagObject TAGEDITOR_JS_READONLY);
|
|
fileInfoObject.setProperty(QStringLiteral("tags"), tagsObject TAGEDITOR_JS_READONLY);
|
|
|
|
// add track information
|
|
const vector<AbstractTrack *> tracks = fileInfo.tracks();
|
|
auto tracksObject = m_engine->newArray(static_cast<uint>(tracks.size()));
|
|
std::uint32_t trackIndex = 0;
|
|
for (auto trackIterator = tracks.cbegin(), end = tracks.cend(); trackIterator != end; ++trackIterator, ++trackIndex) {
|
|
const AbstractTrack &track = **trackIterator;
|
|
auto trackObject = m_engine->newObject();
|
|
trackObject.setProperty(QStringLiteral("mediaType"), qstr(track.mediaTypeName()));
|
|
trackObject.setProperty(QStringLiteral("format"), qstr(track.formatName()));
|
|
trackObject.setProperty(QStringLiteral("formatAbbreviation"), qstr(track.formatAbbreviation()));
|
|
trackObject.setProperty(QStringLiteral("version"), QString::number(track.version()));
|
|
trackObject.setProperty(QStringLiteral("language"), QString::fromStdString(track.locale().someAbbreviatedName()));
|
|
trackObject.setProperty(QStringLiteral("description"), QString::fromStdString(track.description()));
|
|
trackObject.setProperty(QStringLiteral("shortDescription"), QString::fromStdString(track.shortDescription()));
|
|
tracksObject.setProperty(trackIndex, trackObject TAGEDITOR_JS_READONLY);
|
|
}
|
|
fileInfoObject.setProperty(QStringLiteral("tracks"), tracksObject TAGEDITOR_JS_READONLY);
|
|
|
|
return fileInfoObject;
|
|
}
|
|
|
|
TAGEDITOR_JS_VALUE TagEditorObject::parseFileName(const QString &fileName)
|
|
{
|
|
QString title;
|
|
int trackNumber = 0;
|
|
Utility::parseFileName(fileName, title, trackNumber);
|
|
auto result = m_engine->newObject();
|
|
result.setProperty(QStringLiteral("title"), TAGEDITOR_JS_VALUE(title) TAGEDITOR_JS_READONLY);
|
|
result.setProperty(QStringLiteral("trackPos"), TAGEDITOR_JS_VALUE(trackNumber) TAGEDITOR_JS_READONLY);
|
|
return result;
|
|
}
|
|
|
|
TAGEDITOR_JS_VALUE TagEditorObject::allFiles(const QString &dirName)
|
|
{
|
|
const QDir dir(dirName);
|
|
if (!dir.exists()) {
|
|
return TAGEDITOR_JS_VALUE();
|
|
}
|
|
const auto files(dir.entryList(QDir::Files));
|
|
auto entriesObj = m_engine->newArray(static_cast<uint>(files.size()));
|
|
quint32 counter = 0;
|
|
for (const auto &file : files) {
|
|
entriesObj.setProperty(counter++, file TAGEDITOR_JS_READONLY);
|
|
}
|
|
return entriesObj;
|
|
}
|
|
|
|
TAGEDITOR_JS_VALUE TagEditorObject::firstFile(const QString &dirName)
|
|
{
|
|
const QDir dir(dirName);
|
|
if (!dir.exists()) {
|
|
return TAGEDITOR_JS_VALUE();
|
|
}
|
|
const auto files(dir.entryList(QDir::Files));
|
|
if (files.empty()) {
|
|
return TAGEDITOR_JS_VALUE();
|
|
}
|
|
return TAGEDITOR_JS_VALUE(files.first());
|
|
}
|
|
|
|
void TagEditorObject::writeLog(const QString &message)
|
|
{
|
|
cout << message.toStdString() << endl;
|
|
}
|
|
|
|
void TagEditorObject::rename(const QString &newName)
|
|
{
|
|
m_newName = newName;
|
|
m_action = ActionType::Rename;
|
|
}
|
|
|
|
void TagEditorObject::move(const QString &newRelativeDirectory)
|
|
{
|
|
m_newRelativeDirectory = newRelativeDirectory;
|
|
m_action = ActionType::Rename;
|
|
}
|
|
|
|
void TagEditorObject::skip(const QString ¬e)
|
|
{
|
|
m_action = ActionType::Skip;
|
|
m_note = note;
|
|
}
|
|
|
|
} // namespace RenamingUtility
|
|
|
|
#endif
|