summaryrefslogtreecommitdiffstats
path: root/plugins/encoder/ogg
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/ogg
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/ogg')
-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
5 files changed, 1050 insertions, 0 deletions
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