kwave  18.07.70
Kwave::MP3Encoder Class Reference

#include <MP3Encoder.h>

Inheritance diagram for Kwave::MP3Encoder:
Inheritance graph
Collaboration diagram for Kwave::MP3Encoder:
Collaboration graph

Public Member Functions

 MP3Encoder ()
 
virtual ~MP3Encoder ()
 
virtual Kwave::Encoderinstance ()
 
virtual bool encode (QWidget *widget, Kwave::MultiTrackReader &src, QIODevice &dst, const Kwave::MetaDataList &meta_data)
 
virtual QList< Kwave::FilePropertysupportedProperties ()
 
- Public Member Functions inherited from Kwave::Encoder
 Encoder ()
 
virtual ~Encoder ()
 
virtual QList< Kwave::FilePropertyunsupportedProperties (const QList< Kwave::FileProperty > &properties_to_check)
 
- Public Member Functions inherited from Kwave::CodecBase
 CodecBase ()
 
virtual ~CodecBase ()
 
virtual bool supports (const QMimeType &mimetype)
 
virtual bool supports (const QString &mimetype_name)
 
virtual QStringList extensions (const QString &mimetype_name) const
 
virtual const QList< CodecBase::MimeTypemimeTypes ()
 
virtual const QList< Kwave::Compression::TypecompressionTypes ()
 
virtual void addMimeType (const char *name, const QString &description, const char *patterns)
 
virtual void addCompression (Kwave::Compression::Type compression)
 
virtual QString mimeTypeOf (const QUrl &url)
 

Private Slots

void dataAvailable ()
 

Private Member Functions

void encodeID3Tags (const Kwave::MetaDataList &meta_data, ID3_Tag &tag)
 

Private Attributes

ID3_PropertyMap m_property_map
 
QMutex m_lock
 
QIODevice * m_dst
 
QProcess m_process
 
QString m_program
 
QStringList m_params
 
quint8 m_write_buffer [PIPE_BUF]
 
char m_read_buffer [PIPE_BUF]
 

Detailed Description

Definition at line 42 of file MP3Encoder.h.

Constructor & Destructor Documentation

◆ MP3Encoder()

Kwave::MP3Encoder::MP3Encoder ( )

Constructor

Definition at line 52 of file MP3Encoder.cpp.

References Kwave::connect(), dataAvailable(), m_process, REGISTER_COMPRESSION_TYPES, and REGISTER_MIME_TYPES.

Referenced by instance().

53  :Kwave::Encoder(),
55  m_lock(),
56  m_dst(Q_NULLPTR),
57  m_process(this),
58  m_program(),
59  m_params()
60 {
63 
64  connect(&m_process, SIGNAL(readyReadStandardOutput()),
65  this, SLOT(dataAvailable()));
66 }
QProcess m_process
Definition: MP3Encoder.h:98
ID3_PropertyMap m_property_map
Definition: MP3Encoder.h:89
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
#define REGISTER_MIME_TYPES
QIODevice * m_dst
Definition: MP3Encoder.h:95
#define REGISTER_COMPRESSION_TYPES
QStringList m_params
Definition: MP3Encoder.h:104
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~MP3Encoder()

Kwave::MP3Encoder::~MP3Encoder ( )
virtual

Destructor

Definition at line 69 of file MP3Encoder.cpp.

70 {
71 }

Member Function Documentation

◆ dataAvailable

void Kwave::MP3Encoder::dataAvailable ( )
privateslot

called when data from the external process is available

Definition at line 569 of file MP3Encoder.cpp.

References m_dst, m_lock, m_process, and m_read_buffer.

Referenced by MP3Encoder().

570 {
571  while (m_process.bytesAvailable()) {
572  qint64 len = m_process.read(&(m_read_buffer[0]), sizeof(m_read_buffer));
573  if (len) {
574  QMutexLocker _lock(&m_lock);
575  if (m_dst) m_dst->write(&(m_read_buffer[0]), len);
576  }
577  }
578 }
QProcess m_process
Definition: MP3Encoder.h:98
QIODevice * m_dst
Definition: MP3Encoder.h:95
char m_read_buffer[PIPE_BUF]
Definition: MP3Encoder.h:119
Here is the caller graph for this function:

◆ encode()

