improved parsing status
This commit is contained in:
parent
ed10015b1a
commit
ecacccd3c6
|
@ -66,12 +66,14 @@ namespace Media {
|
||||||
* \brief Constructs a new MediaFileInfo.
|
* \brief Constructs a new MediaFileInfo.
|
||||||
*/
|
*/
|
||||||
MediaFileInfo::MediaFileInfo() :
|
MediaFileInfo::MediaFileInfo() :
|
||||||
m_containerParsed(false),
|
m_containerParsingStatus(ParsingStatus::NotParsedYet),
|
||||||
m_containerFormat(ContainerFormat::Unknown),
|
m_containerFormat(ContainerFormat::Unknown),
|
||||||
m_containerOffset(0),
|
m_containerOffset(0),
|
||||||
m_actualExistingId3v1Tag(false),
|
m_actualExistingId3v1Tag(false),
|
||||||
m_tracksParsed(false),
|
m_tracksParsingStatus(ParsingStatus::NotParsedYet),
|
||||||
m_tagParsed(false),
|
m_tagsParsingStatus(ParsingStatus::NotParsedYet),
|
||||||
|
m_chaptersParsingStatus(ParsingStatus::NotParsedYet),
|
||||||
|
m_attachmentsParsingStatus(ParsingStatus::NotParsedYet),
|
||||||
m_forceFullParse(MEDIAINFO_CPP_FORCE_FULL_PARSE)
|
m_forceFullParse(MEDIAINFO_CPP_FORCE_FULL_PARSE)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -82,12 +84,14 @@ MediaFileInfo::MediaFileInfo() :
|
||||||
*/
|
*/
|
||||||
MediaFileInfo::MediaFileInfo(const string &path) :
|
MediaFileInfo::MediaFileInfo(const string &path) :
|
||||||
BasicFileInfo(path),
|
BasicFileInfo(path),
|
||||||
m_containerParsed(false),
|
m_containerParsingStatus(ParsingStatus::NotParsedYet),
|
||||||
m_containerFormat(ContainerFormat::Unknown),
|
m_containerFormat(ContainerFormat::Unknown),
|
||||||
m_containerOffset(0),
|
m_containerOffset(0),
|
||||||
m_actualExistingId3v1Tag(false),
|
m_actualExistingId3v1Tag(false),
|
||||||
m_tracksParsed(false),
|
m_tracksParsingStatus(ParsingStatus::NotParsedYet),
|
||||||
m_tagParsed(false),
|
m_tagsParsingStatus(ParsingStatus::NotParsedYet),
|
||||||
|
m_chaptersParsingStatus(ParsingStatus::NotParsedYet),
|
||||||
|
m_attachmentsParsingStatus(ParsingStatus::NotParsedYet),
|
||||||
m_forceFullParse(MEDIAINFO_CPP_FORCE_FULL_PARSE)
|
m_forceFullParse(MEDIAINFO_CPP_FORCE_FULL_PARSE)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -120,7 +124,7 @@ MediaFileInfo::~MediaFileInfo()
|
||||||
*/
|
*/
|
||||||
void MediaFileInfo::parseContainerFormat()
|
void MediaFileInfo::parseContainerFormat()
|
||||||
{
|
{
|
||||||
if(isContainerParsed()) {
|
if(containerParsingStatus() != ParsingStatus::NotParsedYet) {
|
||||||
// there's no need to read the container format twice
|
// there's no need to read the container format twice
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -145,7 +149,7 @@ startParsingSignature:
|
||||||
m_containerOffset += bytesSkipped;
|
m_containerOffset += bytesSkipped;
|
||||||
// give up after 0x100 bytes
|
// give up after 0x100 bytes
|
||||||
if((m_paddingSize += bytesSkipped) >= 0x100u) {
|
if((m_paddingSize += bytesSkipped) >= 0x100u) {
|
||||||
m_containerParsed = true;
|
m_containerParsingStatus = ParsingStatus::NotSupported;
|
||||||
m_containerFormat = ContainerFormat::Unknown;
|
m_containerFormat = ContainerFormat::Unknown;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -172,7 +176,7 @@ startParsingSignature:
|
||||||
try {
|
try {
|
||||||
static_cast<Mp4Container *>(m_container.get())->validateElementStructure(notifications, &m_paddingSize);
|
static_cast<Mp4Container *>(m_container.get())->validateElementStructure(notifications, &m_paddingSize);
|
||||||
} catch (Failure &) {
|
} catch (Failure &) {
|
||||||
// nothing to do here, notifications will be added
|
m_containerParsingStatus = ParsingStatus::CriticalFailure;
|
||||||
}
|
}
|
||||||
addNotifications(notifications);
|
addNotifications(notifications);
|
||||||
break;
|
break;
|
||||||
|
@ -193,7 +197,7 @@ startParsingSignature:
|
||||||
container->validateIndex();
|
container->validateIndex();
|
||||||
}
|
}
|
||||||
} catch(Failure &) {
|
} catch(Failure &) {
|
||||||
// nothing to do, notificatons will be added
|
m_containerParsingStatus = ParsingStatus::CriticalFailure;
|
||||||
}
|
}
|
||||||
m_container = move(container);
|
m_container = move(container);
|
||||||
addNotifications(notifications);
|
addNotifications(notifications);
|
||||||
|
@ -206,7 +210,13 @@ startParsingSignature:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_containerParsed = true;
|
if(m_containerParsingStatus == ParsingStatus::NotParsedYet) {
|
||||||
|
if(m_containerFormat == ContainerFormat::Unknown) {
|
||||||
|
m_containerParsingStatus = ParsingStatus::NotSupported;
|
||||||
|
} else {
|
||||||
|
m_containerParsingStatus = ParsingStatus::Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -231,7 +241,7 @@ startParsingSignature:
|
||||||
*/
|
*/
|
||||||
void MediaFileInfo::parseTracks()
|
void MediaFileInfo::parseTracks()
|
||||||
{
|
{
|
||||||
if(areTracksParsed()) { // there's no need to read the file segment twice
|
if(tracksParsingStatus() != ParsingStatus::NotParsedYet) { // there's no need to read the tracks twice
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
parseContainerFormat(); // ensure the container format has been load yet
|
parseContainerFormat(); // ensure the container format has been load yet
|
||||||
|
@ -255,12 +265,14 @@ void MediaFileInfo::parseTracks()
|
||||||
}
|
}
|
||||||
m_singleTrack->parseHeader();
|
m_singleTrack->parseHeader();
|
||||||
}
|
}
|
||||||
|
m_tracksParsingStatus = ParsingStatus::Ok;
|
||||||
} catch (NotImplementedException &) {
|
} catch (NotImplementedException &) {
|
||||||
addNotification(NotificationType::Information, "Parsing tracks is not implemented for the container format of the file.", context);
|
addNotification(NotificationType::Information, "Parsing tracks is not implemented for the container format of the file.", context);
|
||||||
|
m_tracksParsingStatus = ParsingStatus::NotSupported;
|
||||||
} catch (Failure &) {
|
} catch (Failure &) {
|
||||||
addNotification(NotificationType::Critical, "Unable to parse tracks.", context);
|
addNotification(NotificationType::Critical, "Unable to parse tracks.", context);
|
||||||
|
m_tracksParsingStatus = ParsingStatus::CriticalFailure;
|
||||||
}
|
}
|
||||||
m_tracksParsed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -286,7 +298,7 @@ void MediaFileInfo::parseTracks()
|
||||||
*/
|
*/
|
||||||
void MediaFileInfo::parseTags()
|
void MediaFileInfo::parseTags()
|
||||||
{
|
{
|
||||||
if(areTagsParsed()) {
|
if(tagsParsingStatus() != ParsingStatus::NotParsedYet) { // there's no need to read the tags twice
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
parseContainerFormat(); // ensure the container format has been load yet
|
parseContainerFormat(); // ensure the container format has been load yet
|
||||||
|
@ -300,13 +312,14 @@ void MediaFileInfo::parseTags()
|
||||||
} catch(NoDataFoundException &) {
|
} catch(NoDataFoundException &) {
|
||||||
m_id3v1Tag.reset(); // no ID3v1 tag found
|
m_id3v1Tag.reset(); // no ID3v1 tag found
|
||||||
} catch(Failure &) {
|
} catch(Failure &) {
|
||||||
|
m_tagsParsingStatus = ParsingStatus::CriticalFailure;
|
||||||
addNotification(NotificationType::Critical, "Unable to parse ID3v1 tag.", context);
|
addNotification(NotificationType::Critical, "Unable to parse ID3v1 tag.", context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// the offsets of the ID3v2 tags have already been parsed when parsing the container format
|
// the offsets of the ID3v2 tags have already been parsed when parsing the container format
|
||||||
m_id3v2Tags.clear();
|
m_id3v2Tags.clear();
|
||||||
for(streamoff offset : m_actualId3v2TagOffsets) {
|
for(const auto offset : m_actualId3v2TagOffsets) {
|
||||||
unique_ptr<Id3v2Tag> id3v2Tag = make_unique<Id3v2Tag>();
|
auto id3v2Tag = make_unique<Id3v2Tag>();
|
||||||
stream().seekg(offset, ios_base::beg);
|
stream().seekg(offset, ios_base::beg);
|
||||||
try {
|
try {
|
||||||
id3v2Tag->parse(stream());
|
id3v2Tag->parse(stream());
|
||||||
|
@ -314,6 +327,7 @@ void MediaFileInfo::parseTags()
|
||||||
} catch(NoDataFoundException &) {
|
} catch(NoDataFoundException &) {
|
||||||
continue;
|
continue;
|
||||||
} catch(Failure &) {
|
} catch(Failure &) {
|
||||||
|
m_tagsParsingStatus = ParsingStatus::CriticalFailure;
|
||||||
addNotification(NotificationType::Critical, "Unable to parse ID3v2 tag.", context);
|
addNotification(NotificationType::Critical, "Unable to parse ID3v2 tag.", context);
|
||||||
}
|
}
|
||||||
m_id3v2Tags.emplace_back(id3v2Tag.release());
|
m_id3v2Tags.emplace_back(id3v2Tag.release());
|
||||||
|
@ -322,12 +336,20 @@ void MediaFileInfo::parseTags()
|
||||||
try {
|
try {
|
||||||
m_container->parseTags();
|
m_container->parseTags();
|
||||||
} catch (NotImplementedException &) {
|
} catch (NotImplementedException &) {
|
||||||
|
if(m_tagsParsingStatus == ParsingStatus::NotParsedYet) {
|
||||||
|
// do not override parsing status from ID3 tags here
|
||||||
|
m_tagsParsingStatus = ParsingStatus::NotSupported;
|
||||||
|
}
|
||||||
addNotification(NotificationType::Information, "Parsing tags is not implemented for the container format of the file.", context);
|
addNotification(NotificationType::Information, "Parsing tags is not implemented for the container format of the file.", context);
|
||||||
} catch (Failure &) {
|
} catch (Failure &) {
|
||||||
|
m_tagsParsingStatus = ParsingStatus::CriticalFailure;
|
||||||
addNotification(NotificationType::Critical, "Unable to parse tag.", context);
|
addNotification(NotificationType::Critical, "Unable to parse tag.", context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_tagParsed = true;
|
if(m_tagsParsingStatus == ParsingStatus::NotParsedYet) {
|
||||||
|
// do not override error status here
|
||||||
|
m_tagsParsingStatus = ParsingStatus::Ok;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -349,32 +371,44 @@ void MediaFileInfo::parseTags()
|
||||||
*/
|
*/
|
||||||
void MediaFileInfo::parseChapters()
|
void MediaFileInfo::parseChapters()
|
||||||
{
|
{
|
||||||
|
if(chaptersParsingStatus() != ParsingStatus::NotParsedYet) { // there's no need to read the chapters twice
|
||||||
|
return;
|
||||||
|
}
|
||||||
static const string context("parsing chapters");
|
static const string context("parsing chapters");
|
||||||
try {
|
try {
|
||||||
if(m_container) {
|
if(m_container) {
|
||||||
m_container->parseChapters();
|
m_container->parseChapters();
|
||||||
|
m_chaptersParsingStatus = ParsingStatus::Ok;
|
||||||
} else {
|
} else {
|
||||||
throw NotImplementedException();
|
throw NotImplementedException();
|
||||||
}
|
}
|
||||||
} catch (NotImplementedException &) {
|
} catch (NotImplementedException &) {
|
||||||
|
m_chaptersParsingStatus = ParsingStatus::NotSupported;
|
||||||
addNotification(NotificationType::Information, "Parsing chapters is not implemented for the container format of the file.", context);
|
addNotification(NotificationType::Information, "Parsing chapters is not implemented for the container format of the file.", context);
|
||||||
} catch (Failure &) {
|
} catch (Failure &) {
|
||||||
|
m_chaptersParsingStatus = ParsingStatus::CriticalFailure;
|
||||||
addNotification(NotificationType::Critical, "Unable to parse chapters.", context);
|
addNotification(NotificationType::Critical, "Unable to parse chapters.", context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaFileInfo::parseAttachments()
|
void MediaFileInfo::parseAttachments()
|
||||||
{
|
{
|
||||||
|
if(attachmentsParsingStatus() != ParsingStatus::NotParsedYet) { // there's no need to read the attachments twice
|
||||||
|
return;
|
||||||
|
}
|
||||||
static const string context("parsing attachments");
|
static const string context("parsing attachments");
|
||||||
try {
|
try {
|
||||||
if(m_container) {
|
if(m_container) {
|
||||||
m_container->parseAttachments();
|
m_container->parseAttachments();
|
||||||
|
m_attachmentsParsingStatus = ParsingStatus::Ok;
|
||||||
} else {
|
} else {
|
||||||
throw NotImplementedException();
|
throw NotImplementedException();
|
||||||
}
|
}
|
||||||
} catch (NotImplementedException &) {
|
} catch (NotImplementedException &) {
|
||||||
|
m_attachmentsParsingStatus = ParsingStatus::NotSupported;
|
||||||
addNotification(NotificationType::Information, "Parsing attachments is not implemented for the container format of the file.", context);
|
addNotification(NotificationType::Information, "Parsing attachments is not implemented for the container format of the file.", context);
|
||||||
} catch (Failure &) {
|
} catch (Failure &) {
|
||||||
|
m_attachmentsParsingStatus = ParsingStatus::CriticalFailure;
|
||||||
addNotification(NotificationType::Critical, "Unable to parse attachments.", context);
|
addNotification(NotificationType::Critical, "Unable to parse attachments.", context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -490,17 +524,51 @@ bool MediaFileInfo::createAppropriateTags(bool treatUnknownFilesAsMp3Files, TagU
|
||||||
* \throws Throws Media::Failure or a derived exception when a making
|
* \throws Throws Media::Failure or a derived exception when a making
|
||||||
* error occurs.
|
* error occurs.
|
||||||
*
|
*
|
||||||
* \remarks The method parseTag() needs to be called before this method can be called.
|
* \remarks Tags and tracks need to be parsed without errors before this method can be called.
|
||||||
|
* All previous parsing results are cleared (using clearParsingResults()). Hence
|
||||||
|
* the file must be reparsed. All related objects (tags, tracks, ...) might get invalidated.
|
||||||
|
* This includes notifications of these objects as well.
|
||||||
*
|
*
|
||||||
* \sa isTagParsed()
|
* \sa clearParsingResults()
|
||||||
* \sa parseTag()
|
|
||||||
*/
|
*/
|
||||||
void MediaFileInfo::applyChanges()
|
void MediaFileInfo::applyChanges()
|
||||||
{
|
{
|
||||||
const string context("making file");
|
const string context("making file");
|
||||||
addNotification(NotificationType::Information, "Changes are about to be applied.", context);
|
addNotification(NotificationType::Information, "Changes are about to be applied.", context);
|
||||||
if(!areTagsParsed() && !areTracksParsed()) {
|
bool previousParsingSucessful = true;
|
||||||
addNotification(NotificationType::Critical, "Tags and tracks have to be parsed before changes can be applied.", context);
|
switch(tagsParsingStatus()) {
|
||||||
|
case ParsingStatus::Ok:
|
||||||
|
case ParsingStatus::NotSupported:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
previousParsingSucessful = false;
|
||||||
|
addNotification(NotificationType::Critical, "Tags have to be parsed without critical errors before changes can be applied.", context);
|
||||||
|
}
|
||||||
|
switch(tracksParsingStatus()) {
|
||||||
|
case ParsingStatus::Ok:
|
||||||
|
case ParsingStatus::NotSupported:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
previousParsingSucessful = false;
|
||||||
|
addNotification(NotificationType::Critical, "Tracks have to be parsed without critical errors before changes can be applied.", context);
|
||||||
|
}
|
||||||
|
// switch(chaptersParsingStatus()) {
|
||||||
|
// case ParsingStatus::Ok:
|
||||||
|
// case ParsingStatus::NotSupported:
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// previousParsingSucessful = false;
|
||||||
|
// addNotification(NotificationType::Critical, "Chapters have to be parsed without critical errors before changes can be applied.", context);
|
||||||
|
// }
|
||||||
|
// switch(attachmentsParsingStatus()) {
|
||||||
|
// case ParsingStatus::Ok:
|
||||||
|
// case ParsingStatus::NotSupported:
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// previousParsingSucessful = false;
|
||||||
|
// addNotification(NotificationType::Critical, "Attachments have to be parsed without critical errors before changes can be applied.", context);
|
||||||
|
// }
|
||||||
|
if(!previousParsingSucessful) {
|
||||||
throw InvalidDataException();
|
throw InvalidDataException();
|
||||||
}
|
}
|
||||||
if(m_container) { // container object takes care
|
if(m_container) { // container object takes care
|
||||||
|
@ -512,13 +580,24 @@ void MediaFileInfo::applyChanges()
|
||||||
addNotification(NotificationType::Warning, "Assigned ID3v2 tag can't be attached and will be ignored.", context);
|
addNotification(NotificationType::Warning, "Assigned ID3v2 tag can't be attached and will be ignored.", context);
|
||||||
}
|
}
|
||||||
m_container->forwardStatusUpdateCalls(this);
|
m_container->forwardStatusUpdateCalls(this);
|
||||||
m_container->makeFile();
|
m_tracksParsingStatus = ParsingStatus::NotParsedYet;
|
||||||
m_tracksParsed &= m_container->areTracksParsed();
|
m_tagsParsingStatus = ParsingStatus::NotParsedYet;
|
||||||
m_tagParsed &= m_container->areTagsParsed();
|
try {
|
||||||
|
m_container->makeFile();
|
||||||
|
} catch(...) {
|
||||||
|
clearParsingResults();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
} else { // implementation if no container object is present
|
} else { // implementation if no container object is present
|
||||||
// assume the file is a MP3 file
|
// assume the file is a MP3 file
|
||||||
makeMp3File();
|
try {
|
||||||
|
makeMp3File();
|
||||||
|
} catch(...) {
|
||||||
|
clearParsingResults();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
clearParsingResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -652,18 +731,16 @@ vector<AbstractTrack *> MediaFileInfo::tracks() const
|
||||||
*/
|
*/
|
||||||
bool MediaFileInfo::hasTracksOfType(MediaType type) const
|
bool MediaFileInfo::hasTracksOfType(MediaType type) const
|
||||||
{
|
{
|
||||||
if(!areTracksParsed()) {
|
if(tracksParsingStatus() != ParsingStatus::NotParsedYet) {
|
||||||
return false;
|
if(m_singleTrack && m_singleTrack->mediaType() == type) {
|
||||||
}
|
return true;
|
||||||
if(type == MediaType::Audio && m_singleTrack) {
|
} else if(m_container) {
|
||||||
return true;
|
for(size_t i = 0, count = m_container->trackCount(); i < count; ++i) {
|
||||||
} else if(m_container) {
|
if(m_container->track(i)->mediaType() == type) {
|
||||||
for(size_t i = 0, count = m_container->trackCount(); i < count; ++i) {
|
return true;
|
||||||
if(m_container->track(i)->mediaType() == type) {
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -703,12 +780,11 @@ ChronoUtilities::TimeSpan MediaFileInfo::duration() const
|
||||||
*/
|
*/
|
||||||
bool MediaFileInfo::removeId3v1Tag()
|
bool MediaFileInfo::removeId3v1Tag()
|
||||||
{
|
{
|
||||||
if(!areTagsParsed()) {
|
if(tagsParsingStatus() != ParsingStatus::NotParsedYet) {
|
||||||
return false;
|
if(m_id3v1Tag) {
|
||||||
}
|
m_id3v1Tag.reset();
|
||||||
if(m_id3v1Tag) {
|
return true;
|
||||||
m_id3v1Tag.reset();
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -730,7 +806,7 @@ bool MediaFileInfo::removeId3v1Tag()
|
||||||
*/
|
*/
|
||||||
Id3v1Tag *MediaFileInfo::createId3v1Tag()
|
Id3v1Tag *MediaFileInfo::createId3v1Tag()
|
||||||
{
|
{
|
||||||
if(!areTagsParsed()) {
|
if(tagsParsingStatus() == ParsingStatus::NotParsedYet) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if(!m_id3v1Tag) {
|
if(!m_id3v1Tag) {
|
||||||
|
@ -754,13 +830,12 @@ Id3v1Tag *MediaFileInfo::createId3v1Tag()
|
||||||
*/
|
*/
|
||||||
bool MediaFileInfo::removeId3v2Tag(Id3v2Tag *tag)
|
bool MediaFileInfo::removeId3v2Tag(Id3v2Tag *tag)
|
||||||
{
|
{
|
||||||
if(!areTagsParsed()) {
|
if(tagsParsingStatus() != ParsingStatus::NotParsedYet) {
|
||||||
return false;
|
for(auto i = m_id3v2Tags.begin(), end = m_id3v2Tags.end(); i != end; ++i) {
|
||||||
}
|
if(i->get() == tag) {
|
||||||
for(auto i = m_id3v2Tags.begin(), end = m_id3v2Tags.end(); i != end; ++i) {
|
m_id3v2Tags.erase(i);
|
||||||
if(i->get() == tag) {
|
return true;
|
||||||
m_id3v2Tags.erase(i);
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -777,7 +852,7 @@ bool MediaFileInfo::removeId3v2Tag(Id3v2Tag *tag)
|
||||||
*/
|
*/
|
||||||
bool MediaFileInfo::removeAllId3v2Tags()
|
bool MediaFileInfo::removeAllId3v2Tags()
|
||||||
{
|
{
|
||||||
if(!areTagsParsed() || m_id3v2Tags.size() == 0) {
|
if(tagsParsingStatus() == ParsingStatus::NotParsedYet || m_id3v2Tags.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_id3v2Tags.clear();
|
m_id3v2Tags.clear();
|
||||||
|
@ -1065,12 +1140,14 @@ NotificationType MediaFileInfo::worstNotificationTypeIncludingRelatedObjects() c
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns the noficications of the current instance and all related
|
* \brief Returns the notifications of the current instance and all related
|
||||||
* objects (tracks, tags, container).
|
* objects (tracks, tags, container, ...).
|
||||||
|
*
|
||||||
|
* \remarks The specified list is not cleared before notifications are added.
|
||||||
*/
|
*/
|
||||||
NotificationList MediaFileInfo::gatherRelatedNotifications() const
|
void MediaFileInfo::gatherRelatedNotifications(NotificationList ¬ifications) const
|
||||||
{
|
{
|
||||||
NotificationList notifications(this->notifications());
|
notifications.insert(notifications.end(), this->notifications().cbegin(), this->notifications().cend());
|
||||||
if(m_container) {
|
if(m_container) {
|
||||||
notifications.insert(notifications.end(), m_container->notifications().cbegin(), m_container->notifications().cend());
|
notifications.insert(notifications.end(), m_container->notifications().cbegin(), m_container->notifications().cend());
|
||||||
}
|
}
|
||||||
|
@ -1083,6 +1160,19 @@ NotificationList MediaFileInfo::gatherRelatedNotifications() const
|
||||||
for(const auto *chapter : chapters()) {
|
for(const auto *chapter : chapters()) {
|
||||||
notifications.insert(notifications.end(), chapter->notifications().cbegin(), chapter->notifications().cend());
|
notifications.insert(notifications.end(), chapter->notifications().cbegin(), chapter->notifications().cend());
|
||||||
}
|
}
|
||||||
|
for(const auto *attachment : attachments()) {
|
||||||
|
notifications.insert(notifications.end(), attachment->notifications().cbegin(), attachment->notifications().cend());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the notifications of the current instance and all related
|
||||||
|
* objects (tracks, tags, container, ...).
|
||||||
|
*/
|
||||||
|
NotificationList MediaFileInfo::gatherRelatedNotifications() const
|
||||||
|
{
|
||||||
|
NotificationList notifications;
|
||||||
|
gatherRelatedNotifications(notifications);
|
||||||
return notifications;
|
return notifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,15 +1182,19 @@ NotificationList MediaFileInfo::gatherRelatedNotifications() const
|
||||||
*
|
*
|
||||||
* This allows a rescan of the file using parsing methods like parseContainerFormat().
|
* This allows a rescan of the file using parsing methods like parseContainerFormat().
|
||||||
* (These methods do nothing if the information to be parsed has already been gathered.)
|
* (These methods do nothing if the information to be parsed has already been gathered.)
|
||||||
|
*
|
||||||
|
* \remarks Any pointers previously returned by tags(), tracks(), ... object are invalidated.
|
||||||
*/
|
*/
|
||||||
void MediaFileInfo::clearParsingResults()
|
void MediaFileInfo::clearParsingResults()
|
||||||
{
|
{
|
||||||
m_containerParsed = false;
|
m_containerParsingStatus = ParsingStatus::NotParsedYet;
|
||||||
m_containerFormat = ContainerFormat::Unknown;
|
m_containerFormat = ContainerFormat::Unknown;
|
||||||
m_containerOffset = 0;
|
m_containerOffset = 0;
|
||||||
m_paddingSize = 0;
|
m_paddingSize = 0;
|
||||||
m_tracksParsed = false;
|
m_tracksParsingStatus = ParsingStatus::NotParsedYet;
|
||||||
m_tagParsed = false;
|
m_tagsParsingStatus = ParsingStatus::NotParsedYet;
|
||||||
|
m_chaptersParsingStatus = ParsingStatus::NotParsedYet;
|
||||||
|
m_attachmentsParsingStatus = ParsingStatus::NotParsedYet;
|
||||||
m_id3v1Tag.reset();
|
m_id3v1Tag.reset();
|
||||||
m_id3v2Tags.clear();
|
m_id3v2Tags.clear();
|
||||||
m_actualId3v2TagOffsets.clear();
|
m_actualId3v2TagOffsets.clear();
|
||||||
|
|
|
@ -31,7 +31,7 @@ enum class MediaType;
|
||||||
enum class TagType : unsigned int;
|
enum class TagType : unsigned int;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Specifies the usage of a certain tag type.
|
* \brief The TagUsage enum specifies the usage of a certain tag type.
|
||||||
*/
|
*/
|
||||||
enum class TagUsage
|
enum class TagUsage
|
||||||
{
|
{
|
||||||
|
@ -40,6 +40,18 @@ enum class TagUsage
|
||||||
Never /**< tags of the type are never used; a possibly existing tag of the type is removed */
|
Never /**< tags of the type are never used; a possibly existing tag of the type is removed */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The ParsingStatus enum specifies whether a certain part of the file (tracks, tags, ...) has
|
||||||
|
* been parsed yet and if what the parsing result is.
|
||||||
|
*/
|
||||||
|
enum class ParsingStatus : byte
|
||||||
|
{
|
||||||
|
NotParsedYet, /**< the part has not been parsed yet */
|
||||||
|
Ok, /**< the part has been parsed and no critical errors occured */
|
||||||
|
NotSupported, /**< tried to parse the part, but the format is not supported */
|
||||||
|
CriticalFailure /**< tried to parse the part, but critical errors occured */
|
||||||
|
};
|
||||||
|
|
||||||
class LIB_EXPORT MediaFileInfo : public BasicFileInfo, public StatusProvider
|
class LIB_EXPORT MediaFileInfo : public BasicFileInfo, public StatusProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -71,24 +83,24 @@ public:
|
||||||
uint64 containerOffset() const;
|
uint64 containerOffset() const;
|
||||||
uint64 paddingSize() const;
|
uint64 paddingSize() const;
|
||||||
AbstractContainer *container() const;
|
AbstractContainer *container() const;
|
||||||
bool isContainerParsed() const;
|
ParsingStatus containerParsingStatus() const;
|
||||||
// ... the capters
|
// ... the capters
|
||||||
bool areChaptersParsed() const;
|
ParsingStatus chaptersParsingStatus() const;
|
||||||
std::vector<AbstractChapter *> chapters() const;
|
std::vector<AbstractChapter *> chapters() const;
|
||||||
bool areChaptersSupported() const;
|
bool areChaptersSupported() const;
|
||||||
// ... the attachments
|
// ... the attachments
|
||||||
bool areAttachmentsParsed() const;
|
ParsingStatus attachmentsParsingStatus() const;
|
||||||
std::vector<AbstractAttachment *> attachments() const;
|
std::vector<AbstractAttachment *> attachments() const;
|
||||||
bool areAttachmentsSupported() const;
|
bool areAttachmentsSupported() const;
|
||||||
// ... the tracks
|
// ... the tracks
|
||||||
bool areTracksParsed() const;
|
ParsingStatus tracksParsingStatus() const;
|
||||||
std::size_t trackCount() const;
|
std::size_t trackCount() const;
|
||||||
std::vector<AbstractTrack *> tracks() const;
|
std::vector<AbstractTrack *> tracks() const;
|
||||||
bool hasTracksOfType(Media::MediaType type) const;
|
bool hasTracksOfType(Media::MediaType type) const;
|
||||||
ChronoUtilities::TimeSpan duration() const;
|
ChronoUtilities::TimeSpan duration() const;
|
||||||
bool areTracksSupported() const;
|
bool areTracksSupported() const;
|
||||||
// ... the tags
|
// ... the tags
|
||||||
bool areTagsParsed() const;
|
ParsingStatus tagsParsingStatus() const;
|
||||||
bool hasId3v1Tag() const;
|
bool hasId3v1Tag() const;
|
||||||
bool hasId3v2Tag() const;
|
bool hasId3v2Tag() const;
|
||||||
bool hasAnyTag() const;
|
bool hasAnyTag() const;
|
||||||
|
@ -116,6 +128,7 @@ public:
|
||||||
// methods to get/wipe notifications
|
// methods to get/wipe notifications
|
||||||
bool haveRelatedObjectsNotifications() const;
|
bool haveRelatedObjectsNotifications() const;
|
||||||
NotificationType worstNotificationTypeIncludingRelatedObjects() const;
|
NotificationType worstNotificationTypeIncludingRelatedObjects() const;
|
||||||
|
void gatherRelatedNotifications(NotificationList ¬ifications) const;
|
||||||
NotificationList gatherRelatedNotifications() const;
|
NotificationList gatherRelatedNotifications() const;
|
||||||
void clearParsingResults();
|
void clearParsingResults();
|
||||||
|
|
||||||
|
@ -132,7 +145,7 @@ private:
|
||||||
// other formats are outsourced to container classes
|
// other formats are outsourced to container classes
|
||||||
void makeMp3File();
|
void makeMp3File();
|
||||||
// fields related to the container
|
// fields related to the container
|
||||||
bool m_containerParsed;
|
ParsingStatus m_containerParsingStatus;
|
||||||
ContainerFormat m_containerFormat;
|
ContainerFormat m_containerFormat;
|
||||||
std::streamoff m_containerOffset;
|
std::streamoff m_containerOffset;
|
||||||
uint64 m_paddingSize;
|
uint64 m_paddingSize;
|
||||||
|
@ -140,12 +153,15 @@ private:
|
||||||
std::list<std::streamoff> m_actualId3v2TagOffsets;
|
std::list<std::streamoff> m_actualId3v2TagOffsets;
|
||||||
std::unique_ptr<AbstractContainer> m_container;
|
std::unique_ptr<AbstractContainer> m_container;
|
||||||
// fields related to the tracks
|
// fields related to the tracks
|
||||||
bool m_tracksParsed;
|
ParsingStatus m_tracksParsingStatus;
|
||||||
std::unique_ptr<AbstractTrack> m_singleTrack;
|
std::unique_ptr<AbstractTrack> m_singleTrack;
|
||||||
// fields related to the tag
|
// fields related to the tag
|
||||||
bool m_tagParsed;
|
ParsingStatus m_tagsParsingStatus;
|
||||||
std::unique_ptr<Id3v1Tag> m_id3v1Tag;
|
std::unique_ptr<Id3v1Tag> m_id3v1Tag;
|
||||||
std::vector<std::unique_ptr<Id3v2Tag> > m_id3v2Tags;
|
std::vector<std::unique_ptr<Id3v2Tag> > m_id3v2Tags;
|
||||||
|
// fields related to the chapters and the attachments
|
||||||
|
ParsingStatus m_chaptersParsingStatus;
|
||||||
|
ParsingStatus m_attachmentsParsingStatus;
|
||||||
// fields specifying object behaviour
|
// fields specifying object behaviour
|
||||||
bool m_forceFullParse;
|
bool m_forceFullParse;
|
||||||
};
|
};
|
||||||
|
@ -153,9 +169,9 @@ private:
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns an indication whether the container format has been parsed yet.
|
* \brief Returns an indication whether the container format has been parsed yet.
|
||||||
*/
|
*/
|
||||||
inline bool MediaFileInfo::isContainerParsed() const
|
inline ParsingStatus MediaFileInfo::containerParsingStatus() const
|
||||||
{
|
{
|
||||||
return m_containerParsed;
|
return m_containerParsingStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -218,17 +234,17 @@ inline uint64 MediaFileInfo::paddingSize() const
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns an indication whether tag information has been parsed yet.
|
* \brief Returns an indication whether tag information has been parsed yet.
|
||||||
*/
|
*/
|
||||||
inline bool MediaFileInfo::areTagsParsed() const
|
inline ParsingStatus MediaFileInfo::tagsParsingStatus() const
|
||||||
{
|
{
|
||||||
return m_tagParsed;
|
return m_tagsParsingStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns an indication whether tracks have been parsed yet.
|
* \brief Returns an indication whether tracks have been parsed yet.
|
||||||
*/
|
*/
|
||||||
inline bool MediaFileInfo::areTracksParsed() const
|
inline ParsingStatus MediaFileInfo::tracksParsingStatus() const
|
||||||
{
|
{
|
||||||
return m_tracksParsed;
|
return m_tracksParsingStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -247,17 +263,17 @@ inline size_t MediaFileInfo::trackCount() const
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns whether the chapters have been parsed yet.
|
* \brief Returns whether the chapters have been parsed yet.
|
||||||
*/
|
*/
|
||||||
inline bool MediaFileInfo::areChaptersParsed() const
|
inline ParsingStatus MediaFileInfo::chaptersParsingStatus() const
|
||||||
{
|
{
|
||||||
return m_container && m_container->areChaptersParsed();
|
return m_chaptersParsingStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns whether the attachments have been parsed yet.
|
* \brief Returns whether the attachments have been parsed yet.
|
||||||
*/
|
*/
|
||||||
inline bool MediaFileInfo::areAttachmentsParsed() const
|
inline ParsingStatus MediaFileInfo::attachmentsParsingStatus() const
|
||||||
{
|
{
|
||||||
return m_container && m_container->areAttachmentsParsed();
|
return m_attachmentsParsingStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
Loading…
Reference in New Issue