Skip to content

Commit

Permalink
Merge pull request #20210 from cbjeukendrup/excerpts_store_by_escaped…
Browse files Browse the repository at this point in the history
…_name

File format: store excerpts by a unique and safe name
  • Loading branch information
DmitryArefiev authored Dec 11, 2023
2 parents 479befe + 8e18026 commit 99c1987
Show file tree
Hide file tree
Showing 88 changed files with 286 additions and 201 deletions.
16 changes: 5 additions & 11 deletions src/engraving/compat/writescorehook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,12 @@ void WriteScoreHook::onWriteExcerpts302(Score* score, XmlWriter& xml, WriteConte
isWriteExcerpts = true;
}

if (isWriteExcerpts) {
if (score->isMaster()) {
if (!selectionOnly) {
MasterScore* mScore = static_cast<MasterScore*>(score);
for (const Excerpt* excerpt : mScore->excerpts()) {
if (excerpt->excerptScore() != score) {
write::Writer::write(excerpt->excerptScore(), xml, ctx, selectionOnly, *this); // recursion write
}
}
if (isWriteExcerpts && score->isMaster() && !selectionOnly) {
MasterScore* mScore = static_cast<MasterScore*>(score);
for (const Excerpt* excerpt : mScore->excerpts()) {
if (excerpt->excerptScore() != score) {
write::Writer::write(excerpt->excerptScore(), xml, ctx, selectionOnly, *this); // recursion write
}
} else {
xml.tag("name", score->excerpt()->name());
}
}
}
62 changes: 59 additions & 3 deletions src/engraving/dom/excerpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,18 @@ const String& Excerpt::name() const
return m_name;
}

void Excerpt::setName(const String& name)
void Excerpt::setName(const String& name, bool saveAndNotify)
{
if (m_name == name) {
return;
}

m_name = name;
writeNameToMetaTags();
m_nameChanged.notify();

if (saveAndNotify) {
writeNameToMetaTags();
m_nameChanged.notify();
}
}

void Excerpt::writeNameToMetaTags()
Expand All @@ -153,6 +156,59 @@ async::Notification Excerpt::nameChanged() const
return m_nameChanged;
}

const String& Excerpt::fileName() const
{
IF_ASSERT_FAILED(!m_fileName.empty()) {
const_cast<Excerpt*>(this)->updateFileName();
}

return m_fileName;
}

void Excerpt::setFileName(const String& fileName)
{
m_fileName = fileName;
}

static inline bool isValidExcerptFileNameCharacter(char16_t c)
{
return (u'a' <= c && c <= u'z')
|| (u'A' <= c && c <= 'Z')
|| (u'0' <= c && c <= '9')
|| c == u'_' || c == u'-' || c == u' ';
}

static inline String escapeExcerptFileName(const String& name)
{
String result;
result.reserve(name.size());

for (const char16_t& c : name.toStdU16String()) {
if (isValidExcerptFileNameCharacter(c)) {
result.append(c);
} else {
result.append(u'_');
}
}

return result;
}

void Excerpt::updateFileName(size_t index)
{
if (index == mu::nidx && m_masterScore) {
index = mu::indexOf(m_masterScore->excerpts(), this);
}

const String escapedName = escapeExcerptFileName(m_name);

if (index == mu::nidx) {
m_fileName = escapedName;
} else {
m_fileName = String(u"%1_%2").arg(String::number(index), escapedName);
}
}

