kwave  18.07.70
Kwave::MimeData Class Reference

#include <MimeData.h>

Inheritance diagram for Kwave::MimeData:
Inheritance graph
Collaboration diagram for Kwave::MimeData:
Collaboration graph

Classes

class  Buffer
 

Public Member Functions

 MimeData ()
 
virtual ~MimeData () Q_DECL_OVERRIDE
 
virtual bool encode (QWidget *widget, Kwave::MultiTrackReader &src, const Kwave::MetaDataList &meta_data)
 
virtual void clear ()
 

Static Public Member Functions

static sample_index_t decode (QWidget *widget, const QMimeData *e, Kwave::SignalManager &sig, sample_index_t pos)
 

Private Attributes

Kwave::MimeData::Buffer m_buffer
 

Detailed Description

Definition at line 40 of file MimeData.h.

Constructor & Destructor Documentation

◆ MimeData()

Kwave::MimeData::MimeData ( )

Constructor

Definition at line 173 of file MimeData.cpp.

174  :QMimeData(), m_buffer()
175 {
176 }
Kwave::MimeData::Buffer m_buffer
Definition: MimeData.h:153

◆ ~MimeData()

Kwave::MimeData::~MimeData ( )
virtual

Destructor

Definition at line 179 of file MimeData.cpp.

180 {
181 }

Member Function Documentation

◆ clear()

void Kwave::MimeData::clear ( )
virtual

Clears the content, makes the storage an empty byte array

Definition at line 434 of file MimeData.cpp.

References Kwave::MimeData::Buffer::close(), and m_buffer.

Referenced by Kwave::ClipBoard::copy().

435 {
436  m_buffer.close();
437 }
Kwave::MimeData::Buffer m_buffer
Definition: MimeData.h:153
virtual void close() Q_DECL_OVERRIDE
Definition: MimeData.cpp:153
Here is the call graph for this function:
Here is the caller graph for this function:

◆ decode()

sample_index_t Kwave::MimeData::decode ( QWidget *  widget,
const QMimeData *  e,
Kwave::SignalManager sig,
sample_index_t  pos 
)
static

Decodes the encoded byte data of the given mime source and initializes a MultiTrackReader.

Parameters
widgetthe widget used for displaying error messages
esource with encoded mime data
sigsignal that receives the mime data
posposition within the signal where to insert the data
Returns
number of decoded samples if successful, zero if failed

Definition at line 237 of file MimeData.cpp.

References Kwave::MetaDataList::add(), Kwave::SignalManager::allTracks(), Kwave::CodecManager::canDecode(), Kwave::connect(), Kwave::Decoder::decode(), Kwave::CodecManager::decoder(), Kwave::MultiWriter::flush(), Kwave::ChannelMixer::init(), Kwave::Insert, Kwave::Decoder::metaData(), Kwave::SignalManager::metaData(), Kwave::FileInfo::metaDataType(), Kwave::SignalManager::newSignal(), Kwave::Decoder::open(), Kwave::SignalManager::rate(), Kwave::MetaDataList::remove(), Kwave::MetaDataList::scalePositions(), Kwave::MetaDataList::selectByType(), Kwave::SignalManager::selectedTracks(), Kwave::StreamObject::setAttribute(), Kwave::MetaDataList::shiftRight(), and Kwave::SignalManager::tracks().

Referenced by Kwave::Drag::decode(), and Kwave::ClipBoard::paste().

