Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#19359 export parts #25998

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 95 additions & 34 deletions src/converter/internal/convertercontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "internal/converterutils.h"

#include "log.h"
#include <iostream>

using namespace mu::converter;
using namespace mu::project;
Expand All @@ -44,6 +45,7 @@ using namespace muse::io;
static const std::string PDF_SUFFIX = "pdf";
static const std::string PNG_SUFFIX = "png";
static const std::string SVG_SUFFIX = "svg";
static const std::string MP3_SUFFIX = "mp3";

Ret ConverterController::batchConvert(const muse::io::path_t& batchJobFile, const muse::io::path_t& stylePath, bool forceMode,
const String& soundProfile, const muse::UriQuery& extensionUri, muse::ProgressPtr progress)
Expand Down Expand Up @@ -131,12 +133,6 @@ Ret ConverterController::fileConvert(const muse::io::path_t& in, const muse::io:
return make_ret(Err::UnknownError);
}

std::string suffix = io::suffix(out);
auto writer = writers()->writer(suffix);
if (!writer) {
return make_ret(Err::ConvertTypeUnknown);
}

Ret ret = notationProject->load(in, stylePath, forceMode);
if (!ret) {
LOGE() << "failed load notation, err: " << ret.toString() << ", path: " << in;
Expand All @@ -158,6 +154,19 @@ Ret ConverterController::fileConvert(const muse::io::path_t& in, const muse::io:

globalContext()->setCurrentProject(notationProject);

// Check if this is a part conversion job
QString baseName = QString::fromStdString(io::completeBasename(out).toStdString());
if (baseName.contains('*')) {
return convertScoreParts(in, out, stylePath, forceMode);
}

std::string suffix = io::suffix(out);

auto writer = writers()->writer(suffix);
if (!writer) {
return make_ret(Err::ConvertTypeUnknown);
}

Leo-Cal marked this conversation as resolved.
Show resolved Hide resolved
// use a extension for convert
if (extensionUri.isValid()) {
ret = convertByExtension(writer, notationProject->masterNotation()->notation(), out, extensionUri);
Expand Down Expand Up @@ -215,6 +224,8 @@ Ret ConverterController::convertScoreParts(const muse::io::path_t& in, const mus
ret = convertScorePartsToPdf(writer, notationProject->masterNotation(), out);
} else if (suffix == PNG_SUFFIX) {
ret = convertScorePartsToPngs(writer, notationProject->masterNotation(), out);
} else if (suffix == MP3_SUFFIX) {
ret = convertScorePartsToMp3(writer, notationProject->masterNotation(), out);
} else {
ret = make_ret(Ret::Code::NotSupported);
}
Expand Down Expand Up @@ -252,7 +263,6 @@ RetVal<ConverterController::BatchJob> ConverterController::parseBatchJob(const m

Job job;
job.in = correctUserInputPath(obj["in"].toString());
job.out = correctUserInputPath(obj["out"].toString());

QJsonObject transposeOptionsObj = obj["transpose"].toObject();
if (!transposeOptionsObj.isEmpty()) {
Expand All @@ -261,12 +271,27 @@ RetVal<ConverterController::BatchJob> ConverterController::parseBatchJob(const m
rv.ret = transposeOptions.ret;
return rv;
}

job.transposeOptions = transposeOptions.val;
}

if (!job.in.empty() && !job.out.empty()) {
QJsonValue outValue = obj["out"];
if (outValue.isString()) {
job.out = correctUserInputPath(outValue.toString());
rv.val.push_back(std::move(job));
} else if (outValue.isArray()) {
QJsonArray outArray = outValue.toArray();
for (const QJsonValue& outItem : outArray) {
Job partJob = job; // Copy the input path
if (outItem.isString()) {
partJob.out = correctUserInputPath(outItem.toString());
} else if (outItem.isArray() && outItem.toArray().size() == 2) {
QJsonArray partOutArray = outItem.toArray();
QString prefix = correctUserInputPath(partOutArray[0].toString());
QString suffix = partOutArray[1].toString();
partJob.out = prefix + "*" + suffix; // Use "*" as a placeholder for part names
}
rv.val.push_back(std::move(partJob));
}
}
}

Expand Down Expand Up @@ -368,28 +393,32 @@ Ret ConverterController::convertScorePartsToPdf(INotationWriterPtr writer, IMast
TRACEFUNC;

INotationPtrList notations;
notations.push_back(masterNotation->notation());

for (IExcerptNotationPtr e : masterNotation->excerpts()) {
notations.push_back(e->notation());
}

File file(out);
if (!file.open(File::WriteOnly)) {
return make_ret(Err::OutFileFailedOpen);
}
for (size_t i = 0; i < notations.size(); ++i) {
QString partName = notations[i]->name();
QString baseName = QString::fromStdString(io::completeBasename(out).toStdString());
muse::io::path_t partOut = io::dirpath(out) + "/" + baseName.replace("*", partName).toStdString() + ".pdf";

INotationWriter::Options options {
{ INotationWriter::OptionKey::UNIT_TYPE, Val(INotationWriter::UnitType::MULTI_PART) },
};
File file(partOut);
if (!file.open(File::WriteOnly)) {
return make_ret(Err::OutFileFailedOpen);
}

Ret ret = writer->writeList(notations, file, options);
if (!ret) {
LOGE() << "failed write, err: " << ret.toString() << ", path: " << out;
return make_ret(Err::OutFileFailedWrite);
}
INotationWriter::Options options {
{ INotationWriter::OptionKey::UNIT_TYPE, Val(INotationWriter::UnitType::PER_PART) },
};

file.close();
Ret ret = writer->write(notations[i], file, options);
if (!ret) {
LOGE() << "failed write, err: " << ret.toString() << ", path: " << partOut;
return make_ret(Err::OutFileFailedWrite);
}

file.close();
}

return make_ret(Ret::Code::Ok);
}
Expand All @@ -399,23 +428,55 @@ Ret ConverterController::convertScorePartsToPngs(INotationWriterPtr writer, mu::
{
TRACEFUNC;

Ret ret = convertPageByPage(writer, masterNotation->notation(), out);
if (!ret) {
return ret;
INotationPtrList notations;
for (IExcerptNotationPtr e : masterNotation->excerpts()) {
notations.push_back(e->notation());
}

INotationPtrList excerpts;
for (size_t i = 0; i < notations.size(); i++) {
QString partName = notations[i]->name();
QString baseName = QString::fromStdString(io::completeBasename(out).toStdString());
muse::io::path_t pngFilePath = io::dirpath(out) + "/" + baseName.replace("*", partName).toStdString() + ".png";
Ret ret2 = convertPageByPage(writer, notations[i], pngFilePath);
if (!ret2) {
return ret2;
}
}

return make_ret(Ret::Code::Ok);
}

Ret ConverterController::convertScorePartsToMp3(INotationWriterPtr writer, IMasterNotationPtr masterNotation,
const muse::io::path_t& out) const
{
TRACEFUNC;

INotationPtrList notations;
for (IExcerptNotationPtr e : masterNotation->excerpts()) {
excerpts.push_back(e->notation());
notations.push_back(e->notation());
}

muse::io::path_t pngFilePath = io::dirpath(out) + "/" + muse::io::path_t(io::completeBasename(out) + "-excerpt.png");
for (size_t i = 0; i < notations.size(); ++i) {
QString partName = notations[i]->name();
QString baseName = QString::fromStdString(io::completeBasename(out).toStdString());
muse::io::path_t partOut = io::dirpath(out) + "/" + baseName.replace("*", partName).toStdString() + ".mp3";

for (size_t i = 0; i < excerpts.size(); i++) {
Ret ret2 = convertPageByPage(writer, excerpts[i], pngFilePath);
if (!ret2) {
return ret2;
File file(partOut);
if (!file.open(File::WriteOnly)) {
return make_ret(Err::OutFileFailedOpen);
}

INotationWriter::Options options {
{ INotationWriter::OptionKey::UNIT_TYPE, Val(INotationWriter::UnitType::PER_PART) },
};
file.setMeta("file_path", partOut.toStdString());
Ret ret = writer->write(notations[i], file, options);
if (!ret) {
LOGE() << "failed write, err: " << ret.toString() << ", path: " << partOut;
return make_ret(Err::OutFileFailedWrite);
}

file.close();
}

return make_ret(Ret::Code::Ok);
Expand Down
2 changes: 2 additions & 0 deletions src/converter/internal/convertercontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,7 @@ class ConverterController : public IConverterController, public muse::Injectable
const muse::io::path_t& out) const;
muse::Ret convertScorePartsToPngs(project::INotationWriterPtr writer, notation::IMasterNotationPtr masterNotation,
const muse::io::path_t& out) const;
muse::Ret convertScorePartsToMp3(project::INotationWriterPtr writer, notation::IMasterNotationPtr masterNotation,
const muse::io::path_t& out) const;
};
}