summaryrefslogtreecommitdiffstats
path: root/plugins/encoder/external
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/external
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/external')
-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
10 files changed, 1234 insertions, 0 deletions
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