bool Kwave::MP3Encoder::encode ( QWidget *  widget,
Kwave::MultiTrackReader src,
QIODevice &  dst,
const Kwave::MetaDataList meta_data 
)
virtual

Encodes a signal into a stream of bytes.

Parameters
widgeta widget that can be used for displaying message boxes or dialogs
srcMultiTrackReader used as source of the audio data
dstfile or other source to receive a stream of bytes
meta_datameta data of the file to save
Returns
true if succeeded, false on errors

Implements Kwave::Encoder.

Definition at line 265 of file MP3Encoder.cpp.

References _, Kwave::FileInfo::bits(), Kwave::SampleArray::constData(), Kwave::FileInfo::contains(), DBG, encodeID3Tags(), Kwave::SampleReader::eof(), Kwave::MessageBox::error(), Kwave::MultiTrackReader::first(), Kwave::FileInfo::get(), Kwave::INF_BITRATE_LOWER, Kwave::INF_BITRATE_NOMINAL, Kwave::INF_BITRATE_UPPER, Kwave::INF_COPYRIGHTED, Kwave::INF_MPEG_EMPHASIS, Kwave::INF_ORIGINAL, Kwave::MultiTrackReader::isCanceled(), Kwave::MultiTrackReader::last(), Kwave::MP3EncoderSettings::load(), Kwave::MP3EncoderSettings::m_bits_per_sample, m_dst, Kwave::MP3EncoderSettings::m_format, m_lock, m_params, Kwave::MP3EncoderSettings::m_path, m_process, m_program, Kwave::MP3EncoderSettings::m_sample_rate, m_write_buffer, OPTION, OPTION_P, Kwave::FileInfo::rate(), Kwave::toUint(), Kwave::MultiTrackSource< SOURCE, INITIALIZE >::tracks(), and Kwave::MessageBox::warningContinueCancel().

Referenced by Kwave::MP3EncoderDialog::testSettings().