240 {
241  // decode, use the first format that matches
242  sample_index_t decoded_length = 0;
243  unsigned int decoded_tracks = 0;
244 
245  // try to find a suitable decoder
246  foreach (const QString &format, e->formats()) {
247  // skip all non-supported formats
248  if (!Kwave::CodecManager::canDecode(format)) continue;
249 
250  Kwave::Decoder *decoder = Kwave::CodecManager::decoder(format);
251  Q_ASSERT(decoder);
252  if (!decoder) return 0;
253 
254  QByteArray raw_data = e->data(format);
255  QBuffer src(&raw_data);
256 
257  // open the mime source and get header information
258  bool ok = decoder->open(widget, src);
259  if (!ok) {
260  delete decoder;
261  continue;
262  }
263 
264  decoded_length = Kwave::FileInfo(decoder->metaData()).length();
265  decoded_tracks = Kwave::FileInfo(decoder->metaData()).tracks();
266  Q_ASSERT(decoded_length);
267  Q_ASSERT(decoded_tracks);
268  if (!decoded_length || !decoded_tracks) {
269  delete decoder;
270  continue;
271  }
272 
273  // get sample rates of source and destination
274  double src_rate = Kwave::FileInfo(decoder->metaData()).rate();
275  double dst_rate = sig.rate();
276 
277  // if the sample rate has to be converted, adjust the length
278  // right border
279  if (!qFuzzyCompare(src_rate, dst_rate) && (dst_rate > 1) && sig.tracks())
280  decoded_length *= (dst_rate / src_rate);
281 
282  sample_index_t left = pos;
283  sample_index_t right = left + decoded_length - 1;
284  QList<unsigned int> tracks = sig.selectedTracks();
285  if (tracks.isEmpty()) tracks = sig.allTracks();
286 
287  // special case: destination is currently empty
288  if (!sig.tracks()) {
289  // encode into an empty window -> create tracks
290  qDebug("Kwave::MimeData::decode(...) -> new signal");
291  dst_rate = src_rate;
292  sig.newSignal(0,
293  src_rate,
294  Kwave::FileInfo(decoder->metaData()).bits(),
295  decoded_tracks);
296  ok = (sig.tracks() == decoded_tracks);
297  if (!ok) {
298  delete decoder;
299  continue;
300  }
301  }
302  const unsigned int dst_tracks = sig.selectedTracks().count();
303 
304  // create the final sink
306  Kwave::Insert, left, right);
307 
308  // if the track count does not match, then we need a channel mixer
309  Q_ASSERT(ok);
310  Kwave::ChannelMixer *mixer = Q_NULLPTR;
311  if (ok && (decoded_tracks != dst_tracks)) {
312  qDebug("Kwave::MimeData::decode(...) -> mixing channels: %u -> %u",
313  decoded_tracks, dst_tracks);
314  mixer = new(std::nothrow)
315  Kwave::ChannelMixer(decoded_tracks, dst_tracks);
316  Q_ASSERT(mixer);
317  ok &= (mixer) && mixer->init();
318  Q_ASSERT(ok);
319  }
320  Q_ASSERT(ok);
321 
322  // if the sample rates do not match, then we need a rate converter
323  Kwave::StreamObject *rate_converter = Q_NULLPTR;
324  if (ok && !qFuzzyCompare(src_rate, dst_rate)) {
325  // create a sample rate converter
326  qDebug("Kwave::MimeData::decode(...) -> rate conversion: "\
327  "%0.1f -> %0.1f", src_rate, dst_rate);
328  rate_converter = new(std::nothrow)
330  dst_tracks, widget);
331  Q_ASSERT(rate_converter);
332  if (rate_converter)
333  rate_converter->setAttribute(SLOT(setRatio(QVariant)),
334  QVariant(dst_rate / src_rate));
335  else
336  ok = false;
337  }
338  Q_ASSERT(ok);
339 
340  // set hourglass cursor
341  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
342 
343  if (ok && (rate_converter || mixer)) {
344  // pass all data through a filter chain
345  Kwave::MultiStreamWriter adapter(decoded_tracks);
346 
347  // pass the data through a sample rate converter
348  // decoder -> adapter -> [mixer] -> [converter] -> dst
349 
350  Kwave::StreamObject *last_output = &adapter;
351 
352  if (ok && mixer) {
353  // connect the channel mixer
354  ok = Kwave::connect(
355  *last_output, SIGNAL(output(Kwave::SampleArray)),
356  *mixer, SLOT(input(Kwave::SampleArray))
357  );
358  last_output = mixer;
359  }
360 
361  if (ok && rate_converter) {
362  // connect the rate converter
363  ok = Kwave::connect(
364  *last_output, SIGNAL(output(Kwave::SampleArray)),
365  *rate_converter, SLOT(input(Kwave::SampleArray))
366  );
367  last_output = rate_converter;
368  }
369 
370  // connect the sink
371  if (ok) {
372  ok = Kwave::connect(
373  *last_output, SIGNAL(output(Kwave::SampleArray)),
374  dst, SLOT(input(Kwave::SampleArray))
375  );
376  }
377 
378  // this also starts the conversion automatically
379  if (ok)
380  ok = decoder->decode(widget, adapter);
381 
382  // flush all samples that are still in the adapter
383  adapter.flush();
384 
385  } else if (ok) {
386  // decode directly without any filter
387  ok = decoder->decode(widget, dst);
388  }
389 
390  dst.flush();
391 
392  // clean up the filter chain
393  if (mixer) delete mixer;
394  if (rate_converter) delete rate_converter;
395 
396  // remove hourglass
397  QApplication::restoreOverrideCursor();
398 
399  // failed :-(
400  Q_ASSERT(ok);
401  if (!ok) {
402  delete decoder;
403  decoded_length = 0;
404  continue;
405  }
406 
407  // take care of the meta data, shift all it by "left" and
408  // add it to the signal
409  Kwave::MetaDataList meta_data = decoder->metaData();
410 
411  // adjust meta data position in case of different sample rate
412  if (!qFuzzyCompare(src_rate, dst_rate))
413  meta_data.scalePositions(dst_rate / src_rate, tracks);
414 
415  meta_data.shiftRight(0, left, tracks);
416 
417  // remove the file info, this must not be handled here, otherwise
418  // this would overwrite the file info of the destination
419  meta_data.remove(meta_data.selectByType(
421 
422  // add the remaining meta data (e.g. labels etc)
423  sig.metaData().add(meta_data);
424 
425  delete decoder;
426  break;
427  }
428 
429 // qDebug("Kwave::MimeData::decode -> decoded_length=%u", decoded_length);
430  return decoded_length;
431 }
virtual void shiftRight(sample_index_t offset, sample_index_t shift, const QList< unsigned int > &tracks)
Kwave::MetaDataList & metaData()
virtual void remove(const MetaData &metadata)
virtual void scalePositions(double scale, const QList< unsigned int > &tracks)
void newSignal(sample_index_t samples, double rate, unsigned int bits, unsigned int tracks)
unsigned int tracks()
quint64 sample_index_t
Definition: Sample.h:28
virtual bool open(QWidget *widget, QIODevice &source)=0
virtual void add(const MetaData &metadata)
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
virtual MetaDataList selectByType(const QString &type) const
virtual bool init()
double rate() const
virtual Kwave::MetaDataList & metaData()
Definition: Decoder.h:78
const QList< unsigned int > allTracks()
static QString metaDataType()
Definition: FileInfo.h:154
virtual bool decode(QWidget *widget, Kwave::MultiWriter &dst)=0
static Kwave::Decoder * decoder(const QString &mimetype_name)
const QList< unsigned int > selectedTracks()
static bool canDecode(const QString &mimetype_name)
void setAttribute(const char *attribute, const QVariant &value)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ encode()