bool Excerpt::containsPart(const Part* part) const
{
for (Part* _part : m_parts) {
Expand Down
12 changes: 9 additions & 3 deletions src/engraving/dom/excerpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
#ifndef MU_ENGRAVING_EXCERPT_H
#define MU_ENGRAVING_EXCERPT_H

#include <map>

#include "types/fraction.h"
#include "types/types.h"
#include "types/string.h"
Expand Down Expand Up @@ -59,9 +57,16 @@ class Excerpt
void setExcerptScore(Score* s);

const String& name() const;
void setName(const String& name);
void setName(const String& name, bool saveAndNotify = true);
async::Notification nameChanged() const;

// The name used to store this excerpt in the msc file/folder.
// When reading/writing, the engraving module sets this value, so that other
// modules can also read/write data about this excerpt using the correct name.
const String& fileName() const;
void setFileName(const String& fileName);
void updateFileName(size_t index = mu::nidx);

std::vector<Part*>& parts() { return m_parts; }
const std::vector<Part*>& parts() const { return m_parts; }
void setParts(const std::vector<Part*>& parts) { m_parts = parts; }
Expand Down Expand Up @@ -99,6 +104,7 @@ class Excerpt
MasterScore* m_masterScore = nullptr;
Score* m_excerptScore = nullptr;
String m_name;
String m_fileName;
async::Notification m_nameChanged;
std::vector<Part*> m_parts;
TracksMap m_tracksMapping;
Expand Down
14 changes: 7 additions & 7 deletions src/engraving/infrastructure/mscreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ ByteArray MscReader::readScoreFile() const
return fileData(mscxFileName);
}

std::vector<String> MscReader::excerptNames() const
std::vector<String> MscReader::excerptFileNames() const
{
if (!reader()->isContainer()) {
NOT_SUPPORTED << " not container";
Expand All @@ -180,16 +180,16 @@ std::vector<String> MscReader::excerptNames() const
return names;
}

ByteArray MscReader::readExcerptStyleFile(const String& name) const
ByteArray MscReader::readExcerptStyleFile(const String& excerptFileName) const
{
String fileName = name + u".mss";
return fileData(u"Excerpts/" + name + u"/" + fileName);
String fileName = excerptFileName + u".mss";
return fileData(u"Excerpts/" + excerptFileName + u"/" + fileName);
}

ByteArray MscReader::readExcerptFile(const String& name) const
ByteArray MscReader::readExcerptFile(const String& excerptFileName) const
{
String fileName = name + u".mscx";
return fileData(u"Excerpts/" + name + u"/" + fileName);
String fileName = excerptFileName + u".mscx";
return fileData(u"Excerpts/" + excerptFileName + u"/" + fileName);
}

ByteArray MscReader::readChordListFile() const
Expand Down
6 changes: 3 additions & 3 deletions src/engraving/infrastructure/mscreader.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ class MscReader
ByteArray readStyleFile() const;
ByteArray readScoreFile() const;

std::vector<String> excerptNames() const;
ByteArray readExcerptStyleFile(const String& name) const;
ByteArray readExcerptFile(const String& name) const;
std::vector<String> excerptFileNames() const;
ByteArray readExcerptStyleFile(const String& excerptFileName) const;
ByteArray readExcerptFile(const String& excerptFileName) const;

ByteArray readChordListFile() const;
ByteArray readThumbnailFile() const;
Expand Down
12 changes: 6 additions & 6 deletions src/engraving/infrastructure/mscwriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,16 @@ void MscWriter::writeScoreFile(const ByteArray& data)
addFileData(mainFileName(), data);
}

void MscWriter::addExcerptStyleFile(const String& name, const ByteArray& data)
void MscWriter::addExcerptStyleFile(const String& excerptFileName, const ByteArray& data)
{
String fileName = name + u".mss";
addFileData(u"Excerpts/" + name + u"/" + fileName, data);
String fileName = excerptFileName + u".mss";
addFileData(u"Excerpts/" + excerptFileName + u"/" + fileName, data);
}

void MscWriter::addExcerptFile(const String& name, const ByteArray& data)
void MscWriter::addExcerptFile(const String& excerptFileName, const ByteArray& data)
{
String fileName = name + u".mscx";
addFileData(u"Excerpts/" + name + u"/" + fileName, data);
String fileName = excerptFileName + u".mscx";
addFileData(u"Excerpts/" + excerptFileName + u"/" + fileName, data);
}

void MscWriter::writeChordListFile(const ByteArray& data)
Expand Down
4 changes: 2 additions & 2 deletions src/engraving/infrastructure/mscwriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class MscWriter

void writeStyleFile(const ByteArray& data);
void writeScoreFile(const ByteArray& data);
void addExcerptStyleFile(const String& name, const ByteArray& data);
void addExcerptFile(const String& name, const ByteArray& data);
void addExcerptStyleFile(const String& excerptFileName, const ByteArray& data);
void addExcerptFile(const String& excerptFileName, const ByteArray& data);
void writeChordListFile(const ByteArray& data);
void writeThumbnailFile(const ByteArray& data);
void addImageFile(const String& fileName, const ByteArray& data);
Expand Down
23 changes: 17 additions & 6 deletions src/engraving/rw/mscloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,24 +133,25 @@ mu::Ret MscLoader::loadMscz(MasterScore* masterScore, const MscReader& mscReader

// Read excerpts
if (ret && masterScore->mscVersion() >= 400) {
std::vector<String> excerptNames = mscReader.excerptNames();
for (const String& excerptName : excerptNames) {
std::vector<String> excerptFileNames = mscReader.excerptFileNames();
for (const String& excerptFileName : excerptFileNames) {
Score* partScore = masterScore->createScore();

compat::ReadStyleHook::setupDefaultStyle(partScore);

Excerpt* ex = new Excerpt(masterScore);
ex->setExcerptScore(partScore);
ex->setFileName(excerptFileName);

ByteArray excerptStyleData = mscReader.readExcerptStyleFile(excerptName);
ByteArray excerptStyleData = mscReader.readExcerptStyleFile(excerptFileName);
Buffer excerptStyleBuf(&excerptStyleData);
excerptStyleBuf.open(IODevice::ReadOnly);
partScore->style().read(&excerptStyleBuf);

ByteArray excerptData = mscReader.readExcerptFile(excerptName);
ByteArray excerptData = mscReader.readExcerptFile(excerptFileName);

XmlReader xml(excerptData);
xml.setDocName(excerptName);
xml.setDocName(excerptFileName);

ReadInOutData partReadInData;
partReadInData.links = masterReadOutData.links;
Expand All @@ -169,7 +170,17 @@ mu::Ret MscLoader::loadMscz(MasterScore* masterScore, const MscReader& mscReader

partScore->linkMeasures(masterScore);

ex->setName(excerptName);
if (ex->name().empty()) {
// If no excerpt name tag was found while reading, try the "partName" meta tag
const String nameFromMeta = partScore->metaTag(u"partName");

if (nameFromMeta.empty()) {
// If that's also empty, fall back to the filename
ex->setName(excerptFileName, /*saveAndNotify=*/ false);
} else {
ex->setName(nameFromMeta, /*saveAndNotify=*/ false);
}
}

masterScore->addExcerpt(ex);
}
Expand Down
53 changes: 31 additions & 22 deletions src/engraving/rw/mscsaver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include "log.h"

using namespace mu;
using namespace mu::io;
using namespace mu::engraving;
using namespace mu::engraving::rw;
Expand Down Expand Up @@ -72,29 +73,37 @@ bool MscSaver::writeMscz(MasterScore* score, MscWriter& mscWriter, bool onlySele
// Write Excerpts
{
if (!onlySelection) {
for (const Excerpt* excerpt : score->excerpts()) {
const std::vector<Excerpt*>& excerpts = score->excerpts();

for (size_t excerptIndex = 0; excerptIndex < excerpts.size(); ++excerptIndex) {
Excerpt* excerpt = excerpts.at(excerptIndex);

Score* partScore = excerpt->excerptScore();
if (partScore != score) {
// Write excerpt style
{
ByteArray excerptStyleData;
Buffer styleStyleBuf(&excerptStyleData);
styleStyleBuf.open(IODevice::WriteOnly);
partScore->style().write(&styleStyleBuf);

mscWriter.addExcerptStyleFile(excerpt->name(), excerptStyleData);
}

// Write excerpt
{
ByteArray excerptData;
Buffer excerptBuf(&excerptData);
excerptBuf.open(IODevice::ReadWrite);

RWRegister::writer()->writeScore(excerpt->excerptScore(), &excerptBuf, onlySelection, &masterWriteOutData);

mscWriter.addExcerptFile(excerpt->name(), excerptData);
}
IF_ASSERT_FAILED(partScore && partScore != score) {
continue;
}

excerpt->updateFileName(excerptIndex);

// Write excerpt style
{
ByteArray excerptStyleData;
Buffer styleStyleBuf(&excerptStyleData);
styleStyleBuf.open(IODevice::WriteOnly);
partScore->style().write(&styleStyleBuf);

mscWriter.addExcerptStyleFile(excerpt->fileName(), excerptStyleData);
}

// Write excerpt
{
ByteArray excerptData;
Buffer excerptBuf(&excerptData);
excerptBuf.open(IODevice::ReadWrite);

RWRegister::writer()->writeScore(excerpt->excerptScore(), &excerptBuf, onlySelection, &masterWriteOutData);

mscWriter.addExcerptFile(excerpt->fileName(), excerptData);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/rw/read206/read206.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3359,7 +3359,7 @@ bool Read206::readScore206(Score* score, XmlReader& e, ReadContext& ctx)
} else if (tag == "name") {
String n = e.readText();
if (!score->isMaster()) { //ignore the name if it's not a child score
score->excerpt()->setName(n);
score->excerpt()->setName(n, /*saveAndNotify=*/ false);
}
} else if (tag == "layoutMode") {
String s = e.readText();
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/rw/read302/read302.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ bool Read302::readScore302(Score* score, XmlReader& e, ReadContext& ctx)
} else if (tag == "name") {
String n = e.readText();
if (!score->isMaster()) { //ignore the name if it's not a child score
score->excerpt()->setName(n);
score->excerpt()->setName(n, /*saveAndNotify=*/ false);
}
} else if (tag == "layoutMode") {
String s = e.readText();
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/rw/read400/read400.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ bool Read400::readScore400(Score* score, XmlReader& e, ReadContext& ctx)
} else if (tag == "name") {
String n = e.readText();
if (!score->isMaster()) { //ignore the name if it's not a child score
score->excerpt()->setName(n);
score->excerpt()->setName(n, /*saveAndNotify=*/ false);
}
} else if (tag == "layoutMode") {
String s = e.readText();
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/rw/read410/read410.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ bool Read410::readScore410(Score* score, XmlReader& e, ReadContext& ctx)
} else if (tag == "name") {
String n = e.readText();
if (!score->isMaster()) { //ignore the name if it's not a child score
score->excerpt()->setName(n);
score->excerpt()->setName(n, /*saveAndNotify=*/ false);
}
} else if (tag == "layoutMode") {
String s = e.readText();
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/rw/read410/tread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1398,7 +1398,7 @@ void TRead::read(Excerpt* item, XmlReader& e, ReadContext&)
while (e.readNextStartElement()) {
const AsciiStringView tag = e.name();
if (tag == "name" || tag == "title") {
item->setName(e.readText().trimmed());
item->setName(e.readText().trimmed(), /*saveAndNotify=*/ false);
} else if (tag == "part") {
size_t partIdx = static_cast<size_t>(e.readInt());
if (partIdx >= pl.size()) {
Expand Down
7 changes: 5 additions & 2 deletions src/engraving/rw/write/writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,11 @@ void Writer::write(Score* score, XmlWriter& xml, WriteContext& ctx, bool selecti

xml.startElement(score);

if (score->excerpt()) {
Excerpt* e = score->excerpt();
if (Excerpt* e = score->excerpt()) {
if (!e->name().empty()) {
xml.tag("name", e->name());
}

const TracksMap& tracks = e->tracksMapping();
if (!(tracks.size() == e->nstaves() * VOICES) && !tracks.empty()) {
for (auto it = tracks.begin(); it != tracks.end(); ++it) {
Expand Down
Loading

0 comments on commit 99c1987

Please sign in to comment.