268 {
269  bool result = true;
270  ID3_Tag id3_tag;
271  Kwave::MP3EncoderSettings settings;
272 
273  settings.load();
274 
275  ID3_TagType id3_tag_type = ID3TT_ID3V2;
276  id3_tag.SetSpec(ID3V2_LATEST);
277 
278  const Kwave::FileInfo info(meta_data);
279 
280  // get info: tracks, sample rate
281  const unsigned int tracks = src.tracks();
282  const sample_index_t length = src.last() - src.first() + 1;
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);
286 
287  // when encoding track count > 2, show a warning that we will mix down
288  // to stereo
289  if (tracks > 2) {
291  widget,
292  i18n("The file format you have chosen supports only mono or "
293  "stereo. This file will be mixed down to stereo when "
294  "saving."),
295  QString(), QString(), QString(),
296  _("mp3_accept_down_mix_on_export")) != KMessageBox::Continue)
297  {
298  return false;
299  }
300  }
301 
302  // open the output device
303  if (!dst.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
305  i18n("Unable to open the file for saving!"));
306  return false;
307  }
308 
309  m_dst = &dst;
310  m_params.clear();
311 
312  // encode meta data into with id3lib
313  ID3_QIODeviceWriter id3_writer(dst);
314  encodeID3Tags(meta_data, id3_tag);
315 
316  OPTION(m_flags.m_prepend); // optional parameters at the very start
317 
318  // mandantory audio input format and encoding options
319  OPTION(m_input.m_raw_format); // input is raw audio
320  OPTION(m_input.m_byte_order); // byte swapping
321  OPTION(m_input.m_signed); // signed sample format
322 
323  // supported sample rates [kHz]
324  // 8 / 11.025 / 12 / 16 / 22.05 / 24 /32 / 44.1 / 48
325  // if our rate is not supported, lame automatically resamples with the
326  // next higher supported rate
327  if (settings.m_format.m_sample_rate.length()) {
328  QString str = settings.m_format.m_sample_rate;
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(' ')));
333  } else {
334  m_params.append(str.arg(rate).split(QLatin1Char(' ')));
335  }
336  }
337 
338  // bits per sample, supported by Kwave are: 8 / 16 / 24 / 32
339  if (!settings.m_format.m_bits_per_sample.contains(QLatin1Char('%'))) {
340  // bits/sample are not selectable => use default=16bit
341  bits = 16;
342  OPTION(m_format.m_bits_per_sample);
343  } else {
344  OPTION_P(m_format.m_bits_per_sample, bits);
345  }
346 
347  // encode one track as "mono" and two tracks as "joint-stereo"
348  if (tracks == 1) {
349  OPTION(m_format.m_channels.m_mono);
350  } else {
351  OPTION(m_format.m_channels.m_stereo);
352  }
353 
354  // nominal / lower / upper bitrate
355  int bitrate_min = 8;
356  int bitrate_max = 320;
357  int bitrate_nom = 128;
358  if (info.contains(Kwave::INF_BITRATE_NOMINAL)) {
359  // nominal bitrate => use ABR mode
360  bitrate_nom = info.get(Kwave::INF_BITRATE_NOMINAL).toInt() / 1000;
361  bitrate_nom = qBound(bitrate_min, bitrate_nom, bitrate_max);
362  OPTION_P(m_quality.m_bitrate.m_avg, bitrate_nom);
363  }
364  if (info.contains(Kwave::INF_BITRATE_LOWER)) {
365  int bitrate = info.get(Kwave::INF_BITRATE_LOWER).toInt() / 1000;
366  bitrate_min = qBound(bitrate_min, bitrate, bitrate_nom);
367  OPTION_P(m_quality.m_bitrate.m_min, bitrate_min);
368  }
369  if (info.contains(Kwave::INF_BITRATE_UPPER)) {
370  int bitrate = info.get(Kwave::INF_BITRATE_UPPER).toInt() / 1000;
371  bitrate_max = qBound(bitrate_nom, bitrate, bitrate_max);
372  OPTION_P(m_quality.m_bitrate.m_max, bitrate_max);
373  }
374  // Kwave::INF_MPEG_LAYER, /**< MPEG Layer, I/II/III */
375  // Kwave::INF_MPEG_MODEEXT, /**< MPEG mode extension */
376  // Kwave::INF_MPEG_VERSION, /**< MPEG version */
377 
378  /* MPEG emphasis mode */
379  if (info.contains(Kwave::INF_MPEG_EMPHASIS)) {
380  int emphasis = info.get(Kwave::INF_MPEG_EMPHASIS).toInt();
381  switch (emphasis) {
382  case 1:
383  OPTION(m_encoding.m_emphasis.m_50_15ms); // 1 = 50/15ms
384  break;
385  case 3:
386  OPTION(m_encoding.m_emphasis.m_ccit_j17); // 3 = CCIT J.17
387  break;
388  case 0: /* FALLTHROUGH */
389  default:
390  OPTION(m_encoding.m_emphasis.m_none); // 0 = none
391  break;
392  }
393  }
394 
395  OPTION(m_encoding.m_noise_shaping); // noise shaping settings
396  OPTION(m_encoding.m_compatibility); // compatibility options
397 
398  if (info.contains(Kwave::INF_COPYRIGHTED) && info.get(Kwave::INF_COPYRIGHTED).toBool()) {
399  OPTION(m_flags.m_copyright); // copyrighted
400  }
401 
402  if (info.contains(Kwave::INF_ORIGINAL) && !info.get(Kwave::INF_ORIGINAL).toBool()) {
403  OPTION(m_flags.m_original); // original
404  }
405 
406  OPTION(m_flags.m_protect); // CRC protection
407  OPTION(m_flags.m_append); // optional parameters at the end
408 
409  m_params.append(_("-")); // infile = stdin
410  m_params.append(_("-")); // outfile = stdout
411 
412  m_program = settings.m_path;
413 
414  qDebug("MP3Encoder::encode(): %s %s",
415  DBG(m_program), DBG(m_params.join(_(" ")))
416  );
417 
418  m_process.setReadChannel(QProcess::StandardOutput);
419 
420  m_process.start(m_program, m_params);
421  QString stdError;
422  if (!m_process.waitForStarted()) {
423  qWarning("cannot start program '%s'", DBG(m_program));
424  m_process.waitForFinished();
425  result = false;
426  }
427 
428  // if a ID3v2 tag is requested, the tag comes at the start
429  if (id3_tag_type == ID3TT_ID3V2)
430  id3_tag.Render(id3_writer, id3_tag_type);
431 
432  // MP3 supports only mono and stereo, prepare a mixer matrix
433  // (not used in case of tracks <= 2)
434  Kwave::MixerMatrix mixer(tracks, out_tracks);
435 
436  // read in from the sample readers
437  const unsigned int buf_len = sizeof(m_write_buffer);
438  const int bytes_per_sample = bits / 8;
439 
440  sample_index_t rest = length;
441  Kwave::SampleArray in_samples(tracks);
442  Kwave::SampleArray out_samples(tracks);
443 
444  while (result && rest && (m_process.state() != QProcess::NotRunning)) {
445  unsigned int x;
446  unsigned int y;
447 
448  // merge the tracks into the sample buffer
449  quint8 *dst_buffer = &(m_write_buffer[0]);
450  unsigned int count = buf_len / (bytes_per_sample * tracks);
451  if (rest < count) count = Kwave::toUint(rest);
452 
453  unsigned int written = 0;
454  for (written = 0; written < count; written++) {
455  const sample_t *src_buf = Q_NULLPTR;
456 
457  // fill input buffer with samples
458  for (x = 0; x < tracks; ++x) {
459  in_samples[x] = 0;
460  Kwave::SampleReader *stream = src[x];
461  Q_ASSERT(stream);
462  if (!stream) continue;
463 
464  if (!stream->eof()) (*stream) >> in_samples[x];
465  }
466 
467  if (tracks > 2) {
468  // multiply matrix with input to get output
469  const Kwave::SampleArray &in = in_samples;
470  for (y = 0; y < out_tracks; ++y) {
471  double sum = 0;
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);
475  }
476 
477  // use output of the matrix
478  src_buf = out_samples.constData();
479  } else {
480  // use input buffer directly
481  src_buf = in_samples.constData();
482  }
483 
484  // sample conversion from 24bit to raw PCM, native endian
485  for (y = 0; y < out_tracks; ++y) {
486  sample_t s = *(src_buf++);
487 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
488  // big endian
489  if (bits >= 8)
490  *(dst_buffer++) = static_cast<quint8>(s >> 16);
491  if (bits > 8)
492  *(dst_buffer++) = static_cast<quint8>(s >> 8);
493  if (bits > 16)
494  *(dst_buffer++) = static_cast<quint8>(s & 0xFF);
495  if (bits > 24)
496  *(dst_buffer++) = 0x00;
497 #else
498  // little endian
499  if (bits > 24)
500  *(dst_buffer++) = 0x00;
501  if (bits > 16)
502  *(dst_buffer++) = static_cast<quint8>(s & 0xFF);
503  if (bits > 8)
504  *(dst_buffer++) = static_cast<quint8>(s >> 8);
505  if (bits >= 8)
506  *(dst_buffer++) = static_cast<quint8>(s >> 16);
507 #endif
508  }
509  }
510 
511  // write out to the stdin of the external process
512  qint64 bytes_written = m_process.write(
513  reinterpret_cast<char *>(&(m_write_buffer[0])),
514  written * (bytes_per_sample * tracks)
515  );
516 
517  // break if eof reached or disk full
518  if (!bytes_written) break;
519 
520  // wait for write to take all data...
521  m_process.waitForBytesWritten();
522 
523  // abort if the user pressed cancel
524  // --> this would leave a corrupted file !!!
525  if (src.isCanceled()) break;
526 
527  Q_ASSERT(rest >= written);
528  rest -= written;
529  }
530 
531  // flush and close the write channel
532  m_process.closeWriteChannel();
533 
534  // wait until the process has finished
535  qDebug("wait for finish of the process");
536  while (m_process.state() != QProcess::NotRunning) {
537  m_process.waitForFinished(100);
538  if (src.isCanceled()) break;
539  }
540 
541  int exit_code = m_process.exitCode();
542  qDebug("exit code=%d", exit_code);
543  if (!result || (exit_code != 0)) {
544  result = false;
545  stdError = QString::fromLocal8Bit(m_process.readAllStandardError());
546  qWarning("stderr output: %s", DBG(stdError));
547 
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",
551  m_program, stdError
552  ));
553  }
554 
555  // if a ID3v1 tag is requested, the tag comes at the end
556  if (id3_tag_type != ID3TT_ID3V2)
557  id3_tag.Render(id3_writer, id3_tag_type);
558 
559  {
560  QMutexLocker _lock(&m_lock);
561  m_dst = Q_NULLPTR;
562  dst.close();
563  }
564 
565  return result;
566 }
QProcess m_process
Definition: MP3Encoder.h:98
virtual sample_index_t first() const
struct Kwave::MP3EncoderSettings::@4 m_format
virtual unsigned int tracks() const Q_DECL_OVERRIDE
quint64 sample_index_t
Definition: Sample.h:28
void encodeID3Tags(const Kwave::MetaDataList &meta_data, ID3_Tag &tag)
Definition: MP3Encoder.cpp:86
bool eof() const
Definition: SampleReader.h:66
static int error(QWidget *widget, QString message, QString caption=QString())
Definition: MessageBox.cpp:126
virtual sample_index_t last() const
static int warningContinueCancel(QWidget *widget, QString message, QString caption=QString(), const QString buttonContinue=QString(), const QString buttonCancel=QString(), const QString &dontAskAgainName=QString())
Definition: MessageBox.cpp:115
const sample_t * constData() const
Definition: SampleArray.h:54
#define OPTION_P(__field__, __value__)
Definition: MP3Encoder.cpp:259
QIODevice * m_dst
Definition: MP3Encoder.h:95
#define _(m)
Definition: memcpy.c:66
quint8 m_write_buffer[PIPE_BUF]
Definition: MP3Encoder.h:116
#define DBG(qs)
Definition: String.h:55
unsigned int toUint(T x)
Definition: Utils.h:109
#define OPTION(__field__)
Definition: MP3Encoder.cpp:256
QStringList m_params
Definition: MP3Encoder.h:104
qint32 sample_t
Definition: Sample.h:37
Here is the call graph for this function:
Here is the caller graph for this function:

◆ encodeID3Tags()

void Kwave::MP3Encoder::encodeID3Tags ( const Kwave::MetaDataList meta_data,
ID3_Tag &  tag 
)
private

encode all meta data into ID3 tags

Parameters
meta_datareference to the meta data to encode
tagthe ID3 tag to receive the ID3 frames

Definition at line 86 of file MP3Encoder.cpp.

References _, Kwave::FileInfo::contains(), DBG, Kwave::ID3_PropertyMap::ENC_COMMENT, Kwave::ID3_PropertyMap::ENC_GENRE_TYPE, Kwave::ID3_PropertyMap::ENC_LENGTH, Kwave::ID3_PropertyMap::ENC_NONE, Kwave::ID3_PropertyMap::ENC_TERMS_OF_USE, Kwave::ID3_PropertyMap::ENC_TEXT, Kwave::ID3_PropertyMap::ENC_TEXT_PARTINSET, Kwave::ID3_PropertyMap::ENC_TEXT_SLASH, Kwave::ID3_PropertyMap::ENC_TEXT_TIMESTAMP, Kwave::ID3_PropertyMap::ENC_TEXT_URL, Kwave::ID3_PropertyMap::ENC_TRACK_NUM, Kwave::ID3_PropertyMap::encoding(), Kwave::ID3_PropertyMap::findProperty(), Kwave::GenreType::fromID3(), Kwave::FileInfo::get(), Kwave::INF_CD, Kwave::INF_CDS, Kwave::INF_TRACK, Kwave::INF_TRACKS, Kwave::FileInfo::length(), m_property_map, Kwave::GenreType::name(), Kwave::FileInfo::properties(), Kwave::FileInfo::rate(), and Kwave::string2date().