bool Kwave::MimeData::encode ( QWidget *  widget,
Kwave::MultiTrackReader src,
const Kwave::MetaDataList meta_data 
)
virtual

Encodes wave data received from a MultiTrackReader into a byte array that is compatible with the format of a wav file.

Parameters
widgetthe widget used as parent for displaying error messages
srcsource of the samples
meta_datainformation about the signal, sample rate, resolution and other meta data
Returns
true if successful

Definition at line 184 of file MimeData.cpp.

References _, Kwave::MimeData::Buffer::byteArray(), Kwave::MimeData::Buffer::close(), Kwave::Encoder::encode(), Kwave::CodecManager::encoder(), Kwave::MultiTrackReader::first(), Kwave::INF_COMPRESSION, Kwave::MultiTrackReader::last(), m_buffer, Kwave::MimeData::Buffer::mapToByteArray(), Kwave::Compression::NONE, Kwave::MetaDataList::replace(), Kwave::MetaDataList::selectByRange(), Kwave::FileInfo::set(), Kwave::FileInfo::setLength(), Kwave::FileInfo::setTracks(), Kwave::MetaDataList::shiftLeft(), Kwave::MultiTrackSource< SOURCE, INITIALIZE >::tracks(), and Kwave::WAVE_FORMAT_PCM.

Referenced by Kwave::ClipBoard::copy(), and Kwave::Drag::encode().

187 {
188  // use our default encoder
190  Q_ASSERT(encoder);
191  if (!encoder) return false;
192 
193  Q_ASSERT(src.tracks());
194  if (!src.tracks()) return false;
195 
196  // set hourglass cursor
197  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
198 
199  sample_index_t first = src.first();
200  sample_index_t last = src.last();
201  Kwave::MetaDataList new_meta_data = meta_data.selectByRange(first, last);
202 
203  // move all meta data left, to start at the beginning of the selection
204  new_meta_data.shiftLeft(first, first, QList<unsigned int>());
205 
206  // fix the length information in the new file info
207  // and change to uncompressed mode
208  Kwave::FileInfo info(meta_data);
210  info.setLength(last - first + 1);
211  info.setTracks(src.tracks());
212  new_meta_data.replace(Kwave::MetaDataList(info));
213 
214  // encode into the buffer
215  m_buffer.close(); // discard old stuff
216  encoder->encode(widget, src, m_buffer, new_meta_data);
217 
218  delete encoder;
219 
220  // set the mime data into this mime data container
221  bool succeeded = m_buffer.mapToByteArray();
222  if (succeeded) {
223  // mmap succeeded
224  setData(_(WAVE_FORMAT_PCM), m_buffer.byteArray());
225  } else {
226  // failed to map memory
227  m_buffer.close();
228  }
229 
230  // remove hourglass
231  QApplication::restoreOverrideCursor();
232 
233  return succeeded;
234 }
virtual MetaDataList selectByRange(sample_index_t first, sample_index_t last) const
virtual sample_index_t first() const
Kwave::MimeData::Buffer m_buffer
Definition: MimeData.h:153
virtual unsigned int tracks() const Q_DECL_OVERRIDE
virtual void close() Q_DECL_OVERRIDE
Definition: MimeData.cpp:153
quint64 sample_index_t
Definition: Sample.h:28
virtual sample_index_t last() const
virtual void replace(const MetaDataList &list)
virtual bool encode(QWidget *widget, Kwave::MultiTrackReader &src, QIODevice &dst, const Kwave::MetaDataList &meta_data)=0
static Kwave::Encoder * encoder(const QString &mimetype_name)
#define _(m)
Definition: memcpy.c:66
virtual void shiftLeft(sample_index_t offset, sample_index_t shift, const QList< unsigned int > &tracks)
const QByteArray & byteArray() const
Definition: MimeData.h:109
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_buffer

Kwave::MimeData::Buffer Kwave::MimeData::m_buffer
private

buffer for the mime data (with swap file support)

Definition at line 153 of file MimeData.h.

Referenced by clear(), and encode().


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