From ae7034653e8080bdb1bd632463ea6fdec63806ff Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 24 Jan 2006 09:09:56 +0000 Subject: [PATCH] added base64-support functions git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@64 0778d3d1-df1d-0410-868b-ea421aaaa00d --- ChangeLog | 29 ++- Makefile.am | 2 + configure.in | 4 +- include/base64.h | 60 ++++++ include/sample_buffer.h | 4 +- .../audio_file_processor.cpp | 3 +- src/lib/base64.cpp | 167 ++++++++++++++++ src/lib/sample_buffer.cpp | 182 ++++-------------- src/tracks/pattern.cpp | 7 +- src/tracks/sample_track.cpp | 3 +- 10 files changed, 296 insertions(+), 165 deletions(-) create mode 100644 include/base64.h create mode 100644 src/lib/base64.cpp diff --git a/ChangeLog b/ChangeLog index 2bab3cf62e..e6801f5587 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,14 +1,25 @@ +2006-01-23 Tobias Doerffel + + * include/sample_buffer.h: + * src/lib/sample_buffer.cpp: + * plugins/audio_file_processor/audio_file_processor.cpp: + use new base64-code + + * include/base64.h: + * src/lib/base64.cpp: + added methods for encoding/decoding binary data to/from base64-encoded + data (wrapper-implementation for Qt4) + 2006-01-23 Andreas Brandmaier - * plugins/bit_invader/bit_invader.cpp - * plugins/bit_invader/bit_invader.h - * plugins/bit_invader/graph.cpp - * plugins/bit_invader/graph.h - improved mouse handling. - replaced waveform generation methods by those - of toby's oscillator class. - added user-loadable waveform - code cleanup + * plugins/bit_invader/bit_invader.cpp: + * plugins/bit_invader/bit_invader.h: + * plugins/bit_invader/graph.cpp: + * plugins/bit_invader/graph.h: + - improved mouse handling. + - replaced waveform generation methods by those of toby's oscillator class + - added user-loadable waveform + - code cleanup 2006-01-22 Tobias Doerffel diff --git a/Makefile.am b/Makefile.am index cec44258d6..e8a27b2544 100644 --- a/Makefile.am +++ b/Makefile.am @@ -143,6 +143,7 @@ lmms_SOURCES = \ $(srcdir)/src/core/track_container.cpp \ $(srcdir)/src/core/surround_area.cpp \ $(srcdir)/src/core/timeline.cpp \ + $(srcdir)/src/lib/base64.cpp \ $(srcdir)/src/lib/buffer_allocator.cpp \ $(srcdir)/src/lib/clipboard.cpp \ $(srcdir)/src/lib/embed.cpp \ @@ -289,6 +290,7 @@ lmms_SOURCES = \ $(srcdir)/include/fade_button.h \ $(srcdir)/include/combobox.h \ $(srcdir)/include/rubberband.h \ + $(srcdir)/include/base64.h \ $(srcdir)/include/qxembed.h diff --git a/configure.in b/configure.in index 6e6224aa99..33e6852bab 100644 --- a/configure.in +++ b/configure.in @@ -2,8 +2,8 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) -AC_INIT(lmms, 0.1.2-cvs20060122, tobydox/at/users.sourceforge.net) -AM_INIT_AUTOMAKE(lmms, 0.1.2-cvs20060122) +AC_INIT(lmms, 0.1.2-cvs20060123, tobydox/at/users/dot/sourceforge/dot/net) +AM_INIT_AUTOMAKE(lmms, 0.1.2-cvs20060123) AM_CONFIG_HEADER(config.h) diff --git a/include/base64.h b/include/base64.h new file mode 100644 index 0000000000..7ef7e7e6eb --- /dev/null +++ b/include/base64.h @@ -0,0 +1,60 @@ +/* + * base64.h - namespace base64 with methods for encoding/decoding binary data + * to/from base64 + * + * Copyright (c) 2006 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _BASE64_H +#define _BASE64_H + +#include "qt3support.h" + +#ifndef QT3 + +#include + +#endif + + +namespace base64 +{ +#ifndef QT3 + inline encode( const char * _data, const int _size, QString & _dst ) + { + _dst = QByteArray( _data, _size ).toBase64(); + } + + inline void decode( const QString & _b64, char * * _data, int * _size ) + { + QByteArray data = QByteArray::fromBase64( _b64.toAscii() ); + *_size = data.size(); + *_data = new char[*_size]; + memcpy( _data, data.constData(), *_size ); + } +#else + void encode( const char * _data, const int _size, QString & _dst ); + void decode( const QString & _b64, char * * _data, int * _size ); +#endif +} ; + +#endif diff --git a/include/sample_buffer.h b/include/sample_buffer.h index 49558cb3bc..f9154bd2b2 100644 --- a/include/sample_buffer.h +++ b/include/sample_buffer.h @@ -1,7 +1,7 @@ /* * sample_buffer.h - container-class sampleBuffer * - * Copyright (c) 2005 Tobias Doerffel + * Copyright (c) 2005-2006 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -124,7 +124,7 @@ public: QString openAudioFile( void ) const; - QString toBase64( void ) const; + QString & toBase64( QString & _dst ) const; static sampleBuffer * FASTCALL resample( sampleFrame * _data, diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index fdbca57228..857e4793b3 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -296,7 +296,8 @@ void audioFileProcessor::saveSettings( QDomDocument & _doc, afp_de.setAttribute( "src", m_sampleBuffer.audioFile() ); if( m_sampleBuffer.audioFile() == "" ) { - afp_de.setAttribute( "sampledata", m_sampleBuffer.toBase64() ); + QString s; + afp_de.setAttribute( "sampledata", m_sampleBuffer.toBase64( s ) ); } afp_de.setAttribute( "sframe", QString::number( m_sampleBuffer.startFrame() / diff --git a/src/lib/base64.cpp b/src/lib/base64.cpp new file mode 100644 index 0000000000..dd658c260a --- /dev/null +++ b/src/lib/base64.cpp @@ -0,0 +1,167 @@ +/* + * base64.cpp - namespace base64 with methods for encoding/decoding binary data + * to/from base64 + * + * Copyright (c) 2006 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + + +#include "base64.h" +#include "types.h" + + +#ifdef QT3 + +namespace base64 +{ + + +void encode( const char * _data, const int _size, QString & _dst ) +{ + // code mostly taken from + // qt-x11-opensource-src-4.0.1/src/corelib/tools/qbytearray.cpp + + const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" + "ghijklmn" "opqrstuv" "wxyz0123" "456789+/"; + const char padchar = '='; + int padlen = 0; + + const int dsize = ( ( _size * 4 ) / 3 ) + 3; + char * ptr = new char[dsize + 1]; + char * out = ptr; + + int i = 0; + while( i < _size ) + { + Uint32 chunk = 0; + chunk |= Uint32( Uint8( _data[i++] ) ) << 16; + if( i == dsize ) + { + padlen = 2; + } + else + { + chunk |= Uint32( Uint8( _data[i++] ) ) << 8; + if( i == _size ) + { + padlen = 1; + } + else + { + chunk |= Uint32( Uint8( _data[i++] ) ); + } + } + + Uint32 j = ( chunk & 0x00fc0000 ) >> 18; + Uint32 k = ( chunk & 0x0003f000 ) >> 12; + Uint32 l = ( chunk & 0x00000fc0 ) >> 6; + Uint32 m = ( chunk & 0x0000003f ); + *out++ = alphabet[j]; + *out++ = alphabet[k]; + if( padlen > 1 ) + { + *out++ = padchar; + } + else + { + *out++ = alphabet[l]; + } + if( padlen > 0 ) + { + *out++ = padchar; + } + else + { + *out++ = alphabet[m]; + } + } + + // terminate string + ptr[out - ptr] = 0; + _dst = ptr; + delete[] ptr; +} + + + +void decode( const QString & _b64, char * * _data, int * _size ) +{ + const char * src = _b64.ascii(); + const csize ssize = _b64.length(); + const csize dsize = *_size = ( ssize * 3 ) / 4; + *_data = new char[dsize]; + + // code mostly taken from + // qt-x11-opensource-src-4.0.1/src/corelib/tools/qbytearray.cpp + unsigned int buf = 0; + int nbits = 0; + int offset = 0; + + for( csize i = 0; i < ssize; ++i ) + { + int ch = src[i]; + int d; + + if( ch >= 'A' && ch <= 'Z' ) + { + d = ch - 'A'; + } + else if( ch >= 'a' && ch <= 'z' ) + { + d = ch - 'a' + 26; + } + else if( ch >= '0' && ch <= '9' ) + { + d = ch - '0' + 52; + } + else if( ch == '+' ) + { + d = 62; + } + else if( ch == '/' ) + { + d = 63; + } + else + { + d = -1; + } + + if( d != -1 ) + { + buf = ( buf << 6 ) | (Uint32)d; + nbits += 6; + if( nbits >= 8 ) + { + nbits -= 8; + ( *_data )[offset++] = buf >> nbits; + buf &= ( 1 << nbits ) - 1; + } + } + } +} + + +} ; + +#endif + diff --git a/src/lib/sample_buffer.cpp b/src/lib/sample_buffer.cpp index 5fb3ede856..075595cc60 100644 --- a/src/lib/sample_buffer.cpp +++ b/src/lib/sample_buffer.cpp @@ -85,6 +85,7 @@ #include "templates.h" #include "config_mgr.h" #include "endian_handling.h" +#include "base64.h" #include "debug.h" @@ -1067,14 +1068,14 @@ void flacStreamEncoderMetadataCallback( const FLAC__StreamEncoder *, #endif -QString sampleBuffer::toBase64( void ) const + +QString & sampleBuffer::toBase64( QString & _dst ) const { if( m_data == NULL || m_frames == 0 ) { - return( "" ); + return( _dst = "" ); } - // the following code is quite confusing as we have to handle four - // different configs (no flac/qt3, no flac/qt4, flac/qt3, flac/qt4) + #ifdef HAVE_FLAC_STREAM_ENCODER_H const Uint32 FRAMES_PER_BUF = 1152; @@ -1124,91 +1125,19 @@ QString sampleBuffer::toBase64( void ) const FLAC__stream_encoder_delete( flac_enc ); printf("%d %d\n", frame_cnt, (int)ba_writer.size() ); ba_writer.close(); -#ifdef QT4 - return( ba_writer.data().toBase64() ); -#else - QByteArray ba = ba_writer.buffer(); - const Uint32 ssize = ba.size(); - const Uint8 * src = (const Uint8 *) ba.data(); -#endif + + base64::encode( ba_writer.buffer().data(), ba_writer.buffer().size(), + _dst ); + #else /* HAVE_FLAC_STREAM_ENCODER_H */ -#ifdef QT4 - return( QByteArray( (const char *) m_data, m_frames * - sizeof( sampleFrame ) ).toBase64() ); -#else - const Uint32 ssize = m_frames * sizeof( sampleFrame ); - const Uint8 * src = (const Uint8 *) m_data; -#endif + base64::encode( (const char *) m_data, + m_frames * sizeof( sampleFrame ), _dst ); #endif /* HAVE_FLAC_STREAM_ENCODER_H */ - -#ifndef QT4 - // code mostly taken from - // qt-x11-opensource-src-4.0.1/src/corelib/tools/qbytearray.cpp - - const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" - "ghijklmn" "opqrstuv" "wxyz0123" "456789+/"; - const char padchar = '='; - int padlen = 0; - - const Uint32 dsize = ( ( ssize * 4 ) / 3 ) + 3; - char * ptr = new char[dsize + 1]; - char * out = ptr; - - Uint32 i = 0; - while( i < ssize ) - { - Uint32 chunk = 0; - chunk |= Uint32( src[i++] ) << 16; - if( i == dsize ) - { - padlen = 2; - } - else - { - chunk |= Uint32( src[i++] ) << 8; - if( i == ssize ) - { - padlen = 1; - } - else - { - chunk |= Uint32( src[i++] ); - } - } - - Uint32 j = ( chunk & 0x00fc0000 ) >> 18; - Uint32 k = ( chunk & 0x0003f000 ) >> 12; - Uint32 l = ( chunk & 0x00000fc0 ) >> 6; - Uint32 m = ( chunk & 0x0000003f ); - *out++ = alphabet[j]; - *out++ = alphabet[k]; - if( padlen > 1 ) - { - *out++ = padchar; - } - else - { - *out++ = alphabet[l]; - } - if( padlen > 0 ) - { - *out++ = padchar; - } - else - { - *out++ = alphabet[m]; - } - } - // terminate string - ptr[out - ptr] = 0; - QString s( ptr ); - delete[] ptr; - return( s ); -#endif + return( _dst ); } @@ -1393,71 +1322,19 @@ void flacStreamDecoderErrorCallback( const FLAC__StreamDecoder *, void sampleBuffer::loadFromBase64( const QString & _data ) { -#ifdef QT4 - QByteArray orig_data = QByteArray::fromBase64( _data.toAscii() ); -#else - const char * src = _data.ascii(); - csize ssize = _data.length(); - csize dsize = ( _data.length() * 3 ) / 4; - char * dst = new char[dsize]; + char * dst = NULL; + int dsize = 0; + base64::decode( _data, &dst, &dsize ); - // code mostly taken from - // qt-x11-opensource-src-4.0.1/src/corelib/tools/qbytearray.cpp - unsigned int buf = 0; - int nbits = 0; - int offset = 0; - - for( csize i = 0; i < ssize; ++i ) - { - int ch = src[i]; - int d; - - if( ch >= 'A' && ch <= 'Z' ) - { - d = ch - 'A'; - } - else if( ch >= 'a' && ch <= 'z' ) - { - d = ch - 'a' + 26; - } - else if( ch >= '0' && ch <= '9' ) - { - d = ch - '0' + 52; - } - else if( ch == '+' ) - { - d = 62; - } - else if( ch == '/' ) - { - d = 63; - } - else - { - d = -1; - } - - if( d != -1 ) - { - buf = ( buf << 6 ) | (Uint32)d; - nbits += 6; - if( nbits >= 8 ) - { - nbits -= 8; - dst[offset++] = buf >> nbits; - buf &= ( 1 << nbits ) - 1; - } - } - } - QByteArray orig_data; - orig_data.setRawData( dst, dsize ); -#endif #ifdef HAVE_FLAC_STREAM_DECODER_H -#ifdef QT4 +#ifndef QT3 + QByteArray orig_data = QByteArray::fromRawData( dst, dsize ); QBuffer ba_reader( &orig_data ); ba_reader.open( QBuffer::ReadOnly ); #else + QByteArray orig_data; + orig_data.setRawData( dst, dsize ); QBuffer ba_reader( orig_data ); ba_reader.open( IO_ReadOnly ); #endif @@ -1490,18 +1367,31 @@ void sampleBuffer::loadFromBase64( const QString & _data ) FLAC__stream_decoder_finish( flac_dec ); FLAC__stream_decoder_delete( flac_dec ); + ba_reader.close(); + orig_data = ba_writer.buffer(); printf("%d\n", (int) orig_data.size() ); -#endif + m_origFrames = orig_data.size() / sizeof( sampleFrame ); delete[] m_origData; m_origData = new sampleFrame[m_origFrames]; memcpy( m_origData, orig_data.data(), orig_data.size() ); + +#else /* HAVE_FLAC_STREAM_DECODER_H */ + + m_origFrames = dsize / sizeof( sampleFrame ); + delete[] m_origData; + m_origData = new sampleFrame[m_origFrames]; + memcpy( m_origData, dst, dsize ); + +#endif + +#ifndef QT3 + delete[] dst; +#endif + m_audioFile = ""; update(); -#ifndef QT4 -// delete[] dst; -#endif } diff --git a/src/tracks/pattern.cpp b/src/tracks/pattern.cpp index aa82e1f1b6..bca93bee15 100644 --- a/src/tracks/pattern.cpp +++ b/src/tracks/pattern.cpp @@ -803,10 +803,9 @@ void pattern::mousePressEvent( QMouseEvent * _me ) else if( m_frozenPattern != NULL && _me->button() == Qt::LeftButton && lmmsMainWin::isShiftPressed() == TRUE ) { - new stringPairDrag( "sampledata", - m_frozenPattern->toBase64(), - embed::getIconPixmap( "freeze" ), - this ); + QString s; + new stringPairDrag( "sampledata", m_frozenPattern->toBase64( s ), + embed::getIconPixmap( "freeze" ), this ); } else { diff --git a/src/tracks/sample_track.cpp b/src/tracks/sample_track.cpp index c1785a5325..ca57c9b28c 100644 --- a/src/tracks/sample_track.cpp +++ b/src/tracks/sample_track.cpp @@ -263,7 +263,8 @@ void FASTCALL sampleTCO::saveSettings( QDomDocument & _doc, sampletco_de.setAttribute( "src", sampleFile() ); if( sampleFile() == "" ) { - sampletco_de.setAttribute( "data", m_sampleBuffer.toBase64() ); + QString s; + sampletco_de.setAttribute( "data", m_sampleBuffer.toBase64( s ) ); } // TODO: start- and end-frame _parent.appendChild( sampletco_de );