25 #include <QDomDocument> 26 #include <QDomElement> 32 #include <QTextStream> 34 #include <KLocalizedString> 58 #define K3B_PROJECT_MIME_TYPE "application/x-k3b" 61 #define K3B_FILE_SUFFIX _("*.k3b") 64 #define OUTFILE_DIGITS 4 67 #define OUTFILE_PATTERN (_("[%0") + _("%1nr]").arg(OUTFILE_DIGITS)) 70 #define OUTFILE_SUFFIX _(".wav") 74 const QVariantList &args)
78 m_selection_only(false),
79 m_export_location(EXPORT_TO_SUB_DIR),
80 m_overwrite_policy(USE_NEW_FILE_NAMES),
97 if (params.count() != 5)
102 if (!
m_url.isValid())
return -EINVAL;
109 int v = param.toInt(&ok);
111 if (!ok)
return -EINVAL;
116 int where = param.toInt(&ok);
118 if (!ok)
return -EINVAL;
125 int overwrite = param.toInt(&ok);
127 if (!ok)
return -EINVAL;
150 QString file_title = info.
get(
INF_NAME).toString();
155 if (!file_title.length()) file_title = base;
158 QString prev_title = file_title;
159 for (
unsigned int index = 1; ; ++index) {
160 block_start = block_end;
163 QString block_title = (!label.
isNull() && label.
name().length()) ?
164 label.
name() : prev_title;
166 if ((block_end > selection_left) && (block_start <= selection_right)) {
173 block.
m_length = block_end - block_start;
181 prev_title = block_title;
187 prev_title = block_title;
190 if (label.
isNull())
break;
199 QString
name = pattern;
200 QString num =
_(
"%1").arg(index,
OUTFILE_DIGITS, 10, QLatin1Char(
'0'));
209 const QString &pattern,
213 if (!pattern.length()) {
222 QMap <QString, QString *> map_patterns;
223 map_patterns.insert(
_(
"[%artist]"), &block.
m_artist);
224 map_patterns.insert(
_(
"[%title]"), &block.
m_title);
229 QMap <int, QString *> map_result;
230 foreach (
const QString &placeholder, map_patterns.keys()) {
231 QString placeholder_esc;
233 if (pattern_esc.contains(placeholder_esc)) {
234 const QString rx_string =
_(
"(.+)");
235 int pos = pattern.indexOf(placeholder);
236 pattern_esc.replace(placeholder_esc, rx_string);
237 map_result.insert(pos, map_patterns[placeholder]);
240 if (map_result.isEmpty())
244 pattern_esc.replace(QRegExp(
_(
"(\\\\\\s)+")),
_(
"\\s+"));
247 QRegExp rx(pattern_esc, Qt::CaseInsensitive);
248 if (!rx.exactMatch(text.trimmed()))
253 for (
int index = 0; index < map_result.count(); ++index) {
254 QString value = rx.cap(index + 1).trimmed();
255 if (value.length()) {
256 QString *result = map_result[map_result.keys()[index]];
257 if (result) *result = value;
269 QString menu_path =
_(
"File/Save/%1").arg(
_(I18N_NOOP2(
270 "menu: /File/Save/Export to K3b Project...",
271 "Export to K3b Project..." 273 emitCommand(
_(
"menu(plugin:setup(export_k3b),%1%2)").arg(
274 menu_path).arg(
_(
"/#group(@SIGNAL)")));
275 emitCommand(
_(
"menu(plugin:setup(export_k3b),%1%2)").arg(
276 menu_path).arg(
_(
"/#icon(application-x-k3b)")));
287 selection(Q_NULLPTR, &selection_left, &selection_right,
false);
291 bool selected_something = (selection_left != selection_right);
292 bool selected_all = ((selection_left == 0) &&
294 bool enable_selection_only = selected_something && !selected_all;
297 QPointer<Kwave::K3BExportDialog> dialog =
299 _(
"kfiledialog:///kwave_export_k3b"),
301 "file type filter when exporting to K3b",
302 "K3b project file (*.k3b)" 309 enable_selection_only,
313 if (!dialog)
return Q_NULLPTR;
316 if (dialog->exec() != QDialog::Accepted) {
321 QStringList *list =
new(std::nothrow) QStringList();
329 QUrl url = dialog->selectedUrl();
336 QString
name = url.path();
337 QFileInfo path(name);
345 int export_location =
static_cast<int>(dialog->exportLocation());
346 int overwrite_policy =
static_cast<int>(dialog->overwritePolicy());
347 bool selection_only = (enable_selection_only) ?
352 *list << QString::number(selection_only);
353 *list << QString::number(export_location);
354 *list << QString::number(overwrite_policy);
357 name +
_(
",") + pattern +
_(
",") +
358 QString::number(selection_only) +
_(
",") +
359 QString::number(export_location) +
_(
",") +
360 QString::number(overwrite_policy) +
_(
")")
363 if (dialog)
delete dialog;
376 QDomDocument doc = part->ownerDocument();
377 QDomElement mainElem = doc.createElement(
_(
"general"));
379 QDomElement propElem = doc.createElement(
_(
"writing_mode"));
380 propElem.appendChild(doc.createTextNode(
_(
"auto")));
381 mainElem.appendChild(propElem);
383 propElem = doc.createElement(
_(
"dummy"));
384 propElem.setAttribute(
_(
"activated"),
_(
"no"));
385 mainElem.appendChild(propElem);
387 propElem = doc.createElement(
_(
"on_the_fly"));
388 propElem.setAttribute(
_(
"activated"),
_(
"true"));
389 mainElem.appendChild(propElem);
391 propElem = doc.createElement(
_(
"only_create_images"));
392 propElem.setAttribute(
_(
"activated"),
_(
"no"));
393 mainElem.appendChild(propElem);
395 propElem = doc.createElement(
_(
"remove_images"));
396 propElem.setAttribute(
_(
"activated"),
_(
"no"));
397 mainElem.appendChild(propElem);
399 part->appendChild( mainElem );
412 #define GET_INF(inf) doc.createTextNode(info.get(inf).toString()) 416 QDomDocument doc = docElem->ownerDocument();
420 QDomElement normalizeElem = doc.createElement(
_(
"normalize"));
421 normalizeElem.appendChild(doc.createTextNode(
_(
"no")));
422 docElem->appendChild(normalizeElem);
425 QDomElement hideFirstTrackElem = doc.createElement(
_(
"hide_first_track"));
426 hideFirstTrackElem.appendChild(doc.createTextNode(
_(
"no")));
427 docElem->appendChild(hideFirstTrackElem);
432 QDomElement ripMain = doc.createElement(
_(
"audio_ripping"));
433 docElem->appendChild(ripMain);
435 QDomElement ripElem = doc.createElement(
_(
"paranoia_mode"));
436 ripElem.appendChild(doc.createTextNode(
_(
"0")));
437 ripMain.appendChild(ripElem);
439 ripElem = doc.createElement(
_(
"read_retries"));
440 ripElem.appendChild(doc.createTextNode(
_(
"0")));
441 ripMain.appendChild(ripElem);
443 ripElem = doc.createElement(
_(
"ignore_read_errors"));
444 ripElem.appendChild(doc.createTextNode(
_(
"no")));
445 ripMain.appendChild(ripElem);
450 QDomElement cdTextMain = doc.createElement(
_(
"cd-text"));
451 cdTextMain.setAttribute(
_(
"activated"),
_(
"yes"));
453 QDomElement cdTextElem = doc.createElement(
_(
"title"));
455 cdTextMain.appendChild(cdTextElem);
457 cdTextElem = doc.createElement(
_(
"artist"));
459 cdTextMain.appendChild(cdTextElem);
461 cdTextElem = doc.createElement(
_(
"arranger"));
463 cdTextMain.appendChild(cdTextElem);
465 cdTextElem = doc.createElement(
_(
"songwriter"));
467 cdTextMain.appendChild(cdTextElem);
469 cdTextElem = doc.createElement(
_(
"composer"));
471 cdTextMain.appendChild(cdTextElem);
473 cdTextElem = doc.createElement(
_(
"disc_id"));
475 cdTextMain.appendChild(cdTextElem);
477 cdTextElem = doc.createElement(
_(
"upc_ean"));
479 cdTextMain.appendChild(cdTextElem);
481 cdTextElem = doc.createElement(
_(
"message"));
483 cdTextMain.appendChild(cdTextElem);
485 docElem->appendChild( cdTextMain );
490 QDomElement contentsElem = doc.createElement(
_(
"contents"));
492 unsigned int index = 1;
496 QString songwriter = QString();
499 QDomElement trackElem = doc.createElement(
_(
"track"));
502 QDomElement sourcesParent = doc.createElement(
_(
"sources"));
503 QDomElement sourceElem = doc.createElement(
_(
"file"));
504 sourceElem.setAttribute(
_(
"url"), url);
505 sourceElem.setAttribute(
_(
"start_offset"),
_(
"00:00:00"));
506 sourceElem.setAttribute(
_(
"end_offset"),
_(
"00:00:00"));
507 sourcesParent.appendChild(sourceElem);
508 trackElem.appendChild(sourcesParent);
511 QDomElement index0Elem = doc.createElement(
_(
"index0"));
512 index0Elem.appendChild(doc.createTextNode(QString::number(index)));
513 trackElem.appendChild(index0Elem);
516 cdTextMain = doc.createElement(
_(
"cd-text"));
517 cdTextElem = doc.createElement(
_(
"title"));
518 cdTextElem.appendChild(doc.createTextNode(title));
519 cdTextMain.appendChild(cdTextElem);
521 cdTextElem = doc.createElement(
_(
"artist"));
522 cdTextElem.appendChild(doc.createTextNode(artist));
523 cdTextMain.appendChild(cdTextElem);
525 cdTextElem = doc.createElement(
_(
"arranger"));
527 cdTextMain.appendChild(cdTextElem);
529 cdTextElem = doc.createElement(
_(
"songwriter"));
530 cdTextElem.appendChild(doc.createTextNode(songwriter));
531 cdTextMain.appendChild(cdTextElem );
533 cdTextElem = doc.createElement(
_(
"composer"));
535 cdTextMain.appendChild(cdTextElem);
537 cdTextElem = doc.createElement(
_(
"isrc"));
539 cdTextMain.appendChild(cdTextElem);
541 cdTextElem = doc.createElement(
_(
"message"));
543 cdTextMain.appendChild(cdTextElem);
545 trackElem.appendChild(cdTextMain);
548 QDomElement copyElem = doc.createElement(
_(
"copy_protection"));
549 copyElem.appendChild(doc.createTextNode(
552 trackElem.appendChild(copyElem);
555 copyElem = doc.createElement(
_(
"pre_emphasis"));
556 copyElem.appendChild(doc.createTextNode(
_(
"no")));
557 trackElem.appendChild(copyElem);
559 contentsElem.appendChild(trackElem);
564 docElem->appendChild(contentsElem);
570 qDebug(
"K3BExportPlugin::start()");
574 if (result)
return result;
577 if (!
m_url.isLocalFile())
581 QString k3b_filename =
m_url.path();
582 QFileInfo fi(k3b_filename);
583 QString base = fi.completeBaseName();
588 out_dir = fi.absolutePath() + QDir::separator() + base +
_(
".dir");
592 out_dir = fi.absolutePath();
595 qDebug(
"out_dir = '%s'",
DBG(out_dir));
596 qDebug(
"out_pattern = '%s'",
DBG(out_pattern));
601 QList<unsigned int> tracks;
602 selection(&tracks, &selection_left, &selection_right,
false);
605 if ((tracks.count() != 1) && (tracks.count() != 2)) {
606 qWarning(
"sorry, K3b can not handle %u tracks", tracks.count());
608 "Only mono and stereo files can be used for an audio CD. " 609 "You can either deselect some channels or export the file " 610 "in a different file format that supports mono and stereo " 611 "only (for example FLAC) and then try again." 616 bool selected_something = (selection_left != selection_right);
617 bool selected_all = ( (selection_left == 0) &&
619 bool enable_selection_only = selected_something && !selected_all;
621 if (!selection_only) {
633 unsigned int first = 1;
636 QString pat = out_pattern;
640 QDir dir(out_dir, pat);
642 files = dir.entryList();
644 for (
unsigned int i = first; i < (first + count); ++i) {
646 QRegExp rx(
_(
"^(") + name +
_(
")$"), Qt::CaseInsensitive);
647 QStringList matches = files.filter(rx);
648 if (matches.count() > 0) first = i + 1;
650 qDebug(
"found first usable index -> %d", first);
656 for (
unsigned int i = 0; i < count; ++i) {
657 m_block_info[i].m_filename = out_dir + QDir::separator() +
661 result =
saveBlocks(selection_only, out_dir, out_pattern);
670 "A K3b project file has been created and audio files have " 672 "Should I start K3b and open the audio CD project now?" 673 )) == KMessageBox::Yes) {
676 args << k3b_filename;
677 if (!QProcess::startDetached(
_(
"k3b"), args)) {
687 const QString &out_dir,
688 const QString &out_pattern)
697 QList<Kwave::FileProperty> unsupported_properties;
706 if (!unsupported_properties.isEmpty()) {
708 file_info.
set(p, QVariant());
722 params << out_dir + QDir::separator() + first_filename;
725 params << (selection_only ?
_(
"1") :
_(
"0"));
738 KZip zip(k3b_filename);
740 bool ok = zip.open(QIODevice::WriteOnly);
741 if (!ok)
return -EIO;
745 zip.setCompression(KZip::NoCompression);
746 zip.setExtraField(KZip::NoExtraField);
747 zip.writeFile(
_(
"mimetype"), app_type);
752 out.open(QIODevice::WriteOnly);
755 QDomDocument xmlDoc(
_(
"k3b_audio_project"));
757 xmlDoc.appendChild(xmlDoc.createProcessingInstruction(
758 _(
"xml"),
_(
"version=\"1.0\" encoding=\"UTF-8\"")
760 QDomElement docElem = xmlDoc.createElement(
_(
"k3b_audio_project"));
761 xmlDoc.appendChild(docElem);
763 QTextStream xmlStream(&out);
764 xmlDoc.save(xmlStream, 0);
768 zip.setCompression(KZip::NoCompression);
769 zip.setExtraField(KZip::NoExtraField);
770 zip.writeFile(
_(
"maindata.xml"), xml.data());
780 QStringList patterns;
781 patterns <<
_(
"[%title] ([%artist])");
782 patterns <<
_(
"[%title], [%artist]");
783 patterns <<
_(
"[%artist]: [%title]");
784 patterns <<
_(
"[%artist] - [%title]");
789 #include "K3BExportPlugin.moc"
int saveK3BFile(const QString &k3b_filename)
void emitCommand(const QString &command)
K3BExportPlugin(QObject *parent, const QVariantList &args)
overwrite_policy_t m_overwrite_policy
QWidget * parentWidget() const
Kwave::MetaDataList & metaData()
export_location_t m_export_location
QVariant get(FileProperty key) const
Kwave::SignalManager & signalManager()
static int sorry(QWidget *widget, QString message, QString caption=QString())
virtual QString name() const
virtual sample_index_t pos() const
static int questionYesNo(QWidget *widget, QString message, QString caption=QString(), const QString buttonYes=QString(), const QString buttonNo=QString(), const QString &dontAskAgainName=QString())
QString createFileName(const QString &pattern, unsigned int index)
static QString mimeTypeOf(const QUrl &url)
Kwave::PluginManager & manager() const
void set(FileProperty key, const QVariant &value)
QListIterator< Kwave::Label > LabelListIterator
virtual int start(QStringList ¶ms) Q_DECL_OVERRIDE
int executePlugin(const QString &name, QStringList *params)
static QString unescape(const QString &text)
static QString escapeForFileName(const QString &text)
virtual QList< Kwave::FileProperty > unsupportedProperties(const QList< Kwave::FileProperty > &properties_to_check)
const QMap< FileProperty, QVariant > properties() const
void saveDocumentData(QDomElement *docElem)
virtual QString name() const
int interpreteParameters(QStringList ¶ms)
void saveGeneralDocumentData(QDomElement *part)
virtual void load(QStringList ¶ms) Q_DECL_OVERRIDE
virtual sample_index_t signalLength()
static QStringList knownPatterns()
void setBits(unsigned int bits)
static Kwave::Encoder * encoder(const QString &mimetype_name)
#define KWAVE_PLUGIN(name, class)
void scanBlocksToSave(const QString &base, sample_index_t selection_left, sample_index_t selection_right)
static QString escape(const QString &text)
virtual QString description() const
virtual QStringList * setup(QStringList ¶ms) Q_DECL_OVERRIDE
bool detectBlockMetaData(const QString &text, const QString &pattern, BlockInfo &block)
#define K3B_PROJECT_MIME_TYPE
QVector< BlockInfo > m_block_info
virtual ~K3BExportPlugin() Q_DECL_OVERRIDE
virtual sample_index_t selection(QList< unsigned int > *tracks=Q_NULLPTR, sample_index_t *left=Q_NULLPTR, sample_index_t *right=Q_NULLPTR, bool expand_if_empty=false)
int saveBlocks(bool selection_only, const QString &out_dir, const QString &out_pattern)