summaryrefslogtreecommitdiffstats
path: root/plugins/encoder
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/encoder
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/encoder')
-rw-r--r--plugins/encoder/Makefile.am9
-rw-r--r--plugins/encoder/external/Makefile.am15
-rw-r--r--plugins/encoder/external/base_k3bexternalencoderconfigwidget.ui148
-rw-r--r--plugins/encoder/external/base_k3bexternalencodereditwidget.ui164
-rw-r--r--plugins/encoder/external/k3bexternalencoder.cpp380
-rw-r--r--plugins/encoder/external/k3bexternalencoder.h68
-rw-r--r--plugins/encoder/external/k3bexternalencoder.plugin9
-rw-r--r--plugins/encoder/external/k3bexternalencodercommand.cpp110
-rw-r--r--plugins/encoder/external/k3bexternalencodercommand.h40
-rw-r--r--plugins/encoder/external/k3bexternalencoderconfigwidget.cpp228
-rw-r--r--plugins/encoder/external/k3bexternalencoderconfigwidget.h72
-rw-r--r--plugins/encoder/lame/Makefile.am15
-rw-r--r--plugins/encoder/lame/base_k3blameencodersettingswidget.ui480
-rw-r--r--plugins/encoder/lame/base_k3bmanualbitratesettingswidget.ui273
-rw-r--r--plugins/encoder/lame/configure.in.bot11
-rw-r--r--plugins/encoder/lame/configure.in.in20
-rw-r--r--plugins/encoder/lame/k3blameencoder.cpp627
-rw-r--r--plugins/encoder/lame/k3blameencoder.h88
-rw-r--r--plugins/encoder/lame/k3blameencoder.plugin9
-rw-r--r--plugins/encoder/ogg/Makefile.am13
-rw-r--r--plugins/encoder/ogg/base_k3boggvorbisencodersettingswidget.ui392
-rw-r--r--plugins/encoder/ogg/k3boggvorbisencoder.cpp555
-rw-r--r--plugins/encoder/ogg/k3boggvorbisencoder.h81
-rw-r--r--plugins/encoder/ogg/k3boggvorbisencoder.plugin9
-rw-r--r--plugins/encoder/skeleton.cpp123
-rw-r--r--plugins/encoder/skeleton.h64
-rw-r--r--plugins/encoder/skeleton.plugin9
-rw-r--r--plugins/encoder/sox/Makefile.am13
-rw-r--r--plugins/encoder/sox/base_k3bsoxencoderconfigwidget.ui258
-rw-r--r--plugins/encoder/sox/k3bsoxencoder.cpp482
-rw-r--r--plugins/encoder/sox/k3bsoxencoder.h82
-rw-r--r--plugins/encoder/sox/k3bsoxencoder.plugin9
32 files changed, 4856 insertions, 0 deletions
diff --git a/plugins/encoder/Makefile.am b/plugins/encoder/Makefile.am
new file mode 100644
index 0000000..35724e1
--- /dev/null
+++ b/plugins/encoder/Makefile.am
@@ -0,0 +1,9 @@
+if include_LAME
+ENCLAMEDIR = lame
+endif
+
+if include_OGG
+ENCOGGDIR = ogg
+endif
+
+SUBDIRS = sox external $(ENCLAMEDIR) $(ENCOGGDIR)
diff --git a/plugins/encoder/external/Makefile.am b/plugins/encoder/external/Makefile.am
new file mode 100644
index 0000000..a095688
--- /dev/null
+++ b/plugins/encoder/external/Makefile.am
@@ -0,0 +1,15 @@
+AM_CPPFLAGS = -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3b/plugin -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3bdevice $(all_includes)
+
+kde_module_LTLIBRARIES = libk3bexternalencoder.la
+
+libk3bexternalencoder_la_SOURCES = base_k3bexternalencoderconfigwidget.ui \
+ base_k3bexternalencodereditwidget.ui k3bexternalencoder.cpp \
+ k3bexternalencoderconfigwidget.cpp k3bexternalencodercommand.cpp
+
+libk3bexternalencoder_la_LIBADD = ../../../libk3b/libk3b.la $(LIB_KDECORE)
+libk3bexternalencoder_la_LDFLAGS = -avoid-version -module -no-undefined $(all_libraries)
+
+pluginsdir = $(kde_datadir)/k3b/plugins
+plugins_DATA = k3bexternalencoder.plugin
+
+METASOURCES = AUTO
diff --git a/plugins/encoder/external/base_k3bexternalencoderconfigwidget.ui b/plugins/encoder/external/base_k3bexternalencoderconfigwidget.ui
new file mode 100644
index 0000000..dd32d08
--- /dev/null
+++ b/plugins/encoder/external/base_k3bexternalencoderconfigwidget.ui
@@ -0,0 +1,148 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bExternalEncoderConfigWidget</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bExternalEncoderConfigWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>441</width>
+ <height>354</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KActiveLabel">
+ <property name="name">
+ <cstring>kActiveLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;p&gt;This dialog can be used to setup external command line applications as audio encoders. These can then be used by K3b to encode audio data (Tracks from an audio CD or the titles from an audio project) to formats that are normally not supported (i.e. no encoder plugin exists).
+&lt;p&gt;K3b comes with a selection of predefined external applications that depends on the installed applications.</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Configured Encoders</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QListView">
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Extension</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Command</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_viewEncoders</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>71</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonRemove</cstring>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonEdit</cstring>
+ </property>
+ <property name="text">
+ <string>Edit...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonAdd</cstring>
+ </property>
+ <property name="text">
+ <string>Add...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kactivelabel.h</includehint>
+</includehints>
+</UI>
diff --git a/plugins/encoder/external/base_k3bexternalencodereditwidget.ui b/plugins/encoder/external/base_k3bexternalencodereditwidget.ui
new file mode 100644
index 0000000..9f3fb5a
--- /dev/null
+++ b/plugins/encoder/external/base_k3bexternalencodereditwidget.ui
@@ -0,0 +1,164 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bExternalEncoderEditWidget</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bExternalEncoderEditWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>529</width>
+ <height>514</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>General</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>m_editExtension</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="1" column="0">
+ <property name="name">
+ <cstring>m_editName</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Filename extension:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>Command</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KActiveLabel">
+ <property name="name">
+ <cstring>kActiveLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;p&gt;&lt;b&gt;Command&lt;/b&gt;&lt;br&gt;
+Please insert the command used to encode the audio data. The command has to read raw little endian (see &lt;em&gt;Swap Byte Order&lt;/em&gt;) 16bit stereo audio frames from stdin.
+&lt;p&gt;The following strings will be replaced by K3b:&lt;br&gt;
+&lt;b&gt;%f&lt;/b&gt; - The filename of the resulting file. This is where the command has to write its output to.&lt;br&gt;
+&lt;em&gt;The following refer to metadata stored for example in the ID3 tag of am mp3 file (Be aware that these values might be empty).&lt;/em&gt;&lt;br&gt;
+&lt;b&gt;%t&lt;/b&gt; - Title&lt;br&gt;
+&lt;b&gt;%a&lt;/b&gt; - Artist&lt;br&gt;
+&lt;b&gt;%c&lt;/b&gt; - Comment&lt;br&gt;
+&lt;b&gt;%n&lt;/b&gt; - Track number&lt;br&gt;
+&lt;b&gt;%m&lt;/b&gt; - Album Title&lt;br&gt;
+&lt;b&gt;%r&lt;/b&gt; - Album Artist&lt;br&gt;
+&lt;b&gt;%x&lt;/b&gt; - Album comment&lt;br&gt;
+&lt;b&gt;%y&lt;/b&gt; - Release Year</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_editCommand</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox4</cstring>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkSwapByteOrder</cstring>
+ </property>
+ <property name="text">
+ <string>Swap &amp;Byte Order</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Swap the byte order of the input data</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt; If this option is checked K3b will swap the byte order of the input data. Thus, the command has to read big endian audio frames.
+&lt;p&gt;If the resulting audio file sounds bad it is highly likely that the byte order is wrong and this option has to be checked.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkWriteWaveHeader</cstring>
+ </property>
+ <property name="text">
+ <string>Write W&amp;ave Header</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Create a wave header for the input data</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked K3b will write a wave header. This is useful in case the encoder application cannot read plain raw audio data.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+</widget>
+<tabstops>
+ <tabstop>m_editName</tabstop>
+ <tabstop>m_editExtension</tabstop>
+ <tabstop>m_editCommand</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kactivelabel.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/plugins/encoder/external/k3bexternalencoder.cpp b/plugins/encoder/external/k3bexternalencoder.cpp
new file mode 100644
index 0000000..4eb0218
--- /dev/null
+++ b/plugins/encoder/external/k3bexternalencoder.cpp
@@ -0,0 +1,380 @@
+/*
+ *
+ * $Id: k3bexternalencoder.cpp 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003-2007 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 "k3bexternalencoder.h"
+#include "k3bexternalencodercommand.h"
+#include "k3bexternalencoderconfigwidget.h"
+
+#include <k3bpluginfactory.h>
+#include <k3bprocess.h>
+#include <k3bcore.h>
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+#include <qregexp.h>
+#include <qfile.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+
+K_EXPORT_COMPONENT_FACTORY( libk3bexternalencoder, K3bPluginFactory<K3bExternalEncoder>( "libk3bexternalencoder" ) )
+
+
+static const char s_riffHeader[] =
+{
+ 0x52, 0x49, 0x46, 0x46, // 0 "RIFF"
+ 0x00, 0x00, 0x00, 0x00, // 4 wavSize
+ 0x57, 0x41, 0x56, 0x45, // 8 "WAVE"
+ 0x66, 0x6d, 0x74, 0x20, // 12 "fmt "
+ 0x10, 0x00, 0x00, 0x00, // 16
+ 0x01, 0x00, 0x02, 0x00, // 20
+ 0x44, 0xac, 0x00, 0x00, // 24
+ 0x10, 0xb1, 0x02, 0x00, // 28
+ 0x04, 0x00, 0x10, 0x00, // 32
+ 0x64, 0x61, 0x74, 0x61, // 36 "data"
+ 0x00, 0x00, 0x00, 0x00 // 40 byteCount
+};
+
+
+
+
+
+static K3bExternalEncoderCommand commandByExtension( const QString& extension )
+{
+ QValueList<K3bExternalEncoderCommand> cmds( K3bExternalEncoderCommand::readCommands() );
+ for( QValueList<K3bExternalEncoderCommand>::iterator it = cmds.begin(); it != cmds.end(); ++it )
+ if( (*it).extension == extension )
+ return *it;
+
+ kdDebug() << "(K3bExternalEncoder) could not find command for extension " << extension << endl;
+
+ return K3bExternalEncoderCommand();
+}
+
+
+class K3bExternalEncoder::Private
+{
+public:
+ Private()
+ : process(0) {
+ }
+
+ K3bProcess* process;
+ QString fileName;
+ QString extension;
+ K3b::Msf length;
+
+ K3bExternalEncoderCommand cmd;
+
+ bool initialized;
+
+ // the metaData we support
+ QString artist;
+ QString title;
+ QString comment;
+ QString trackNumber;
+ QString cdArtist;
+ QString cdTitle;
+ QString cdComment;
+ QString year;
+ QString genre;
+};
+
+
+K3bExternalEncoder::K3bExternalEncoder( QObject* parent, const char* name )
+ : K3bAudioEncoder( parent, name )
+{
+ d = new Private();
+}
+
+
+K3bExternalEncoder::~K3bExternalEncoder()
+{
+ delete d->process;
+ delete d;
+}
+
+
+void K3bExternalEncoder::setMetaDataInternal( K3bAudioEncoder::MetaDataField f, const QString& value )
+{
+ switch( f ) {
+ case META_TRACK_TITLE:
+ d->title = value;
+ break;
+ case META_TRACK_ARTIST:
+ d->artist = value;
+ break;
+ case META_TRACK_COMMENT:
+ d->comment = value;
+ break;
+ case META_TRACK_NUMBER:
+ d->trackNumber = value;
+ break;
+ case META_ALBUM_TITLE:
+ d->cdTitle = value;
+ break;
+ case META_ALBUM_ARTIST:
+ d->cdArtist = value;
+ break;
+ case META_ALBUM_COMMENT:
+ d->cdComment = value;
+ break;
+ case META_YEAR:
+ d->year = value;
+ break;
+ case META_GENRE:
+ d->genre = value;
+ break;
+ }
+}
+
+
+void K3bExternalEncoder::finishEncoderInternal()
+{
+ if( d->process ) {
+ if( d->process->isRunning() ) {
+ ::close( d->process->stdinFd() );
+
+ // this is kind of evil...
+ // but we need to be sure the process exited when this method returnes
+ ::waitpid( d->process->pid(), 0, 0 );
+ }
+ }
+}
+
+
+void K3bExternalEncoder::slotExternalProgramFinished( KProcess* p )
+{
+ if( !p->normalExit() || p->exitStatus() != 0 )
+ kdDebug() << "(K3bExternalEncoder) program exited with error." << endl;
+}
+
+
+bool K3bExternalEncoder::openFile( const QString& ext, const QString& filename, const K3b::Msf& length )
+{
+ d->fileName = filename;
+ d->extension = ext;
+ d->initialized = false;
+ d->length = length;
+
+ // delete existing files as some programs (like flac for example) might refuse to overwrite files
+ if( QFile::exists( filename ) )
+ QFile::remove( filename );
+
+ return true;
+}
+
+
+void K3bExternalEncoder::closeFile()
+{
+ finishEncoderInternal();
+}
+
+
+bool K3bExternalEncoder::initEncoderInternal( const QString& extension )
+{
+ d->initialized = true;
+
+ // find the correct command
+ d->cmd = commandByExtension( extension );
+
+ if( d->cmd.command.isEmpty() ) {
+ setLastError( i18n("Invalid command: the command is empty.") );
+ return false;
+ }
+
+ // setup the process
+ delete d->process;
+ d->process = new K3bProcess();
+ d->process->setSplitStdout(true);
+ d->process->setRawStdin(true);
+
+ connect( d->process, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotExternalProgramFinished(KProcess*)) );
+ connect( d->process, SIGNAL(stderrLine(const QString&)),
+ this, SLOT(slotExternalProgramOutputLine(const QString&)) );
+ connect( d->process, SIGNAL(stdoutLine(const QString&)),
+ this, SLOT(slotExternalProgramOutputLine(const QString&)) );
+
+
+ // create the commandline
+ QStringList params = QStringList::split( ' ', d->cmd.command, false );
+ for( QStringList::iterator it = params.begin(); it != params.end(); ++it ) {
+ (*it).replace( "%f", d->fileName );
+ (*it).replace( "%a", d->artist );
+ (*it).replace( "%t", d->title );
+ (*it).replace( "%c", d->comment );
+ (*it).replace( "%y", d->year );
+ (*it).replace( "%m", d->cdTitle );
+ (*it).replace( "%r", d->cdArtist );
+ (*it).replace( "%x", d->cdComment );
+ (*it).replace( "%n", d->trackNumber );
+ (*it).replace( "%g", d->genre );
+
+ *d->process << *it;
+ }
+
+
+ kdDebug() << "***** external parameters:" << endl;
+ const QValueList<QCString>& args = d->process->args();
+ QString s;
+ for( QValueList<QCString>::const_iterator it = args.begin(); it != args.end(); ++it ) {
+ s += *it + " ";
+ }
+ kdDebug() << s << flush << endl;
+
+ // set one general error message
+ setLastError( i18n("Command failed: %1").arg( s ) );
+
+ if( d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) {
+ if( d->cmd.writeWaveHeader )
+ return writeWaveHeader();
+ else
+ return true;
+ }
+ else {
+ QString commandName = d->cmd.command.section( QRegExp("\\s+"), 0 );
+ if( !KStandardDirs::findExe( commandName ).isEmpty() )
+ setLastError( i18n("Could not find program '%1'").arg(commandName) );
+
+ return false;
+ }
+}
+
+
+bool K3bExternalEncoder::writeWaveHeader()
+{
+ kdDebug() << "(K3bExternalEncoder) writing wave header" << endl;
+
+ // write the RIFF thing
+ if( ::write( d->process->stdinFd(), s_riffHeader, 4 ) != 4 ) {
+ kdDebug() << "(K3bExternalEncoder) failed to write riff header." << endl;
+ return false;
+ }
+
+ // write the wave size
+ Q_INT32 dataSize( d->length.audioBytes() );
+ Q_INT32 wavSize( dataSize + 44 - 8 );
+ char c[4];
+
+ c[0] = (wavSize >> 0 ) & 0xff;
+ c[1] = (wavSize >> 8 ) & 0xff;
+ c[2] = (wavSize >> 16) & 0xff;
+ c[3] = (wavSize >> 24) & 0xff;
+
+ if( ::write( d->process->stdinFd(), c, 4 ) != 4 ) {
+ kdDebug() << "(K3bExternalEncoder) failed to write wave size." << endl;
+ return false;
+ }
+
+ // write static part of the header
+ if( ::write( d->process->stdinFd(), s_riffHeader+8, 32 ) != 32 ) {
+ kdDebug() << "(K3bExternalEncoder) failed to write wave header." << endl;
+ return false;
+ }
+
+ c[0] = (dataSize >> 0 ) & 0xff;
+ c[1] = (dataSize >> 8 ) & 0xff;
+ c[2] = (dataSize >> 16) & 0xff;
+ c[3] = (dataSize >> 24) & 0xff;
+
+ if( ::write( d->process->stdinFd(), c, 4 ) != 4 ) {
+ kdDebug() << "(K3bExternalEncoder) failed to write data size." << endl;
+ return false;
+ }
+
+ return true;
+}
+
+
+long K3bExternalEncoder::encodeInternal( const char* data, Q_ULONG len )
+{
+ if( !d->initialized )
+ if( !initEncoderInternal( d->extension ) )
+ return -1;
+
+ if( d->process ) {
+ if( d->process->isRunning() ) {
+
+ long written = 0;
+
+ //
+ // we swap the bytes to reduce user irritation ;)
+ // This is a little confused: We used to swap the byte order
+ // in older versions of this encoder since little endian seems
+ // to "feel" more natural.
+ // So now that we have a swap option we have to invert it to ensure
+ // compatibility
+ //
+ if( !d->cmd.swapByteOrder ) {
+ char* buffer = new char[len];
+ for( unsigned int i = 0; i < len-1; i+=2 ) {
+ buffer[i] = data[i+1];
+ buffer[i+1] = data[i];
+ }
+
+ written = ::write( d->process->stdinFd(), (const void*)buffer, len );
+ delete [] buffer;
+ }
+ else
+ written = ::write( d->process->stdinFd(), (const void*)data, len );
+
+ return written;
+ }
+ else
+ return -1;
+ }
+ else
+ return -1;
+}
+
+
+void K3bExternalEncoder::slotExternalProgramOutputLine( const QString& line )
+{
+ kdDebug() << "(" << d->cmd.name << ") " << line << endl;
+}
+
+
+QStringList K3bExternalEncoder::extensions() const
+{
+ QStringList el;
+ QValueList<K3bExternalEncoderCommand> cmds( K3bExternalEncoderCommand::readCommands() );
+ for( QValueList<K3bExternalEncoderCommand>::iterator it = cmds.begin(); it != cmds.end(); ++it )
+ el.append( (*it).extension );
+
+ return el;
+}
+
+
+QString K3bExternalEncoder::fileTypeComment( const QString& ext ) const
+{
+ return commandByExtension( ext ).name;
+}
+
+
+K3bPluginConfigWidget* K3bExternalEncoder::createConfigWidget( QWidget* parent,
+ const char* name ) const
+{
+ return new K3bExternalEncoderSettingsWidget( parent, name );
+}
+
+
+#include "k3bexternalencoder.moc"
diff --git a/plugins/encoder/external/k3bexternalencoder.h b/plugins/encoder/external/k3bexternalencoder.h
new file mode 100644
index 0000000..1612927
--- /dev/null
+++ b/plugins/encoder/external/k3bexternalencoder.h
@@ -0,0 +1,68 @@
+/*
+ *
+ * $Id: k3bexternalencoder.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_EXTERNAL_ENCODER_H_
+#define _K3B_EXTERNAL_ENCODER_H_
+
+
+#include <k3baudioencoder.h>
+
+
+class base_K3bExternalEncoderConfigWidget;
+class KProcess;
+
+
+class K3bExternalEncoder : public K3bAudioEncoder
+{
+ Q_OBJECT
+
+ public:
+ K3bExternalEncoder( QObject* parent = 0, const char* name = 0 );
+ ~K3bExternalEncoder();
+
+ QStringList extensions() const;
+
+ QString fileTypeComment( const QString& ) const;
+
+ int pluginSystemVersion() const { return 3; }
+
+ K3bPluginConfigWidget* createConfigWidget( QWidget* parent,
+ const char* name ) const;
+
+ /**
+ * reimplemented since the external program is intended to write the file
+ * TODO: allow writing to stdout.
+ */
+ bool openFile( const QString& ext, const QString& filename, const K3b::Msf& length );
+ void closeFile();
+
+ class Command;
+
+ private slots:
+ void slotExternalProgramFinished( KProcess* );
+ void slotExternalProgramOutputLine( const QString& );
+
+ private:
+ void finishEncoderInternal();
+ bool initEncoderInternal( const QString& extension );
+ long encodeInternal( const char* data, Q_ULONG len );
+ void setMetaDataInternal( MetaDataField, const QString& );
+ bool writeWaveHeader();
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/plugins/encoder/external/k3bexternalencoder.plugin b/plugins/encoder/external/k3bexternalencoder.plugin
new file mode 100644
index 0000000..2faaa3a
--- /dev/null
+++ b/plugins/encoder/external/k3bexternalencoder.plugin
@@ -0,0 +1,9 @@
+[K3b Plugin]
+Lib=libk3bexternalencoder
+Group=AudioEncoder
+Name=K3b External Audio Encoder
+Author=Sebastian Trueg
+Email=trueg@k3b.org
+Version=4.0
+Comment=Encoding module that allows specifying an encoding commmand
+License=GPL
diff --git a/plugins/encoder/external/k3bexternalencodercommand.cpp b/plugins/encoder/external/k3bexternalencodercommand.cpp
new file mode 100644
index 0000000..5dcfb23
--- /dev/null
+++ b/plugins/encoder/external/k3bexternalencodercommand.cpp
@@ -0,0 +1,110 @@
+/*
+ *
+ * $Id: k3bexternalencoder.cpp 567280 2006-07-28 13:26:27Z trueg $
+ * Copyright (C) 2003-2007 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 "k3bexternalencodercommand.h"
+
+#include <k3bcore.h>
+
+#include <kconfig.h>
+#include <kstandarddirs.h>
+
+
+QValueList<K3bExternalEncoderCommand> K3bExternalEncoderCommand::readCommands()
+{
+ KConfig* c = k3bcore->config();
+
+ c->setGroup( "K3bExternalEncoderPlugin" );
+
+ QValueList<K3bExternalEncoderCommand> cl;
+
+ QStringList cmds = c->readListEntry( "commands" );
+ for( QStringList::iterator it = cmds.begin(); it != cmds.end(); ++it ) {
+ QStringList cmdString = c->readListEntry( "command_" + *it );
+ K3bExternalEncoderCommand cmd;
+ cmd.name = cmdString[0];
+ cmd.extension = cmdString[1];
+ cmd.command = cmdString[2];
+ for( unsigned int i = 3; i < cmdString.count(); ++i ) {
+ if( cmdString[i] == "swap" )
+ cmd.swapByteOrder = true;
+ else if( cmdString[i] == "wave" )
+ cmd.writeWaveHeader = true;
+ }
+ cl.append(cmd);
+ }
+
+ // some defaults
+ if( cmds.isEmpty() ) {
+ // check if the lame encoding plugin has been compiled
+#ifndef HAVE_LAME
+ K3bExternalEncoderCommand lameCmd;
+ lameCmd.name = "Mp3 (Lame)";
+ lameCmd.extension = "mp3";
+ lameCmd.command = "lame -h --tt %t --ta %a --tl %m --ty %y --tc %c - %f";
+
+ cl.append( lameCmd );
+#endif
+
+ if( !KStandardDirs::findExe( "flac" ).isEmpty() ) {
+ K3bExternalEncoderCommand flacCmd;
+ flacCmd.name = "Flac";
+ flacCmd.extension = "flac";
+ flacCmd.command = "flac "
+ "-V "
+ "-o %f "
+ "--force-raw-format "
+ "--endian=big "
+ "--channels=2 "
+ "--sample-rate=44100 "
+ "--sign=signed "
+ "--bps=16 "
+ "-T ARTIST=%a "
+ "-T TITLE=%t "
+ "-T TRACKNUMBER=%n "
+ "-T DATE=%y "
+ "-T ALBUM=%m "
+ "-";
+
+ cl.append( flacCmd );
+ }
+
+ if( !KStandardDirs::findExe( "mppenc" ).isEmpty() ) {
+ K3bExternalEncoderCommand mppCmd;
+ mppCmd.name = "Musepack";
+ mppCmd.extension = "mpc";
+ mppCmd.command = "mppenc "
+ "--standard "
+ "--overwrite "
+ "--silent "
+ "--artist %a "
+ "--title %t "
+ "--track %n "
+ "--album %m "
+ "--comment %c "
+ "--year %y "
+ "- "
+ "%f";
+ mppCmd.swapByteOrder = true;
+ mppCmd.writeWaveHeader = true;
+
+ cl.append( mppCmd );
+ }
+ }
+
+ return cl;
+}
+
diff --git a/plugins/encoder/external/k3bexternalencodercommand.h b/plugins/encoder/external/k3bexternalencodercommand.h
new file mode 100644
index 0000000..3351191
--- /dev/null
+++ b/plugins/encoder/external/k3bexternalencodercommand.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * $Id: k3bexternalencoder.cpp 567280 2006-07-28 13:26:27Z trueg $
+ * Copyright (C) 2003-2007 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_EXTERNAL_ENCODER_COMMAND_H_
+#define _K3B_EXTERNAL_ENCODER_COMMAND_H_
+
+#include <qstring.h>
+#include <qvaluelist.h>
+
+class K3bExternalEncoderCommand
+{
+public:
+ K3bExternalEncoderCommand()
+ : swapByteOrder(false),
+ writeWaveHeader(false) {
+ }
+
+ QString name;
+ QString extension;
+ QString command;
+
+ bool swapByteOrder;
+ bool writeWaveHeader;
+
+ static QValueList<K3bExternalEncoderCommand> readCommands();
+};
+
+#endif
diff --git a/plugins/encoder/external/k3bexternalencoderconfigwidget.cpp b/plugins/encoder/external/k3bexternalencoderconfigwidget.cpp
new file mode 100644
index 0000000..3ab59c7
--- /dev/null
+++ b/plugins/encoder/external/k3bexternalencoderconfigwidget.cpp
@@ -0,0 +1,228 @@
+/*
+ *
+ * $Id: k3bexternalencoder.cpp 567280 2006-07-28 13:26:27Z trueg $
+ * Copyright (C) 2003-2007 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 "k3bexternalencoderconfigwidget.h"
+
+#include <k3bcore.h>
+
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qlistview.h>
+#include <qpushbutton.h>
+
+#include <klineedit.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <klocale.h>
+
+
+
+
+K3bExternalEncoderEditDialog::K3bExternalEncoderEditDialog( QWidget* parent )
+ : KDialogBase( Swallow,
+ i18n("Editing external audio encoder"),
+ Ok|Cancel,
+ Ok,
+ parent )
+{
+ m_editW = new base_K3bExternalEncoderEditWidget( this );
+ setMainWidget( m_editW );
+}
+
+
+K3bExternalEncoderEditDialog::~K3bExternalEncoderEditDialog()
+{
+}
+
+
+K3bExternalEncoderCommand K3bExternalEncoderEditDialog::currentCommand() const
+{
+ K3bExternalEncoderCommand cmd;
+ cmd.name = m_editW->m_editName->text();
+ cmd.extension = m_editW->m_editExtension->text();
+ cmd.command = m_editW->m_editCommand->text();
+ cmd.swapByteOrder = m_editW->m_checkSwapByteOrder->isChecked();
+ cmd.writeWaveHeader = m_editW->m_checkWriteWaveHeader->isChecked();
+ return cmd;
+}
+
+
+void K3bExternalEncoderEditDialog::setCommand( const K3bExternalEncoderCommand& cmd )
+{
+ m_editW->m_editName->setText( cmd.name );
+ m_editW->m_editExtension->setText( cmd.extension );
+ m_editW->m_editCommand->setText( cmd.command );
+ m_editW->m_checkSwapByteOrder->setChecked( cmd.swapByteOrder );
+ m_editW->m_checkWriteWaveHeader->setChecked( cmd.writeWaveHeader );
+}
+
+
+void K3bExternalEncoderEditDialog::slotOk()
+{
+ if( m_editW->m_editName->text().isEmpty() ) {
+ KMessageBox::error( this,
+ i18n("Please specify a name for the command."),
+ i18n("No name specified") );
+ }
+ else if( m_editW->m_editExtension->text().isEmpty() ) {
+ KMessageBox::error( this,
+ i18n("Please specify an extension for the command."),
+ i18n("No extension specified") );
+ }
+ else if( m_editW->m_editCommand->text().isEmpty() ) {
+ KMessageBox::error( this,
+ i18n("Please specify the command line."),
+ i18n("No command line specified") );
+ }
+ else if( !m_editW->m_editCommand->text().contains( "%f" ) ) {
+ KMessageBox::error( this,
+ i18n("Please add the output filename (%f) to the command line."),
+ i18n("No filename specified") );
+ }
+ // FIXME: check for name and extension uniqueness
+ else {
+ KDialogBase::slotOk();
+ }
+}
+
+
+
+
+
+
+class K3bExternalEncoderSettingsWidget::Private
+{
+public:
+ QMap<QListViewItem*, K3bExternalEncoderCommand> commands;
+};
+
+
+K3bExternalEncoderSettingsWidget::K3bExternalEncoderSettingsWidget( QWidget* parent, const char* name )
+ : K3bPluginConfigWidget( parent, name )
+{
+ d = new Private();
+
+ w = new base_K3bExternalEncoderConfigWidget( this );
+ QHBoxLayout* lay = new QHBoxLayout( this );
+ lay->setMargin( 0 );
+ lay->addWidget( w );
+
+ connect( w->m_viewEncoders, SIGNAL(selectionChanged()),
+ this, SLOT(slotSelectionChanged()) );
+ connect( w->m_buttonAdd, SIGNAL(clicked()),
+ this, SLOT(slotNewCommand()) );
+ connect( w->m_buttonEdit, SIGNAL(clicked()),
+ this, SLOT(slotEditCommand()) );
+ connect( w->m_buttonRemove, SIGNAL(clicked()),
+ this, SLOT(slotRemoveCommand()) );
+
+ m_editDlg = new K3bExternalEncoderEditDialog( this );
+}
+
+
+K3bExternalEncoderSettingsWidget::~K3bExternalEncoderSettingsWidget()
+{
+ delete d;
+}
+
+
+void K3bExternalEncoderSettingsWidget::slotNewCommand()
+{
+ // clear the dialog
+ m_editDlg->setCommand( K3bExternalEncoderCommand() );
+
+ if( m_editDlg->exec() == QDialog::Accepted ) {
+ K3bExternalEncoderCommand cmd = m_editDlg->currentCommand();
+ d->commands.insert( new QListViewItem( w->m_viewEncoders,
+ w->m_viewEncoders->lastItem(),
+ cmd.name,
+ cmd.extension,
+ cmd.command ),
+ cmd );
+ }
+}
+
+
+void K3bExternalEncoderSettingsWidget::slotSelectionChanged()
+{
+ w->m_buttonRemove->setEnabled( w->m_viewEncoders->selectedItem() != 0 );
+ w->m_buttonEdit->setEnabled( w->m_viewEncoders->selectedItem() != 0 );
+}
+
+
+void K3bExternalEncoderSettingsWidget::slotEditCommand()
+{
+ if( QListViewItem* item = w->m_viewEncoders->selectedItem() ) {
+ m_editDlg->setCommand( d->commands[item] );
+ if( m_editDlg->exec() == QDialog::Accepted ) {
+ d->commands[item] = m_editDlg->currentCommand();
+ }
+ }
+}
+
+
+void K3bExternalEncoderSettingsWidget::slotRemoveCommand()
+{
+ if( QListViewItem* item = w->m_viewEncoders->selectedItem() ) {
+ d->commands.erase( item );
+ delete item;
+ }
+}
+
+
+void K3bExternalEncoderSettingsWidget::loadConfig()
+{
+ d->commands.clear();
+ w->m_viewEncoders->clear();
+
+ QValueList<K3bExternalEncoderCommand> cmds( K3bExternalEncoderCommand::readCommands() );
+ for( QValueList<K3bExternalEncoderCommand>::iterator it = cmds.begin();
+ it != cmds.end(); ++it ) {
+ K3bExternalEncoderCommand& cmd = *it;
+ d->commands.insert( new QListViewItem( w->m_viewEncoders,
+ w->m_viewEncoders->lastItem(),
+ cmd.name,
+ cmd.extension,
+ cmd.command ),
+ cmd );
+ }
+}
+
+
+void K3bExternalEncoderSettingsWidget::saveConfig()
+{
+ KConfig* c = k3bcore->config();
+ c->deleteGroup( "K3bExternalEncoderPlugin", true );
+ c->setGroup( "K3bExternalEncoderPlugin" );
+
+ QStringList cmdNames;
+ for( QMapIterator<QListViewItem*, K3bExternalEncoderCommand> it = d->commands.begin();
+ it != d->commands.end(); ++it ) {
+ QStringList cmd;
+ cmd << it.data().name << it.data().extension << it.data().command;
+ if( it.data().swapByteOrder )
+ cmd << "swap";
+ if( it.data().writeWaveHeader )
+ cmd << "wave";
+ c->writeEntry( "command_" + it.data().name, cmd );
+ cmdNames << it.data().name;
+ }
+ c->writeEntry( "commands", cmdNames );
+}
+
+
+
+
+#include "k3bexternalencoderconfigwidget.moc"
diff --git a/plugins/encoder/external/k3bexternalencoderconfigwidget.h b/plugins/encoder/external/k3bexternalencoderconfigwidget.h
new file mode 100644
index 0000000..4f6dd47
--- /dev/null
+++ b/plugins/encoder/external/k3bexternalencoderconfigwidget.h
@@ -0,0 +1,72 @@
+/*
+ *
+ * $Id: k3bexternalencoder.cpp 567280 2006-07-28 13:26:27Z trueg $
+ * Copyright (C) 2003-2007 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_EXTERNAL_ENCODER_CONFIG_WIDGET_H_
+#define _K3B_EXTERNAL_ENCODER_CONFIG_WIDGET_H_
+
+#include "base_k3bexternalencodereditwidget.h"
+#include "base_k3bexternalencoderconfigwidget.h"
+#include "k3bexternalencodercommand.h"
+
+#include <k3bpluginconfigwidget.h>
+#include <kdialogbase.h>
+
+
+class K3bExternalEncoderEditDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ K3bExternalEncoderEditDialog( QWidget* parent );
+ ~K3bExternalEncoderEditDialog();
+
+ K3bExternalEncoderCommand currentCommand() const;
+ void setCommand( const K3bExternalEncoderCommand& cmd );
+
+ private slots:
+ void slotOk();
+
+ private:
+ base_K3bExternalEncoderEditWidget* m_editW;
+};
+
+
+class K3bExternalEncoderSettingsWidget : public K3bPluginConfigWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bExternalEncoderSettingsWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bExternalEncoderSettingsWidget();
+
+ public slots:
+ void loadConfig();
+ void saveConfig();
+
+ private slots:
+ void slotSelectionChanged();
+ void slotNewCommand();
+ void slotEditCommand();
+ void slotRemoveCommand();
+
+ private:
+ base_K3bExternalEncoderConfigWidget* w;
+ K3bExternalEncoderEditDialog* m_editDlg;
+
+ class Private;
+ Private* d;
+};
+
+#endif
diff --git a/plugins/encoder/lame/Makefile.am b/plugins/encoder/lame/Makefile.am
new file mode 100644
index 0000000..4a4d61e
--- /dev/null
+++ b/plugins/encoder/lame/Makefile.am
@@ -0,0 +1,15 @@
+AM_CPPFLAGS = -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3b/plugin -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3bdevice $(all_includes)
+
+kde_module_LTLIBRARIES = libk3blameencoder.la
+
+libk3blameencoder_la_SOURCES = base_k3blameencodersettingswidget.ui \
+ base_k3bmanualbitratesettingswidget.ui \
+ k3blameencoder.cpp
+
+libk3blameencoder_la_LIBADD = ../../../libk3b/libk3b.la $(LIB_KDECORE) -lmp3lame
+libk3blameencoder_la_LDFLAGS = -avoid-version -module -no-undefined $(all_libraries)
+
+pluginsdir = $(kde_datadir)/k3b/plugins
+plugins_DATA = k3blameencoder.plugin
+
+METASOURCES = AUTO
diff --git a/plugins/encoder/lame/base_k3blameencodersettingswidget.ui b/plugins/encoder/lame/base_k3blameencodersettingswidget.ui
new file mode 100644
index 0000000..199895e
--- /dev/null
+++ b/plugins/encoder/lame/base_k3blameencodersettingswidget.ui
@@ -0,0 +1,480 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bLameEncoderSettingsWidget</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>337</width>
+ <height>295</height>
+ </rect>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>m_mainTab</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Settings</string>
+ </attribute>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>m_groupVariableBitrate</cstring>
+ </property>
+ <property name="title">
+ <string>Quality Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioQualityLevel</cstring>
+ </property>
+ <property name="text">
+ <string>Preset:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_labelQualityLevel</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>textLabel1</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>m_qualityLevelFrame</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <italic>1</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string>high quality</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <italic>1</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string>small file</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_sliderQuality</cstring>
+ </property>
+ <property name="maxValue">
+ <number>9</number>
+ </property>
+ <property name="pageStep">
+ <number>3</number>
+ </property>
+ <property name="value">
+ <number>3</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioManual</cstring>
+ </property>
+ <property name="text">
+ <string>Manual settings:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_labelManualSettings</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>textLabel2</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2_2_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_buttonManualSettings</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Change Settings...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Advanced</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Encoder Quality</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="KIntNumInput">
+ <property name="name">
+ <cstring>m_spinEncoderQuality</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Choose the noise shaping &amp; psycho acoustic algorithm.</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Bitrate is of course the main influence on quality. The higher the bitrate, the higher the quality. But for a given bitrate, we have a choice of algorithms to determine the best scalefactors and huffman encoding (noise shaping).
+&lt;p&gt;The quality increases from 0 to 9 while the encoding speed drops.
+&lt;p&gt;9 uses the slowest &amp; best possible version of all algorithms.
+&lt;p&gt;&lt;b&gt;7 is the recommended setting&lt;/b&gt; while 4 still produced reasonable quality at good speed.
+&lt;p&gt;0 disables almost all algorithms including psy-model resulting in poor quality.
+&lt;p&gt;&lt;b&gt;This setting has no influence on the size of the resulting file.&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <italic>1</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string>fast encoding</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <italic>1</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string>high quality</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkCopyright</cstring>
+ </property>
+ <property name="text">
+ <string>Mark copyrighted</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Mark the encoded file as being copyrighted.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkOriginal</cstring>
+ </property>
+ <property name="text">
+ <string>Mark as original</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Mark the encoded file as being a copy.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkISO</cstring>
+ </property>
+ <property name="text">
+ <string>Strict ISO compliance</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Enforce strict ISO compliance</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked LAME will enforce the 7680 bit limitation on total frame size.&lt;br&gt;
+This results in many wasted bits for high bitrate encodings but will ensure strict ISO compatibility. This compatibility might be important for hardware players.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkError</cstring>
+ </property>
+ <property name="text">
+ <string>Error protection</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Turn on CRC error protection.</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;If this option is checked a cyclic redundancy check (CRC) code will be added to each frame, allowing transmission errors that could occur on the MP3 stream to be detected; however, it takes 16 bits per frame that would otherwise be used for encoding, thus slightly reducing the sound quality.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ </widget>
+ </hbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>m_radioManual</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_buttonManualSettings</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioQualityLevel</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_qualityLevelFrame</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioQualityLevel</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_labelQualityLevel</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioManual</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_labelManualSettings</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/plugins/encoder/lame/base_k3bmanualbitratesettingswidget.ui b/plugins/encoder/lame/base_k3bmanualbitratesettingswidget.ui
new file mode 100644
index 0000000..a3bff90
--- /dev/null
+++ b/plugins/encoder/lame/base_k3bmanualbitratesettingswidget.ui
@@ -0,0 +1,273 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bManualBitrateSettingsWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>base_K3bManualBitrateSettingsWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>283</width>
+ <height>298</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup2</cstring>
+ </property>
+ <property name="title">
+ <string>Quality</string>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioConstantBitrate</cstring>
+ </property>
+ <property name="text">
+ <string>Constant Bitrate</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>m_comboConstantBitrate</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioVariableBitrate</cstring>
+ </property>
+ <property name="text">
+ <string>Variable Bitrate</string>
+ </property>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame5</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KComboBox" row="2" column="2">
+ <property name="name">
+ <cstring>m_comboMinimumBitrate</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <spacer row="0" column="0" rowspan="3" colspan="1">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KComboBox" row="0" column="2">
+ <property name="name">
+ <cstring>m_comboMaximumBitrate</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_checkBitrateMaximum</cstring>
+ </property>
+ <property name="text">
+ <string>Maximum bitrate:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>m_checkBitrateMinimum</cstring>
+ </property>
+ <property name="text">
+ <string>Minimum bitrate:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>m_checkBitrateAverage</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Average bitrate:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="1" column="2">
+ <property name="name">
+ <cstring>m_spinAverageBitrate</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="suffix">
+ <string> kbps</string>
+ </property>
+ <property name="buttonSymbols">
+ <enum>UpDownArrows</enum>
+ </property>
+ <property name="maxValue">
+ <number>310</number>
+ </property>
+ <property name="minValue">
+ <number>8</number>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>Channel Mode</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KComboBox">
+ <item>
+ <property name="text">
+ <string>Stereo</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joint Stereo</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Mono</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_comboMode</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select the channel mode.</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Select the channel mode of the resulting Mp3 file:
+&lt;p&gt;&lt;b&gt;Stereo&lt;/b&gt;&lt;br&gt;
+In this mode, the encoder makes no use of potential correlations between the two input channels; it can, however, negotiate the bit demand between both channel, i.e. give one channel more bits if the other contains silence or needs fewer bits because of a lower complexity.
+&lt;p&gt;&lt;b&gt;Joint-Stereo&lt;/b&gt;&lt;br&gt;
+In this mode, the encoder will make use of correlations between both channels. The signal will be matrixed into a sum ("mid"), computed by L+R, and difference ("side") signal, computed by L-R, and more bits are allocated to the mid channel. This will effectively increase the bandwidth if the signal does not have too much stereo separation, thus giving a significant gain in encoding quality.
+&lt;p&gt;&lt;b&gt;Mono&lt;/b&gt;&lt;br&gt;
+The input will be encoded as a mono signal. If it was a stereo signal, it will be downsampled to mono. The downmix is calculated as the sum of the left and right channel, attenuated by 6 dB.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>m_radioVariableBitrate</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>frame5</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioConstantBitrate</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_comboConstantBitrate</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkBitrateMaximum</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_comboMaximumBitrate</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkBitrateAverage</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_spinAverageBitrate</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkBitrateMinimum</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_comboMinimumBitrate</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/plugins/encoder/lame/configure.in.bot b/plugins/encoder/lame/configure.in.bot
new file mode 100644
index 0000000..5bb35c9
--- /dev/null
+++ b/plugins/encoder/lame/configure.in.bot
@@ -0,0 +1,11 @@
+echo ""
+
+if test x$have_lame = xyes; then
+ echo "K3b - Lame Mp3 encoder plugin: yes"
+else
+ echo "K3b - Lame Mp3 encoder plugin no"
+if test "$ac_cv_use_lame" = "yes"; then
+ echo "K3b - You are missing the Lame headers and libraries."
+ echo "K3b - The Lame Mp3 encoding plugin won't be compiled."
+fi
+fi
diff --git a/plugins/encoder/lame/configure.in.in b/plugins/encoder/lame/configure.in.in
new file mode 100644
index 0000000..f2a5283
--- /dev/null
+++ b/plugins/encoder/lame/configure.in.in
@@ -0,0 +1,20 @@
+dnl === test for LAME - begin ====
+AC_ARG_WITH(
+ lame,
+ AS_HELP_STRING([--without-lame], [build K3b without LAME support (default=no)]),
+ [ac_cv_use_lame=$withval],
+ [ac_cv_use_lame=yes]
+)
+
+have_lame=no
+if test "$ac_cv_use_lame" = "yes"; then
+ KDE_CHECK_HEADERS(lame/lame.h, [
+ AC_CHECK_LIB(mp3lame, lame_init, [
+ have_lame=yes
+ AC_DEFINE(HAVE_LAME,1,[defined if you have the lame header and lib])
+ ], [], $all_libraries -lm)
+ ])
+fi
+
+AM_CONDITIONAL(include_LAME, [test x$have_lame = xyes])
+dnl === test for LAME - end ====
diff --git a/plugins/encoder/lame/k3blameencoder.cpp b/plugins/encoder/lame/k3blameencoder.cpp
new file mode 100644
index 0000000..089c7d0
--- /dev/null
+++ b/plugins/encoder/lame/k3blameencoder.cpp
@@ -0,0 +1,627 @@
+/*
+ *
+ * $Id: k3blameencoder.cpp 653779 2007-04-14 07:58:51Z 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 "k3blameencoder.h"
+
+#include <k3bcore.h>
+#include <k3bpluginfactory.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kinstance.h>
+#include <knuminput.h>
+#include <kcombobox.h>
+#include <kdialogbase.h>
+
+#include <qlayout.h>
+#include <qcstring.h>
+#include <qradiobutton.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qgroupbox.h>
+#include <qbuttongroup.h>
+#include <qtextcodec.h>
+#include <qfile.h>
+#include <qslider.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+
+#include <stdio.h>
+#include <lame/lame.h>
+
+
+K_EXPORT_COMPONENT_FACTORY( libk3blameencoder, K3bPluginFactory<K3bLameEncoder>( "libk3blameencoder" ) )
+
+
+static const int s_lame_bitrates[] = {
+ 32,
+ 40,
+ 48,
+ 56,
+ 64,
+ 80,
+ 96,
+ 112,
+ 128,
+ 160,
+ 192,
+ 224,
+ 256,
+ 320,
+ 0 // just used for the loops below
+};
+
+
+static const int s_lame_presets[] = {
+ 56, // ABR for Voice, Radio, Mono, etc.
+ 90, //
+
+ V6, // ~115 kbps
+ V5, // ~130 kbps | Portable - small size
+ V4, // ~160 kbps
+
+ V3, // ~175 kbps
+ V2, // ~190 kbps | HiFi - for home or quite listening
+ V1, // ~210 kbps |
+ V0, // ~230 kbps
+
+ 320 // ABR 320 neary lossless for archiving (not recommended, use flac instead)
+};
+
+
+static const int s_lame_preset_approx_bitrates[] = {
+ 56,
+ 90,
+ 115,
+ 130,
+ 160,
+ 175,
+ 190,
+ 210,
+ 230,
+ 320
+};
+
+
+static const char* s_lame_preset_strings[] = {
+ I18N_NOOP("Low quality (56 kbps)"),
+ I18N_NOOP("Low quality (90 kbps)"),
+
+ I18N_NOOP("Portable (average 115 kbps)"),
+ I18N_NOOP("Portable (average 130 kbps)"),
+ I18N_NOOP("Portable (average 160 kbps)"),
+
+ I18N_NOOP("HiFi (average 175 kbps)"),
+ I18N_NOOP("HiFi (average 190 kbps)"),
+ I18N_NOOP("HiFi (average 210 kbps)"),
+ I18N_NOOP("HiFi (average 230 kbps)"),
+
+ I18N_NOOP("Archiving (320 kbps)"),
+};
+
+
+static const char* s_lame_mode_strings[] = {
+ I18N_NOOP("Stereo"),
+ I18N_NOOP("Joint Stereo"),
+ I18N_NOOP("Mono")
+};
+
+
+
+class K3bLameEncoder::Private
+{
+public:
+ Private()
+ : flags(0),
+ fid(0) {
+ }
+
+ lame_global_flags* flags;
+
+ char buffer[8000];
+
+ QString filename;
+ FILE* fid;
+};
+
+
+
+
+K3bLameEncoder::K3bLameEncoder( QObject* parent, const char* name )
+ : K3bAudioEncoder( parent, name )
+{
+ d = new Private();
+}
+
+
+K3bLameEncoder::~K3bLameEncoder()
+{
+ closeFile();
+
+ delete d;
+}
+
+
+bool K3bLameEncoder::openFile( const QString& extension, const QString& filename, const K3b::Msf& length )
+{
+ closeFile();
+
+ d->filename = filename;
+ d->fid = ::fopen( QFile::encodeName( filename ), "w+" );
+ if( d->fid )
+ return initEncoder( extension, length );
+ else
+ return false;
+}
+
+
+bool K3bLameEncoder::isOpen() const
+{
+ return ( d->fid != 0 );
+}
+
+
+void K3bLameEncoder::closeFile()
+{
+ if( isOpen() ) {
+ finishEncoder();
+ ::fclose( d->fid );
+ d->fid = 0;
+ d->filename.truncate(0);
+ }
+}
+
+
+const QString& K3bLameEncoder::filename() const
+{
+ return d->filename;
+}
+
+
+bool K3bLameEncoder::initEncoderInternal( const QString&, const K3b::Msf& length )
+{
+ KConfig* c = k3bcore->config();
+ c->setGroup( "K3bLameEncoderPlugin" );
+
+ d->flags = lame_init();
+
+ if( d->flags == 0 ) {
+ kdDebug() << "(K3bLameEncoder) lame_init failed." << endl;
+ return false;
+ }
+
+ //
+ // set the format of the input data
+ //
+ lame_set_num_samples( d->flags, length.lba()*588 );
+ lame_set_in_samplerate( d->flags, 44100 );
+ lame_set_num_channels( d->flags, 2 );
+
+ //
+ // Lame by default determines the samplerate based on the bitrate
+ // since we have no option for the user to influence this yet
+ // we just keep to the good old 44.1 khz
+ //
+ lame_set_out_samplerate( d->flags, 44100 );
+
+ //
+ // Choose the quality level
+ //
+ if( c->readBoolEntry( "Manual Bitrate Settings", false ) ) {
+ //
+ // Mode
+ //
+ QString mode = c->readEntry( "Mode", "stereo" );
+ if( mode == "stereo" )
+ lame_set_mode( d->flags, STEREO );
+ else if( mode == "joint" )
+ lame_set_mode( d->flags, JOINT_STEREO );
+ else // mono
+ lame_set_mode( d->flags, MONO );
+
+ //
+ // Variable Bitrate
+ //
+ if( c->readBoolEntry( "VBR", false ) ) {
+ // we use the default algorithm here
+ lame_set_VBR( d->flags, vbr_default );
+
+ if( c->readBoolEntry( "Use Maximum Bitrate", false ) ) {
+ lame_set_VBR_max_bitrate_kbps( d->flags, c->readNumEntry( "Maximum Bitrate", 224 ) );
+ }
+ if( c->readBoolEntry( "Use Minimum Bitrate", false ) ) {
+ lame_set_VBR_min_bitrate_kbps( d->flags, c->readNumEntry( "Minimum Bitrate", 32 ) );
+
+ // TODO: lame_set_hard_min
+ }
+ if( c->readBoolEntry( "Use Average Bitrate", true ) ) {
+ lame_set_VBR( d->flags, vbr_abr );
+ lame_set_VBR_mean_bitrate_kbps( d->flags, c->readNumEntry( "Average Bitrate", 128 ) );
+ }
+ }
+
+ //
+ // Constant Bitrate
+ //
+ else {
+ lame_set_VBR( d->flags, vbr_off );
+ lame_set_brate( d->flags, c->readNumEntry( "Constant Bitrate", 128 ) );
+ }
+ }
+
+ else {
+ //
+ // In lame 0 is the highest quality. Since that is just confusing for the user
+ // if we call the setting "Quality" we simply invert the value.
+ //
+ int q = c->readNumEntry( "Quality Level", 5 );
+ if( q < 0 ) q = 0;
+ if( q > 9 ) q = 9;
+
+ kdDebug() << "(K3bLameEncoder) setting preset encoding value to " << q << endl;
+
+ if ( q < 2 || q > 8 ) {
+ lame_set_VBR( d->flags, vbr_abr );
+ }
+ else {
+ lame_set_VBR( d->flags, vbr_default );
+ }
+ lame_set_preset( d->flags, s_lame_presets[q] );
+
+ if( q < 2 )
+ lame_set_mode( d->flags, MONO );
+ }
+
+
+ //
+ // file options
+ //
+ lame_set_copyright( d->flags, c->readBoolEntry( "Copyright", false ) );
+ lame_set_original( d->flags, c->readBoolEntry( "Original", true ) );
+ lame_set_strict_ISO( d->flags, c->readBoolEntry( "ISO compliance", false ) );
+ lame_set_error_protection( d->flags, c->readBoolEntry( "Error Protection", false ) );
+
+
+ //
+ // Used Algorithm
+ //
+ // default to 2 which is the same as the -h lame option
+ // THIS HAS NO INFLUENCE ON THE SIZE OF THE FILE!
+ //
+ //
+ // In lame 0 is the highest quality. Since that is just confusing for the user
+ // if we call the setting "Quality" we simply invert the value.
+ //
+ int q = c->readNumEntry( "Encoder Quality", 7 );
+ if( q < 0 ) q = 0;
+ if( q > 9 ) q = 9;
+ lame_set_quality( d->flags, 9-q );
+
+ //
+ // ID3 settings
+ //
+ // for now we default to both v1 and v2 tags
+ id3tag_add_v2( d->flags );
+ id3tag_pad_v2( d->flags );
+
+ return( lame_init_params( d->flags ) != -1 );
+}
+
+
+long K3bLameEncoder::encodeInternal( const char* data, Q_ULONG len )
+{
+ // FIXME: we may have to swap data here
+ int size = lame_encode_buffer_interleaved( d->flags,
+ (short int*)data,
+ len/4,
+ (unsigned char*)d->buffer,
+ 8000 );
+ if( size < 0 ) {
+ kdDebug() << "(K3bLameEncoder) lame_encode_buffer_interleaved failed." << endl;
+ return -1;
+ }
+
+ return ::fwrite( d->buffer, 1, size, d->fid );
+}
+
+
+void K3bLameEncoder::finishEncoderInternal()
+{
+ int size = lame_encode_flush( d->flags,
+ (unsigned char*)d->buffer,
+ 8000 );
+ if( size > 0 )
+ ::fwrite( d->buffer, 1, size, d->fid );
+
+ lame_mp3_tags_fid( d->flags, d->fid );
+
+ lame_close( d->flags );
+ d->flags = 0;
+}
+
+
+void K3bLameEncoder::setMetaDataInternal( K3bAudioEncoder::MetaDataField f, const QString& value )
+{
+ // let's not use UTF-8 here since I don't know how to tell lame...
+ // FIXME: when we use the codec we only get garbage. Why?
+ QTextCodec* codec = 0;//QTextCodec::codecForName( "ISO8859-1" );
+// if( !codec )
+// kdDebug() << "(K3bLameEncoder) could not find codec ISO8859-1." << endl;
+
+ switch( f ) {
+ case META_TRACK_TITLE:
+ id3tag_set_title( d->flags, codec ? codec->fromUnicode(value).data() : value.latin1() );
+ break;
+ case META_TRACK_ARTIST:
+ id3tag_set_artist( d->flags, codec ? codec->fromUnicode(value).data() : value.latin1() );
+ break;
+ case META_ALBUM_TITLE:
+ id3tag_set_album( d->flags, codec ? codec->fromUnicode(value).data() : value.latin1() );
+ break;
+ case META_ALBUM_COMMENT:
+ id3tag_set_comment( d->flags, codec ? codec->fromUnicode(value).data() : value.latin1() );
+ break;
+ case META_YEAR:
+ id3tag_set_year( d->flags, codec ? codec->fromUnicode(value).data() : value.latin1() );
+ break;
+ case META_TRACK_NUMBER:
+ id3tag_set_track( d->flags, codec ? codec->fromUnicode(value).data() : value.latin1() );
+ break;
+ case META_GENRE:
+ if( id3tag_set_genre( d->flags, codec ? codec->fromUnicode(value).data() : value.latin1() ) )
+ kdDebug() << "(K3bLameEncoder) unable to set genre." << endl;
+ break;
+ default:
+ return;
+ }
+
+ if( lame_init_params( d->flags ) < 0 )
+ kdDebug() << "(K3bLameEncoder) lame_init_params failed." << endl;
+}
+
+
+
+
+
+K3bLameEncoderSettingsWidget::K3bLameEncoderSettingsWidget( QWidget* parent, const char* name )
+ : K3bPluginConfigWidget( parent, name )
+{
+ m_w = new base_K3bLameEncoderSettingsWidget( this );
+ m_w->m_sliderQuality->setRange( 0, 9 );
+ m_w->m_spinEncoderQuality->setRange( 0, 9, true );
+
+ m_manualSettingsDlg = new KDialogBase( this, 0, true,
+ i18n("(Lame) Manual Quality Settings") );
+ m_brW = new base_K3bManualBitrateSettingsWidget( m_manualSettingsDlg );
+ m_manualSettingsDlg->setMainWidget( m_brW );
+
+ for( int i = 0; s_lame_bitrates[i]; ++i )
+ m_brW->m_comboMaximumBitrate->insertItem( i18n("%1 kbps" ).arg(s_lame_bitrates[i]) );
+
+ for( int i = 0; s_lame_bitrates[i]; ++i )
+ m_brW->m_comboMinimumBitrate->insertItem( i18n("%1 kbps" ).arg(s_lame_bitrates[i]) );
+
+ for( int i = 0; s_lame_bitrates[i]; ++i )
+ m_brW->m_comboConstantBitrate->insertItem( i18n("%1 kbps" ).arg(s_lame_bitrates[i]) );
+
+
+ QHBoxLayout* lay = new QHBoxLayout( this );
+ lay->setMargin( 0 );
+ lay->addWidget( m_w );
+
+ // TODO: add whatsthis help for the quality level.
+ // QString qualityLevelWhatsThis = i18n("<p>");
+
+ connect( m_w->m_buttonManualSettings, SIGNAL(clicked()),
+ this, SLOT(slotShowManualSettings()) );
+ connect( m_w->m_sliderQuality, SIGNAL(valueChanged(int)),
+ this, SLOT(slotQualityLevelChanged(int)) );
+
+ updateManualSettingsLabel();
+ slotQualityLevelChanged( 5 );
+}
+
+
+K3bLameEncoderSettingsWidget::~K3bLameEncoderSettingsWidget()
+{
+}
+
+
+void K3bLameEncoderSettingsWidget::slotShowManualSettings()
+{
+ // save current settings for proper cancellation
+ bool constant = m_brW->m_radioConstantBitrate->isChecked();
+ int constBitrate = m_brW->m_comboConstantBitrate->currentItem();
+ int max = m_brW->m_comboMaximumBitrate->currentItem();
+ int min = m_brW->m_comboMinimumBitrate->currentItem();
+ int av = m_brW->m_spinAverageBitrate->value();
+ int mode = m_brW->m_comboMode->currentItem();
+
+ if( m_manualSettingsDlg->exec() == QDialog::Rejected ) {
+ m_brW->m_radioConstantBitrate->setChecked( constant );
+ m_brW->m_comboConstantBitrate->setCurrentItem( constBitrate );
+ m_brW->m_comboMaximumBitrate->setCurrentItem( max );
+ m_brW->m_comboMinimumBitrate->setCurrentItem( min );
+ m_brW->m_spinAverageBitrate->setValue( av );
+ m_brW->m_comboMode->setCurrentItem( mode );
+ }
+ else
+ updateManualSettingsLabel();
+}
+
+
+void K3bLameEncoderSettingsWidget::updateManualSettingsLabel()
+{
+ if( m_brW->m_radioConstantBitrate->isChecked() )
+ m_w->m_labelManualSettings->setText( i18n("Constant Bitrate: %1 kbps (%2)")
+ .arg(s_lame_bitrates[m_brW->m_comboConstantBitrate->currentItem()])
+ .arg(i18n(s_lame_mode_strings[m_brW->m_comboMode->currentItem()])) );
+ else
+ m_w->m_labelManualSettings->setText( i18n("Variable Bitrate (%1)")
+ .arg(i18n(s_lame_mode_strings[m_brW->m_comboMode->currentItem()])) );
+}
+
+
+void K3bLameEncoderSettingsWidget::slotQualityLevelChanged( int val )
+{
+ m_w->m_labelQualityLevel->setText( i18n(s_lame_preset_strings[val]) );
+}
+
+
+void K3bLameEncoderSettingsWidget::loadConfig()
+{
+ KConfig* c = k3bcore->config();
+ c->setGroup( "K3bLameEncoderPlugin" );
+
+ QString mode = c->readEntry( "Mode", "stereo" );
+ if( mode == "stereo" )
+ m_brW->m_comboMode->setCurrentItem( 0 );
+ else if( mode == "joint" )
+ m_brW->m_comboMode->setCurrentItem( 1 );
+ else // mono
+ m_brW->m_comboMode->setCurrentItem( 2 );
+
+ bool manual = c->readBoolEntry( "Manual Bitrate Settings", false );
+ if( manual )
+ m_w->m_radioManual->setChecked(true);
+ else
+ m_w->m_radioQualityLevel->setChecked(true);
+
+ if( c->readBoolEntry( "VBR", false ) )
+ m_brW->m_radioVariableBitrate->setChecked( true );
+ else
+ m_brW->m_radioConstantBitrate->setChecked( true );
+
+ m_brW->m_comboConstantBitrate->setCurrentItem( i18n("%1 kbps").arg(c->readNumEntry( "Constant Bitrate", 128 )) );
+ m_brW->m_comboMaximumBitrate->setCurrentItem( i18n("%1 kbps").arg(c->readNumEntry( "Maximum Bitrate", 224 )) );
+ m_brW->m_comboMinimumBitrate->setCurrentItem( i18n("%1 kbps").arg(c->readNumEntry( "Minimum Bitrate", 32 )) );
+ m_brW->m_spinAverageBitrate->setValue( c->readNumEntry( "Average Bitrate", 128) );
+
+ m_brW->m_checkBitrateMaximum->setChecked( c->readBoolEntry( "Use Maximum Bitrate", false ) );
+ m_brW->m_checkBitrateMinimum->setChecked( c->readBoolEntry( "Use Minimum Bitrate", false ) );
+ m_brW->m_checkBitrateAverage->setChecked( c->readBoolEntry( "Use Average Bitrate", true ) );
+
+ m_w->m_sliderQuality->setValue( c->readNumEntry( "Quality Level", 5 ) );
+
+ m_w->m_checkCopyright->setChecked( c->readBoolEntry( "Copyright", false ) );
+ m_w->m_checkOriginal->setChecked( c->readBoolEntry( "Original", true ) );
+ m_w->m_checkISO->setChecked( c->readBoolEntry( "ISO compliance", false ) );
+ m_w->m_checkError->setChecked( c->readBoolEntry( "Error Protection", false ) );
+
+ // default to 2 which is the same as the -h lame option
+ m_w->m_spinEncoderQuality->setValue( c->readNumEntry( "Encoder Quality", 7 ) );
+
+ updateManualSettingsLabel();
+}
+
+
+void K3bLameEncoderSettingsWidget::saveConfig()
+{
+ KConfig* c = k3bcore->config();
+ c->setGroup( "K3bLameEncoderPlugin" );
+
+ QString mode;
+ switch( m_brW->m_comboMode->currentItem() ) {
+ case 0:
+ mode = "stereo";
+ break;
+ case 1:
+ mode = "joint";
+ break;
+ case 2:
+ mode = "mono";
+ break;
+ }
+ c->writeEntry( "Mode", mode );
+
+ c->writeEntry( "Manual Bitrate Settings", m_w->m_radioManual->isChecked() );
+
+ c->writeEntry( "VBR", !m_brW->m_radioConstantBitrate->isChecked() );
+ c->writeEntry( "Constant Bitrate", m_brW->m_comboConstantBitrate->currentText().left(3).toInt() );
+ c->writeEntry( "Maximum Bitrate", m_brW->m_comboMaximumBitrate->currentText().left(3).toInt() );
+ c->writeEntry( "Minimum Bitrate", m_brW->m_comboMinimumBitrate->currentText().left(3).toInt() );
+ c->writeEntry( "Average Bitrate", m_brW->m_spinAverageBitrate->value() );
+
+ c->writeEntry( "Use Maximum Bitrate", m_brW->m_checkBitrateMaximum->isChecked() );
+ c->writeEntry( "Use Minimum Bitrate", m_brW->m_checkBitrateMinimum->isChecked() );
+ c->writeEntry( "Use Average Bitrate", m_brW->m_checkBitrateAverage->isChecked() );
+
+ c->writeEntry( "Quality Level", m_w->m_sliderQuality->value() );
+
+ c->writeEntry( "Copyright", m_w->m_checkCopyright->isChecked() );
+ c->writeEntry( "Original", m_w->m_checkOriginal->isChecked() );
+ c->writeEntry( "ISO compliance", m_w->m_checkISO->isChecked() );
+ c->writeEntry( "Error Protection", m_w->m_checkError->isChecked() );
+
+ // default to 2 which is the same as the -h lame option
+ c->writeEntry( "Encoder Quality", m_w->m_spinEncoderQuality->value() );
+}
+
+
+
+QStringList K3bLameEncoder::extensions() const
+{
+ return QStringList( "mp3" );
+}
+
+
+QString K3bLameEncoder::fileTypeComment( const QString& ) const
+{
+ return "MPEG1 Layer III (mp3)";
+}
+
+
+long long K3bLameEncoder::fileSize( const QString&, const K3b::Msf& msf ) const
+{
+ KConfig* c = k3bcore->config();
+ c->setGroup( "K3bLameEncoderPlugin" );
+ int bitrate = 0;
+ if( c->readBoolEntry( "Manual Bitrate Settings", false ) ) {
+ if( c->readBoolEntry( "VBR", false ) ) {
+ if( c->readBoolEntry( "Use Maximum Bitrate", false ) )
+ bitrate = c->readNumEntry( "Maximum Bitrate", 224 );
+ if( c->readBoolEntry( "Use Minimum Bitrate", false ) )
+ bitrate = ( bitrate > 0
+ ? (bitrate - c->readNumEntry( "Minimum Bitrate", 32 )) / 2
+ : c->readNumEntry( "Minimum Bitrate", 32 ) );
+ if( c->readBoolEntry( "Use Average Bitrate", true ) )
+ bitrate = c->readNumEntry( "Average Bitrate", 128 );
+ }
+ else {
+ bitrate = c->readNumEntry( "Constant Bitrate", 128 );
+ }
+ }
+ else {
+ int q = c->readNumEntry( "Quality Level", 5 );
+ if( q < 0 ) q = 0;
+ if( q > 9 ) q = 9;
+ bitrate = s_lame_preset_approx_bitrates[q];
+ }
+
+ return (msf.totalFrames()/75 * bitrate * 1000)/8;
+}
+
+
+K3bPluginConfigWidget* K3bLameEncoder::createConfigWidget( QWidget* parent,
+ const char* name ) const
+{
+ return new K3bLameEncoderSettingsWidget( parent, name );
+}
+
+
+#include "k3blameencoder.moc"
diff --git a/plugins/encoder/lame/k3blameencoder.h b/plugins/encoder/lame/k3blameencoder.h
new file mode 100644
index 0000000..424ea64
--- /dev/null
+++ b/plugins/encoder/lame/k3blameencoder.h
@@ -0,0 +1,88 @@
+/*
+ *
+ * $Id: k3blameencoder.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_LAME_ENCODER_H_
+#define _K3B_LAME_ENCODER_H_
+
+
+#include <k3baudioencoder.h>
+#include <k3bpluginconfigwidget.h>
+
+#include "base_k3blameencodersettingswidget.h"
+#include "base_k3bmanualbitratesettingswidget.h"
+
+
+class KDialogBase;
+
+
+class K3bLameEncoder : public K3bAudioEncoder
+{
+ Q_OBJECT
+
+ public:
+ K3bLameEncoder( QObject* parent = 0, const char* name = 0 );
+ ~K3bLameEncoder();
+
+ bool openFile( const QString& extension, const QString& filename, const K3b::Msf& length );
+ bool isOpen() const;
+ void closeFile();
+ const QString& filename() const;
+
+ QStringList extensions() const;
+
+ QString fileTypeComment( const QString& ) const;
+
+ long long fileSize( const QString&, const K3b::Msf& msf ) const;
+
+ int pluginSystemVersion() const { return 3; }
+
+ K3bPluginConfigWidget* createConfigWidget( QWidget* parent = 0,
+ const char* name = 0 ) const;
+
+ private:
+ void finishEncoderInternal();
+ bool initEncoderInternal( const QString& extension, const K3b::Msf& length );
+ long encodeInternal( const char* data, Q_ULONG len );
+ void setMetaDataInternal( MetaDataField, const QString& );
+
+ class Private;
+ Private* d;
+};
+
+
+class K3bLameEncoderSettingsWidget : public K3bPluginConfigWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bLameEncoderSettingsWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bLameEncoderSettingsWidget();
+
+ public slots:
+ void loadConfig();
+ void saveConfig();
+
+ private slots:
+ void slotQualityLevelChanged( int val );
+ void slotShowManualSettings();
+ void updateManualSettingsLabel();
+
+ private:
+ base_K3bLameEncoderSettingsWidget* m_w;
+ base_K3bManualBitrateSettingsWidget* m_brW;
+ KDialogBase* m_manualSettingsDlg;
+};
+
+#endif
diff --git a/plugins/encoder/lame/k3blameencoder.plugin b/plugins/encoder/lame/k3blameencoder.plugin
new file mode 100644
index 0000000..432bc58
--- /dev/null
+++ b/plugins/encoder/lame/k3blameencoder.plugin
@@ -0,0 +1,9 @@
+[K3b Plugin]
+Lib=libk3blameencoder
+Group=AudioEncoder
+Name=K3b Lame Mp3 Encoder
+Author=Sebastian Trueg
+Email=trueg@k3b.org
+Version=3.0
+Comment=Encoding module to encode MPEG1 Layer III (mp3) files
+License=GPL
diff --git a/plugins/encoder/ogg/Makefile.am b/plugins/encoder/ogg/Makefile.am
new file mode 100644
index 0000000..712adbb
--- /dev/null
+++ b/plugins/encoder/ogg/Makefile.am
@@ -0,0 +1,13 @@
+AM_CPPFLAGS = -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3b/plugin -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3bdevice $(all_includes)
+
+kde_module_LTLIBRARIES = libk3boggvorbisencoder.la
+
+libk3boggvorbisencoder_la_SOURCES = base_k3boggvorbisencodersettingswidget.ui k3boggvorbisencoder.cpp
+
+libk3boggvorbisencoder_la_LIBADD = ../../../libk3b/libk3b.la $(LIB_KDECORE) -logg -lvorbis -lvorbisenc
+libk3boggvorbisencoder_la_LDFLAGS = -avoid-version -module -no-undefined $(all_libraries)
+
+pluginsdir = $(kde_datadir)/k3b/plugins
+plugins_DATA = k3boggvorbisencoder.plugin
+
+METASOURCES = AUTO
diff --git a/plugins/encoder/ogg/base_k3boggvorbisencodersettingswidget.ui b/plugins/encoder/ogg/base_k3boggvorbisencodersettingswidget.ui
new file mode 100644
index 0000000..3e31265
--- /dev/null
+++ b/plugins/encoder/ogg/base_k3boggvorbisencodersettingswidget.ui
@@ -0,0 +1,392 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>base_K3bOggVorbisEncoderSettingsWidget</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>335</width>
+ <height>271</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup1</cstring>
+ </property>
+ <property name="title">
+ <string>File Quality</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioQualityLevel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Quality level:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Controls the quality of the encoded files</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Vorbis' audio quality is not best measured in kilobits per second, but on a scale from -1 to 10 called "quality". &lt;p&gt;For now, quality -1 is roughly equivalent to 45kbps average, 5 is roughly 160kbps, and 10 gives about 400kbps. Most people seeking very-near-CD-quality audio encode at a quality of 5 or, for lossless stereo coupling, 6. The default setting is quality 3, which at approximately 110kbps gives a smaller filesize and significantly better fidelity than .mp3 compression at 128kbps. &lt;p&gt;&lt;em&gt;This explanation was copied from the www.vorbis.com FAQ.&lt;/em&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_labelQualityLevel</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>textLabel1</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame6</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSlider" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_slideQualityLevel</cstring>
+ </property>
+ <property name="minValue">
+ <number>-1</number>
+ </property>
+ <property name="maxValue">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>3</number>
+ </property>
+ <property name="value">
+ <number>3</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <italic>1</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string>high quality</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3_2</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <italic>1</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string>small file</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioManual</cstring>
+ </property>
+ <property name="text">
+ <string>M&amp;anual settings:</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_checkBitrateUpper</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Upper bitrate:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>m_checkBitrateLower</cstring>
+ </property>
+ <property name="text">
+ <string>Lower &amp;bitrate:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="0" column="1">
+ <property name="name">
+ <cstring>m_inputBitrateUpper</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>m_inputBitrateNominal</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="2" column="1">
+ <property name="name">
+ <cstring>m_inputBitrateLower</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>kbps</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="2">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>kbps</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>kbps</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>m_checkBitrateNominal</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Nominal bitrate:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>m_radioManual</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>frame3</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkBitrateUpper</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_inputBitrateUpper</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkBitrateNominal</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_inputBitrateNominal</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkBitrateLower</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_inputBitrateLower</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioQualityLevel</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_labelQualityLevel</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioQualityLevel</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>frame6</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/plugins/encoder/ogg/k3boggvorbisencoder.cpp b/plugins/encoder/ogg/k3boggvorbisencoder.cpp
new file mode 100644
index 0000000..54e6ecb
--- /dev/null
+++ b/plugins/encoder/ogg/k3boggvorbisencoder.cpp
@@ -0,0 +1,555 @@
+/*
+ *
+ * $Id: k3boggvorbisencoder.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 "k3boggvorbisencoder.h"
+#include "base_k3boggvorbisencodersettingswidget.h"
+
+#include <k3bcore.h>
+#include <k3bpluginfactory.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <knuminput.h>
+
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qslider.h>
+#include <qlcdnumber.h>
+#include <qcheckbox.h>
+#include <qcstring.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+
+#include <vorbis/vorbisenc.h>
+
+// for the random generator
+#include <stdlib.h>
+#include <time.h>
+
+
+K_EXPORT_COMPONENT_FACTORY( libk3boggvorbisencoder, K3bPluginFactory<K3bOggVorbisEncoder>( "libk3boggvorbisencoder" ) )
+
+// quality levels -1 to 10 map to 0 to 11
+static const int s_rough_average_quality_level_bitrates[] = {
+ 45,
+ 64,
+ 80,
+ 96,
+ 112,
+ 128,
+ 160,
+ 192,
+ 224,
+ 256,
+ 320,
+ 400
+};
+
+// quality levels -1 to 10 map to 0 to 11
+// static const char* s_ogg_quality_level_strings[] = {
+// I18N_NOOP("Low quality"),
+// I18N_NOOP(""),
+// I18N_NOOP(""),
+// I18N_NOOP(""),
+// I18N_NOOP(""),
+// I18N_NOOP("targetted %1 kbps"),
+// I18N_NOOP("targetted %1 kbps"),
+// I18N_NOOP("targetted %1 kbps"),
+// I18N_NOOP(""),
+// I18N_NOOP(""),
+// I18N_NOOP(""),
+// I18N_NOOP(""),
+// };
+
+
+// THIS IS BASED ON THE OGG VORBIS LIB EXAMPLE
+// BECAUSE OF THE LACK OF DOCUMENTATION
+
+
+class K3bOggVorbisEncoder::Private
+{
+public:
+ Private()
+ : manualBitrate(false),
+ qualityLevel(4),
+ bitrateUpper(-1),
+ bitrateNominal(-1),
+ bitrateLower(-1),
+ // sampleRate(44100),
+ oggStream(0),
+ oggPage(0),
+ oggPacket(0),
+ vorbisInfo(0),
+ vorbisComment(0),
+ vorbisDspState(0),
+ vorbisBlock(0),
+ headersWritten(false) {
+ }
+
+ // encoding settings
+ bool manualBitrate;
+ // 0 to 10 -> 0.0 - 1.0
+ int qualityLevel;
+ int bitrateUpper;
+ int bitrateNominal;
+ int bitrateLower;
+ // int sampleRate;
+
+ // encoding structures
+ ogg_stream_state *oggStream; // take physical pages, weld into a logical stream of packets
+ ogg_page *oggPage; // one Ogg bitstream page. Vorbis packets are inside
+ ogg_packet *oggPacket; // one raw packet of data for decode
+ vorbis_info *vorbisInfo; // struct that stores all the static vorbis bitstream settings
+ vorbis_comment *vorbisComment; // struct that stores all the user comments
+ vorbis_dsp_state *vorbisDspState; // central working state for the packet->PCM decoder
+ vorbis_block *vorbisBlock; // local working space for packet->PCM decode
+
+ bool headersWritten;
+};
+
+
+K3bOggVorbisEncoder::K3bOggVorbisEncoder( QObject* parent, const char* name )
+ : K3bAudioEncoder( parent, name )
+{
+ d = new Private();
+}
+
+
+K3bOggVorbisEncoder::~K3bOggVorbisEncoder()
+{
+ cleanup();
+ delete d;
+}
+
+
+bool K3bOggVorbisEncoder::initEncoderInternal( const QString&, const K3b::Msf& )
+{
+ cleanup();
+
+ // load user settings
+ loadConfig();
+
+ d->oggPage = new ogg_page;
+ d->oggPacket = new ogg_packet;
+ d->vorbisInfo = new vorbis_info;
+
+ vorbis_info_init( d->vorbisInfo );
+
+ int ret = 0;
+
+ if( d->manualBitrate ) {
+ kdDebug() << "(K3bOggVorbisEncoder) calling: "
+ << "vorbis_encode_init( d->vorbisInfo, 2, 44100, "
+ << (d->bitrateUpper != -1 ? d->bitrateUpper*1000 : -1) << ", "
+ << (d->bitrateNominal != -1 ? d->bitrateNominal*1000 : -1) << ", "
+ << (d->bitrateLower != -1 ? d->bitrateLower*1000 : -1) << " );" << endl;
+
+ ret = vorbis_encode_init( d->vorbisInfo,
+ 2, // 2 channels: stereo
+ 44100,
+ d->bitrateUpper != -1 ? d->bitrateUpper*1000 : -1,
+ d->bitrateNominal != -1 ? d->bitrateNominal*1000 : -1,
+ d->bitrateLower != -1 ? d->bitrateLower*1000 : -1 );
+ }
+ else {
+ if( d->qualityLevel < -1 )
+ d->qualityLevel = -1;
+ else if( d->qualityLevel > 10 )
+ d->qualityLevel = 10;
+
+ kdDebug() << "(K3bOggVorbisEncoder) calling: "
+ << "vorbis_encode_init_vbr( d->vorbisInfo, 2, 44100, "
+ << (float)d->qualityLevel/10.0 << ");" << endl;
+
+ ret = vorbis_encode_init_vbr( d->vorbisInfo,
+ 2, // 2 channels: stereo
+ 44100,
+ (float)d->qualityLevel/10.0 );
+ }
+
+ if( ret ) {
+ kdDebug() << "(K3bOggVorbisEncoder) vorbis_encode_init failed: " << ret << endl;
+ cleanup();
+ return false;
+ }
+
+ // init the comment stuff
+ d->vorbisComment = new vorbis_comment;
+ vorbis_comment_init( d->vorbisComment );
+
+ // add the encoder tag (so everybody knows we did it! ;)
+ vorbis_comment_add_tag( d->vorbisComment, QCString("ENCODER").data(), QCString("K3bOggVorbisEncoderPlugin").data() );
+
+ // set up the analysis state and auxiliary encoding storage
+ d->vorbisDspState = new vorbis_dsp_state;
+ d->vorbisBlock = new vorbis_block;
+ vorbis_analysis_init( d->vorbisDspState, d->vorbisInfo );
+ vorbis_block_init( d->vorbisDspState, d->vorbisBlock );
+
+ // set up our packet->stream encoder
+ // pick a random serial number; that way we can more likely build
+ // chained streams just by concatenation
+ d->oggStream = new ogg_stream_state;
+ srand( time(0) );
+ ogg_stream_init( d->oggStream, rand() );
+
+ return true;
+}
+
+
+bool K3bOggVorbisEncoder::writeOggHeaders()
+{
+ if( !d->oggStream ) {
+ kdDebug() << "(K3bOggVorbisEncoder) call to writeOggHeaders without init." << endl;
+ return false;
+ }
+ if( d->headersWritten ) {
+ kdDebug() << "(K3bOggVorbisEncoder) headers already written." << endl;
+ return true;
+ }
+
+ //
+ // Vorbis streams begin with three headers; the initial header (with
+ // most of the codec setup parameters) which is mandated by the Ogg
+ // bitstream spec. The second header holds any comment fields. The
+ // third header holds the bitstream codebook. We merely need to
+ // make the headers, then pass them to libvorbis one at a time;
+ // libvorbis handles the additional Ogg bitstream constraints
+ //
+ ogg_packet header;
+ ogg_packet header_comm;
+ ogg_packet header_code;
+
+ vorbis_analysis_headerout( d->vorbisDspState,
+ d->vorbisComment,
+ &header,
+ &header_comm,
+ &header_code);
+
+ // automatically placed in its own page
+ ogg_stream_packetin( d->oggStream, &header );
+ ogg_stream_packetin( d->oggStream, &header_comm );
+ ogg_stream_packetin( d->oggStream, &header_code );
+
+ //
+ // This ensures the actual
+ // audio data will start on a new page, as per spec
+ //
+ QByteArray data;
+ while( ogg_stream_flush( d->oggStream, d->oggPage ) ) {
+ writeData( (char*)d->oggPage->header, d->oggPage->header_len );
+ writeData( (char*)d->oggPage->body, d->oggPage->body_len );
+ }
+
+ d->headersWritten = true;
+
+ return true;
+}
+
+
+long K3bOggVorbisEncoder::encodeInternal( const char* data, Q_ULONG len )
+{
+ if( !d->headersWritten )
+ if( !writeOggHeaders() )
+ return -1;
+
+ // expose the buffer to submit data
+ float** buffer = vorbis_analysis_buffer( d->vorbisDspState, len/4 );
+
+ // uninterleave samples
+ unsigned long i = 0;
+ for( i = 0; i < len/4; i++ ) {
+ buffer[0][i]=( (data[i*4+1]<<8) | (0x00ff&(int)data[i*4]) ) / 32768.f;
+ buffer[1][i]=( (data[i*4+3]<<8) | (0x00ff&(int)data[i*4+2]) ) / 32768.f;
+ }
+
+ // tell the library how much we actually submitted
+ vorbis_analysis_wrote( d->vorbisDspState, i );
+
+ return flushVorbis();
+}
+
+
+long K3bOggVorbisEncoder::flushVorbis()
+{
+ // vorbis does some data preanalysis, then divvies up blocks for
+ // more involved (potentially parallel) processing. Get a single
+ // block for encoding now
+ long writtenData = 0;
+ while( vorbis_analysis_blockout( d->vorbisDspState, d->vorbisBlock ) == 1 ) {
+
+ // analysis
+ vorbis_analysis( d->vorbisBlock, 0 );
+ vorbis_bitrate_addblock( d->vorbisBlock );
+
+ while( vorbis_bitrate_flushpacket( d->vorbisDspState, d->oggPacket ) ) {
+
+ // weld the packet into the bitstream
+ ogg_stream_packetin( d->oggStream, d->oggPacket );
+
+ // write out pages (if any)
+ while( ogg_stream_pageout( d->oggStream, d->oggPage ) ) {
+ writeData( (char*)d->oggPage->header, d->oggPage->header_len );
+ writeData( (char*)d->oggPage->body, d->oggPage->body_len );
+
+ writtenData += ( d->oggPage->header_len + d->oggPage->body_len );
+ }
+ }
+ }
+
+ return writtenData;
+}
+
+
+void K3bOggVorbisEncoder::finishEncoderInternal()
+{
+ if( d->vorbisDspState ) {
+ vorbis_analysis_wrote( d->vorbisDspState, 0 );
+ flushVorbis();
+ }
+ else
+ kdDebug() << "(K3bOggVorbisEncoder) call to finishEncoderInternal without init." << endl;
+}
+
+
+void K3bOggVorbisEncoder::setMetaDataInternal( K3bAudioEncoder::MetaDataField f, const QString& value )
+{
+ if( d->vorbisComment ) {
+ QCString key;
+
+ switch( f ) {
+ case META_TRACK_TITLE:
+ key = "TITLE";
+ break;
+ case META_TRACK_ARTIST:
+ key = "ARTIST";
+ break;
+ case META_ALBUM_TITLE:
+ key = "ALBUM";
+ break;
+ case META_ALBUM_COMMENT:
+ key = "DESCRIPTION";
+ break;
+ case META_YEAR:
+ key = "DATE";
+ break;
+ case META_TRACK_NUMBER:
+ key = "TRACKNUMBER";
+ break;
+ case META_GENRE:
+ key = "GENRE";
+ break;
+ default:
+ return;
+ }
+
+ vorbis_comment_add_tag( d->vorbisComment, key.data(), value.utf8().data() );
+ }
+ else
+ kdDebug() << "(K3bOggVorbisEncoder) call to setMetaDataInternal without init." << endl;
+}
+
+
+void K3bOggVorbisEncoder::cleanup()
+{
+ if( d->oggStream ) {
+ ogg_stream_clear( d->oggStream );
+ delete d->oggStream;
+ d->oggStream = 0;
+ }
+ if( d->vorbisBlock ) {
+ vorbis_block_clear( d->vorbisBlock );
+ delete d->vorbisBlock;
+ d->vorbisBlock = 0;
+ }
+ if( d->vorbisDspState ) {
+ vorbis_dsp_clear( d->vorbisDspState );
+ delete d->vorbisDspState;
+ d->vorbisDspState = 0;
+ }
+ if( d->vorbisComment ) {
+ vorbis_comment_clear( d->vorbisComment );
+ delete d->vorbisComment;
+ d->vorbisComment = 0;
+ }
+ if( d->vorbisInfo ) {
+ vorbis_info_clear( d->vorbisInfo );
+ delete d->vorbisInfo;
+ d->vorbisInfo = 0;
+ }
+
+ // ogg_page and ogg_packet structs always point to storage in
+ // libvorbis. They're never freed or manipulated directly
+ if( d->oggPage ) {
+ delete d->oggPage;
+ d->oggPage = 0;
+ }
+ if( d->oggPacket ) {
+ delete d->oggPacket;
+ d->oggPacket = 0;
+ }
+
+ d->headersWritten = false;
+}
+
+
+void K3bOggVorbisEncoder::loadConfig()
+{
+ KConfig* c = k3bcore->config();
+
+ c->setGroup( "K3bOggVorbisEncoderPlugin" );
+
+ d->manualBitrate = c->readBoolEntry( "manual bitrate", false );
+ d->qualityLevel = c->readNumEntry( "quality level", 4 );
+ d->bitrateUpper = c->readNumEntry( "bitrate upper", -1 );
+ d->bitrateNominal = c->readNumEntry( "bitrate nominal", -1 );
+ d->bitrateLower = c->readNumEntry( "bitrate lower", -1 );
+ // d->sampleRate = c->readNumEntry( "samplerate", 44100 );
+}
+
+
+
+
+K3bOggVorbisEncoderSettingsWidget::K3bOggVorbisEncoderSettingsWidget( QWidget* parent, const char* name )
+ : K3bPluginConfigWidget( parent, name )
+{
+ w = new base_K3bOggVorbisEncoderSettingsWidget( this );
+
+ QString ttQuality = i18n("Controls the quality of the encoded files.");
+ QString wsQuality = i18n("<p>Vorbis' audio quality is not best measured in kilobits per second, "
+ "but on a scale from -1 to 10 called <em>quality</em>."
+ "<p>For now, quality -1 is roughly equivalent to 45kbps average, "
+ "5 is roughly 160kbps, and 10 gives about 400kbps. "
+ "Most people seeking very-near-CD-quality audio encode at a quality of 5 or, "
+ "for lossless stereo coupling, 6. The quality 3 gives, at "
+ "approximately 110kbps a smaller filesize and significantly better fidelity "
+ "than .mp3 compression at 128kbps."
+ "<p><em>This explanation is based on the one from the www.vorbis.com FAQ.</em>");
+
+ QToolTip::add( w->m_radioQualityLevel, ttQuality );
+ QToolTip::add( w->m_labelQualityLevel, ttQuality );
+ QToolTip::add( w->m_slideQualityLevel, ttQuality );
+ QWhatsThis::add( w->m_radioQualityLevel, wsQuality );
+ QWhatsThis::add( w->m_labelQualityLevel, wsQuality );
+ QWhatsThis::add( w->m_slideQualityLevel, wsQuality );
+
+
+ QHBoxLayout* lay = new QHBoxLayout( this );
+ lay->setMargin( 0 );
+
+ lay->addWidget( w );
+
+ connect( w->m_slideQualityLevel, SIGNAL(valueChanged(int)),
+ this, SLOT(slotQualityLevelChanged(int)) );
+
+ slotQualityLevelChanged( 4 );
+}
+
+
+K3bOggVorbisEncoderSettingsWidget::~K3bOggVorbisEncoderSettingsWidget()
+{
+}
+
+
+void K3bOggVorbisEncoderSettingsWidget::slotQualityLevelChanged( int val )
+{
+ w->m_labelQualityLevel->setText( QString::number(val) + " "
+ + i18n("(targetted VBR of %1)").arg(s_rough_average_quality_level_bitrates[val+1]) );
+}
+
+
+void K3bOggVorbisEncoderSettingsWidget::loadConfig()
+{
+ KConfig* c = k3bcore->config();
+
+ c->setGroup( "K3bOggVorbisEncoderPlugin" );
+
+ if( c->readBoolEntry( "manual bitrate", false ) )
+ w->m_radioManual->setChecked(true);
+ else
+ w->m_radioQualityLevel->setChecked(true);
+ w->m_slideQualityLevel->setValue( c->readNumEntry( "quality level", 4 ) );
+ w->m_inputBitrateUpper->setValue( c->readNumEntry( "bitrate upper", -1 ) );
+ w->m_checkBitrateUpper->setChecked( c->readNumEntry( "bitrate upper", -1 ) != -1 );
+ w->m_inputBitrateNominal->setValue( c->readNumEntry( "bitrate nominal", -1 ) );
+ w->m_checkBitrateNominal->setChecked( c->readNumEntry( "bitrate nominal", -1 ) != -1 );
+ w->m_inputBitrateLower->setValue( c->readNumEntry( "bitrate lower", -1 ) );
+ w->m_checkBitrateLower->setChecked( c->readNumEntry( "bitrate lower", -1 ) != -1 );
+ // w->m_inputSamplerate->setValue( c->readNumEntry( "samplerate", 44100 ) );
+}
+
+
+void K3bOggVorbisEncoderSettingsWidget::saveConfig()
+{
+ KConfig* c = k3bcore->config();
+
+ c->setGroup( "K3bOggVorbisEncoderPlugin" );
+
+ c->writeEntry( "manual bitrate", w->m_radioManual->isChecked() );
+ c->writeEntry( "quality level", w->m_slideQualityLevel->value() );
+ c->writeEntry( "bitrate upper", w->m_checkBitrateUpper->isChecked() ? w->m_inputBitrateUpper->value() : -1 );
+ c->writeEntry( "bitrate nominal", w->m_checkBitrateNominal->isChecked() ? w->m_inputBitrateNominal->value() : -1 );
+ c->writeEntry( "bitrate lower", w->m_checkBitrateLower->isChecked() ? w->m_inputBitrateLower->value() : -1 );
+ // c->writeEntry( "samplerate", w->m_inputSamplerate->value() );
+}
+
+
+QString K3bOggVorbisEncoder::fileTypeComment( const QString& ) const
+{
+ return i18n("Ogg-Vorbis");
+}
+
+
+long long K3bOggVorbisEncoder::fileSize( const QString&, const K3b::Msf& msf ) const
+{
+ KConfig* c = k3bcore->config();
+ c->setGroup( "K3bOggVorbisEncoderPlugin" );
+
+ // the following code is based on the size estimation from the audiocd kioslave
+ // TODO: reimplement.
+
+ if( !c->readBoolEntry( "manual bitrate", false ) ) {
+ // Estimated numbers based on the Vorbis FAQ:
+ // http://www.xiph.org/archives/vorbis-faq/200203/0030.html
+
+// static long vorbis_q_bitrate[] = { 45, 60, 74, 86, 106, 120, 152,
+// 183, 207, 239, 309, 440 };
+
+ int qualityLevel = c->readNumEntry( "quality level", 4 );
+
+ if( qualityLevel < -1 )
+ qualityLevel = -1;
+ else if( qualityLevel > 10 )
+ qualityLevel = 10;
+ return ( (msf.totalFrames()/75) * s_rough_average_quality_level_bitrates[qualityLevel+1] * 1000 ) / 8;
+ }
+ else {
+ return (msf.totalFrames()/75) * c->readNumEntry( "bitrate nominal", 160 ) * 1000 / 8;
+ }
+}
+
+
+K3bPluginConfigWidget* K3bOggVorbisEncoder::createConfigWidget( QWidget* parent,
+ const char* name ) const
+{
+ return new K3bOggVorbisEncoderSettingsWidget( parent, name );
+}
+
+
+#include "k3boggvorbisencoder.moc"
diff --git a/plugins/encoder/ogg/k3boggvorbisencoder.h b/plugins/encoder/ogg/k3boggvorbisencoder.h
new file mode 100644
index 0000000..0148713
--- /dev/null
+++ b/plugins/encoder/ogg/k3boggvorbisencoder.h
@@ -0,0 +1,81 @@
+/*
+ *
+ * $Id: k3boggvorbisencoder.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_OGG_VORBIS_ENCODER_H_
+#define _K3B_OGG_VORBIS_ENCODER_H_
+
+
+#include <k3baudioencoder.h>
+#include <k3bpluginconfigwidget.h>
+
+
+class base_K3bOggVorbisEncoderSettingsWidget;
+
+
+class K3bOggVorbisEncoder : public K3bAudioEncoder
+{
+ Q_OBJECT
+
+ public:
+ K3bOggVorbisEncoder( QObject* parent = 0, const char* name = 0 );
+ ~K3bOggVorbisEncoder();
+
+ QStringList extensions() const { return QStringList("ogg"); }
+
+ QString fileTypeComment( const QString& ) const;
+
+ long long fileSize( const QString&, const K3b::Msf& msf ) const;
+
+ int pluginSystemVersion() const { return 3; }
+
+ K3bPluginConfigWidget* createConfigWidget( QWidget* parent = 0,
+ const char* name = 0 ) const;
+
+ private:
+ void loadConfig();
+ void finishEncoderInternal();
+ bool initEncoderInternal( const QString& extension, const K3b::Msf& length );
+ long encodeInternal( const char* data, Q_ULONG len );
+ void setMetaDataInternal( MetaDataField, const QString& );
+
+ bool writeOggHeaders();
+ void cleanup();
+ long flushVorbis();
+
+ class Private;
+ Private* d;
+};
+
+
+class K3bOggVorbisEncoderSettingsWidget : public K3bPluginConfigWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bOggVorbisEncoderSettingsWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bOggVorbisEncoderSettingsWidget();
+
+ public slots:
+ void loadConfig();
+ void saveConfig();
+
+ private slots:
+ void slotQualityLevelChanged( int val );
+
+ private:
+ base_K3bOggVorbisEncoderSettingsWidget* w;
+};
+
+#endif
diff --git a/plugins/encoder/ogg/k3boggvorbisencoder.plugin b/plugins/encoder/ogg/k3boggvorbisencoder.plugin
new file mode 100644
index 0000000..2f73e8e
--- /dev/null
+++ b/plugins/encoder/ogg/k3boggvorbisencoder.plugin
@@ -0,0 +1,9 @@
+[K3b Plugin]
+Lib=libk3boggvorbisencoder
+Group=AudioEncoder
+Name=K3b Ogg Vorbis Encoder
+Author=Sebastian Trueg
+Email=trueg@k3b.org
+Version=2.1
+Comment=Encoding module to encode Ogg Vorbis files
+License=GPL
diff --git a/plugins/encoder/skeleton.cpp b/plugins/encoder/skeleton.cpp
new file mode 100644
index 0000000..7a46caf
--- /dev/null
+++ b/plugins/encoder/skeleton.cpp
@@ -0,0 +1,123 @@
+/*
+ *
+ * $Id: skeleton.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 "k3b<name>encoder.h"
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+
+K_EXPORT_COMPONENT_FACTORY( libk3b<name>encoder, K3bPluginFactory<K3b<name>Encoder>( "libk3b<name>encoder" ) )
+
+
+K3b<name>Encoder::K3b<name>Encoder( QObject* parent, const char* name )
+ : K3bAudioEncoder( parent, name )
+{
+}
+
+
+K3b<name>Encoder::~K3b<name>Encoder()
+{
+}
+
+
+bool K3b<name>Encoder::initEncoderInternal( const QString& )
+{
+ // PUT YOUR CODE HERE
+ return false;
+}
+
+
+long K3b<name>Encoder::encodeInternal( const char* data, Q_ULONG len )
+{
+ // PUT YOUR CODE HERE
+ return false;
+}
+
+
+void K3b<name>Encoder::finishEncoderInternal()
+{
+ // PUT YOUR CODE HERE
+}
+
+
+void K3b<name>Encoder::setMetaDataInternal( K3bAudioEncoder::MetaDataField f, const QString& value )
+{
+ // PUT YOUR CODE HERE
+}
+
+
+QStringList K3b<name>Encoder::extensions() const
+{
+ // PUT YOUR CODE HERE
+ return QStringList( "" );
+}
+
+
+QString K3b<name>Encoder::fileTypeComment( const QString& ) const
+{
+ // PUT YOUR CODE HERE
+ return "";
+}
+
+
+long long K3b<name>Encoder::fileSize( const QString&, const K3b::Msf& msf ) const
+{
+ // PUT YOUR CODE HERE
+ return -1;
+}
+
+
+K3bPluginConfigWidget* K3b<name>Encoder::createConfigWidget( QWidget* parent,
+ const char* name ) const
+{
+ return new K3b<name>EncoderSettingsWidget( parent, name );
+}
+
+
+
+K3b<name>EncoderSettingsWidget::K3b<name>EncoderSettingsWidget( QWidget* parent, const char* name )
+ : K3bPluginConfigWidget( parent, name )
+{
+}
+
+
+K3b<name>EncoderSettingsWidget::~K3b<name>EncoderSettingsWidget()
+{
+}
+
+
+void K3b<name>EncoderSettingsWidget::loadConfig()
+{
+ KConfig* c = k3bcore->config();
+ c->setGroup( "K3b<name>EncoderPlugin" );
+
+ // PUT YOUR CODE HERE
+}
+
+
+void K3b<name>EncoderSettingsWidget::saveConfig()
+{
+ KConfig* c = k3bcore->config();
+ c->setGroup( "K3b<name>EncoderPlugin" );
+
+ // PUT YOUR CODE HERE
+}
+
+
+#include "k3b<name>encoder.moc"
diff --git a/plugins/encoder/skeleton.h b/plugins/encoder/skeleton.h
new file mode 100644
index 0000000..78c733e
--- /dev/null
+++ b/plugins/encoder/skeleton.h
@@ -0,0 +1,64 @@
+/*
+ *
+ * $Id: skeleton.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_<name>_ENCODER_H_
+#define _K3B_<name>_ENCODER_H_
+
+
+#include <k3baudioencoder.h>
+#include <k3bpluginconfigwidget.h>
+
+
+class K3b<name>Encoder : public K3bAudioEncoder
+{
+ Q_OBJECT
+
+ public:
+ K3b<name>Encoder( QObject* parent = 0, const char* name = 0 );
+ ~K3b<name>Encoder();
+
+ QStringList extensions() const;
+
+ QString fileTypeComment( const QString& ) const;
+
+ long long fileSize( const QString&, const K3b::Msf& msf ) const;
+
+ int pluginSystemVersion() const { return 3; }
+
+ K3bPluginConfigWidget* createConfigWidget( QWidget* parent = 0,
+ const char* name = 0 ) const;
+
+ private:
+ void finishEncoderInternal();
+ bool initEncoderInternal( const QString& extension );
+ long encodeInternal( const char* data, Q_ULONG len );
+ void setMetaDataInternal( MetaDataField, const QString& );
+};
+
+
+class K3b<name>EncoderSettingsWidget : public K3bPluginConfigWidget
+{
+ Q_OBJECT
+
+ public:
+ K3b<name>EncoderSettingsWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3b<name>EncoderSettingsWidget();
+
+ public slots:
+ void loadConfig();
+ void saveConfig();
+};
+
+#endif
diff --git a/plugins/encoder/skeleton.plugin b/plugins/encoder/skeleton.plugin
new file mode 100644
index 0000000..cf178b7
--- /dev/null
+++ b/plugins/encoder/skeleton.plugin
@@ -0,0 +1,9 @@
+[K3b Plugin]
+Lib=libk3b<name>encoder
+Group=AudioEncoder
+Name=K3b ??? Encoder
+Author=???
+Email=???
+Version=??
+Comment=Encoding module to encode <name> files
+License=???
diff --git a/plugins/encoder/sox/Makefile.am b/plugins/encoder/sox/Makefile.am
new file mode 100644
index 0000000..535b1c0
--- /dev/null
+++ b/plugins/encoder/sox/Makefile.am
@@ -0,0 +1,13 @@
+AM_CPPFLAGS = -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3b/plugin -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3bdevice $(all_includes)
+
+kde_module_LTLIBRARIES = libk3bsoxencoder.la
+
+libk3bsoxencoder_la_SOURCES = base_k3bsoxencoderconfigwidget.ui k3bsoxencoder.cpp
+
+libk3bsoxencoder_la_LIBADD = ../../../libk3b/libk3b.la $(LIB_KDECORE)
+libk3bsoxencoder_la_LDFLAGS = -avoid-version -module -no-undefined $(all_libraries)
+
+pluginsdir = $(kde_datadir)/k3b/plugins
+plugins_DATA = k3bsoxencoder.plugin
+
+METASOURCES = AUTO
diff --git a/plugins/encoder/sox/base_k3bsoxencoderconfigwidget.ui b/plugins/encoder/sox/base_k3bsoxencoderconfigwidget.ui
new file mode 100644
index 0000000..7d8ee43
--- /dev/null
+++ b/plugins/encoder/sox/base_k3bsoxencoderconfigwidget.ui
@@ -0,0 +1,258 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>base_K3bSoxEncoderConfigWidget</class>
+<author>Sebastian Trueg</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>419</width>
+ <height>201</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_checkManual</cstring>
+ </property>
+ <property name="text">
+ <string>Manual settings (used for all file types)</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Sample rate:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="2" column="1">
+ <item>
+ <property name="text">
+ <string>Signed Linear</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Unsigned Linear</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>u-law (logarithmic)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>A-law (logarithmic)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ADPCM</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>IMA_ADPCM</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>GSM</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Floating-Point</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_comboEncoding</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;The sample data encoding is signed linear (2's complement), unsigned linear, u-law (logarithmic), A-law (logarithmic), ADPCM, IMA_ADPCM, GSM, or Floating-point.&lt;/p&gt;
+&lt;p&gt;&lt;b&gt;U-law&lt;/b&gt; (actually shorthand for mu-law) and &lt;b&gt;A-law&lt;/b&gt; are the U.S. and international standards for logarithmic telephone sound compression. When uncompressed u-law has roughly the precision of 14-bit PCM audio and A-law has roughly the precision of 13-bit PCM audio. A-law and u-law data is sometimes encoded using a reversed bit-ordering (i.e. MSB becomes LSB).&lt;br&gt; &lt;b&gt;ADPCM &lt;/b&gt; is a form of sound compression that has a good compromise between good sound quality and fast encoding/decoding time. It is used for telephone sound compression and places where full fidelity is not as important. When uncompressed it has roughly the precision of 16-bit PCM audio. Popular versions of ADPCM include G.726, MS ADPCM, and IMA ADPCM. It has different meanings in different file handlers. In .wav files it represents MS ADPCM files, in all others it means G.726 ADPCM. &lt;br&gt; &lt;b&gt;IMA ADPCM&lt;/b&gt; is a specific form of ADPCM compression, slightly simpler and slightly lower fidelity than Microsoft's flavor of ADPCM. IMA ADPCM is also called DVI ADPCM.&lt;br&gt; &lt;b&gt;GSM&lt;/b&gt; is a standard used for telephone sound compression in European countries and is gaining popularity because of its good quality. It is usually CPU intensive to work with GSM audio data.&lt;/p&gt; &lt;p&gt;&lt;em&gt;Description based on the SoX manpage&lt;/em&gt;&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>m_editSamplerate</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>14400</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Data size:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Data encoding:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Channels:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>1 (mono)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>2 (stereo)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>4 (quad sound)</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_comboChannels</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="3" column="1">
+ <item>
+ <property name="text">
+ <string>Bytes</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>16-bit Words</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>32-bit Words</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_comboSize</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>250</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>m_checkManual</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_comboChannels</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkManual</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_editSamplerate</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkManual</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_comboEncoding</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkManual</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_comboSize</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/plugins/encoder/sox/k3bsoxencoder.cpp b/plugins/encoder/sox/k3bsoxencoder.cpp
new file mode 100644
index 0000000..ecae2e4
--- /dev/null
+++ b/plugins/encoder/sox/k3bsoxencoder.cpp
@@ -0,0 +1,482 @@
+/*
+ *
+ * $Id: k3bsoxencoder.cpp 731310 2007-10-31 10:30:05Z 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 "k3bsoxencoder.h"
+#include "base_k3bsoxencoderconfigwidget.h"
+
+#include <k3bprocess.h>
+#include <k3bcore.h>
+#include <k3bexternalbinmanager.h>
+#include <k3bpluginfactory.h>
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <klocale.h>
+
+#include <qfileinfo.h>
+#include <qfile.h>
+#include <qvalidator.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+
+K_EXPORT_COMPONENT_FACTORY( libk3bsoxencoder, K3bPluginFactory<K3bSoxEncoder>( "libk3bsoxencoder" ) )
+
+
+// the sox external program
+class K3bSoxProgram : public K3bExternalProgram
+{
+ public:
+ K3bSoxProgram()
+ : K3bExternalProgram( "sox" ) {
+ }
+
+ bool scan( const QString& p ) {
+ if( p.isEmpty() )
+ return false;
+
+ QString path = p;
+ QFileInfo fi( path );
+ if( fi.isDir() ) {
+ if( path[path.length()-1] != '/' )
+ path.append("/");
+ path.append("sox");
+ }
+
+ if( !QFile::exists( path ) )
+ return false;
+
+ K3bExternalBin* bin = 0;
+
+ // probe version
+ KProcess vp;
+ K3bProcessOutputCollector out( &vp );
+
+ vp << path << "-h";
+ if( vp.start( KProcess::Block, KProcess::AllOutput ) ) {
+ int pos = out.output().find( "sox: SoX Version" );
+ if ( pos < 0 )
+ pos = out.output().find( "sox: SoX v" ); // newer sox versions
+ int endPos = out.output().find( "\n", pos );
+ if( pos > 0 && endPos > 0 ) {
+ pos += 17;
+ bin = new K3bExternalBin( this );
+ bin->path = path;
+ bin->version = out.output().mid( pos, endPos-pos );
+
+ addBin( bin );
+
+ return true;
+ }
+ else {
+ pos = out.output().find( "sox: Version" );
+ endPos = out.output().find( "\n", pos );
+ if( pos > 0 && endPos > 0 ) {
+ pos += 13;
+ bin = new K3bExternalBin( this );
+ bin->path = path;
+ bin->version = out.output().mid( pos, endPos-pos );
+
+ addBin( bin );
+
+ return true;
+ }
+ else
+ return false;
+ }
+ }
+ else
+ return false;
+ }
+};
+
+
+class K3bSoxEncoder::Private
+{
+public:
+ Private()
+ : process(0) {
+ }
+
+ K3bProcess* process;
+ QString fileName;
+};
+
+
+K3bSoxEncoder::K3bSoxEncoder( QObject* parent, const char* name )
+ : K3bAudioEncoder( parent, name )
+{
+ if( k3bcore->externalBinManager()->program( "sox" ) == 0 )
+ k3bcore->externalBinManager()->addProgram( new K3bSoxProgram() );
+
+ d = new Private();
+}
+
+
+K3bSoxEncoder::~K3bSoxEncoder()
+{
+ delete d->process;
+ delete d;
+}
+
+
+void K3bSoxEncoder::finishEncoderInternal()
+{
+ if( d->process ) {
+ if( d->process->isRunning() ) {
+ ::close( d->process->stdinFd() );
+
+ // this is kind of evil...
+ // but we need to be sure the process exited when this method returnes
+ ::waitpid( d->process->pid(), 0, 0 );
+ }
+ }
+}
+
+
+void K3bSoxEncoder::slotSoxFinished( KProcess* p )
+{
+ if( !p->normalExit() || p->exitStatus() != 0 )
+ kdDebug() << "(K3bSoxEncoder) sox exited with error." << endl;
+}
+
+
+bool K3bSoxEncoder::openFile( const QString& ext, const QString& filename, const K3b::Msf& )
+{
+ d->fileName = filename;
+ return initEncoderInternal( ext );
+}
+
+
+void K3bSoxEncoder::closeFile()
+{
+ finishEncoderInternal();
+}
+
+
+bool K3bSoxEncoder::initEncoderInternal( const QString& extension )
+{
+ const K3bExternalBin* soxBin = k3bcore->externalBinManager()->binObject( "sox" );
+ if( soxBin ) {
+ delete d->process;
+ d->process = new K3bProcess();
+ d->process->setSplitStdout(true);
+ d->process->setRawStdin(true);
+
+ connect( d->process, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotSoxFinished(KProcess*)) );
+ connect( d->process, SIGNAL(stderrLine(const QString&)),
+ this, SLOT(slotSoxOutputLine(const QString&)) );
+ connect( d->process, SIGNAL(stdoutLine(const QString&)),
+ this, SLOT(slotSoxOutputLine(const QString&)) );
+
+ // input settings
+ *d->process << soxBin->path
+ << "-t" << "raw" // raw samples
+ << "-r" << "44100" // samplerate
+ << "-s" // signed linear
+ << "-w" // 16-bit words
+ << "-c" << "2" // stereo
+ << "-"; // read from stdin
+
+ // output settings
+ *d->process << "-t" << extension;
+
+ KConfig* c = k3bcore->config();
+ c->setGroup( "K3bSoxEncoderPlugin" );
+ if( c->readBoolEntry( "manual settings", false ) ) {
+ *d->process << "-r" << QString::number( c->readNumEntry( "samplerate", 44100 ) )
+ << "-c" << QString::number( c->readNumEntry( "channels", 2 ) );
+
+ int size = c->readNumEntry( "data size", 16 );
+ *d->process << ( size == 8 ? QString("-b") : ( size == 32 ? QString("-l") : QString("-w") ) );
+
+ QString encoding = c->readEntry( "data encoding", "signed" );
+ if( encoding == "unsigned" )
+ *d->process << "-u";
+ else if( encoding == "u-law" )
+ *d->process << "-U";
+ else if( encoding == "A-law" )
+ *d->process << "-A";
+ else if( encoding == "ADPCM" )
+ *d->process << "-a";
+ else if( encoding == "IMA_ADPCM" )
+ *d->process << "-i";
+ else if( encoding == "GSM" )
+ *d->process << "-g";
+ else if( encoding == "Floating-point" )
+ *d->process << "-f";
+ else
+ *d->process << "-s";
+ }
+
+ *d->process << d->fileName;
+
+ kdDebug() << "***** sox parameters:" << endl;
+ const QValueList<QCString>& args = d->process->args();
+ QString s;
+ for( QValueList<QCString>::const_iterator it = args.begin(); it != args.end(); ++it ) {
+ s += *it + " ";
+ }
+ kdDebug() << s << flush << endl;
+
+
+ return d->process->start( KProcess::NotifyOnExit, KProcess::All );
+ }
+ else {
+ kdDebug() << "(K3bSoxEncoder) could not find sox bin." << endl;
+ return false;
+ }
+}
+
+
+long K3bSoxEncoder::encodeInternal( const char* data, Q_ULONG len )
+{
+ if( d->process ) {
+ if( d->process->isRunning() )
+ return ::write( d->process->stdinFd(), (const void*)data, len );
+ else
+ return -1;
+ }
+ else
+ return -1;
+}
+
+
+void K3bSoxEncoder::slotSoxOutputLine( const QString& line )
+{
+ kdDebug() << "(sox) " << line << endl;
+}
+
+
+QStringList K3bSoxEncoder::extensions() const
+{
+ static QStringList s_extensions;
+ if( s_extensions.isEmpty() ) {
+ s_extensions << "au"
+ << "8svx"
+ << "aiff"
+ << "avr"
+ << "cdr"
+ << "cvs"
+ << "dat"
+ << "gsm"
+ << "hcom"
+ << "maud"
+ << "sf"
+ << "sph"
+ << "smp"
+ << "txw"
+ << "vms"
+ << "voc"
+ << "wav"
+ << "wve"
+ << "raw";
+ }
+
+ if( k3bcore->externalBinManager()->foundBin( "sox" ) )
+ return s_extensions;
+ else
+ return QStringList(); // no sox -> no encoding
+}
+
+
+QString K3bSoxEncoder::fileTypeComment( const QString& ext ) const
+{
+ if( ext == "au" )
+ return i18n("Sun AU");
+ else if( ext == "8svx" )
+ return i18n("Amiga 8SVX");
+ else if( ext == "aiff" )
+ return i18n("AIFF");
+ else if( ext == "avr" )
+ return i18n("Audio Visual Research");
+ else if( ext == "cdr" )
+ return i18n("CD-R");
+ else if( ext == "cvs" )
+ return i18n("CVS");
+ else if( ext == "dat" )
+ return i18n("Text Data");
+ else if( ext == "gsm" )
+ return i18n("GSM Speech");
+ else if( ext == "hcom" )
+ return i18n("Macintosh HCOM");
+ else if( ext == "maud" )
+ return i18n("Maud (Amiga)");
+ else if( ext == "sf" )
+ return i18n("IRCAM");
+ else if( ext == "sph" )
+ return i18n("SPHERE");
+ else if( ext == "smp" )
+ return i18n("Turtle Beach SampleVision");
+ else if( ext == "txw" )
+ return i18n("Yamaha TX-16W");
+ else if( ext == "vms" )
+ return i18n("VMS");
+ else if( ext == "voc" )
+ return i18n("Sound Blaster VOC");
+ else if( ext == "wav" )
+ return i18n("Wave (Sox)");
+ else if( ext == "wve" )
+ return i18n("Psion 8-bit A-law");
+ else if( ext == "raw" )
+ return i18n("Raw");
+ else
+ return i18n("Error");
+}
+
+
+long long K3bSoxEncoder::fileSize( const QString&, const K3b::Msf& msf ) const
+{
+ // for now we make a rough assumption based on the settings
+ KConfig* c = k3bcore->config();
+ c->setGroup( "K3bSoxEncoderPlugin" );
+ if( c->readBoolEntry( "manual settings", false ) ) {
+ int sr = c->readNumEntry( "samplerate", 44100 );
+ int ch = c->readNumEntry( "channels", 2 );
+ int wsize = c->readNumEntry( "data size", 16 );
+
+ return msf.totalFrames()*sr*ch*wsize/75;
+ }
+ else {
+ // fallback to raw
+ return msf.audioBytes();
+ }
+}
+
+
+K3bPluginConfigWidget* K3bSoxEncoder::createConfigWidget( QWidget* parent,
+ const char* name ) const
+{
+ return new K3bSoxEncoderSettingsWidget( parent, name );
+}
+
+
+
+K3bSoxEncoderSettingsWidget::K3bSoxEncoderSettingsWidget( QWidget* parent, const char* name )
+ : K3bPluginConfigWidget( parent, name )
+{
+ w = new base_K3bSoxEncoderConfigWidget( this );
+ w->m_editSamplerate->setValidator( new QIntValidator( w->m_editSamplerate ) );
+
+ QHBoxLayout* lay = new QHBoxLayout( this );
+ lay->setMargin( 0 );
+
+ lay->addWidget( w );
+}
+
+
+K3bSoxEncoderSettingsWidget::~K3bSoxEncoderSettingsWidget()
+{
+}
+
+
+void K3bSoxEncoderSettingsWidget::loadConfig()
+{
+ KConfig* c = k3bcore->config();
+
+ c->setGroup( "K3bSoxEncoderPlugin" );
+
+ w->m_checkManual->setChecked( c->readBoolEntry( "manual settings", false ) );
+
+ int channels = c->readNumEntry( "channels", 2 );
+ w->m_comboChannels->setCurrentItem( channels == 4 ? 2 : channels-1 );
+
+ w->m_editSamplerate->setText( QString::number( c->readNumEntry( "samplerate", 44100 ) ) );
+
+ QString encoding = c->readEntry( "data encoding", "signed" );
+ if( encoding == "unsigned" )
+ w->m_comboEncoding->setCurrentItem(1);
+ else if( encoding == "u-law" )
+ w->m_comboEncoding->setCurrentItem(2);
+ else if( encoding == "A-law" )
+ w->m_comboEncoding->setCurrentItem(3);
+ else if( encoding == "ADPCM" )
+ w->m_comboEncoding->setCurrentItem(4);
+ else if( encoding == "IMA_ADPCM" )
+ w->m_comboEncoding->setCurrentItem(5);
+ else if( encoding == "GSM" )
+ w->m_comboEncoding->setCurrentItem(6);
+ else if( encoding == "Floating-point" )
+ w->m_comboEncoding->setCurrentItem(7);
+ else
+ w->m_comboEncoding->setCurrentItem(0);
+
+ int size = c->readNumEntry( "data size", 16 );
+ w->m_comboSize->setCurrentItem( size == 8 ? 0 : ( size == 32 ? 2 : 1 ) );
+}
+
+
+void K3bSoxEncoderSettingsWidget::saveConfig()
+{
+ KConfig* c = k3bcore->config();
+
+ c->setGroup( "K3bSoxEncoderPlugin" );
+
+ c->writeEntry( "manual settings", w->m_checkManual->isChecked() );
+
+ c->writeEntry( "channels", w->m_comboChannels->currentItem() == 0
+ ? 1
+ : ( w->m_comboChannels->currentItem() == 2
+ ? 4
+ : 2 ) );
+
+ c->writeEntry( "data size", w->m_comboSize->currentItem() == 0
+ ? 8
+ : ( w->m_comboSize->currentItem() == 2
+ ? 32
+ : 16 ) );
+
+ c->writeEntry( "samplerate", w->m_editSamplerate->text().toInt() );
+
+ QString enc;
+ switch( w->m_comboEncoding->currentItem() ) {
+ case 1:
+ enc = "unsigned";
+ break;
+ case 2:
+ enc = "u-law";
+ break;
+ case 3:
+ enc = "A-law";
+ break;
+ case 4:
+ enc = "ADPCM";
+ break;
+ case 5:
+ enc = "IMA_ADPCM";
+ break;
+ case 6:
+ enc = "GSM";
+ break;
+ case 7:
+ enc = "Floating-point";
+ break;
+ default:
+ enc = "signed";
+ break;
+ }
+ c->writeEntry( "data encoding", enc );
+}
+
+
+#include "k3bsoxencoder.moc"
diff --git a/plugins/encoder/sox/k3bsoxencoder.h b/plugins/encoder/sox/k3bsoxencoder.h
new file mode 100644
index 0000000..555f44e
--- /dev/null
+++ b/plugins/encoder/sox/k3bsoxencoder.h
@@ -0,0 +1,82 @@
+/*
+ *
+ * $Id: k3bsoxencoder.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_SOX_ENCODER_H_
+#define _K3B_SOX_ENCODER_H_
+
+
+#include <k3baudioencoder.h>
+#include <k3bpluginconfigwidget.h>
+
+
+class base_K3bSoxEncoderConfigWidget;
+class KProcess;
+
+class K3bSoxEncoder : public K3bAudioEncoder
+{
+ Q_OBJECT
+
+ public:
+ K3bSoxEncoder( QObject* parent = 0, const char* name = 0 );
+ ~K3bSoxEncoder();
+
+ QStringList extensions() const;
+
+ QString fileTypeComment( const QString& ) const;
+
+ long long fileSize( const QString&, const K3b::Msf& msf ) const;
+
+ int pluginSystemVersion() const { return 3; }
+
+ K3bPluginConfigWidget* createConfigWidget( QWidget* parent = 0,
+ const char* name = 0 ) const;
+
+ /**
+ * reimplemented since sox writes the file itself
+ */
+ bool openFile( const QString& ext, const QString& filename, const K3b::Msf& );
+ void closeFile();
+
+ private slots:
+ void slotSoxFinished( KProcess* );
+ void slotSoxOutputLine( const QString& );
+
+ private:
+ void finishEncoderInternal();
+ bool initEncoderInternal( const QString& extension );
+ long encodeInternal( const char* data, Q_ULONG len );
+
+ class Private;
+ Private* d;
+};
+
+
+class K3bSoxEncoderSettingsWidget : public K3bPluginConfigWidget
+{
+ Q_OBJECT
+
+ public:
+ K3bSoxEncoderSettingsWidget( QWidget* parent = 0, const char* name = 0 );
+ ~K3bSoxEncoderSettingsWidget();
+
+ public slots:
+ void loadConfig();
+ void saveConfig();
+
+ private:
+ base_K3bSoxEncoderConfigWidget* w;
+};
+
+#endif
diff --git a/plugins/encoder/sox/k3bsoxencoder.plugin b/plugins/encoder/sox/k3bsoxencoder.plugin
new file mode 100644
index 0000000..dd43f7d
--- /dev/null
+++ b/plugins/encoder/sox/k3bsoxencoder.plugin
@@ -0,0 +1,9 @@
+[K3b Plugin]
+Lib=libk3bsoxencoder
+Group=AudioEncoder
+Name=K3b SoX Audio Encoder
+Author=Sebastian Trueg
+Email=trueg@k3b.org
+Version=2.0
+Comment=Encoding module to encode many file formats using SoX
+License=GPL