Referenced by encode().

88 {
89  const Kwave::FileInfo info(meta_data);
90  ID3_FrameInfo frameInfo;
91 
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) {
95  const Kwave::FileProperty &property = it.key();
96  const QVariant &value = it.value();
97 
98  ID3_FrameID id = m_property_map.findProperty(property);
99  if (id == ID3FID_NOFRAME) continue;
100 
101  if (info.contains(Kwave::INF_CD) && (property == Kwave::INF_CDS))
102  continue; /* INF_CDS has already been handled by INF_CD */
103  if (info.contains(Kwave::INF_TRACK) && (property == Kwave::INF_TRACKS))
104  continue; /* INF_TRACKS has already been handled by INF_TRACK */
105 
106  ID3_Frame *frame = new ID3_Frame;
107  Q_ASSERT(frame);
108  if (!frame) break;
109 
110  QString str_val = value.toString();
111 // qDebug("encoding ID3 tag #%02d, property='%s', value='%s'",
112 // static_cast<int>(id),
113 // DBG(info.name(property)),
114 // DBG(str_val)
115 // );
116 
117  // encode in UCS16
118  frame->SetID(id);
119  ID3_Field *field = frame->GetField(ID3FN_TEXT);
120  if (!field) {
121  qWarning("no field, frame id=%d", static_cast<int>(id));
122  delete frame;
123  continue;
124  }
125 
127  switch (encoding) {
129  {
130  field->SetEncoding(ID3TE_UTF16);
131 
132  // if "number of CDs is available: append with "/"
133  int cds = info.get(Kwave::INF_CDS).toInt();
134  if (cds > 0)
135  str_val += _("/%1").arg(cds);
136 
137  field->Set(static_cast<const unicode_t *>(str_val.utf16()));
138  break;
139  }
141  {
142  // if "number of tracks is available: append with "/"
143  int tracks = info.get(Kwave::INF_TRACKS).toInt();
144  if (tracks > 0)
145  str_val += _("/%1").arg(tracks);
146 
147  field->SetEncoding(ID3TE_UTF16);
148  field->Set(static_cast<const unicode_t *>(str_val.utf16()));
149  break;
150  }
152  // the same as ENC_COMMENT, but without "Description"
153  /* FALLTHROUGH */
155  {
156  // detect language at the start "[xxx] "
157  QString lang;
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()));
165  }
166  /* frame->GetField(ID3FN_DESCRIPTION)->Set(""); */
167  field->SetEncoding(ID3TE_UTF16);
168  field->Set(static_cast<const unicode_t *>(str_val.utf16()));
169  break;
170  }
172  {
173  int genre = Kwave::GenreType::fromID3(str_val);
174  if (genre >= 0)
175  str_val = Kwave::GenreType::name(genre, false);
176  // else: user defined genre type, take it as it is
177 
178  field->SetEncoding(ID3TE_UTF16);
179  field->Set(static_cast<const unicode_t *>(str_val.utf16()));
180  break;
181  }
183  {
184  // length in milliseconds
185  const double rate = info.rate();
186  const sample_index_t samples = info.length();
187  if ((rate > 0) && samples) {
188  const sample_index_t ms = static_cast<sample_index_t>(
189  (static_cast<double>(samples) * 1E3) / rate);
190 
191  str_val = QString::number(ms);
192 
193  field->SetEncoding(ID3TE_UTF16);
194  field->Set(static_cast<const unicode_t *>(str_val.utf16()));
195  } else {
196  delete frame;
197  frame = Q_NULLPTR;
198  }
199  break;
200  }
202  {
203  // ISO 8601 timestamp: "yyyy-MM-ddTHH:mm:ss"
204  QString s = Kwave::string2date(str_val);
205 
206  // if failed, try "yyyy" format (year only)
207  if (!s.length()) {
208  int year = str_val.toInt();
209  if ((year > 0) && (year < 9999)) {
210  frame->SetID(ID3FID_YEAR);
211  // -> re-get the field !
212  // it has become invalid through "SetID()"
213  field = frame->GetField(ID3FN_TEXT);
214  if (!field) {
215  qWarning("no field, frame id=%d",
216  static_cast<int>(id));
217  break;
218  }
219  s = _("%1").arg(year, 4, 10, QLatin1Char('0'));
220  }
221  }
222 
223  if (s.length()) {
224  field->SetEncoding(ID3TE_UTF16);
225  field->Set(static_cast<const unicode_t *>(s.utf16()));
226  } else {
227  // date is invalid, unknown format
228  qWarning("MP3Encoder::encodeID3Tags(): invalid date: '%s'",
229  DBG(str_val));
230  delete frame;
231  frame = Q_NULLPTR;
232  }
233  break;
234  }
235  case ID3_PropertyMap::ENC_TEXT_SLASH: /* FALLTHROUGH */
236  case ID3_PropertyMap::ENC_TEXT_URL: /* FALLTHROUGH */
238  field->SetEncoding(ID3TE_UTF16);
239  field->Set(static_cast<const unicode_t *>(str_val.utf16()));
240  break;
241  case ID3_PropertyMap::ENC_NONE: /* FALLTHROUGH */
242  default:
243  // ignore
244  delete frame;
245  frame = Q_NULLPTR;
246  break;
247  }
248 
249  if (frame) tag.AttachFrame(frame);
250  }
251 
252  tag.Strip();
253  tag.Update();
254 }
static QString name(int id, bool localized)
Definition: GenreType.cpp:34
ID3_PropertyMap m_property_map
Definition: MP3Encoder.h:89
quint64 sample_index_t
Definition: Sample.h:28
QString Q_DECL_EXPORT string2date(const QString &s)
Definition: Utils.cpp:126
ID3_FrameID findProperty(const Kwave::FileProperty property) const
Encoding encoding(const ID3_FrameID id) const
#define _(m)
Definition: memcpy.c:66
#define DBG(qs)
Definition: String.h:55
static int fromID3(const QString &tag)
Definition: GenreType.cpp:45
FileProperty
Definition: FileInfo.h:45
Here is the call graph for this function:
Here is the caller graph for this function:

◆ instance()

Kwave::Encoder * Kwave::MP3Encoder::instance ( )
virtual

Returns a new instance of the encoder

Implements Kwave::Encoder.

Definition at line 74 of file MP3Encoder.cpp.

References MP3Encoder().

75 {
76  return new MP3Encoder();
77 }
Here is the call graph for this function:

◆ supportedProperties()

QList< Kwave::FileProperty > Kwave::MP3Encoder::supportedProperties ( )
virtual

Returns a list of supported file properties

Reimplemented from Kwave::Encoder.

Definition at line 80 of file MP3Encoder.cpp.

References m_property_map, and Kwave::ID3_PropertyMap::properties().

81 {
82  return m_property_map.properties();
83 }
ID3_PropertyMap m_property_map
Definition: MP3Encoder.h:89
QList< Kwave::FileProperty > properties() const
Here is the call graph for this function:

Member Data Documentation

◆ m_dst

QIODevice* Kwave::MP3Encoder::m_dst
private

pointer to the QIODevice for storing, used while encoding

Definition at line 95 of file MP3Encoder.h.

Referenced by dataAvailable(), and encode().

◆ m_lock

QMutex Kwave::MP3Encoder::m_lock
private

lock for protecting m_dst and m_process

Definition at line 92 of file MP3Encoder.h.

