summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Eschenbacher <[email protected]>2017-04-22 21:14:35 +0200
committerThomas Eschenbacher <[email protected]>2017-04-22 21:14:35 +0200
commit4fe719ff71c31e7bb1735519788b6cdb8844740d (patch)
tree70c424de13c973d6a65307b39c46c8d2248987f0
parent4ebea305914b65e642a32f8e4c57dbd8f216cf2c (diff)
new plugin: export to K3B project file
-rw-r--r--AUTHORS5
-rw-r--r--CHANGES1
-rw-r--r--CMakeLists.txt1
-rw-r--r--LICENSES12
-rw-r--r--doc/en/index.docbook240
-rw-r--r--plugins/CMakeLists.txt1
-rw-r--r--plugins/export_k3b/CMakeLists.txt43
-rw-r--r--plugins/export_k3b/K3BExportDialog.cpp95
-rw-r--r--plugins/export_k3b/K3BExportDialog.h95
-rw-r--r--plugins/export_k3b/K3BExportPlugin.cpp789
-rw-r--r--plugins/export_k3b/K3BExportPlugin.h179
-rw-r--r--plugins/export_k3b/K3BExportWidget.cpp125
-rw-r--r--plugins/export_k3b/K3BExportWidget.h83
-rw-r--r--plugins/export_k3b/K3BExportWidgetBase.ui204
-rw-r--r--plugins/export_k3b/kwaveplugin_export_k3b.desktop.in11
-rw-r--r--plugins/saveblocks/SaveBlocksPlugin.cpp9
-rw-r--r--scripts/screenshots.kwave12
17 files changed, 1898 insertions, 7 deletions
diff --git a/AUTHORS b/AUTHORS
index d113f27..588b313 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -62,6 +62,11 @@ Sven-Steffen Arndt <[email protected]>
minor contributors, copyright holders and others
================================================
+Sebastian Trueg <[email protected]>,
+Gustavo Pichorim Boiko <[email protected]>
+Michal Malek <[email protected]>
+ * parts of plugins/export_k3b/K3BExportPlugin.cpp
+
Aaron Holtzman <[email protected]>
* libkwave/cpu_accel.cpp
diff --git a/CHANGES b/CHANGES
index d41d049..e38d2fe 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,7 @@ xx.xx.x [xxxx-xx-xx]
* reduced flicker of position widget
* bugfix: deleting labels per menu did not work
+ * new plugin: export to K3B project file
17.04.0 [2017-03-19]
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 70b6c87..b509ab1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -219,6 +219,7 @@ INCLUDE(GenerateExportHeader)
INCLUDE(FeatureSummary)
FIND_PACKAGE(KF5 REQUIRED COMPONENTS
+ Archive
Completion
Config
ConfigWidgets
diff --git a/LICENSES b/LICENSES
index c20a07a..56bda8a 100644
--- a/LICENSES
+++ b/LICENSES
@@ -630,6 +630,18 @@ COMPLETE LIST OF FILES AND THEIR LICENSE
plugins/debug/DebugPlugin.h GPL2+
plugins/debug/kwaveplugin_debug.desktop.in GPL2+
+ plugins/export_k3b/CMakeLists.txt BSD (3 clause)
+ plugins/export_k3b/K3BExportDialog.cpp GPL2+
+ plugins/export_k3b/K3BExportDialog.h GPL2+
+ plugins/export_k3b/K3BExportPlugin.cpp GPL2+ / Sebastian Trueg <[email protected]>,
+ Gustavo Pichorim Boiko <[email protected]>
+ Michal Malek <[email protected]>
+ plugins/export_k3b/K3BExportPlugin.h GPL2+
+ plugins/export_k3b/K3BExportWidget.cpp GPL2+
+ plugins/export_k3b/K3BExportWidget.h GPL2+
+ plugins/export_k3b/K3BExportWidegetBase.ui GPL2+
+ plugins/export_k3b/kwaveplugin_export_k3b.desktop.in GPL2+
+
plugins/goto/CMakeLists.txt BSD (3 clause)
plugins/goto/GotoDialog.cpp GPL2+
plugins/goto/GotoDialog.h GPL2+
diff --git a/doc/en/index.docbook b/doc/en/index.docbook
index 84f17b1..4079b4f 100644
--- a/doc/en/index.docbook
+++ b/doc/en/index.docbook
@@ -17,6 +17,7 @@
<!ENTITY url_flac "http://flac.sourceforge.net/">
<!ENTITY url_homepage "http://kwave.sourceforge.net/">
<!ENTITY url_id3lib "http://id3lib.sourceforge.net/">
+ <!ENTITY url_k3b "http://www.k3b.org/">
<!ENTITY url_lame "http://lame.sourceforge.net/">
<!ENTITY url_levelmeter "https://web.archive.org/web/*/http://www.rikkus.info/esound-level-meter/">
<!ENTITY url_libaudiofile "http://www.68k.org/~michael/audiofile/">
@@ -147,6 +148,7 @@
<!ENTITY no-i18n-plugin_codec_ogg "codec_ogg">
<!ENTITY no-i18n-plugin_codec_wav "codec_wav">
<!ENTITY no-i18n-plugin_debug "debug">
+ <!ENTITY no-i18n-plugin_export_k3b "export_k3b">
<!ENTITY no-i18n-plugin_fileinfo "fileinfo">
<!ENTITY no-i18n-plugin_goto "goto">
<!ENTITY no-i18n-plugin_insert_at "insert_at">
@@ -4456,6 +4458,9 @@
<indexdiv><title>d</title>
<indexentry><primaryie><link linkend="plugin_sect_debug" endterm="plugin_title_debug"/></primaryie></indexentry>
</indexdiv>
+ <indexdiv><title>e</title>
+ <indexentry><primaryie><link linkend="plugin_sect_export_k3b" endterm="plugin_title_export_k3b"/></primaryie></indexentry>
+ </indexdiv>
<indexdiv><title>f</title>
<indexentry><primaryie><link linkend="plugin_sect_fileinfo" endterm="plugin_title_fileinfo"/></primaryie></indexentry>
</indexdiv>
@@ -5355,6 +5360,227 @@
</variablelist>
</sect1>
+ <!-- @[email protected] export_k3b -->
+ <sect1 id="plugin_sect_export_k3b"><title id="plugin_title_export_k3b">&no-i18n-plugin_export_k3b; (Export to K3B Project)</title>
+ <screenshot>
+ <screeninfo>Screenshot</screeninfo>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="kwave-plugin-export_k3b.png" format="PNG"/>
+ </imageobject>
+ <textobject>
+ <phrase>Screenshot of the K3B Export Plugin</phrase>
+ </textobject>
+ </mediaobject>
+ </screenshot>
+ <variablelist>
+ <varlistentry>
+ <term><emphasis role="bold">&i18n-plugin_lbl_internal_name;</emphasis></term>
+ <listitem><para><literal>&no-i18n-plugin_export_k3b;</literal></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><emphasis role="bold">&i18n-plugin_lbl_type;</emphasis></term>
+ <listitem><para>function</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><emphasis role="bold">&i18n-plugin_lbl_description;</emphasis></term>
+ <listitem>
+ <para>
+ Saves all sections between markers into a separate file and creates
+ a K3B project file. After having successfully written all files it
+ is possible to start <ulink url="&url_k3b;">K3B</ulink> and
+ burn the result to an audio CD.
+ This is useful for splitting a file with a recording that consists
+ of several parts, which are separated by labels, and then burn it
+ to an audio CD with multiple tracks, including CD text meta data
+ which is extracted from the descriptions of the labels.
+ </para>
+ <para>
+ (This plugin is internally using the
+ <link linkend="plugin_sect_saveblocks" endterm="plugin_title_saveblocks"/>
+ plugin.)
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><emphasis role="bold">&i18n-plugin_lbl_parameters;</emphasis></term>
+ <listitem>
+ <variablelist>
+ <varlistentry>
+ <term><replaceable>filename</replaceable></term>
+ <listitem>
+ <para>
+ The name of the K3B project file, will be used as
+ base name for the exported file names.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>pattern</replaceable></term>
+ <listitem>
+ <para>
+ A pattern that will be used for detecting
+ title and artist from the label at the start
+ of a section.
+ It supports the following wildcards which
+ will be replaced by the corresponding content
+ when creating the CD text meta data:
+ </para>
+ <informaltable frame='all'>
+ <tgroup cols='2'>
+ <thead>
+ <row>
+ <entry align='left'>wildcard</entry>
+ <entry align='left'>description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>&no-i18n-tag;<command>[%artist]</command></entry>
+ <entry>
+ Will be replaced with the artist that performed
+ the corresponding block or alternatively the author.
+ </entry>
+ </row>
+ <row>
+ <entry>&no-i18n-tag;<command>[%title]</command></entry>
+ <entry>
+ Will be replaced with the title of the block, which is taken
+ from the descriptive text of the label at the
+ <emphasis>start</emphasis> of the block.
+ If that text is empty it will fall back to the title
+ of the file (see file information item
+ "<link linkend="INF_NAME">Name</link>").
+ If this also does not exist, it will fall back to the
+ base file name as described above.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ Example: <quote><command><literal>[%title] ([%artist])</literal></command></quote>
+ will detect author <quote><command><literal>Beethoven</literal></command></quote> and title
+ <quote><command><literal>Symphony No. 5</literal></command></quote> from the string
+ <quote><command><literal>Symphony No. 5 (Beethoven)</literal></command></quote>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>selection only</replaceable></term>
+ <listitem>
+ <para>
+ <informaltable frame='all'>
+ <tgroup cols='2'>
+ <thead>
+ <row>
+ <entry align='left'>value</entry>
+ <entry align='left'>description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>&no-i18n-tag;<command>0</command></entry>
+ <entry>
+ Save all sections of the whole file.
+ </entry>
+ </row>
+ <row>
+ <entry>&no-i18n-tag;<command>1</command></entry>
+ <entry>
+ Save only the sections that are within the
+ current selection. If nothing is selected,
+ the whole file will be saved.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>export location</replaceable></term>
+ <listitem>
+ <para>
+ Determines where the blocks should be saved.
+ <informaltable frame='all'>
+ <tgroup cols='2'>
+ <thead>
+ <row>
+ <entry align='left'>value</entry>
+ <entry align='left'>description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>&no-i18n-tag;<command>0</command></entry>
+ <entry>
+ Save to the same directory as the
+ K3B project file.
+ </entry>
+ </row>
+ <row>
+ <entry>&no-i18n-tag;<command>1</command></entry>
+ <entry>
+ Save into a sub directory of the directory
+ of the K3B project file, using the K3B
+ project file name as base and appending
+ <quote><command><literal>.dir</literal></command></quote>.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>overwrite policy</replaceable></term>
+ <listitem>
+ <para>
+ Determines where the numbering should start.
+ <informaltable frame='all'>
+ <tgroup cols='2'>
+ <thead>
+ <row>
+ <entry align='left'>value</entry>
+ <entry align='left'>description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>&no-i18n-tag;<command>0</command></entry>
+ <entry>
+ Always start with index 1, with the risk
+ of overwriting existing files.
+ </entry>
+ </row>
+ <row>
+ <entry>&no-i18n-tag;<command>1</command></entry>
+ <entry>
+ Continue after the index of the highest
+ index that already exists, this avoids
+ overwriting existing files.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect1>
+
<!-- @[email protected] fileinfo -->
<sect1 id="plugin_sect_fileinfo"><title id="plugin_title_fileinfo">&no-i18n-plugin_fileinfo; (File Info)</title>
<screenshot>
@@ -6618,7 +6844,7 @@
<row>
<entry>&no-i18n-tag;<command>[%title]</command></entry>
<entry>
- Will be replaced with the title the block, which is taken
+ Will be replaced with the title of the block, which is taken
from the descriptive text of the label at the
<emphasis>start</emphasis> of the block.
If that text is empty it will fall back to the title
@@ -7722,6 +7948,18 @@
plugins/record/Record-PulseAudio.h
</para>
</listitem>
+ <listitem>
+ <para><emphasis role="bold">
+ Sebastian Trueg <email>[email protected]</email>,
+
+ Gustavo Pichorim Boiko <email>[email protected]</email>,
+
+ Michal Malek <email>[email protected]</email>
+ </emphasis></para>
+ <para>
+ parts of plugins/export_k3b/K3BExportPlugin.cpp
+ </para>
+ </listitem>
</itemizedlist>
</para>
</sect1>
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index e2ee803..0a2d9de 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -105,6 +105,7 @@ ADD_SUBDIRECTORY( codec_mp3 ) # needs libmad + id3lib + "lame"
ADD_SUBDIRECTORY( codec_ogg ) # needs libogg and (libvorbis or libopus)
ADD_SUBDIRECTORY( codec_wav ) # needs libaudiofile
ADD_SUBDIRECTORY( debug )
+ADD_SUBDIRECTORY( export_k3b )
ADD_SUBDIRECTORY( fileinfo )
ADD_SUBDIRECTORY( goto )
ADD_SUBDIRECTORY( lowpass )
diff --git a/plugins/export_k3b/CMakeLists.txt b/plugins/export_k3b/CMakeLists.txt
new file mode 100644
index 0000000..caee206
--- /dev/null
+++ b/plugins/export_k3b/CMakeLists.txt
@@ -0,0 +1,43 @@
+#############################################################################
+## Kwave - plugins/export_k3b/CMakeLists.txt
+## -------------------
+## begin : Thu Mar 23 2017
+## copyright : (C) 2017 by Thomas Eschenbacher
+## email : [email protected]
+#############################################################################
+#
+#############################################################################
+# #
+# Redistribution and use in source and binary forms, with or without #
+# modification, are permitted provided that the following conditions #
+# are met: #
+# #
+# 1. Redistributions of source code must retain the above copyright #
+# notice, this list of conditions and the following disclaimer. #
+# 2. Redistributions in binary form must reproduce the above copyright #
+# notice, this list of conditions and the following disclaimer in the #
+# documentation and/or other materials provided with the distribution. #
+# #
+# For details see the accompanying cmake/COPYING-CMAKE-SCRIPTS file. #
+# #
+#############################################################################
+
+SET(plugin_export_k3b_LIB_SRCS
+ K3BExportDialog.cpp
+ K3BExportPlugin.cpp
+ K3BExportWidget.cpp
+)
+
+SET(plugin_export_k3b_LIB_UI
+ K3BExportWidgetBase.ui
+)
+
+SET(plugin_export_k3b_LIBS
+ KF5::Archive
+)
+
+KWAVE_PLUGIN(export_k3b)
+
+#############################################################################
+#############################################################################
+
diff --git a/plugins/export_k3b/K3BExportDialog.cpp b/plugins/export_k3b/K3BExportDialog.cpp
new file mode 100644
index 0000000..47f276b
--- /dev/null
+++ b/plugins/export_k3b/K3BExportDialog.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * K3BExportDialog.cpp - Extended KwaveFileDialog for exporting to K3B
+ * -------------------
+ * begin : Thu Apr 13 2017
+ * copyright : (C) 2017 by Thomas Eschenbacher
+ * email : [email protected]
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "config.h"
+
+#include <QString>
+#include <QUrl>
+
+#include <KComboBox>
+#include <KUrlComboBox>
+
+#include "libkwave/String.h"
+
+#include "K3BExportDialog.h"
+#include "K3BExportWidget.h"
+
+//***************************************************************************
+Kwave::K3BExportDialog::K3BExportDialog(
+ const QString &startDir,
+ const QString &filter,
+ QWidget *parent,
+ const QUrl &last_url,
+ const QString &last_ext,
+ QString &pattern,
+ bool selection_only,
+ bool have_selection,
+ Kwave::K3BExportPlugin::export_location_t export_location,
+ Kwave::K3BExportPlugin::overwrite_policy_t overwrite_policy
+)
+ :Kwave::FileDialog(startDir, Kwave::FileDialog::SaveFile, filter, parent,
+ last_url, last_ext),
+ m_widget(new(std::nothrow) Kwave::K3BExportWidget(
+ this, pattern, selection_only, have_selection,
+ export_location, overwrite_policy
+ ))
+{
+ Q_ASSERT(m_widget);
+ setCustomWidget(m_widget);
+}
+
+//***************************************************************************
+Kwave::K3BExportDialog::~K3BExportDialog()
+{
+ if (m_widget) delete m_widget;
+ m_widget = 0;
+}
+
+// //***************************************************************************
+QString Kwave::K3BExportDialog::pattern() const
+{
+ Q_ASSERT(m_widget);
+ return (m_widget) ? m_widget->pattern() : _("");
+}
+
+//***************************************************************************
+bool Kwave::K3BExportDialog::selectionOnly() const
+{
+ Q_ASSERT(m_widget);
+ return (m_widget) ? m_widget->selectionOnly() : false;
+}
+
+//***************************************************************************
+Kwave::K3BExportPlugin::export_location_t
+ Kwave::K3BExportDialog::exportLocation() const
+{
+ Q_ASSERT(m_widget);
+ return (m_widget) ? m_widget->exportLocation() :
+ Kwave::K3BExportPlugin::EXPORT_TO_SUB_DIR;
+}
+
+//***************************************************************************
+Kwave::K3BExportPlugin::overwrite_policy_t
+ Kwave::K3BExportDialog::overwritePolicy() const
+{
+ Q_ASSERT(m_widget);
+ return (m_widget) ? m_widget->overwritePolicy() :
+ Kwave::K3BExportPlugin::USE_NEW_FILE_NAMES;
+}
+
+//***************************************************************************
+//***************************************************************************
diff --git a/plugins/export_k3b/K3BExportDialog.h b/plugins/export_k3b/K3BExportDialog.h
new file mode 100644
index 0000000..7080514
--- /dev/null
+++ b/plugins/export_k3b/K3BExportDialog.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * K3BExportDialog.h - Extended KwaveFileDialog for exporting to K3B
+ * -------------------
+ * begin : Thu Apr 13 2017
+ * copyright : (C) 2017 by Thomas Eschenbacher
+ * email : [email protected]
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef K3B_EXPORT_DIALOG_H
+#define K3B_EXPORT_DIALOG_H
+
+#include "config.h"
+
+#include <QObject>
+#include <QString>
+#include <QWidget>
+
+#include "K3BExportPlugin.h"
+#include "libgui/FileDialog.h"
+
+class QUrl;
+
+namespace Kwave
+{
+
+ class K3BExportWidget;
+
+ class K3BExportDialog: public Kwave::FileDialog
+ {
+ Q_OBJECT
+ public:
+
+ /**
+ * Constructor.
+ * @see KFileFialog
+ * @param startDir the start directory
+ * @param filter string with a file type filter
+ * @param parent the parent widget
+ * @param last_url the last used URL
+ * @param last_ext the last used extension (preset only)
+ * @param pattern the pattern used for detecting title and artist
+ * @param selection_only if true, save only the selection
+ * @param have_selection if true, there is a selection
+ * @param export_location where to export files with tracks
+ * @param overwrite_policy overwrite existing files or use a new name
+ */
+ K3BExportDialog(
+ const QString &startDir,
+ const QString &filter,
+ QWidget *parent,
+ const QUrl &last_url,
+ const QString &last_ext,
+ QString &pattern,
+ bool selection_only,
+ bool have_selection,
+ Kwave::K3BExportPlugin::export_location_t export_location,
+ Kwave::K3BExportPlugin::overwrite_policy_t overwrite_policy
+ );
+
+ /** Destructor */
+ virtual ~K3BExportDialog();
+
+ /** returns the title/artist detection pattern (as is, not escaped) */
+ QString pattern() const;
+
+ /** returns true if only the selection should be saved */
+ bool selectionOnly() const;
+
+ /** returns export location of the files of the tracks */
+ Kwave::K3BExportPlugin::export_location_t exportLocation() const;
+
+ /** returns the file overwrite policy */
+ Kwave::K3BExportPlugin::overwrite_policy_t overwritePolicy() const;
+
+ private:
+
+ /** the widget with extra settings for K3B export */
+ Kwave::K3BExportWidget *m_widget;
+
+ };
+}
+
+#endif /* K3B_EXPORT_DIALOG_H */
+
+//***************************************************************************
+//***************************************************************************
diff --git a/plugins/export_k3b/K3BExportPlugin.cpp b/plugins/export_k3b/K3BExportPlugin.cpp
new file mode 100644
index 0000000..8e9054b
--- /dev/null
+++ b/plugins/export_k3b/K3BExportPlugin.cpp
@@ -0,0 +1,789 @@
+/*************************************************************************
+ * K3BExportPlugin.cpp - export of K3B project files
+ * -------------------
+ * begin : Thu Apr 13 2017
+ * copyright : (C) 2017 by Thomas Eschenbacher
+ * email : [email protected]
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "config.h"
+
+#include <errno.h>
+
+#include <QBuffer>
+#include <QByteArray>
+#include <QDir>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QFileInfo>
+#include <QIODevice>
+#include <QMap>
+#include <QProcess>
+#include <QRegExp>
+#include <QTextStream>
+
+#include <KLocalizedString> // for the i18n macro
+#include <KZip>
+
+#include "libkwave/CodecManager.h"
+#include "libkwave/Encoder.h"
+#include "libkwave/FileInfo.h"
+#include "libkwave/Label.h"
+#include "libkwave/LabelList.h"
+#include "libkwave/Logger.h"
+#include "libkwave/MessageBox.h"
+#include "libkwave/MetaDataList.h"
+#include "libkwave/Parser.h"
+#include "libkwave/Plugin.h"
+#include "libkwave/PluginManager.h"
+#include "libkwave/SignalManager.h"
+#include "libkwave/String.h"
+#include "libkwave/Utils.h"
+
+#include "K3BExportDialog.h"
+#include "K3BExportPlugin.h"
+
+KWAVE_PLUGIN(export_k3b, K3BExportPlugin)
+
+/** mime type of K3B project files */
+#define K3B_PROJECT_MIME_TYPE "application/x-k3b"
+
+/** file suffix of K3B project files */
+#define K3B_FILE_SUFFIX _("*.k3b")
+
+/** number of digits to use for out files */
+#define OUTFILE_DIGITS 4
+
+/** file name pattern for out files */
+#define OUTFILE_PATTERN (_("[%0") + _("%1nr]").arg(OUTFILE_DIGITS))
+
+/** file suffix for out files */
+#define OUTFILE_SUFFIX _(".wav")
+
+//***************************************************************************
+Kwave::K3BExportPlugin::K3BExportPlugin(QObject *parent,
+ const QVariantList &args)
+ :Kwave::Plugin(parent, args),
+ m_url(),
+ m_pattern(),
+ m_selection_only(false),
+ m_export_location(EXPORT_TO_SUB_DIR),
+ m_overwrite_policy(USE_NEW_FILE_NAMES),
+ m_block_info()
+{
+}
+
+//***************************************************************************
+Kwave::K3BExportPlugin::~K3BExportPlugin()
+{
+}
+
+//***************************************************************************
+int Kwave::K3BExportPlugin::interpreteParameters(QStringList &params)
+{
+ bool ok;
+ QString param;
+
+ // evaluate the parameter list
+ if (params.count() != 5)
+ return -EINVAL;
+
+ // the selected URL
+ m_url = QUrl::fromUserInput(Kwave::Parser::unescape(params[0]));
+ if (!m_url.isValid()) return -EINVAL;
+
+ // label pattern
+ m_pattern = Kwave::Parser::unescape(params[1]);
+
+ // selection only
+ param = params[2];
+ int v = param.toInt(&ok);
+ Q_ASSERT(ok);
+ if (!ok) return -EINVAL;
+ m_selection_only = (v != 0);
+
+ // export location
+ param = params[3];
+ int where = param.toInt(&ok);
+ Q_ASSERT(ok);
+ if (!ok) return -EINVAL;
+ if ((where != EXPORT_TO_SAME_DIR) &&
+ (where != EXPORT_TO_SUB_DIR)) return -EINVAL;
+ m_export_location = static_cast<export_location_t>(where);
+
+ // overwrite policy
+ param = params[4];
+ int overwrite = param.toInt(&ok);
+ Q_ASSERT(ok);
+ if (!ok) return -EINVAL;
+ if ((overwrite != OVERWRITE_EXISTING_FILES) &&
+ (overwrite != USE_NEW_FILE_NAMES)) return -EINVAL;
+ m_overwrite_policy = static_cast<overwrite_policy_t>(overwrite);
+
+ return 0;
+}
+
+//***************************************************************************
+void Kwave::K3BExportPlugin::scanBlocksToSave(const QString &base,
+ sample_index_t selection_left,
+ sample_index_t selection_right)
+{
+ sample_index_t block_start;
+ sample_index_t block_end = 0;
+
+ Kwave::LabelList labels(signalManager().metaData());
+ Kwave::LabelListIterator it(labels);
+ Kwave::Label label = (it.hasNext()) ? it.next() : Kwave::Label();
+
+ // get the title of the whole file, in case that a block does not have
+ // an own title
+ FileInfo info(signalManager().metaData());
+ QString file_title = info.get(INF_NAME).toString();
+ QString file_artist = info.get(INF_AUTHOR).toString();
+
+ // fallback: if there is no INF_NAME either, fall back to the file
+ // name as last resort
+ if (!file_title.length()) file_title = base;
+
+ m_block_info.clear();
+ QString prev_title = file_title;
+ for (unsigned int index = 1; ; ++index) {
+ block_start = block_end;
+ block_end = (label.isNull()) ? signalLength() : label.pos();
+
+ QString block_title = (!label.isNull() && label.name().length()) ?
+ label.name() : prev_title;
+
+ if ((block_end > selection_left) && (block_start <= selection_right)) {
+ BlockInfo block;
+
+ // init and set reasonable defaults
+ block.m_index = index;
+ block.m_filename = QString();
+ block.m_start = block_start;
+ block.m_length = block_end - block_start;
+ block.m_title = block_title;
+ block.m_artist = file_artist;
+
+ // detect title and artist
+ detectBlockMetaData(block_title, m_pattern, block);
+ m_block_info.append(block);
+
+ prev_title = block.m_title;
+
+// qDebug("#%d [%llu...%llu]", index, block_start, block_end);
+// qDebug(" title = '%s'", DBG(block.m_title));
+// qDebug(" artist = '%s'", DBG(block.m_artist));
+ }
+
+ if (label.isNull()) break;
+ label = (it.hasNext()) ? it.next() : Kwave::Label();
+ }
+}
+
+//***************************************************************************
+QString Kwave::K3BExportPlugin::createFileName(const QString &pattern,
+ unsigned int index)
+{
+ QString name = pattern;
+ QString num = _("%1").arg(index, OUTFILE_DIGITS, 10, QLatin1Char('0'));
+ name.replace(OUTFILE_PATTERN, num);
+ name += OUTFILE_SUFFIX;
+ return name;
+}
+
+//***************************************************************************
+bool Kwave::K3BExportPlugin::detectBlockMetaData(
+ const QString &text,
+ const QString &pattern,
+ Kwave::K3BExportPlugin::BlockInfo &block
+)
+{
+ if (!pattern.length()) {
+ // auto detect -> try all known patterns
+ foreach (const QString &p, knownPatterns())
+ if (detectBlockMetaData(text, p, block))
+ return true;
+ return false;
+ }
+
+ // list of placeholders and pointers to the resulting strings
+ QMap <QString, QString *> map_patterns;
+ map_patterns.insert(_("[%artist]"), &block.m_artist);
+ map_patterns.insert(_("[%title]"), &block.m_title);
+
+ // try to find the placeholders within the pattern
+ // NOTE: we use a map because it will automatically be sorted (by pos)
+ QString pattern_esc = Kwave::Parser::escape(pattern);
+ QMap <int, QString *> map_result;
+ foreach (const QString &placeholder, map_patterns.keys()) {
+ QString placeholder_esc;
+ placeholder_esc = Kwave::Parser::escape(placeholder);
+ if (pattern_esc.contains(placeholder_esc)) {
+ const QString rx_string = _("(.+)");
+ int pos = pattern.indexOf(placeholder);
+ pattern_esc.replace(placeholder_esc, rx_string);
+ map_result.insert(pos, map_patterns[placeholder]);
+ }
+ }
+ if (map_result.isEmpty())
+ return false; // no placeholders found in the patterns
+
+ // relax the pattern: turn single whitespace to one or more whitespaces
+ pattern_esc.replace(QRegExp(_("(\\\\\\s)+")), _("\\s+"));
+
+ // try to match the pattern on the given text
+ QRegExp rx(pattern_esc, Qt::CaseInsensitive);
+ if (!rx.exactMatch(text.trimmed()))
+ return false; // does not match :-(
+
+ // we found a match
+ // -> now map the results into the corresponding result strings
+ for (int index = 0; index < map_result.count(); ++index) {
+ QString value = rx.cap(index + 1).trimmed();
+ if (value.length()) {
+ QString *result = map_result[map_result.keys()[index]];
+ if (result) *result = value;
+ }
+ }
+
+ return true;
+}
+
+//***************************************************************************
+void Kwave::K3BExportPlugin::load(QStringList &params)
+{
+ Q_UNUSED(params);
+
+ QString menu_path = _("File/Save/%1").arg(i18nc(
+ "menu: /File/Save/Export to K3B Project...",
+ "Export to K3B Project..."
+ ));
+ emitCommand(_("menu(plugin:setup(export_k3b),%1%2)").arg(
+ menu_path).arg(_("/#group(@SIGNAL)")));
+ emitCommand(_("menu(plugin:setup(export_k3b),%1%2)").arg(
+ menu_path).arg(_("/#icon(application-x-k3b)")));
+}
+
+//***************************************************************************
+QStringList *Kwave::K3BExportPlugin::setup(QStringList &params)
+{
+ // try to interpret the previous parameters
+ interpreteParameters(params);
+
+ sample_index_t selection_left = 0;
+ sample_index_t selection_right = 0;
+ selection(0, &selection_left, &selection_right, false);
+
+ // enable the "selection only" checkbox only if there is something
+ // selected but not everything
+ bool selected_something = (selection_left != selection_right);
+ bool selected_all = ((selection_left == 0) &&
+ (selection_right + 1 >= signalLength()));
+ bool enable_selection_only = selected_something && !selected_all;
+
+ // show a "File / Save As..." dialog for the *.k3b file
+ QPointer<Kwave::K3BExportDialog> dialog =
+ new(std::nothrow) Kwave::K3BExportDialog(
+ _("kfiledialog:///kwave_export_k3b"),
+ K3B_FILE_SUFFIX + _("|") + i18nc(
+ "file type filter when exporting to K3B",
+ "K3B project file (*.k3b)"
+ ),
+ parentWidget(),
+ QUrl::fromUserInput(signalName()),
+ _("*.k3b"),
+ m_pattern,
+ m_selection_only,
+ enable_selection_only,
+ m_export_location,
+ m_overwrite_policy
+ );
+ if (!dialog) return 0;
+
+ dialog->setWindowTitle(description());
+ if (dialog->exec() != QDialog::Accepted) {
+ delete dialog;
+ return 0;
+ }
+
+ QStringList *list = new(std::nothrow) QStringList();
+ Q_ASSERT(list);
+ if (!list) {
+ delete dialog;
+ return 0;
+ }
+
+ // user has pressed "OK"
+ QUrl url = dialog->selectedUrl();
+ if (url.isEmpty()) {
+ delete dialog;
+ delete list;
+ return 0;
+ }
+
+ QString name = url.path();
+ QFileInfo path(name);
+
+ // add the correct extension if necessary
+ if (path.suffix() != K3B_FILE_SUFFIX.mid(2))
+ url.setPath(name + K3B_FILE_SUFFIX.mid(1));
+
+ name = Kwave::Parser::escape(url.toString());
+ QString pattern = Kwave::Parser::escape(dialog->pattern());
+ int export_location = static_cast<int>(dialog->exportLocation());
+ int overwrite_policy = static_cast<int>(dialog->overwritePolicy());
+ bool selection_only = (enable_selection_only) ?
+ dialog->selectionOnly() : m_selection_only;
+
+ *list << name; // url
+ *list << pattern; // pattern
+ *list << QString::number(selection_only); // selection only
+ *list << QString::number(export_location); // export location
+ *list << QString::number(overwrite_policy); // overwrite policy
+
+ emitCommand(_("plugin:execute(export_k3b,") +
+ name + _(",") + pattern + _(",") +
+ QString::number(selection_only) + _(",") +
+ QString::number(export_location) + _(",") +
+ QString::number(overwrite_policy) + _(")")
+ );
+
+ if (dialog) delete dialog;
+ return list;
+}
+
+//***************************************************************************
+/*
+ * taken from K3B, libk3b/projects/k3bdoc.cpp
+ *
+ * Copyright (C) 2003-2008 Sebastian Trueg <[email protected]>
+ *
+ */
+void Kwave::K3BExportPlugin::saveGeneralDocumentData(QDomElement *part)
+{
+ QDomDocument doc = part->ownerDocument();
+ QDomElement mainElem = doc.createElement(_("general"));
+
+ QDomElement propElem = doc.createElement(_("writing_mode"));
+ propElem.appendChild(doc.createTextNode(_("auto")));
+ mainElem.appendChild(propElem);
+
+ propElem = doc.createElement(_("dummy"));
+ propElem.setAttribute(_("activated"), _("no"));
+ mainElem.appendChild(propElem);
+
+ propElem = doc.createElement(_("on_the_fly"));
+ propElem.setAttribute(_("activated"), _("true"));
+ mainElem.appendChild(propElem);
+
+ propElem = doc.createElement(_("only_create_images"));
+ propElem.setAttribute(_("activated"), _("no"));
+ mainElem.appendChild(propElem);
+
+ propElem = doc.createElement(_("remove_images"));
+ propElem.setAttribute(_("activated"), _("no"));
+ mainElem.appendChild(propElem);
+
+ part->appendChild( mainElem );
+}
+
+//***************************************************************************
+/*
+ * taken from K3B, libk3b/projects/audiocd/k3baudiodoc.cpp
+ *
+ * Copyright (C) 2003-2008 Sebastian Trueg <[email protected]>
+ * Copyright (C) 2009 Gustavo Pichorim Boiko <[email protected]>
+ * Copyright (C) 2010 Michal Malek <[email protected]>
+ */
+void Kwave::K3BExportPlugin::saveDocumentData(QDomElement *docElem)
+{
+ #define GET_INF(inf) doc.createTextNode(info.get(inf).toString())
+
+ const Kwave::FileInfo info(signalManager().metaData());
+
+ QDomDocument doc = docElem->ownerDocument();
+ saveGeneralDocumentData(docElem);
+
+ // add normalize
+ QDomElement normalizeElem = doc.createElement(_("normalize"));
+ normalizeElem.appendChild(doc.createTextNode(_("no")));
+ docElem->appendChild(normalizeElem);
+
+ // add hide track
+ QDomElement hideFirstTrackElem = doc.createElement(_("hide_first_track"));
+ hideFirstTrackElem.appendChild(doc.createTextNode(_("no")));
+ docElem->appendChild(hideFirstTrackElem);
+
+ // save the audio cd ripping settings
+ // paranoia mode, read retries, and ignore read errors
+ // ------------------------------------------------------------
+ QDomElement ripMain = doc.createElement(_("audio_ripping"));
+ docElem->appendChild(ripMain);
+
+ QDomElement ripElem = doc.createElement(_("paranoia_mode"));
+ ripElem.appendChild(doc.createTextNode(_("0")));
+ ripMain.appendChild(ripElem);
+
+ ripElem = doc.createElement(_("read_retries"));
+ ripElem.appendChild(doc.createTextNode(_("0")));
+ ripMain.appendChild(ripElem);
+
+ ripElem = doc.createElement(_("ignore_read_errors"));
+ ripElem.appendChild(doc.createTextNode(_("no")));
+ ripMain.appendChild(ripElem);
+ // ------------------------------------------------------------
+
+ // save disc cd-text
+ // -------------------------------------------------------------
+ QDomElement cdTextMain = doc.createElement(_("cd-text"));
+ cdTextMain.setAttribute(_("activated"), _("yes"));
+
+ QDomElement cdTextElem = doc.createElement(_("title"));
+ cdTextElem.appendChild(GET_INF(INF_NAME));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("artist"));
+ cdTextElem.appendChild(GET_INF(INF_AUTHOR));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("arranger"));
+ cdTextElem.appendChild(GET_INF(INF_TECHNICAN));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("songwriter"));
+ cdTextElem.appendChild(GET_INF(INF_PERFORMER));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("composer"));
+ cdTextElem.appendChild(GET_INF(INF_ORGANIZATION));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("disc_id"));
+ cdTextElem.appendChild(GET_INF(INF_CD));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("upc_ean"));
+ cdTextElem.appendChild(GET_INF(INF_ISRC));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("message"));
+ cdTextElem.appendChild(GET_INF(INF_COMMENTS));
+ cdTextMain.appendChild(cdTextElem);
+
+ docElem->appendChild( cdTextMain );
+ // -------------------------------------------------------------
+
+ // save the tracks
+ // -------------------------------------------------------------
+ QDomElement contentsElem = doc.createElement(_("contents"));
+
+ unsigned int index = 1;
+ foreach (const Kwave::K3BExportPlugin::BlockInfo &block, m_block_info) {
+ QString title = block.m_title;
+ QString artist = block.m_artist;
+ QString songwriter = QString();
+ QString url = block.m_filename;
+
+ QDomElement trackElem = doc.createElement(_("track"));
+
+ // add sources
+ QDomElement sourcesParent = doc.createElement(_("sources"));
+ QDomElement sourceElem = doc.createElement(_("file"));
+ sourceElem.setAttribute(_("url"), url);
+ sourceElem.setAttribute(_("start_offset"), _("00:00:00"));
+ sourceElem.setAttribute(_("end_offset"), _("00:00:00"));
+ sourcesParent.appendChild(sourceElem);
+ trackElem.appendChild(sourcesParent);
+
+ // index 0
+ QDomElement index0Elem = doc.createElement(_("index0"));
+ index0Elem.appendChild(doc.createTextNode(QString::number(index)));
+ trackElem.appendChild(index0Elem);
+
+ // add cd-text
+ cdTextMain = doc.createElement(_("cd-text"));
+ cdTextElem = doc.createElement(_("title"));
+ cdTextElem.appendChild(doc.createTextNode(title));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("artist"));
+ cdTextElem.appendChild(doc.createTextNode(artist));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("arranger"));
+ cdTextElem.appendChild(GET_INF(INF_TECHNICAN));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("songwriter"));
+ cdTextElem.appendChild(doc.createTextNode(songwriter));
+ cdTextMain.appendChild(cdTextElem );
+
+ cdTextElem = doc.createElement(_("composer"));
+ cdTextElem.appendChild(GET_INF(INF_ORGANIZATION));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("isrc"));
+ cdTextElem.appendChild(GET_INF(INF_ISRC));
+ cdTextMain.appendChild(cdTextElem);
+
+ cdTextElem = doc.createElement(_("message"));
+ cdTextElem.appendChild(GET_INF(INF_COMMENTS));
+ cdTextMain.appendChild(cdTextElem);
+
+ trackElem.appendChild(cdTextMain);
+
+ // add copy protection
+ QDomElement copyElem = doc.createElement(_("copy_protection"));
+ copyElem.appendChild(doc.createTextNode(
+ info.get(INF_COPYRIGHTED).toInt() ? _("yes") : _("no")
+ ));
+ trackElem.appendChild(copyElem);
+
+ // add pre emphasis
+ copyElem = doc.createElement(_("pre_emphasis"));
+ copyElem.appendChild(doc.createTextNode(_("no")));
+ trackElem.appendChild(copyElem);
+
+ contentsElem.appendChild(trackElem);
+ index++;
+ }
+ // -------------------------------------------------------------
+
+ docElem->appendChild(contentsElem);
+}
+
+//***************************************************************************
+int Kwave::K3BExportPlugin::start(QStringList &params)
+{
+ qDebug("K3BExportPlugin::start()");
+
+ // interpret the parameters
+ int result = interpreteParameters(params);
+ if (result) return result;
+
+ // check the output file
+ if (!m_url.isLocalFile())
+ return -EINVAL; // sorry, KZip supports only local files
+
+ // determine output directory and file name pattern
+ QString k3b_filename = m_url.path();
+ QFileInfo fi(k3b_filename);
+ QString base = fi.completeBaseName();
+ QString out_dir;
+ QString out_pattern;
+ if (m_export_location == Kwave::K3BExportPlugin::EXPORT_TO_SUB_DIR) {
+ // export to a subdir with the name "<filename>.dir"
+ out_dir = fi.absolutePath() + QDir::separator() + base + _(".dir");
+ out_pattern = _("track-") + OUTFILE_PATTERN;
+ } else {
+ // use the same directory as the *.k3b file
+ out_dir = fi.absolutePath();
+ out_pattern = base + _("-track-") + OUTFILE_PATTERN;
+ }
+ qDebug("out_dir = '%s'", DBG(out_dir));
+ qDebug("out_pattern = '%s'", DBG(out_pattern));
+
+ // determine the selection settings
+ sample_index_t selection_left = 0;
+ sample_index_t selection_right = 0;
+ QList<unsigned int> tracks;
+ selection(&tracks, &selection_left, &selection_right, false);
+
+ // check: only mono or stereo files are supported
+ if ((tracks.count() != 1) && (tracks.count() != 2)) {
+ qWarning("sorry, K3B can not handle %u tracks", tracks.count());
+ Kwave::MessageBox::sorry(parentWidget(), i18n(
+ "Only mono and stereo files can be used for an audio CD. "
+ "You can either deselect some channels or export the file "
+ "in a different file format that supports mono and stereo "
+ "only (for example FLAC) and then try again."
+ ));
+ return -EINVAL;
+ }
+
+ bool selected_something = (selection_left != selection_right);
+ bool selected_all = ( (selection_left == 0) &&
+ ((selection_right + 1) >= signalLength()) );
+ bool enable_selection_only = selected_something && !selected_all;
+ bool selection_only = enable_selection_only && m_selection_only;
+ if (!selection_only) {
+ selection_left = 0;
+ selection_right = signalLength() - 1;
+ }
+
+ // create a list of blocks to save, but not yet the output file names
+ scanBlocksToSave(base, selection_left, selection_right);
+ unsigned int count = m_block_info.count();
+ if (!count)
+ return -EINVAL;
+
+ // find the start index of the file numbering
+ unsigned int first = 1;
+ if (m_overwrite_policy == Kwave::K3BExportPlugin::USE_NEW_FILE_NAMES) {
+ // use new files, find out the highest existing index
+ QString pat = out_pattern;
+ pat.replace(OUTFILE_PATTERN, _("*"));
+ pat += OUTFILE_SUFFIX;
+
+ QDir dir(out_dir, pat);
+ QStringList files;
+ files = dir.entryList();
+
+ for (unsigned int i = first; i < (first + count); ++i) {
+ QString name = createFileName(out_pattern, i);
+ QRegExp rx(_("^(") + name + _(")$"), Qt::CaseInsensitive);
+ QStringList matches = files.filter(rx);
+ if (matches.count() > 0) first = i + 1;
+ }
+ qDebug("found first usable index -> %d", first);
+ } else {
+ // overwrite mode, always start at 1
+ }
+
+ // create the complete file names
+ for (unsigned int i = 0; i < count; ++i) {
+ m_block_info[i].m_filename = out_dir + QDir::separator() +
+ createFileName(out_pattern, first + i);
+ }
+
+ result = saveBlocks(selection_only, out_dir, out_pattern);
+ if (result != 0)
+ return result; // aborted or failed -> do not create a k3b file
+
+ result = saveK3BFile(k3b_filename);
+ if (result != 0)
+ return result; // aborted or failed -> do not ask about starting k3b
+
+ if (Kwave::MessageBox::questionYesNo(parentWidget(), i18n(
+ "A K3B project file has been created and audio files have "
+ "been exported.\n"
+ "Should I start K3B and open the audio CD project now?"
+ )) == KMessageBox::Yes) {
+ // call k3b and pass the project file name (must be full path)
+ QStringList args;
+ args << k3b_filename;
+ if (!QProcess::startDetached(_("k3b"), args)) {
+ return -EIO;
+ }
+ }
+
+ return result;
+}
+
+//***************************************************************************
+int Kwave::K3BExportPlugin::saveBlocks(bool selection_only,
+ const QString &out_dir,
+ const QString &out_pattern)
+{
+ QString first_filename = Kwave::Parser::escapeForFileName(
+ QUrl::fromLocalFile(createFileName(out_pattern, 1)).toString());
+
+ // remember the original file info remove all unsupported/ properties,
+ // to avoid that the saveblocks plugin complains...
+ const Kwave::FileInfo orig_file_info(signalManager().metaData());
+ Kwave::FileInfo file_info(orig_file_info);
+ QList<Kwave::FileProperty> unsupported_properties;
+ {
+ QString mimetype = Kwave::CodecManager::whatContains(m_url);
+ Kwave::Encoder *encoder = Kwave::CodecManager::encoder(mimetype);
+ if (encoder) {
+ unsupported_properties = encoder->unsupportedProperties(
+ file_info.properties().keys());
+ delete encoder;
+ }
+ if (!unsupported_properties.isEmpty()) {
+ foreach (const Kwave::FileProperty &p, unsupported_properties) {
+ file_info.set(p, QVariant());
+ }
+ }
+ }
+
+ // make sure that the file uses 16 bits/sample only
+ file_info.setBits(16);
+
+ signalManager().metaData().replace(Kwave::MetaDataList(file_info));
+
+ // call the saveblocks plugin and let it do the main work of exporting
+ // the *.wav files with all the tracks...
+
+ QStringList params;
+ params << out_dir + QDir::separator() + first_filename;
+ params << Kwave::Parser::escape(out_pattern);
+ params << ((m_overwrite_policy == USE_NEW_FILE_NAMES) ? _("0") : _("1"));
+ params << (selection_only ? _("1") : _("0"));
+ int result = manager().executePlugin(_("saveblocks"), &params);
+
+ // restore the original file info
+ signalManager().metaData().replace(Kwave::MetaDataList(orig_file_info));
+
+ return result;
+}
+
+//***************************************************************************
+int Kwave::K3BExportPlugin::saveK3BFile(const QString &k3b_filename)
+{
+ // create the K3B file
+ KZip zip(k3b_filename);
+
+ bool ok = zip.open(QIODevice::WriteOnly);
+ if (!ok) return -EIO;
+
+ // write the mime type
+ QByteArray app_type(K3B_PROJECT_MIME_TYPE);
+ zip.setCompression(KZip::NoCompression);
+ zip.setExtraField(KZip::NoExtraField);
+ zip.writeFile(_("mimetype"), app_type);
+
+ // export file global data
+ QByteArray xml;
+ QBuffer out(&xml);
+ out.open(QIODevice::WriteOnly);
+
+ // save the data in the document
+ QDomDocument xmlDoc(_("k3b_audio_project"));
+
+ xmlDoc.appendChild(xmlDoc.createProcessingInstruction(
+ _("xml"), _("version=\"1.0\" encoding=\"UTF-8\"")
+ ));
+ QDomElement docElem = xmlDoc.createElement(_("k3b_audio_project"));
+ xmlDoc.appendChild(docElem);
+ saveDocumentData(&docElem);
+ QTextStream xmlStream(&out);
+ xmlDoc.save(xmlStream, 0);
+
+ out.close();
+
+ zip.setCompression(KZip::NoCompression);
+ zip.setExtraField(KZip::NoExtraField);
+ zip.writeFile(_("maindata.xml"), xml.data());
+ zip.close();
+
+ return 0;
+}
+
+//***************************************************************************
+QStringList Kwave::K3BExportPlugin::knownPatterns()
+{
+ // list of all known detection patterns
+ QStringList patterns;
+ patterns << _("[%title] ([%artist])");
+ patterns << _("[%title], [%artist]");
+ patterns << _("[%artist]: [%title]");
+ patterns << _("[%artist] - [%title]");
+ return patterns;
+}
+
+//***************************************************************************
+#include "K3BExportPlugin.moc"
+//***************************************************************************
+//***************************************************************************
diff --git a/plugins/export_k3b/K3BExportPlugin.h b/plugins/export_k3b/K3BExportPlugin.h
new file mode 100644
index 0000000..12137e8
--- /dev/null
+++ b/plugins/export_k3b/K3BExportPlugin.h
@@ -0,0 +1,179 @@
+/*************************************************************************
+ * K3BExportPlugin.h - export of K3B project files
+ * -------------------
+ * begin : Thu Apr 13 2017
+ * copyright : (C) 2017 by Thomas Eschenbacher
+ * email : [email protected]
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef K3B_EXPORT_PLUGIN_H
+#define K3B_EXPORT_PLUGIN_H
+
+#include "config.h"
+
+#include <QObject>
+#include <QStringList>
+#include <QUrl>
+#include <QVariantList>
+#include <QVector>
+
+#include "libkwave/Plugin.h"
+
+class QDomElement;
+
+namespace Kwave
+{
+
+ class K3BExportPlugin: public Kwave::Plugin
+ {
+ Q_OBJECT
+ public:
+
+ typedef enum {
+ EXPORT_TO_SAME_DIR = 0,
+ EXPORT_TO_SUB_DIR = 1
+ } export_location_t ;
+
+ typedef enum {
+ OVERWRITE_EXISTING_FILES = 0,
+ USE_NEW_FILE_NAMES = 1
+ } overwrite_policy_t;
+
+ /**
+ * Constructor
+ * @param parent reference to our plugin manager
+ * @param args argument list [unused]
+ */
+ K3BExportPlugin(QObject *parent, const QVariantList &args);
+
+ /** Destructor */
+ virtual ~K3BExportPlugin();
+
+ /** @see Kwave::Plugin::load() */
+ virtual void load(QStringList &params);
+
+ /**
+ * Normally this method is used to set up all necessary parameters
+ * for executing the plugin. This plugin uses it for performing
+ * actions in the context of the GUI thread.
+ *
+ * @param params some parameters
+ * @return string list with parameters or null pointer
+ */
+ virtual QStringList *setup(QStringList &params);
+
+ /**
+ * Saves the K3B project file, using the settings made in "setup()"
+ * @see Kwave::Plugin::start()
+ */
+ virtual int start(QStringList &params);
+
+ /** returns a list of all known detection patterns */
+ static QStringList knownPatterns();
+
+ protected:
+
+ typedef struct {
+ unsigned int m_index; /**< track index [1...N] */
+ QString m_filename; /**< file name for saving */
+ sample_index_t m_start; /**< start of the block [samples] */
+ sample_index_t m_length; /**< length of the block [samples] */
+ QString m_title; /**< title of the block */
+ QString m_artist; /**< artist of the song */
+ } BlockInfo;
+
+ /** reads values from the parameter list */
+ int interpreteParameters(QStringList &params);
+
+ /**
+ * determines the blocks which should be saved, including
+ * start position, length and title.
+ * @param base the base name, without indices, extension etc...
+ * @param selection_left index of the first sample
+ * @param selection_right index of the last sample
+ */
+ void scanBlocksToSave(const QString &base,
+ sample_index_t selection_left,
+ sample_index_t selection_right);
+
+ /**
+ * create a filename (with extension) out of a given name pattern
+ * and index
+ * @param pattern the pattern for creating the filename
+ * @param index the index of the current file
+ * @return the name of the file
+ */
+ QString createFileName(const QString &pattern, unsigned int index);
+
+ /**
+ * detects the meta data of a block from splitting the description
+ * text of a label
+ * @param text the description of a label
+ * @param pattern a pattern describing the format of the text
+ * @param block a BlockInfo structure that receives artist and title
+ * @return true if the pattern did match, false otherwise
+ */
+ bool detectBlockMetaData(const QString &text,
+ const QString &pattern,
+ BlockInfo &block);
+
+ /** save the "general" section */
+ void saveGeneralDocumentData(QDomElement *part);
+
+ /** save the K3B project document data */
+ void saveDocumentData(QDomElement *docElem);
+
+ /**
+ * save the blocks through the saveblocks plugin
+ * @param selection_only if true, save only the selection
+ * @param out_dir output directory for saving the blocks
+ * @param out_pattern the pattern for creating the block filenames
+ * @return zero if succeeded, or error code if failed
+ */
+ int saveBlocks(bool selection_only,
+ const QString &out_dir,
+ const QString &out_pattern);
+
+ /**
+ * save the *.k3b file
+ * @param k3b_filename path to the *.k3b file
+ * @return zero if succeeded, or error code if failed
+ */
+ int saveK3BFile(const QString &k3b_filename);
+
+ private:
+
+ /** the URL of the project file */
+ QUrl m_url;
+
+ /** pattern for detecting title and artist */
+ QString m_pattern;
+
+ /** if true, export only the selected range */
+ bool m_selection_only;
+
+ /** where to export the files of the tracks, subdir, same dir, ... */
+ export_location_t m_export_location;
+
+ /** overwrite existing files or create a new file name */
+ overwrite_policy_t m_overwrite_policy;
+
+ /** list of all blocks to save */
+ QVector<BlockInfo> m_block_info;
+ };
+}
+
+#endif /* K3B_EXPORT_PLUGIN_H */
+
+//***************************************************************************
+//***************************************************************************
+
diff --git a/plugins/export_k3b/K3BExportWidget.cpp b/plugins/export_k3b/K3BExportWidget.cpp
new file mode 100644
index 0000000..d2aae30
--- /dev/null
+++ b/plugins/export_k3b/K3BExportWidget.cpp
@@ -0,0 +1,125 @@
+/***************************************************************************
+ * K3BExportWidget.cpp - widget for K3B export options in the file open dlg
+ * -------------------
+ * begin : Thu Apr 13 2017
+ * copyright : (C) 2017 by Thomas Eschenbacher
+ * email : [email protected]
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "config.h"
+
+#include <QCheckBox>
+#include <QLineEdit>
+
+#include <KComboBox>
+
+#include "libkwave/String.h"
+
+#include "K3BExportWidget.h"
+
+//***************************************************************************
+Kwave::K3BExportWidget::K3BExportWidget(
+ QWidget *parent,
+ QString &pattern,
+ bool selection_only,
+ bool have_selection,
+ Kwave::K3BExportPlugin::export_location_t export_location,
+ Kwave::K3BExportPlugin::overwrite_policy_t overwrite_policy
+)
+ :QWidget(parent), Ui::K3BExportWidgetBase()
+{
+ setupUi(this);
+
+ cbLabelPattern->addItem(i18nc(
+ "default entry of the list of placeholder patterns in "
+ "the K3B export plugin (used for detecting title and artist "
+ "from a label description)",
+ "(auto detect)"
+ ));
+ foreach (const QString &p, Kwave::K3BExportPlugin::knownPatterns())
+ cbLabelPattern->addItem(p);
+
+ Q_ASSERT(cbLabelPattern);
+ if (pattern.trimmed().length())
+ cbLabelPattern->setCurrentText(pattern.trimmed());
+ else
+ cbLabelPattern->setCurrentIndex(0);
+
+ // the "selection only" checkbox
+ Q_ASSERT(chkSelectionOnly);
+ if (have_selection) {
+ // we have a selection
+ chkSelectionOnly->setEnabled(true);
+ chkSelectionOnly->setChecked(selection_only);
+ } else {
+ // no selection -> force it to "off"
+ chkSelectionOnly->setEnabled(false);
+ chkSelectionOnly->setChecked(false);
+ }
+
+ Q_ASSERT(cbExportLocation);
+ cbExportLocation->setCurrentIndex(static_cast<int>(export_location));
+
+ Q_ASSERT(cbOverwritePolicy);
+ cbOverwritePolicy->setCurrentIndex(static_cast<int>(overwrite_policy));
+}
+
+//***************************************************************************
+Kwave::K3BExportWidget::~K3BExportWidget()
+{
+}
+
+//***************************************************************************
+QString Kwave::K3BExportWidget::pattern() const
+{
+ Q_ASSERT(cbLabelPattern);
+ if (!cbLabelPattern) return QString();
+
+ // special handling: the first entry in the list is the default pattern
+ // (which is "auto-detect") -> map this to empty pattern
+ QString p = cbLabelPattern->currentText().trimmed();
+ if (p == cbLabelPattern->itemText(0)) return QString();
+
+ return p;
+}
+
+//***************************************************************************
+bool Kwave::K3BExportWidget::selectionOnly() const
+{
+ Q_ASSERT(chkSelectionOnly);
+ return (chkSelectionOnly) ? chkSelectionOnly->isChecked() : false;
+}
+
+//***************************************************************************
+Kwave::K3BExportPlugin::export_location_t
+ Kwave::K3BExportWidget::exportLocation() const
+{
+ Q_ASSERT(cbExportLocation);
+ return static_cast<Kwave::K3BExportPlugin::export_location_t>(
+ (cbExportLocation) ?
+ cbExportLocation->currentIndex() : 0
+ );
+}
+
+//***************************************************************************
+Kwave::K3BExportPlugin::overwrite_policy_t
+ Kwave::K3BExportWidget::overwritePolicy() const
+{
+ Q_ASSERT(cbOverwritePolicy);
+ return static_cast<Kwave::K3BExportPlugin::overwrite_policy_t>(
+ (cbOverwritePolicy) ?
+ cbOverwritePolicy->currentIndex() : 0
+ );
+}
+
+//***************************************************************************
+//***************************************************************************
diff --git a/plugins/export_k3b/K3BExportWidget.h b/plugins/export_k3b/K3BExportWidget.h
new file mode 100644
index 0000000..5495e89
--- /dev/null
+++ b/plugins/export_k3b/K3BExportWidget.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * K3BExportWidget.h - widget for K3B export options in the file open dlg
+ * -------------------
+ * begin : Thu Apr 13 2017
+ * copyright : (C) 2017 by Thomas Eschenbacher
+ * email : [email protected]
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef K3B_EXPORT_WIDGET_H
+#define K3B_EXPORT_WIDGET_H
+
+#include <QWidget>
+
+#include "K3BExportPlugin.h"
+#include "ui_K3BExportWidgetBase.h"
+
+namespace Kwave
+{
+ class K3BExportWidget: public QWidget, public Ui::K3BExportWidgetBase
+ {
+ Q_OBJECT
+ public:
+
+ /**
+ * Constructor
+ * @param widget pointer to the parent widget
+ * @param pattern the pattern used for detecting title and artist
+ * @param selection_only if true, save only the selection
+ * @param have_selection if true, there is a selection
+ * @param export_location where to export files with tracks
+ * @param overwrite_policy overwrite existing files or use a new name
+ */
+ K3BExportWidget(
+ QWidget *widget,
+ QString &pattern,
+ bool selection_only,
+ bool have_selection,
+ Kwave::K3BExportPlugin::export_location_t export_location,
+ Kwave::K3BExportPlugin::overwrite_policy_t overwrite_policy
+ );
+
+ /** Destructor */
+ virtual ~K3BExportWidget();
+
+ /** @see KPreviewWidgetBase::showPreview() */
+ virtual void showPreview(const QUrl &url)
+ {
+ Q_UNUSED(url);
+ }
+
+ /** @see KPreviewWidgetBase::clearPreview */
+ virtual void clearPreview()
+ {
+ }
+
+ /** returns the title/artist detection pattern (as is, not escaped) */
+ QString pattern() const;
+
+ /** returns true if only the selection should be saved */
+ bool selectionOnly() const;
+
+ /** returns export location of the files of the tracks */
+ Kwave::K3BExportPlugin::export_location_t exportLocation() const;
+
+ /** returns the file overwrite policy */
+ Kwave::K3BExportPlugin::overwrite_policy_t overwritePolicy() const;
+
+ };
+}
+
+#endif /* K3B_EXPORT_WIDGET_H */
+
+//***************************************************************************
+//***************************************************************************
diff --git a/plugins/export_k3b/K3BExportWidgetBase.ui b/plugins/export_k3b/K3BExportWidgetBase.ui
new file mode 100644
index 0000000..5569473
--- /dev/null
+++ b/plugins/export_k3b/K3BExportWidgetBase.ui
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>K3BExportWidgetBase</class>
+ <widget class="QWidget" name="K3BExportWidgetBase">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>410</width>
+ <height>219</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>20</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="grpInputSettings">
+ <property name="title">
+ <string>Input Settings</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="margin">
+ <number>10</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="lblLabelFormat">
+ <property name="text">
+ <string>Format of Labels:</string>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KComboBox" name="cbLabelPattern">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select a pattern for detecting title and artist from the text of a label.&lt;br/&gt;It currently understands the following placeholders:&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Courier New,courier'; font-weight:600;&quot;&gt;[%title] &lt;/span&gt;title of the song&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Courier New,courier'; font-weight:600;&quot;&gt;[%artist]&lt;/span&gt; name of the artist&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="chkSelectionOnly">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis">
+ <string>If checked, &lt;b&gt;save only the blocks that overlap with the current selection&lt;/b&gt;, otherwise the whole file. &lt;br&gt;&lt;i&gt;Please note that this option is disabled if nothing is selected or the selection already covers the whole file.&lt;/i&gt;</string>
+ </property>
+ <property name="text">
+ <string>Use Selection only</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="grpOutputSettings">
+ <property name="title">
+ <string>Output Settings</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <property name="leftMargin">
+ <number>10</number>
+ </property>
+ <property name="topMargin">
+ <number>10</number>
+ </property>
+ <property name="bottomMargin">
+ <number>10</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="lblExportLocation">
+ <property name="text">
+ <string>Export Location:</string>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="KComboBox" name="cbExportLocation">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis">
+ <string>Specify where to place the exported sound files which are used for the tracks of the audio CD.</string>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ <item>
+ <property name="text">
+ <string>Same Directory as K3B File</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Sub Directory</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="lblOverwritePolicy">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Overwrite Policy:</string>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="KComboBox" name="cbOverwritePolicy">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis">
+ <string>Select whether existing files are overwritten or new file names are used when exporting the files to use as tracks of the audio CD.</string>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ <item>
+ <property name="text">
+ <string>Overwrite Existing Files</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Use new File Names</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="10" margin="10"/>
+ <customwidgets>
+ <customwidget>
+ <class>KComboBox</class>
+ <extends>QComboBox</extends>
+ <header>kcombobox.h</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>cbLabelPattern</tabstop>
+ <tabstop>chkSelectionOnly</tabstop>
+ <tabstop>cbExportLocation</tabstop>
+ <tabstop>cbOverwritePolicy</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/plugins/export_k3b/kwaveplugin_export_k3b.desktop.in b/plugins/export_k3b/kwaveplugin_export_k3b.desktop.in
new file mode 100644
index 0000000..cfe7c2c
--- /dev/null
+++ b/plugins/export_k3b/kwaveplugin_export_k3b.desktop.in
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=K3B Project Export
+Name[x-test]=xxK3B Project Exportxx
+Type=Service
+ServiceTypes=Kwave/Plugin
+X-KDE-PluginInfo-Author=Thomas Eschenbacher
+X-KDE-PluginInfo-Name=export_k3b
+X-KDE-PluginInfo-License=GPL-2.0+
+X-KDE-PluginInfo-EnabledByDefault=true
diff --git a/plugins/saveblocks/SaveBlocksPlugin.cpp b/plugins/saveblocks/SaveBlocksPlugin.cpp
index 075e58e..c2f7680 100644
--- a/plugins/saveblocks/SaveBlocksPlugin.cpp
+++ b/plugins/saveblocks/SaveBlocksPlugin.cpp
@@ -202,14 +202,11 @@ int Kwave::SaveBlocksPlugin::start(QStringList &params)
selection(0, &selection_left, &selection_right, false);
bool selected_something = (selection_left != selection_right);
- bool selected_all = ((selection_left == 0) &&
- (selection_right+1 >= signalLength()));
+ bool selected_all = ( (selection_left == 0) &&
+ ((selection_right + 1) >= signalLength()) );
bool enable_selection_only = selected_something && !selected_all;
bool selection_only = enable_selection_only && m_selection_only;
-
- if (selection_only) {
- selection(0, &selection_left, &selection_right, true);
- } else {
+ if (!selection_only) {
selection_left = 0;
selection_right = signalLength() - 1;
}
diff --git a/scripts/screenshots.kwave b/scripts/screenshots.kwave
index 0de3ff8..5fcfab9 100644
--- a/scripts/screenshots.kwave
+++ b/scripts/screenshots.kwave
@@ -173,6 +173,18 @@ plugin-codec_mp3:
sync()
#
+# screenshot of the K3B export setup dialog
+#
+plugin-export_k3b:
+ selectall()
+ select_track:off(1)
+ delayed(500,window:screenshot(Kwave::K3BExportDialog, /var/tmp/screenshots/${LANG}/kwave-plugin-export_k3b.png))
+ delayed(100,window:close(Kwave::K3BExportDialog))
+ plugin:setup(export_k3b)
+ sync()
+ select_track:on(1)
+
+#
# screenshot of the File Info dialog
#
plugin-fileinfo: