2626#include < QJSValueIterator>
2727
2828#include " engraving/compat/scoreaccess.h"
29+ #include " engraving/dom/masterscore.h"
2930#include " engraving/dom/factory.h"
3031#include " engraving/dom/interval.h"
3132#include " engraving/types/types.h"
3233
34+ #include " notation/inotation.h"
35+ #include " project/inotationwriter.h"
36+
3337// api
3438#include " apitypes.h"
3539#include " engravingapiv1.h"
@@ -237,14 +241,52 @@ QQmlListProperty<apiv1::Score> PluginAPI::scores()
237241bool PluginAPI::writeScore (Score* s, const QString& name, const QString& ext)
238242{
239243 if (!s || !s->score ()) {
244+ LOGW (" PluginAPI::writeScore: no score provided" );
240245 return false ;
241246 }
242247
243- UNUSED (name);
244- UNUSED (ext);
248+ if (s->score () != currentScore ()) {
249+ LOGW (" PluginAPI::writeScore: only writing the selected score is currently supported" );
250+ return false ;
251+ }
245252
246- NOT_IMPLEMENTED;
247- return false ;
253+ const notation::INotationPtr notation = context ()->currentNotation ();
254+
255+ if (!notation) {
256+ LOGW (" PluginAPI::writeScore: no notation found" );
257+ return false ;
258+ }
259+
260+ const auto unitType = determineWriterUnitType (ext.toStdString ());
261+
262+ if (!unitType) {
263+ LOGW (" PluginAPI::writeScore: '%s' format is not supported" , ext.toUtf8 ().constData ());
264+ return false ;
265+ }
266+
267+ const QString outPath = name.endsWith (ext) ? name : (name + ' .' + ext);
268+ return exportProjectScenario ()->exportScores ({ notation }, outPath, *unitType, /* openDestinationFolderOnExport */ false );
269+ }
270+
271+ std::optional<project::INotationWriter::UnitType> PluginAPI::determineWriterUnitType (const std::string& ext) const
272+ {
273+ const project::INotationWriterPtr writer = writers ()->writer (ext);
274+
275+ if (!writer) {
276+ return std::nullopt ;
277+ }
278+
279+ project::INotationWriter::UnitType unitType;
280+
281+ if (writer->supportsUnitType (project::INotationWriter::UnitType::PER_PAGE)) {
282+ unitType = project::INotationWriter::UnitType::PER_PAGE;
283+ } else if (writer->supportsUnitType (project::INotationWriter::UnitType::PER_PART)) {
284+ unitType = project::INotationWriter::UnitType::PER_PART;
285+ } else {
286+ unitType = project::INotationWriter::UnitType::MULTI_PART;
287+ }
288+
289+ return unitType;
248290}
249291
250292// ---------------------------------------------------------
@@ -259,11 +301,21 @@ bool PluginAPI::writeScore(Score* s, const QString& name, const QString& ext)
259301
260302apiv1::Score* PluginAPI::readScore (const QString& name, bool noninteractive)
261303{
262- UNUSED (name);
263- UNUSED (noninteractive);
304+ const bool hadScoreOpened = currentScore ();
264305
265- NOT_IMPLEMENTED;
266- return nullptr ;
306+ if (hadScoreOpened) {
307+ LOGW (" PluginAPI::readScore: will open a score in a new window" );
308+ }
309+
310+ if (noninteractive) {
311+ LOGW (" PluginAPI::readScore: noninteractive flag is not yet implemented" );
312+ }
313+
314+ const muse::io::path_t path (name);
315+ const project::ProjectFile file (path);
316+ const muse::Ret ret = projectFilesController ()->openProject (file);
317+
318+ return (ret.success () && !hadScoreOpened) ? curScore () : nullptr ;
267319}
268320
269321// ---------------------------------------------------------
@@ -272,9 +324,17 @@ apiv1::Score* PluginAPI::readScore(const QString& name, bool noninteractive)
272324
273325void PluginAPI::closeScore (apiv1::Score* score)
274326{
275- UNUSED (score);
327+ if (!score || !score->score ()) {
328+ LOGW (" PluginAPI::closeScore: no score provided" );
329+ return ;
330+ }
276331
277- NOT_IMPLEMENTED;
332+ if (score->score () != currentScore ()) {
333+ LOGW (" PluginAPI::closeScore: only closing the selected score is currently supported" );
334+ return ;
335+ }
336+
337+ projectFilesController ()->closeOpenedProject ();
278338}
279339
280340// ---------------------------------------------------------
0 commit comments