summaryrefslogtreecommitdiffstats
path: root/krec/ogg_export/krecexport_ogg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'krec/ogg_export/krecexport_ogg.cpp')
-rw-r--r--krec/ogg_export/krecexport_ogg.cpp254
1 files changed, 254 insertions, 0 deletions
diff --git a/krec/ogg_export/krecexport_ogg.cpp b/krec/ogg_export/krecexport_ogg.cpp
new file mode 100644
index 00000000..6a5d5735
--- /dev/null
+++ b/krec/ogg_export/krecexport_ogg.cpp
@@ -0,0 +1,254 @@
+/***************************************************************************
+ copyright : (C) 2003 by Arnold Krille
+ email : arnold@arnoldarts.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <config.h>
+
+#ifdef HAVE_VORBIS
+
+#include "krecexport_ogg.h"
+#include "krecexport_ogg.moc"
+
+#include "krecglobal.h"
+
+#include <kdebug.h>
+#include <ktempfile.h>
+#include <qfile.h>
+#include <qtimer.h>
+#include <kconfig.h>
+#include <stdlib.h>
+#include <time.h>
+#include <qdatetime.h>
+#include <kgenericfactory.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+K_EXPORT_COMPONENT_FACTORY( libkrecexport_ogg, KGenericFactory<KRecExport_OGG> )
+
+KRecExport_OGG krecExportOGG( 0 );
+
+KRecExport_OGG::KRecExport_OGG( QObject* p, const char* n, const QStringList& )
+ : KRecExportItem( p,n )
+ , _file( 0 )
+ , init_done( false )
+{
+kdDebug( 60005 ) << k_funcinfo << endl;
+ registerAtGlobal( this );
+kdDebug( 60005 ) << "Registered Exports: " << KRecGlobal::the()->exportFormats() << endl;
+}
+KRecExport_OGG::~KRecExport_OGG() {
+kdDebug( 60005 ) << k_funcinfo << endl;
+}
+
+KRecExport_OGG* KRecExport_OGG::newItem() {
+kdDebug( 60005 ) << k_funcinfo << endl;
+ return new KRecExport_OGG( 0 );
+}
+
+QStringList KRecExport_OGG::extensions() {
+ //kdDebug( 60005 ) << k_funcinfo << endl;
+ QStringList tmp;
+ tmp << "*.ogg" << "*.OGG";
+ return tmp;
+}
+
+bool KRecExport_OGG::initialize( const QString &filename ) {
+kdDebug( 60005 ) << k_funcinfo << endl;
+ if ( !_file &&
+ !( samplingRate()!=44100 && bits()!=16 && channels()!=2 &&
+ KMessageBox::warningContinueCancel( KRecGlobal::the()->mainWidget(),
+ i18n( "At this time OGG-export only supports files in 44kHz " \
+ "samplingrate, 16bit and 2 channels." )
+ ) == KMessageBox::Cancel
+ )
+ ) {
+ KMessageBox::information( KRecGlobal::the()->mainWidget(),
+ i18n( "Please note that this plugin takes its qualitysettings from" \
+ " the corresponding section of the audiocd:/ configuration. Make use" \
+ " of the Control Center to configure these settings." ),
+ i18n( "Quality Configuration" ), "qualityinfo_ogg" );
+ _file = new QFile( filename );
+ if ( _file->open( IO_Raw|IO_WriteOnly ) ) {
+ if ( ! init_done ) {
+ setOggParameters();
+ vorbis_analysis_init( &vd, &vi );
+ vorbis_block_init( &vd, &vb );
+
+ srand( time( NULL ) );
+ ogg_stream_init( &os, rand() );
+ }
+ if ( _file->size() == 0 ) {
+ ogg_packet header;
+ ogg_packet header_comm;
+ ogg_packet header_code;
+
+ vorbis_comment_init( &vc );
+ vorbis_comment_add_tag ( &vc, const_cast<char *>( "kde-encoder" ),
+ const_cast<char *>( "KRec" ) );
+ if ( write_vorbis_comments ) {
+ QDateTime dt = QDateTime::currentDateTime();
+ vorbis_comment_add_tag ( &vc, const_cast<char *>( "title" ),
+ const_cast<char *>( "" ) );
+ vorbis_comment_add_tag ( &vc, const_cast<char *>( "artist" ),
+ const_cast<char *>( "" ) );
+ vorbis_comment_add_tag ( &vc, const_cast<char *>( "album" ),
+ const_cast<char *>( "" ) );
+ vorbis_comment_add_tag ( &vc, const_cast<char *>( "genre" ),
+ const_cast<char *>( "" ) );
+ vorbis_comment_add_tag ( &vc, const_cast<char *>( "tracknumber" ),
+ const_cast<char *>( "" ) );
+ vorbis_comment_add_tag ( &vc, const_cast<char *>( "date" ),
+ const_cast<char *>( dt.toString( "yyyy-MM-dd hh:mm:ss" ).utf8().data() ) );
+ }
+ vorbis_analysis_headerout( &vd, &vc, &header, &header_comm, &header_code );
+
+ ogg_stream_packetin( &os, &header );
+ ogg_stream_packetin( &os, &header_comm );
+ ogg_stream_packetin( &os, &header_code );
+
+ while ( ogg_stream_flush( &os, &og ) ) {
+ //kdDebug( 60005 ) << "Writing Ogg/Vorbis Header." << endl;
+ _file->writeBlock( reinterpret_cast<char *>( og.header ), og.header_len );
+ _file->writeBlock( reinterpret_cast<char *>( og.body ), og.body_len );
+ }
+ } else
+ _file->at( _file->size() );
+ init_done = true;
+ } else return false;
+ return true;
+ }
+ return false;
+}
+bool KRecExport_OGG::process() {
+ //kdDebug( 60005 ) << k_funcinfo << endl;
+ if ( _file ) {
+ if ( running() ) {
+ QByteArray bytearray( 4096 );
+ emit getData( bytearray );
+ float **buffer = vorbis_analysis_buffer( &vd, bytearray.size() >> 2 );
+
+ // uninterleave samples
+ unsigned int i;
+ int index = 0;
+ int16_t sample;
+ unsigned char *packet = reinterpret_cast<unsigned char *>( bytearray.data() );
+ for ( i = 0; i < ( bytearray.size() >> 2 ); i++ ) {
+ sample = packet[ index ] | ( packet[ index + 1 ] << 8 );
+ index += 2;
+ buffer[ 0 ][ i ] = sample / 32768.0;
+ sample = packet[ index ] | ( packet[ index + 1 ] << 8 );
+ index += 2;
+ buffer[ 1 ][ i ] = sample / 32768.0;
+ }
+
+ vorbis_analysis_wrote( &vd, i );
+
+ while ( vorbis_analysis_blockout( &vd, &vb ) == 1 ) {
+#if HAVE_VORBIS >= 2
+ vorbis_analysis( &vb, NULL );
+ vorbis_bitrate_addblock( &vb );
+ while ( vorbis_bitrate_flushpacket( &vd, &op ) ) {
+#else
+ // Support for very old libvorbis
+ vorbis_analysis( &vb, &op );
+ {
+#endif
+ ogg_stream_packetin( &os, &op );
+ while ( ogg_stream_pageout( &os, &og ) ) {
+ _file->writeBlock( reinterpret_cast<char *>( og.header ), og.header_len );
+ _file->writeBlock( reinterpret_cast<char *>( og.body ), og.body_len );
+ }
+ }
+ }
+ QTimer::singleShot( 10, this, SLOT( process() ) );
+ }
+ return true;
+ } else return false;
+}
+bool KRecExport_OGG::finalize() {
+kdDebug( 60005 ) << k_funcinfo << endl;
+ if ( _file ) {
+ ogg_stream_clear( &os );
+ vorbis_block_clear( &vb );
+ vorbis_dsp_clear( &vd );
+ vorbis_info_clear( &vi );
+
+ _file->close();
+ delete _file;
+ _file = 0;
+
+ return true;
+ } else return false;
+}
+
+
+// Derived from kdemultimedia/kioslave/audiocd/audiocd.cpp.
+// We use the encoding settings from kcmaudiocd.
+void KRecExport_OGG::setOggParameters() {
+kdDebug( 60005 ) << k_funcinfo << endl;
+ KConfig *config;
+ config = new KConfig( "kcmaudiocdrc" );
+
+ config->setGroup( "Vorbis" );
+
+ // 0 for quality, 1 for managed bitrate
+ int vorbis_encode_method = config->readNumEntry( "encmethod", 0 );
+ // default quality level of 3, to match oggenc
+ double vorbis_quality = config->readDoubleNumEntry( "quality",3.0 );
+
+ int vorbis_bitrate_lower = -1;
+ if ( config->readBoolEntry( "set_vorbis_min_bitrate",false ) )
+ vorbis_bitrate_lower = config->readNumEntry( "vorbis_min_bitrate",40 ) * 1000;
+
+ int vorbis_bitrate_upper = -1;
+ if ( config->readBoolEntry( "set_vorbis_max_bitrate",false ) )
+ vorbis_bitrate_upper = config->readNumEntry( "vorbis_max_bitrate",350 ) * 1000;
+
+ // this is such a hack!
+ int vorbis_bitrate;
+ if ( vorbis_bitrate_upper != -1 && vorbis_bitrate_lower != -1 )
+ vorbis_bitrate = 104000; // empirically determined ...?!
+ else
+ vorbis_bitrate = 160 * 1000;
+
+ int vorbis_bitrate_nominal = -1;
+ if ( config->readBoolEntry( "set_vorbis_nominal_bitrate",true ) ) {
+ vorbis_bitrate_nominal = config->readNumEntry( "vorbis_nominal_bitrate",160 ) * 1000;
+ vorbis_bitrate = vorbis_bitrate_nominal;
+ }
+
+ write_vorbis_comments = config->readBoolEntry( "vorbis_comments",true );
+
+ vorbis_info_init( &vi );
+ switch ( vorbis_encode_method ) {
+ case 0:
+ // Support very old libvorbis by simply falling through
+#if HAVE_VORBIS >= 2
+ vorbis_encode_init_vbr( &vi, 2/*this->channels()*/,
+ 44100/*this->samplingRate()*/,
+ vorbis_quality/10.0 );
+ break;
+#endif
+ case 1:
+ vorbis_encode_init( &vi, 2/*this->channels()*/,
+ 44100/*this->samplingRate()*/,
+ vorbis_bitrate_upper, vorbis_bitrate_nominal,
+ vorbis_bitrate_lower );
+ break;
+ }
+
+ delete config;
+}
+
+#endif // vorbis
+
+// vim:sw=4:ts=4