22 #include <id3/globals.h> 23 #include <id3/misc_support.h> 29 #include <QLatin1Char> 33 #include <KLocalizedString> 90 ID3_FrameInfo frameInfo;
92 const QMap<Kwave::FileProperty, QVariant> properties(info.
properties());
93 QMap<Kwave::FileProperty, QVariant>::const_iterator it;
94 for (it = properties.begin(); it != properties.end(); ++it) {
96 const QVariant &value = it.value();
99 if (
id == ID3FID_NOFRAME)
continue;
106 ID3_Frame *frame =
new ID3_Frame;
110 QString str_val = value.toString();
119 ID3_Field *field = frame->GetField(ID3FN_TEXT);
121 qWarning(
"no field, frame id=%d", static_cast<int>(
id));
130 field->SetEncoding(ID3TE_UTF16);
135 str_val +=
_(
"/%1").arg(cds);
137 field->Set(static_cast<const unicode_t *>(str_val.utf16()));
145 str_val +=
_(
"/%1").arg(tracks);
147 field->SetEncoding(ID3TE_UTF16);
148 field->Set(static_cast<const unicode_t *>(str_val.utf16()));
158 if (str_val.startsWith(QLatin1Char(
'[')) &&
159 (str_val.at(4) == QLatin1Char(
']'))) {
160 lang = str_val.mid(1,3);
161 str_val = str_val.mid(5);
162 frame->GetField(ID3FN_DESCRIPTION)->Set(
"");
163 frame->GetField(ID3FN_LANGUAGE)->Set(
164 static_cast<const char *>(lang.toLatin1().data()));
167 field->SetEncoding(ID3TE_UTF16);
168 field->Set(static_cast<const unicode_t *>(str_val.utf16()));
178 field->SetEncoding(ID3TE_UTF16);
179 field->Set(static_cast<const unicode_t *>(str_val.utf16()));
185 const double rate = info.
rate();
187 if ((rate > 0) && samples) {
189 (
static_cast<double>(samples) * 1E3) / rate);
191 str_val = QString::number(ms);
193 field->SetEncoding(ID3TE_UTF16);
194 field->Set(static_cast<const unicode_t *>(str_val.utf16()));
208 int year = str_val.toInt();
209 if ((year > 0) && (year < 9999)) {
210 frame->SetID(ID3FID_YEAR);
213 field = frame->GetField(ID3FN_TEXT);
215 qWarning(
"no field, frame id=%d",
216 static_cast<int>(
id));
219 s =
_(
"%1").arg(year, 4, 10, QLatin1Char(
'0'));
224 field->SetEncoding(ID3TE_UTF16);
225 field->Set(static_cast<const unicode_t *>(s.utf16()));
228 qWarning(
"MP3Encoder::encodeID3Tags(): invalid date: '%s'",
238 field->SetEncoding(ID3TE_UTF16);
239 field->Set(static_cast<const unicode_t *>(str_val.utf16()));
249 if (frame) tag.AttachFrame(frame);
256 #define OPTION(__field__) \ 257 if (settings.__field__.length()) m_params.append(settings.__field__) 259 #define OPTION_P(__field__, __value__) \ 260 if (settings.__field__.length()) \ 262 QString(settings.__field__.arg(__value__)).split(QLatin1Char(' '))) 275 ID3_TagType id3_tag_type = ID3TT_ID3V2;
276 id3_tag.SetSpec(ID3V2_LATEST);
281 const unsigned int tracks = src.
tracks();
283 unsigned int bits = qBound(8U, ((info.
bits() + 7) & ~0x7), 32U);
284 const double rate = info.
rate();
285 const unsigned int out_tracks = qMin(tracks, 2U);
292 i18n(
"The file format you have chosen supports only mono or " 293 "stereo. This file will be mixed down to stereo when " 295 QString(), QString(), QString(),
296 _(
"mp3_accept_down_mix_on_export")) != KMessageBox::Continue)
303 if (!dst.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
305 i18n(
"Unable to open the file for saving!"));
316 OPTION(m_flags.m_prepend);
319 OPTION(m_input.m_raw_format);
320 OPTION(m_input.m_byte_order);
329 if (str.contains(
_(
"[%khz]"))) {
330 str = str.replace(
_(
"[%khz]"),
331 _(
"%1")).arg(rate / 1000.0, 1,
'f', 2);
332 m_params.append(str.split(QLatin1Char(
' ')));
334 m_params.append(str.arg(rate).split(QLatin1Char(
' ')));
342 OPTION(m_format.m_bits_per_sample);
344 OPTION_P(m_format.m_bits_per_sample, bits);
349 OPTION(m_format.m_channels.m_mono);
351 OPTION(m_format.m_channels.m_stereo);
356 int bitrate_max = 320;
357 int bitrate_nom = 128;
361 bitrate_nom = qBound(bitrate_min, bitrate_nom, bitrate_max);
362 OPTION_P(m_quality.m_bitrate.m_avg, bitrate_nom);
366 bitrate_min = qBound(bitrate_min, bitrate, bitrate_nom);
367 OPTION_P(m_quality.m_bitrate.m_min, bitrate_min);
371 bitrate_max = qBound(bitrate_nom, bitrate, bitrate_max);
372 OPTION_P(m_quality.m_bitrate.m_max, bitrate_max);
383 OPTION(m_encoding.m_emphasis.m_50_15ms);
386 OPTION(m_encoding.m_emphasis.m_ccit_j17);
390 OPTION(m_encoding.m_emphasis.m_none);
395 OPTION(m_encoding.m_noise_shaping);
396 OPTION(m_encoding.m_compatibility);
399 OPTION(m_flags.m_copyright);
403 OPTION(m_flags.m_original);
406 OPTION(m_flags.m_protect);
414 qDebug(
"MP3Encoder::encode(): %s %s",
418 m_process.setReadChannel(QProcess::StandardOutput);
429 if (id3_tag_type == ID3TT_ID3V2)
430 id3_tag.Render(id3_writer, id3_tag_type);
438 const int bytes_per_sample = bits / 8;
444 while (result && rest && (
m_process.state() != QProcess::NotRunning)) {
450 unsigned int count = buf_len / (bytes_per_sample * tracks);
453 unsigned int written = 0;
454 for (written = 0; written < count; written++) {
455 const sample_t *src_buf = Q_NULLPTR;
458 for (x = 0; x < tracks; ++x) {
462 if (!stream)
continue;
464 if (!stream->
eof()) (*stream) >> in_samples[x];
470 for (y = 0; y < out_tracks; ++y) {
472 for (x = 0; x < tracks; ++x)
473 sum += static_cast<double>(in[x]) * mixer[x][y];
474 out_samples[y] =
static_cast<sample_t>(sum);
485 for (y = 0; y < out_tracks; ++y) {
487 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 490 *(dst_buffer++) = static_cast<quint8>(s >> 16);
492 *(dst_buffer++) = static_cast<quint8>(s >> 8);
494 *(dst_buffer++) = static_cast<quint8>(s & 0xFF);
496 *(dst_buffer++) = 0x00;
500 *(dst_buffer++) = 0x00;
502 *(dst_buffer++) = static_cast<quint8>(s & 0xFF);
504 *(dst_buffer++) = static_cast<quint8>(s >> 8);
506 *(dst_buffer++) = static_cast<quint8>(s >> 16);
514 written * (bytes_per_sample * tracks)
518 if (!bytes_written)
break;
527 Q_ASSERT(rest >= written);
535 qDebug(
"wait for finish of the process");
536 while (
m_process.state() != QProcess::NotRunning) {
542 qDebug(
"exit code=%d", exit_code);
543 if (!result || (exit_code != 0)) {
545 stdError = QString::fromLocal8Bit(
m_process.readAllStandardError());
546 qWarning(
"stderr output: %s",
DBG(stdError));
549 i18nc(
"%1=name of the external program, %2=stderr of the program",
550 "An error occurred while calling the external encoder '%1':\n\n%2",
556 if (id3_tag_type != ID3TT_ID3V2)
557 id3_tag.Render(id3_writer, id3_tag_type);
560 QMutexLocker _lock(&
m_lock);
574 QMutexLocker _lock(&
m_lock);
bool contains(const FileProperty property) const
virtual QList< Kwave::FileProperty > supportedProperties()
virtual sample_index_t first() const
static QString name(int id, bool localized)
virtual Kwave::Encoder * instance()
struct Kwave::MP3EncoderSettings::@4 m_format
ID3_PropertyMap m_property_map
virtual unsigned int tracks() const Q_DECL_OVERRIDE
QVariant get(FileProperty key) const
QList< Kwave::FileProperty > properties() const
void encodeID3Tags(const Kwave::MetaDataList &meta_data, ID3_Tag &tag)
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
static int error(QWidget *widget, QString message, QString caption=QString())
QString Q_DECL_EXPORT string2date(const QString &s)
ID3_FrameID findProperty(const Kwave::FileProperty property) const
sample_index_t length() const
virtual sample_index_t last() const
const QMap< FileProperty, QVariant > properties() const
QString m_bits_per_sample
#define REGISTER_MIME_TYPES
static int warningContinueCancel(QWidget *widget, QString message, QString caption=QString(), const QString buttonContinue=QString(), const QString buttonCancel=QString(), const QString &dontAskAgainName=QString())
const sample_t * constData() const
#define OPTION_P(__field__, __value__)
char m_read_buffer[PIPE_BUF]
#define REGISTER_COMPRESSION_TYPES
Encoding encoding(const ID3_FrameID id) const
quint8 m_write_buffer[PIPE_BUF]
virtual bool encode(QWidget *widget, Kwave::MultiTrackReader &src, QIODevice &dst, const Kwave::MetaDataList &meta_data)
unsigned int bits() const
static int fromID3(const QString &tag)
#define OPTION(__field__)