summaryrefslogtreecommitdiffstats
path: root/plugins/decoder/wave
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:15:56 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:15:56 +0000
commit50b48aec6ddd451a6d1709c0942477b503457663 (patch)
treea9ece53ec06fd0a2819de7a2a6de997193566626 /plugins/decoder/wave
downloadk3b-50b48aec6ddd451a6d1709c0942477b503457663.tar.gz
k3b-50b48aec6ddd451a6d1709c0942477b503457663.zip
Added abandoned KDE3 version of K3B
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/k3b@1084400 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'plugins/decoder/wave')
-rw-r--r--plugins/decoder/wave/Makefile.am13
-rw-r--r--plugins/decoder/wave/k3bwavedecoder.cpp392
-rw-r--r--plugins/decoder/wave/k3bwavedecoder.h74
-rw-r--r--plugins/decoder/wave/k3bwavedecoder.plugin9
4 files changed, 488 insertions, 0 deletions
diff --git a/plugins/decoder/wave/Makefile.am b/plugins/decoder/wave/Makefile.am
new file mode 100644
index 0000000..5debea1
--- /dev/null
+++ b/plugins/decoder/wave/Makefile.am
@@ -0,0 +1,13 @@
+AM_CPPFLAGS = -I$(srcdir)/../../../libk3b/plugin -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3bdevice $(all_includes)
+
+kde_module_LTLIBRARIES = libk3bwavedecoder.la
+
+libk3bwavedecoder_la_SOURCES = k3bwavedecoder.cpp
+
+libk3bwavedecoder_la_LIBADD = $(LIB_KDECORE) ../../../libk3b/libk3b.la
+libk3bwavedecoder_la_LDFLAGS = -avoid-version -module -no-undefined $(all_libraries)
+
+pluginsdir = $(kde_datadir)/k3b/plugins
+plugins_DATA = k3bwavedecoder.plugin
+
+METASOURCES = AUTO
diff --git a/plugins/decoder/wave/k3bwavedecoder.cpp b/plugins/decoder/wave/k3bwavedecoder.cpp
new file mode 100644
index 0000000..6494e5c
--- /dev/null
+++ b/plugins/decoder/wave/k3bwavedecoder.cpp
@@ -0,0 +1,392 @@
+/*
+ *
+ * $Id: k3bwavedecoder.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * 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.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#include "k3bwavedecoder.h"
+
+#include <k3bpluginfactory.h>
+
+#include <qfile.h>
+#include <qcstring.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+
+
+K_EXPORT_COMPONENT_FACTORY( libk3bwavedecoder, K3bPluginFactory<K3bWaveDecoderFactory>( "libk3bwavedecoder" ) )
+
+
+static unsigned short le_a_to_u_short( unsigned char* a ) {
+ return ((unsigned short)
+ ((a[0] & 0xFF) |
+ (a[1] << 8 & 0xFF00)) );
+}
+
+static unsigned long le_a_to_u_long( unsigned char* a ) {
+ return ((unsigned long)
+ ((a[0] & 0xFF) |
+ (a[1] << 8 & 0xFF00) |
+ (a[2] << 16 & 0xFF0000) |
+ (a[3] << 24 & 0xFF000000)) );
+}
+
+
+/**
+ * Returns the length of the wave file in bytes
+ * Otherwise 0 is returned.
+ * leave file seek pointer past WAV header.
+ */
+static unsigned long identifyWaveFile( QFile* f, int* samplerate = 0, int* channels = 0, int* samplesize = 0 )
+{
+ typedef struct {
+ unsigned char ckid[4];
+ unsigned char cksize[4];
+ } chunk_t;
+
+ typedef struct {
+ unsigned char wave[4];
+ } riff_chunk;
+
+ typedef struct {
+ unsigned char fmt_tag[2];
+ unsigned char channels[2];
+ unsigned char sample_rate[4];
+ unsigned char av_byte_rate[4];
+ unsigned char block_size[2];
+ unsigned char bits_per_sample[2];
+ } fmt_chunk;
+
+ static const char* WAV_RIFF_MAGIC = "RIFF"; // Magic for file format
+ static const char* WAV_WAVE_MAGIC = "WAVE"; // Magic for Waveform Audio
+ static const char* WAV_FMT_MAGIC = "fmt "; // Start of Waveform format
+ static const char* WAV_DATA_MAGIC = "data"; // Start of data chunk
+
+ chunk_t chunk;
+ riff_chunk riff;
+ fmt_chunk fmt;
+
+
+ // read riff chunk
+ if( f->readBlock( (char*)&chunk, sizeof(chunk) ) != sizeof(chunk) ) {
+ kdDebug() << "(K3bWaveDecoder) unable to read from " << f->name() << endl;
+ return 0;
+ }
+ if( qstrncmp( (char*)chunk.ckid, WAV_RIFF_MAGIC, 4 ) ) {
+ kdDebug() << "(K3bWaveDecoder) " << f->name() << ": not a RIFF file." << endl;
+ return 0;
+ }
+
+ // read wave chunk
+ if( f->readBlock( (char*)&riff, sizeof(riff) ) != sizeof(riff) ) {
+ kdDebug() << "(K3bWaveDecoder) unable to read from " << f->name() << endl;
+ return 0;
+ }
+ if( qstrncmp( (char*)riff.wave, WAV_WAVE_MAGIC, 4 ) ) {
+ kdDebug() << "(K3bWaveDecoder) " << f->name() << ": not a WAVE file." << endl;
+ return 0;
+ }
+
+
+ // read fmt chunk
+ if( f->readBlock( (char*)&chunk, sizeof(chunk) ) != sizeof(chunk) ) {
+ kdDebug() << "(K3bWaveDecoder) unable to read from " << f->name() << endl;
+ return 0;
+ }
+ if( qstrncmp( (char*)chunk.ckid, WAV_FMT_MAGIC, 4 ) ) {
+ kdDebug() << "(K3bWaveDecoder) " << f->name() << ": could not find format chunk." << endl;
+ return 0;
+ }
+ if( f->readBlock( (char*)&fmt, sizeof(fmt) ) != sizeof(fmt) ) {
+ kdDebug() << "(K3bWaveDecoder) unable to read from " << f->name() << endl;
+ return 0;
+ }
+ if( le_a_to_u_short(fmt.fmt_tag) != 1 ||
+ le_a_to_u_short(fmt.channels) > 2 ||
+ ( le_a_to_u_short(fmt.bits_per_sample) != 16 &&
+ le_a_to_u_short(fmt.bits_per_sample) != 8 ) ) {
+ kdDebug() << "(K3bWaveDecoder) " << f->name() << ": wrong format:" << endl
+ << " format: " << le_a_to_u_short(fmt.fmt_tag) << endl
+ << " channels: " << le_a_to_u_short(fmt.channels) << endl
+ << " samplerate: " << le_a_to_u_long(fmt.sample_rate) << endl
+ << " bits/sample: " << le_a_to_u_short(fmt.bits_per_sample) << endl;
+ return 0;
+ }
+
+ int sampleRate = le_a_to_u_long(fmt.sample_rate);
+ int ch = le_a_to_u_short(fmt.channels);
+ int sampleSize = le_a_to_u_short(fmt.bits_per_sample);;
+ if( samplerate )
+ *samplerate = sampleRate;
+ if( channels )
+ *channels = ch;
+ if( samplesize )
+ *samplesize = sampleSize;
+
+ // skip all other (unknown) format chunk fields
+ if( !f->at( f->at() + le_a_to_u_long(chunk.cksize) - sizeof(fmt) ) ) {
+ kdDebug() << "(K3bWaveDecoder) " << f->name() << ": could not seek in file." << endl;
+ return 0;
+ }
+
+
+ // find data chunk
+ bool foundData = false;
+ while( !foundData ) {
+ if( f->readBlock( (char*)&chunk, sizeof(chunk) ) != sizeof(chunk) ) {
+ kdDebug() << "(K3bWaveDecoder) unable to read from " << f->name() << endl;
+ return 0;
+ }
+
+ // skip chunk data of unknown chunk
+ if( qstrncmp( (char*)chunk.ckid, WAV_DATA_MAGIC, 4 ) ) {
+ kdDebug() << "(K3bWaveDecoder) skipping chunk: " << (char*)chunk.ckid << endl;
+ if( !f->at( f->at() + le_a_to_u_long(chunk.cksize) ) ) {
+ kdDebug() << "(K3bWaveDecoder) " << f->name() << ": could not seek in file." << endl;
+ return 0;
+ }
+ }
+ else
+ foundData = true;
+ }
+
+ // found data chunk
+ unsigned long size = le_a_to_u_long(chunk.cksize);
+ if( f->at() + size > (unsigned long)f->size() ) {
+ kdDebug() << "(K3bWaveDecoder) " << f->name() << ": file length " << f->size()
+ << " does not match length from WAVE header " << f->at() << " + " << size
+ << " - using actual length." << endl;
+ size = (f->size() - f->at());
+ }
+
+ return size;
+}
+
+
+class K3bWaveDecoder::Private {
+public:
+ Private()
+ : buffer(0),
+ bufferSize(0) {
+ }
+
+ QFile* file;
+
+ long headerLength;
+ int sampleRate;
+ int channels;
+ int sampleSize;
+ unsigned long size;
+ unsigned long alreadyRead;
+
+ char* buffer;
+ int bufferSize;
+};
+
+
+K3bWaveDecoder::K3bWaveDecoder( QObject* parent, const char* name )
+ : K3bAudioDecoder( parent, name )
+{
+ d = new Private();
+ d->file = new QFile();
+}
+
+
+K3bWaveDecoder::~K3bWaveDecoder()
+{
+ delete d->file;
+ delete d;
+}
+
+
+int K3bWaveDecoder::decodeInternal( char* _data, int maxLen )
+{
+ int read = 0;
+
+ maxLen = QMIN( maxLen, (int)(d->size - d->alreadyRead) );
+
+ if( d->sampleSize == 16 ) {
+ read = d->file->readBlock( _data, maxLen );
+ if( read > 0 ) {
+ d->alreadyRead += read;
+
+ if( read % 2 > 0 ) {
+ kdDebug() << "(K3bWaveDecoder) data length is not a multiple of 2! Cutting data." << endl;
+ read -= 1;
+ }
+
+ // swap bytes
+ char buf;
+ for( int i = 0; i < read; i+=2 ) {
+ buf = _data[i];
+ _data[i] = _data[i+1];
+ _data[i+1] = buf;
+ }
+ }
+ }
+ else {
+ if( !d->buffer ) {
+ d->buffer = new char[maxLen/2];
+ d->bufferSize = maxLen/2;
+ }
+
+ read = d->file->readBlock( d->buffer, QMIN(maxLen/2, d->bufferSize) );
+ d->alreadyRead += read;
+
+ // stretch samples to 16 bit
+ from8BitTo16BitBeSigned( d->buffer, _data, read );
+
+ read *= 2;
+ }
+
+ return read;
+}
+
+
+bool K3bWaveDecoder::analyseFileInternal( K3b::Msf& frames, int& samplerate, int& channels )
+{
+ // handling wave files is very easy...
+ if( initDecoderInternal() ) {
+
+ //
+ // d->size is the number of bytes in the wave file
+ //
+ unsigned long size = d->size;
+ if( d->sampleRate != 44100 )
+ size = (int)((double)size * 44100.0 / (double)d->sampleRate);
+
+ if( d->sampleSize == 8 )
+ size *= 2;
+ if( d->channels == 1 )
+ size *= 2;
+
+ //
+ // we pad to a multiple of 2352 bytes
+ // (the actual padding of zero data will be done by the K3bAudioDecoder class)
+ //
+ if( (size%2352) > 0 )
+ size = (size/2352) + 1;
+ else
+ size = size/2352;
+
+ frames = size;
+ samplerate = d->sampleRate;
+ channels = d->channels;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+bool K3bWaveDecoder::initDecoderInternal()
+{
+ cleanup();
+
+ d->file->setName( filename() );
+ if( !d->file->open( IO_ReadOnly ) ) {
+ kdDebug() << "(K3bWaveDecoder) could not open file." << endl;
+ return false;
+ }
+
+ // skip the header
+ d->size = identifyWaveFile( d->file, &d->sampleRate, &d->channels, &d->sampleSize );
+ if( d->size <= 0 ) {
+ kdDebug() << "(K3bWaveDecoder) no supported wave file." << endl;
+ cleanup();
+ return false;
+ }
+
+ d->headerLength = d->file->at();
+ d->alreadyRead = 0;
+
+ return true;
+}
+
+
+bool K3bWaveDecoder::seekInternal( const K3b::Msf& pos )
+{
+ return( d->file->at( d->headerLength + (pos.totalFrames()*2352) ) );
+}
+
+
+void K3bWaveDecoder::cleanup()
+{
+ if( d->file->isOpen() )
+ d->file->close();
+}
+
+
+QString K3bWaveDecoder::fileType() const
+{
+ return i18n("WAVE");
+}
+
+
+QStringList K3bWaveDecoder::supportedTechnicalInfos() const
+{
+ return QStringList::split( ";",
+ i18n("Channels") + ";" +
+ i18n("Sampling Rate") + ";" +
+ i18n("Sample Size") );
+}
+
+
+QString K3bWaveDecoder::technicalInfo( const QString& name ) const
+{
+ if( name == i18n("Channels") )
+ return QString::number(d->channels);
+ else if( name == i18n("Sampling Rate") )
+ return i18n("%1 Hz").arg(d->sampleRate);
+ else if( name == i18n("Sample Size") )
+ return i18n("%1 bits").arg(d->sampleSize);
+ else
+ return QString::null;
+}
+
+
+K3bWaveDecoderFactory::K3bWaveDecoderFactory( QObject* parent, const char* name )
+ : K3bAudioDecoderFactory( parent, name )
+{
+}
+
+
+K3bWaveDecoderFactory::~K3bWaveDecoderFactory()
+{
+}
+
+
+K3bAudioDecoder* K3bWaveDecoderFactory::createDecoder( QObject* parent,
+ const char* name ) const
+{
+ return new K3bWaveDecoder( parent, name );
+}
+
+
+bool K3bWaveDecoderFactory::canDecode( const KURL& url )
+{
+ QFile f( url.path() );
+ if( !f.open( IO_ReadOnly ) ) {
+ kdDebug() << "(K3bWaveDecoder) could not open file " << url.path() << endl;
+ return false;
+ }
+
+ return (identifyWaveFile( &f ) > 0);
+}
+
+
+
+#include "k3bwavedecoder.moc"
diff --git a/plugins/decoder/wave/k3bwavedecoder.h b/plugins/decoder/wave/k3bwavedecoder.h
new file mode 100644
index 0000000..3f92e9a
--- /dev/null
+++ b/plugins/decoder/wave/k3bwavedecoder.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * $Id: k3bwavedecoder.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * 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.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#ifndef _K3B_WAVE_DECODER_H_
+#define _K3B_WAVE_DECODER_H_
+
+#include <k3baudiodecoder.h>
+#include <k3b_export.h>
+
+#include <kurl.h>
+#include <qcstring.h>
+
+
+class QFile;
+
+
+class LIBK3B_EXPORT K3bWaveDecoderFactory : public K3bAudioDecoderFactory
+{
+ Q_OBJECT
+
+ public:
+ K3bWaveDecoderFactory( QObject* parent = 0, const char* name = 0 );
+ ~K3bWaveDecoderFactory();
+
+ bool canDecode( const KURL& filename );
+
+ int pluginSystemVersion() const { return 3; }
+
+ K3bAudioDecoder* createDecoder( QObject* parent = 0,
+ const char* name = 0 ) const;
+};
+
+
+class LIBK3B_EXPORT K3bWaveDecoder : public K3bAudioDecoder
+{
+ Q_OBJECT
+
+ public:
+ K3bWaveDecoder( QObject* parent = 0, const char* name = 0 );
+ ~K3bWaveDecoder();
+
+ void cleanup();
+
+ bool seekInternal( const K3b::Msf& );
+
+ QString fileType() const;
+
+ QStringList supportedTechnicalInfos() const;
+
+ QString technicalInfo( const QString& ) const;
+
+ protected:
+ bool analyseFileInternal( K3b::Msf& frames, int& samplerate, int& channels );
+ bool initDecoderInternal();
+ int decodeInternal( char* data, int maxLen );
+
+ private:
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/plugins/decoder/wave/k3bwavedecoder.plugin b/plugins/decoder/wave/k3bwavedecoder.plugin
new file mode 100644
index 0000000..7b0a4f4
--- /dev/null
+++ b/plugins/decoder/wave/k3bwavedecoder.plugin
@@ -0,0 +1,9 @@
+[K3b Plugin]
+Lib=libk3bwavedecoder
+Group=AudioDecoder
+Name=K3b Wave Decoder
+Author=Sebastian Trueg
+Email=trueg@k3b.org
+Version=3.0
+Comment=Decoding module to decode wave files
+License=GPL