You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kaffeine/kaffeine/src/input/disc/plugins/oggvorbis/koggenc.cpp

237 lines
7.1 KiB

/*
* koggenc.cpp
*
* Copyright (C) 2002-2006 Christophe Thommeret <hftom@free.fr>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <tqslider.h>
#include <tdeparts/genericfactory.h>
#include <kiconloader.h>
#include <kpushbutton.h>
#include "koggenc.h"
#include "koggenc.moc"
OggSettings::OggSettings( TQWidget *parent, TDEConfig *confile ) : OggConfig( parent )
{
TDEIconLoader *icon = new TDEIconLoader();
okBtn->setGuiItem( KGuiItem(i18n("OK"), icon->loadIconSet("ok", TDEIcon::Small) ) );
cancelBtn->setGuiItem( KGuiItem(i18n("Cancel"), icon->loadIconSet("cancel", TDEIcon::Small) ) );
delete icon;
Conf = confile;
Conf->setGroup("OggVorbis");
oggSlid->setValue( Conf->readNumEntry( "Quality", 4 ) );
}
OggSettings::~OggSettings()
{
}
void OggSettings::accept()
{
Conf->setGroup("OggVorbis");
Conf->writeEntry( "Quality", oggSlid->value() );
done( Accepted );
}
int OggSettings::getQuality()
{
return oggSlid->value();
}
K_EXPORT_COMPONENT_FACTORY (libkaffeineoggvorbis, KParts::GenericFactory<KOggEnc>)
KOggEnc::KOggEnc( TQWidget*, const char*, TQObject* parent, const char* name, const TQStringList& )
: KaffeineAudioEncoder(parent,name)
{
setInstance(KParts::GenericFactory<KOggEnc>::instance());
encodingQuality = 0.4;
bufEncode = new char[1];
tmpBuf = new char[1];
}
TDEAboutData *KOggEnc::createAboutData()
{
TDEAboutData* aboutData = new TDEAboutData( "kaffeineoggvorbis", I18N_NOOP("KaffeineOggVorbis"),
"0.1", I18N_NOOP("A Ogg Vorbis encoder plugin for Kaffeine."),
TDEAboutData::License_GPL,
"(c) 2006, Christophe Thommeret.", 0 );
aboutData->addAuthor("Christophe Thommeret.",0, "hftom@free.fr");
return aboutData;
}
TQString KOggEnc::getExtension()
{
return TQString(".ogg");
}
bool KOggEnc::options( TQWidget *parent, TDEConfig *conf )
{
OggSettings dlg( parent, conf );
int ret = dlg.exec();
if ( ret!=TQDialog::Accepted )
return false;
encodingQuality = dlg.getQuality()/10.0;
return true;
}
void KOggEnc::start( TQString title, TQString artist, TQString album, TQString tracknumber, TQString genre )
{
char* tag;
vorbis_info_init( &vi );
vorbis_encode_init_vbr( &vi, 2, 44100, encodingQuality );
/* add a comment */
vorbis_comment_init( &vc );
vorbis_comment_add_tag( &vc, "description", "Encoded by Kaffeine" );
//vorbis_comment_add_tag( &vc, "vendor", "KOggEnc (Kilogram)" );
/* set up the analysis state and auxiliary encoding storage */
vorbis_analysis_init( &vd, &vi );
vorbis_block_init( &vd, &vb );
/* set up our packet->stream encoder */
/* pick a random serial number; that way we can more likely build
chained streams just by concatenation */
srand( time(NULL) );
ogg_stream_init( &os, rand() );
if ( !title.isNull() ) {
tag = tqstrdup( title.utf8() );
vorbis_comment_add_tag( &vc, "title", tag );
delete [] tag;
}
if ( !artist.isNull() ) {
tag = tqstrdup( artist.utf8() );
vorbis_comment_add_tag( &vc, "artist", tag );
delete [] tag;
}
if ( !album.isNull() ) {
tag = tqstrdup( album.utf8() );
vorbis_comment_add_tag( &vc, "album", tag );
delete [] tag;
}
if ( !tracknumber.isNull() ) {
tag = tqstrdup( tracknumber.utf8() );
vorbis_comment_add_tag( &vc, "tracknumber", tag );
delete [] tag;
}
if ( !genre.isNull() ) {
tag = tqstrdup( genre.utf8() );
vorbis_comment_add_tag( &vc, "genre", tag );
delete [] tag;
}
}
char* KOggEnc::getHeader( int &len )
{
int buflen=0;
vorbis_analysis_headerout( &vd, &vc, &header, &header_comm, &header_code );
ogg_stream_packetin( &os, &header ); /* automatically placed in its own page */
ogg_stream_packetin( &os, &header_comm );
ogg_stream_packetin( &os, &header_code );
while( ogg_stream_flush( &os, &og ) ){
delete [] bufEncode;
bufEncode = new char[ og.header_len+og.body_len+buflen ];
//memcpy( mempcpy( mempcpy( bufEncode, tmpBuf, buflen ), og.header, og.header_len ), og.body, og.body_len );
memcpy( (char*)memcpy( (char*)memcpy( bufEncode, tmpBuf, buflen )+buflen, og.header, og.header_len )+og.header_len, og.body, og.body_len );
buflen+= og.header_len;
buflen+= og.body_len;
delete [] tmpBuf;
tmpBuf = new char[ buflen ];
memcpy( tmpBuf, bufEncode, buflen );
}
len = buflen;
return bufEncode;
}
char* KOggEnc::encode( char *data, int datalen, int &len )
{
int buflen=0;
int i;
float **buffer=vorbis_analysis_buffer( &vd, datalen/4 );
for( i=0; i<datalen/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;
}
vorbis_analysis_wrote( &vd, i );
while( vorbis_analysis_blockout( &vd, &vb)==1 ) {
vorbis_analysis( &vb, NULL );
vorbis_bitrate_addblock( &vb );
while( vorbis_bitrate_flushpacket( &vd, &op ) ) {
ogg_stream_packetin( &os, &op );
while( ogg_stream_pageout( &os, &og ) ) {
delete [] bufEncode;
bufEncode = new char[ og.header_len+og.body_len+buflen ];
//memcpy( mempcpy( mempcpy( bufEncode, tmpBuf, buflen ), og.header, og.header_len ), og.body, og.body_len );
memcpy( (char*)memcpy( (char*)memcpy( bufEncode, tmpBuf, buflen )+buflen, og.header, og.header_len )+og.header_len, og.body, og.body_len );
buflen+= og.header_len;
buflen+= og.body_len;
delete [] tmpBuf;
tmpBuf = new char[ buflen ];
memcpy( tmpBuf, bufEncode, buflen );
}
}
}
len = buflen;
return bufEncode;
}
char* KOggEnc::stop( int &len )
{
int buflen=0;
vorbis_analysis_wrote( &vd, 0 );
while( vorbis_analysis_blockout( &vd, &vb)==1 ) {
vorbis_analysis( &vb, NULL );
vorbis_bitrate_addblock( &vb );
while( vorbis_bitrate_flushpacket( &vd, &op ) ) {
ogg_stream_packetin( &os, &op );
while( ogg_stream_pageout( &os, &og ) ) {
delete [] bufEncode;
bufEncode = new char[ og.header_len+og.body_len+buflen ];
//memcpy( mempcpy( mempcpy( bufEncode, tmpBuf, buflen ), og.header, og.header_len ), og.body, og.body_len );
memcpy( (char*)memcpy( (char*)memcpy( bufEncode, tmpBuf, buflen )+buflen, og.header, og.header_len )+og.header_len, og.body, og.body_len );
buflen+= og.header_len;
buflen+= og.body_len;
delete [] tmpBuf;
tmpBuf = new char[ buflen ];
memcpy( tmpBuf, bufEncode, buflen );
}
}
}
ogg_stream_clear( &os );
vorbis_block_clear( &vb );
vorbis_dsp_clear( &vd );
vorbis_comment_clear( &vc );
vorbis_info_clear( &vi );
len = buflen;
if ( len>0 )
return bufEncode;
else
return NULL;
}
KOggEnc::~KOggEnc()
{
delete [] bufEncode;
delete [] tmpBuf;
}