34
34
#include " internal/converterutils.h"
35
35
36
36
#include " log.h"
37
+ #include < iostream>
37
38
38
39
using namespace mu ::converter;
39
40
using namespace mu ::project;
@@ -44,6 +45,7 @@ using namespace muse::io;
44
45
static const std::string PDF_SUFFIX = " pdf" ;
45
46
static const std::string PNG_SUFFIX = " png" ;
46
47
static const std::string SVG_SUFFIX = " svg" ;
48
+ static const std::string MP3_SUFFIX = " mp3" ;
47
49
48
50
Ret ConverterController::batchConvert (const muse::io::path_t & batchJobFile, const muse::io::path_t & stylePath, bool forceMode,
49
51
const String& soundProfile, const muse::UriQuery& extensionUri, muse::ProgressPtr progress)
@@ -131,12 +133,6 @@ Ret ConverterController::fileConvert(const muse::io::path_t& in, const muse::io:
131
133
return make_ret (Err::UnknownError);
132
134
}
133
135
134
- std::string suffix = io::suffix (out);
135
- auto writer = writers ()->writer (suffix);
136
- if (!writer) {
137
- return make_ret (Err::ConvertTypeUnknown);
138
- }
139
-
140
136
Ret ret = notationProject->load (in, stylePath, forceMode);
141
137
if (!ret) {
142
138
LOGE () << " failed load notation, err: " << ret.toString () << " , path: " << in;
@@ -158,6 +154,19 @@ Ret ConverterController::fileConvert(const muse::io::path_t& in, const muse::io:
158
154
159
155
globalContext ()->setCurrentProject (notationProject);
160
156
157
+ // Check if this is a part conversion job
158
+ QString baseName = QString::fromStdString (io::completeBasename (out).toStdString ());
159
+ if (baseName.contains (' *' )) {
160
+ return convertScoreParts (in, out, stylePath, forceMode);
161
+ }
162
+
163
+ std::string suffix = io::suffix (out);
164
+
165
+ auto writer = writers ()->writer (suffix);
166
+ if (!writer) {
167
+ return make_ret (Err::ConvertTypeUnknown);
168
+ }
169
+
161
170
// use a extension for convert
162
171
if (extensionUri.isValid ()) {
163
172
ret = convertByExtension (writer, notationProject->masterNotation ()->notation (), out, extensionUri);
@@ -215,6 +224,8 @@ Ret ConverterController::convertScoreParts(const muse::io::path_t& in, const mus
215
224
ret = convertScorePartsToPdf (writer, notationProject->masterNotation (), out);
216
225
} else if (suffix == PNG_SUFFIX) {
217
226
ret = convertScorePartsToPngs (writer, notationProject->masterNotation (), out);
227
+ } else if (suffix == MP3_SUFFIX) {
228
+ ret = convertScorePartsToMp3 (writer, notationProject->masterNotation (), out);
218
229
} else {
219
230
ret = make_ret (Ret::Code::NotSupported);
220
231
}
@@ -252,7 +263,6 @@ RetVal<ConverterController::BatchJob> ConverterController::parseBatchJob(const m
252
263
253
264
Job job;
254
265
job.in = correctUserInputPath (obj[" in" ].toString ());
255
- job.out = correctUserInputPath (obj[" out" ].toString ());
256
266
257
267
QJsonObject transposeOptionsObj = obj[" transpose" ].toObject ();
258
268
if (!transposeOptionsObj.isEmpty ()) {
@@ -261,12 +271,27 @@ RetVal<ConverterController::BatchJob> ConverterController::parseBatchJob(const m
261
271
rv.ret = transposeOptions.ret ;
262
272
return rv;
263
273
}
264
-
265
274
job.transposeOptions = transposeOptions.val ;
266
275
}
267
276
268
- if (!job.in .empty () && !job.out .empty ()) {
277
+ QJsonValue outValue = obj[" out" ];
278
+ if (outValue.isString ()) {
279
+ job.out = correctUserInputPath (outValue.toString ());
269
280
rv.val .push_back (std::move (job));
281
+ } else if (outValue.isArray ()) {
282
+ QJsonArray outArray = outValue.toArray ();
283
+ for (const QJsonValue& outItem : outArray) {
284
+ Job partJob = job; // Copy the input path
285
+ if (outItem.isString ()) {
286
+ partJob.out = correctUserInputPath (outItem.toString ());
287
+ } else if (outItem.isArray () && outItem.toArray ().size () == 2 ) {
288
+ QJsonArray partOutArray = outItem.toArray ();
289
+ QString prefix = correctUserInputPath (partOutArray[0 ].toString ());
290
+ QString suffix = partOutArray[1 ].toString ();
291
+ partJob.out = prefix + " *" + suffix; // Use "*" as a placeholder for part names
292
+ }
293
+ rv.val .push_back (std::move (partJob));
294
+ }
270
295
}
271
296
}
272
297
@@ -368,28 +393,32 @@ Ret ConverterController::convertScorePartsToPdf(INotationWriterPtr writer, IMast
368
393
TRACEFUNC;
369
394
370
395
INotationPtrList notations;
371
- notations.push_back (masterNotation->notation ());
372
-
373
396
for (IExcerptNotationPtr e : masterNotation->excerpts ()) {
374
397
notations.push_back (e->notation ());
375
398
}
376
399
377
- File file (out);
378
- if (!file. open (File::WriteOnly)) {
379
- return make_ret (Err::OutFileFailedOpen );
380
- }
400
+ for ( size_t i = 0 ; i < notations. size (); ++i) {
401
+ QString partName = notations[i]-> name ();
402
+ QString baseName = QString::fromStdString ( io::completeBasename (out). toStdString () );
403
+ muse::io:: path_t partOut = io::dirpath (out) + " / " + baseName. replace ( " * " , partName). toStdString () + " .pdf " ;
381
404
382
- INotationWriter::Options options {
383
- { INotationWriter::OptionKey::UNIT_TYPE, Val (INotationWriter::UnitType::MULTI_PART) },
384
- };
405
+ File file (partOut);
406
+ if (!file.open (File::WriteOnly)) {
407
+ return make_ret (Err::OutFileFailedOpen);
408
+ }
385
409
386
- Ret ret = writer->writeList (notations, file, options);
387
- if (!ret) {
388
- LOGE () << " failed write, err: " << ret.toString () << " , path: " << out;
389
- return make_ret (Err::OutFileFailedWrite);
390
- }
410
+ INotationWriter::Options options {
411
+ { INotationWriter::OptionKey::UNIT_TYPE, Val (INotationWriter::UnitType::PER_PART) },
412
+ };
391
413
392
- file.close ();
414
+ Ret ret = writer->write (notations[i], file, options);
415
+ if (!ret) {
416
+ LOGE () << " failed write, err: " << ret.toString () << " , path: " << partOut;
417
+ return make_ret (Err::OutFileFailedWrite);
418
+ }
419
+
420
+ file.close ();
421
+ }
393
422
394
423
return make_ret (Ret::Code::Ok);
395
424
}
@@ -399,23 +428,55 @@ Ret ConverterController::convertScorePartsToPngs(INotationWriterPtr writer, mu::
399
428
{
400
429
TRACEFUNC;
401
430
402
- Ret ret = convertPageByPage (writer, masterNotation-> notation (), out) ;
403
- if (!ret ) {
404
- return ret ;
431
+ INotationPtrList notations ;
432
+ for (IExcerptNotationPtr e : masterNotation-> excerpts () ) {
433
+ notations. push_back (e-> notation ()) ;
405
434
}
406
435
407
- INotationPtrList excerpts;
436
+ for (size_t i = 0 ; i < notations.size (); i++) {
437
+ QString partName = notations[i]->name ();
438
+ QString baseName = QString::fromStdString (io::completeBasename (out).toStdString ());
439
+ muse::io::path_t pngFilePath = io::dirpath (out) + " /" + baseName.replace (" *" , partName).toStdString () + " .png" ;
440
+ Ret ret2 = convertPageByPage (writer, notations[i], pngFilePath);
441
+ if (!ret2) {
442
+ return ret2;
443
+ }
444
+ }
445
+
446
+ return make_ret (Ret::Code::Ok);
447
+ }
448
+
449
+ Ret ConverterController::convertScorePartsToMp3 (INotationWriterPtr writer, IMasterNotationPtr masterNotation,
450
+ const muse::io::path_t & out) const
451
+ {
452
+ TRACEFUNC;
453
+
454
+ INotationPtrList notations;
408
455
for (IExcerptNotationPtr e : masterNotation->excerpts ()) {
409
- excerpts .push_back (e->notation ());
456
+ notations .push_back (e->notation ());
410
457
}
411
458
412
- muse::io::path_t pngFilePath = io::dirpath (out) + " /" + muse::io::path_t (io::completeBasename (out) + " -excerpt.png" );
459
+ for (size_t i = 0 ; i < notations.size (); ++i) {
460
+ QString partName = notations[i]->name ();
461
+ QString baseName = QString::fromStdString (io::completeBasename (out).toStdString ());
462
+ muse::io::path_t partOut = io::dirpath (out) + " /" + baseName.replace (" *" , partName).toStdString () + " .mp3" ;
413
463
414
- for (size_t i = 0 ; i < excerpts.size (); i++) {
415
- Ret ret2 = convertPageByPage (writer, excerpts[i], pngFilePath);
416
- if (!ret2) {
417
- return ret2;
464
+ File file (partOut);
465
+ if (!file.open (File::WriteOnly)) {
466
+ return make_ret (Err::OutFileFailedOpen);
467
+ }
468
+
469
+ INotationWriter::Options options {
470
+ { INotationWriter::OptionKey::UNIT_TYPE, Val (INotationWriter::UnitType::PER_PART) },
471
+ };
472
+ file.setMeta (" file_path" , partOut.toStdString ());
473
+ Ret ret = writer->write (notations[i], file, options);
474
+ if (!ret) {
475
+ LOGE () << " failed write, err: " << ret.toString () << " , path: " << partOut;
476
+ return make_ret (Err::OutFileFailedWrite);
418
477
}
478
+
479
+ file.close ();
419
480
}
420
481
421
482
return make_ret (Ret::Code::Ok);
0 commit comments