Referenced by dataAvailable(), and encode().

◆ m_params

QStringList Kwave::MP3Encoder::m_params
private

list with commandline parameters

Definition at line 104 of file MP3Encoder.h.

Referenced by encode().

◆ m_process

QProcess Kwave::MP3Encoder::m_process
private

the external process with the encoder

Definition at line 98 of file MP3Encoder.h.

Referenced by dataAvailable(), encode(), and MP3Encoder().

◆ m_program

QString Kwave::MP3Encoder::m_program
private

path to the external program

Definition at line 101 of file MP3Encoder.h.

Referenced by encode().

◆ m_property_map

ID3_PropertyMap Kwave::MP3Encoder::m_property_map
private

property - to - ID3 mapping

Definition at line 89 of file MP3Encoder.h.

Referenced by encodeID3Tags(), and supportedProperties().

◆ m_read_buffer

char Kwave::MP3Encoder::m_read_buffer[PIPE_BUF]
private

buffer for reading from the encoder (size is not critical)

Definition at line 119 of file MP3Encoder.h.

Referenced by dataAvailable().

◆ m_write_buffer

quint8 Kwave::MP3Encoder::m_write_buffer[PIPE_BUF]
private

buffer for writing to the encoder

Note
The size of this buffer should never be bigger than PIPE_BUF (see POSIX.1-2001), otherwise there could be some leftover when writing to the stdin queue of the process which would be caught and queued up within Qt. After some time that leads to a critically increasing memory consumption and a large delay when the progress bar has reached 99%.

Definition at line 116 of file MP3Encoder.h.

Referenced by encode().


The documentation for this class was generated from the following files: