diff --git a/ChangeLog b/ChangeLog index db4b05497a..beee8c39e9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2005-12-19 Tobias Doerffel + * src/widgets/knob.cpp: + made knob ready for drag'n'drop of values + * src/tracks/sample_track.cpp: load and save/load sample-data which doesn't come from sample in/from XML-node (base64-encoded) diff --git a/TODO b/TODO index ad63cfa1cf..776c7467a8 100644 --- a/TODO +++ b/TODO @@ -5,7 +5,6 @@ to be done as soon as possible: - add note-len- and note-alignment-selectbox to piano-roll - fix audio/midi-settings stuff/translation - tooltips for controls in MIDI-tab -- dnd: knob-values - DSSI-support - save/load parameters of VST-plugin - somehow avoid hidden plugin-descriptor-widgets plugin-browser if height of window is too small -> add scrollbar diff --git a/configure.in b/configure.in index eea727eb66..5d36a30adc 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.1-cvs20051218, tobydox/at/users.sourceforge.net) -AM_INIT_AUTOMAKE(lmms, 0.1.1-cvs20051218) +AC_INIT(lmms, 0.1.1-cvs20051219, tobydox/at/users.sourceforge.net) +AM_INIT_AUTOMAKE(lmms, 0.1.1-cvs20051219) AM_CONFIG_HEADER(config.h) @@ -214,6 +214,25 @@ fi AM_CONDITIONAL(HAVE_LIBVORBIS, test ! -z "$OGG_SUPPORT") +# check for libFLAC +AC_ARG_WITH(flac, + AS_HELP_STRING([--without-flac], + [disable support for internal encoding/decoding with FLAC]), , + [ with_flac=yes ]) +AH_TEMPLATE(HAVE_FLAC_STREAM_ENCODER_H, [Define to 1 if you have the header file.]) +AH_TEMPLATE(HAVE_FLAC_STREAM_DECODER_H, [Define to 1 if you have the header file.]) +if test "x$with_flac" = "xyes" ; then + AC_CHECK_HEADER(FLAC/stream_encoder.h, HAVE_FLAC_STREAM_ENCODER_H="true") + AC_CHECK_HEADER(FLAC/stream_decoder.h, HAVE_FLAC_STREAM_DECODER_H="true") + AC_CHECK_LIB([FLAC], [FLAC__stream_encoder_new], HAVE_LIBFLAC="true") +fi +if test ! -z "$HAVE_FLAC_STREAM_ENCODER_H" -a ! -z "$HAVE_FLAC_STREAM_DECODER_H" -a ! -z "$HAVE_LIBFLAC"; then + AC_DEFINE(HAVE_FLAC_STREAM_ENCODER_H) + AC_DEFINE(HAVE_FLAC_STREAM_DECODER_H) +fi +AM_CONDITIONAL(HAVE_LIBFLAC, test ! -z "$HAVE_LIBFLAC") + + # check for libsamplerate AC_ARG_WITH(libsrc, AS_HELP_STRING([--without-libsrc], diff --git a/include/knob.h b/include/knob.h index a3f6216c13..640547edf9 100644 --- a/include/knob.h +++ b/include/knob.h @@ -115,14 +115,16 @@ signals: protected: - virtual void paintEvent( QPaintEvent * _me ); - virtual void resizeEvent( QResizeEvent * _me ); + virtual void contextMenuEvent( QContextMenuEvent * _me ); + virtual void dragEnterEvent( QDragEnterEvent * _dee ); + virtual void dropEvent( QDropEvent * _de ); virtual void mousePressEvent( QMouseEvent * _me ); virtual void mouseReleaseEvent( QMouseEvent * _me ); virtual void mouseMoveEvent( QMouseEvent * _me ); virtual void mouseDoubleClickEvent( QMouseEvent * _me ); + virtual void paintEvent( QPaintEvent * _me ); + virtual void resizeEvent( QResizeEvent * _me ); virtual void wheelEvent( QWheelEvent * _me ); - virtual void contextMenuEvent( QContextMenuEvent * _me ); void drawKnob( QPainter * _p ); void setPosition( const QPoint & _p ); diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index 118709e33c..a8f71cc3f7 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #else diff --git a/src/core/file_browser.cpp b/src/core/file_browser.cpp index a686983066..3619f5443c 100644 --- a/src/core/file_browser.cpp +++ b/src/core/file_browser.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #else diff --git a/src/core/track.cpp b/src/core/track.cpp index ca84f4dc16..11f41c2554 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -226,7 +226,8 @@ void trackContentObject::leaveEvent( QEvent * _e ) void trackContentObject::mousePressEvent( QMouseEvent * _me ) { - if( _me->button() == Qt::LeftButton && lmmsMainWin::isCtrlPressed() ) + if( _me->button() == Qt::LeftButton && + lmmsMainWin::isCtrlPressed() == TRUE ) { multimediaProject mmp( multimediaProject::DRAG_N_DROP_DATA ); saveSettings( mmp, mmp.content() ); diff --git a/src/lib/sample_buffer.cpp b/src/lib/sample_buffer.cpp index 84d39ac16a..d241470d77 100644 --- a/src/lib/sample_buffer.cpp +++ b/src/lib/sample_buffer.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #else @@ -46,6 +47,7 @@ #include #include #include +#include #if QT_VERSION < 0x030100 #include @@ -68,6 +70,14 @@ #include #endif +#ifdef HAVE_FLAC_STREAM_ENCODER_H +#include +#endif + +#ifdef HAVE_FLAC_STREAM_DECODER_H +#include +#endif + #include "sample_buffer.h" #include "interpolation.h" @@ -78,6 +88,16 @@ #include "debug.h" +#ifndef QT4 + +#define write writeBlock +#define read readBlock +#define seek at +#define pos at + +#endif + + sampleBuffer::sampleBuffer( const QString & _audio_file, bool _is_base64_data ) : @@ -379,9 +399,6 @@ Uint32 sampleBuffer::decodeSampleSF( const char * _f, Sint16 * & _buf, // callback-functions for reading ogg-file #ifndef QT4 -#define read readBlock -#define seek at -#define pos at #endif size_t qfileReadCallback( void * _ptr, size_t _size, size_t _n, void * _udata ) @@ -429,9 +446,6 @@ long qfileTellCallback( void * _udata ) return( static_cast( _udata )->pos() ); } -#undef read -#undef seek -#undef pos @@ -951,6 +965,39 @@ QString sampleBuffer::openAudioFile( void ) const } +#undef HAVE_FLAC_STREAM_ENCODER_H /* not yet... */ +#ifdef HAVE_FLAC_STREAM_ENCODER_H +FLAC__StreamEncoderWriteStatus flacStreamEncoderWriteCallback( + const FLAC__StreamEncoder * + /*_encoder*/, + const FLAC__byte _buffer[], + unsigned int/* _samples*/, + unsigned int _bytes, + unsigned int/* _current_frame*/, + void * _client_data ) +{ + if( _bytes == 0 ) + { + return( FLAC__STREAM_ENCODER_WRITE_STATUS_OK ); + } + return( ( static_cast( _client_data )->write( + (const char *) _buffer, _bytes ) == -1 ) ? + FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR : + FLAC__STREAM_ENCODER_WRITE_STATUS_OK ); +} + + +void flacStreamEncoderMetadataCallback( const FLAC__StreamEncoder *, + const FLAC__StreamMetadata * + /* _metadata*/, + void * /*_client_data*/ ) +{ +/* QBuffer * b = static_cast( _client_data ); + b->seek( 0 ); + b->write( (const char *) _metadata, sizeof( *_metadata ) );*/ +} + +#endif QString sampleBuffer::toBase64( void ) const @@ -959,9 +1006,68 @@ QString sampleBuffer::toBase64( void ) const { return( "" ); } +#ifdef HAVE_FLAC_STREAM_ENCODER_H + const Uint32 FRAMES_PER_BUF = 1024; + + FLAC__StreamEncoder * flac_enc = FLAC__stream_encoder_new(); + FLAC__stream_encoder_set_channels( flac_enc, DEFAULT_CHANNELS ); + FLAC__stream_encoder_set_blocksize( flac_enc, FRAMES_PER_BUF ); + FLAC__stream_encoder_set_do_exhaustive_model_search( flac_enc, TRUE ); +// FLAC__stream_encoder_set_do_mid_side_stereo( flac_enc, TRUE ); + FLAC__stream_encoder_set_sample_rate( flac_enc, + mixer::inst()->sampleRate() ); + QBuffer ba_writer; + ba_writer.open( IO_WriteOnly ); + + FLAC__stream_encoder_set_client_data( flac_enc, &ba_writer ); + FLAC__stream_encoder_set_write_callback( flac_enc, + flacStreamEncoderWriteCallback ); + FLAC__stream_encoder_set_metadata_callback( flac_enc, + flacStreamEncoderMetadataCallback ); + FLAC__stream_encoder_init( flac_enc ); + Uint32 frame_cnt = 0; + while( frame_cnt < m_frames ) + { + Uint32 remaining = tMin( FRAMES_PER_BUF, + m_frames - frame_cnt ); + FLAC__int32 buf[FRAMES_PER_BUF * DEFAULT_CHANNELS]; + for( Uint32 f = 0; f < remaining; ++f ) + { + for( Uint8 ch = 0; ch < DEFAULT_CHANNELS; ++ch ) + { + buf[f*DEFAULT_CHANNELS+ch] = (FLAC__int32)( + mixer::clip( m_data[f][ch] ) * + OUTPUT_SAMPLE_MULTIPLIER ); + } + } + FLAC__stream_encoder_process_interleaved( flac_enc, buf, + remaining ); + frame_cnt += remaining; + } + FLAC__stream_encoder_finish( flac_enc ); + FLAC__stream_encoder_delete( flac_enc ); + ba_writer.close(); #ifdef QT4 - return( QByteArray::toBase64( QByteArray( m_data, m_frames ) ) ); + return( QByteArray::toBase64( ba_writer.data() ) ); #else + QByteArray ba = ba_writer.buffer(); + const Uint32 ssize = ba.size(); + const Uint8 * src = (const Uint8 *) ba.data(); +#endif + +#else /* HAVE_FLAC_STREAM_ENCODER_H */ + +#ifdef QT4 + return( QByteArray( (const char *) m_data, m_frames ).toBase64() ); +#else + const Uint32 ssize = m_frames * sizeof( sampleFrame ); + const Uint8 * src = (const Uint8 *) m_data; +#endif + +#endif /* HAVE_FLAC_STREAM_ENCODER_H */ + + +#ifndef QT4 // code mostly taken from // qt-x11-opensource-src-4.0.1/src/corelib/tools/qbytearray.cpp @@ -970,9 +1076,7 @@ QString sampleBuffer::toBase64( void ) const const char padchar = '='; int padlen = 0; - Uint32 ssize = m_frames * sizeof( sampleFrame ); - Uint32 dsize = ( ( ssize * 4 ) / 3 ) + 3; - const Uint8 * src = (const Uint8 *) m_data; + const Uint32 dsize = ( ( ssize * 4 ) / 3 ) + 3; char * ptr = new char[dsize + 1]; char * out = ptr; @@ -1061,7 +1165,7 @@ void sampleBuffer::loadFromBase64( const QString & _data ) m_origFrames = _data.length() * 3 / ( 4 * sizeof( sampleFrame ) ); m_origData = new sampleFrame[m_origFrames]; #ifdef QT4 - QByteArray data = QByteArray::fromBase64( _audio_file.toAscii() ); + QByteArray data = QByteArray::fromBase64( _data.toAscii() ); memcpy( m_origData, data.data(), data.size() ); #else // code mostly taken from @@ -1175,6 +1279,11 @@ void sampleBuffer::deleteResamplingData( void * * _ptr ) } +#undef write +#undef read +#undef seek +#undef pos + #include "sample_buffer.moc" diff --git a/src/lib/string_pair_drag.cpp b/src/lib/string_pair_drag.cpp index 71c1e30805..beb903cc6f 100644 --- a/src/lib/string_pair_drag.cpp +++ b/src/lib/string_pair_drag.cpp @@ -73,7 +73,7 @@ bool stringPairDrag::processDragEnterEvent( QDragEnterEvent * _dee, #ifdef QT4 if( !_dee->mimeData()->hasFormat( "lmms/stringpair" ) ) { - return; + return( FALSE ); } QString txt = _dee->mimeData()->data( "lmms/stringpair" ); if( _allowed_keys.split( ',' ).contains( txt.section( ':', 0, 0 ) ) ) diff --git a/src/tracks/sample_track.cpp b/src/tracks/sample_track.cpp index 3780fbf17c..f018d70a93 100644 --- a/src/tracks/sample_track.cpp +++ b/src/tracks/sample_track.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #else diff --git a/src/widgets/knob.cpp b/src/widgets/knob.cpp index 68523bb308..044a8d60c6 100644 --- a/src/widgets/knob.cpp +++ b/src/widgets/knob.cpp @@ -73,6 +73,7 @@ #include "mixer.h" #include "gui_templates.h" #include "templates.h" +#include "string_pair_drag.h" @@ -112,6 +113,8 @@ knob::knob( int _knob_num, QWidget * _parent, const QString & _name ) : s_textFloat = new textFloat( this ); } + setAcceptDrops( TRUE ); + #ifdef QT4 setAccessibleName( _name ); m_knobPixmap = new QPixmap( embed::getIconPixmap( QString( "knob0" + @@ -294,14 +297,6 @@ void knob::rangeChange() -void knob::resizeEvent( QResizeEvent * ) -{ - layoutKnob( FALSE ); -} - - - - // Recalculate the slider's geometry and layout based on // the current rect and fonts. void knob::layoutKnob( bool _update_geometry ) @@ -316,40 +311,6 @@ void knob::layoutKnob( bool _update_geometry ) -void knob::paintEvent( QPaintEvent * _me ) -{ - QRect ur = _me->rect(); -#ifndef QT4 - if( ur.isValid() ) - { -#endif -#ifdef QT4 - QPainter p( this ); -#else - QPixmap pix( ur.size() ); - pix.fill( this, ur.topLeft() ); - QPainter p( &pix, this ); -#endif - p.translate( -ur.x(), -ur.y() ); - drawKnob( &p ); - if( m_label != "" ) - { - p.setFont( pointSize<6>( p.font() ) ); - p.setPen( QColor( 255, 255, 255 ) ); - p.drawText( width() / 2 - - QFontMetrics( p.font() ).width( m_label ) / 2, - height() - 2, m_label ); - } -#ifndef QT4 - p.end(); - bitBlt( this, ur.topLeft(), &pix ); - } -#endif - -} - - - void knob::recalcAngle( void ) { // @@ -370,10 +331,77 @@ void knob::recalcAngle( void ) +void knob::contextMenuEvent( QContextMenuEvent * ) +{ + // for the case, the user clicked right while pressing left mouse- + // button, the context-menu appears while mouse-cursor is still hidden + // and it isn't shown again until user does something which causes + // an QApplication::restoreOverrideCursor()-call... + mouseReleaseEvent( NULL ); + + QMenu contextMenu( this ); +#ifdef QT4 + contextMenu.setTitle( accessibleName() ); +#else + QLabel * caption = new QLabel( "" + + QString( accessibleName() ) + "", this ); + caption->setPaletteBackgroundColor( QColor( 0, 0, 192 ) ); + caption->setAlignment( Qt::AlignCenter ); + contextMenu.addAction( caption ); +#endif + contextMenu.addAction( embed::getIconPixmap( "reload" ), + tr( "&Reset (%1%2)" ).arg( m_initValue ).arg( + m_hintTextAfterValue ), + this, SLOT( reset() ) ); + contextMenu.addSeparator(); + contextMenu.addAction( embed::getIconPixmap( "edit_copy" ), + tr( "&Copy value (%1%2)" ).arg( value() ).arg( + m_hintTextAfterValue ), + this, SLOT( copyValue() ) ); + contextMenu.addAction( embed::getIconPixmap( "edit_paste" ), + tr( "&Paste value (%1%2)" + ).arg( s_copiedValue ).arg( + m_hintTextAfterValue ), + this, SLOT( pasteValue() ) ); + contextMenu.addSeparator(); + contextMenu.addAction( tr( "Connect to MIDI-device" ), this, + SLOT( connectToMidiDevice() ) ); + contextMenu.addSeparator(); + contextMenu.addAction( embed::getIconPixmap( "help" ), tr( "&Help" ), + this, SLOT( displayHelp() ) ); + contextMenu.exec( QCursor::pos() ); +} + + + + +void knob::dragEnterEvent( QDragEnterEvent * _dee ) +{ + stringPairDrag::processDragEnterEvent( _dee, "float_value" ); +} + + + + +void knob::dropEvent( QDropEvent * _de ) +{ + QString type = stringPairDrag::decodeKey( _de ); + QString value = stringPairDrag::decodeValue( _de ); + if( type == "float_value" ) + { + setValue( value.toFloat() ); + _de->accept(); + } +} + + + + //! Mouse press event handler void knob::mousePressEvent( QMouseEvent * _me ) { - if( _me->button() == Qt::LeftButton ) + if( _me->button() == Qt::LeftButton && + lmmsMainWin::inst()->isCtrlPressed() == FALSE ) { const QPoint & p = _me->pos(); m_origMousePos = p; @@ -399,6 +427,12 @@ void knob::mousePressEvent( QMouseEvent * _me ) s_textFloat->show(); m_buttonPressed = TRUE; } + else if( _me->button() == Qt::LeftButton && + lmmsMainWin::isCtrlPressed() == TRUE ) + { + new stringPairDrag( "float_value", QString::number( value() ), + QPixmap(), this ); + } else if( _me->button() == Qt::MidButton ) { reset(); @@ -463,6 +497,49 @@ void knob::mouseDoubleClickEvent( QMouseEvent * ) +void knob::paintEvent( QPaintEvent * _me ) +{ + QRect ur = _me->rect(); +#ifndef QT4 + if( ur.isValid() ) + { +#endif +#ifdef QT4 + QPainter p( this ); +#else + QPixmap pix( ur.size() ); + pix.fill( this, ur.topLeft() ); + QPainter p( &pix, this ); +#endif + p.translate( -ur.x(), -ur.y() ); + drawKnob( &p ); + if( m_label != "" ) + { + p.setFont( pointSize<6>( p.font() ) ); + p.setPen( QColor( 255, 255, 255 ) ); + p.drawText( width() / 2 - + QFontMetrics( p.font() ).width( m_label ) / 2, + height() - 2, m_label ); + } +#ifndef QT4 + p.end(); + bitBlt( this, ur.topLeft(), &pix ); + } +#endif + +} + + + + +void knob::resizeEvent( QResizeEvent * ) +{ + layoutKnob( FALSE ); +} + + + + //! Qt wheel event void knob::wheelEvent( QWheelEvent * _we ) { @@ -667,50 +744,6 @@ void knob::setStep( float _vstep ) -void knob::contextMenuEvent( QContextMenuEvent * ) -{ - // for the case, the user clicked right while pressing left mouse- - // button, the context-menu appears while mouse-cursor is still hidden - // and it isn't shown again until user does something which causes - // an QApplication::restoreOverrideCursor()-call... - mouseReleaseEvent( NULL ); - - QMenu contextMenu( this ); -#ifdef QT4 - contextMenu.setTitle( accessibleName() ); -#else - QLabel * caption = new QLabel( "" + - QString( accessibleName() ) + "", this ); - caption->setPaletteBackgroundColor( QColor( 0, 0, 192 ) ); - caption->setAlignment( Qt::AlignCenter ); - contextMenu.addAction( caption ); -#endif - contextMenu.addAction( embed::getIconPixmap( "reload" ), - tr( "&Reset (%1%2)" ).arg( m_initValue ).arg( - m_hintTextAfterValue ), - this, SLOT( reset() ) ); - contextMenu.addSeparator(); - contextMenu.addAction( embed::getIconPixmap( "edit_copy" ), - tr( "&Copy value (%1%2)" ).arg( value() ).arg( - m_hintTextAfterValue ), - this, SLOT( copyValue() ) ); - contextMenu.addAction( embed::getIconPixmap( "edit_paste" ), - tr( "&Paste value (%1%2)" - ).arg( s_copiedValue ).arg( - m_hintTextAfterValue ), - this, SLOT( pasteValue() ) ); - contextMenu.addSeparator(); - contextMenu.addAction( tr( "Connect to MIDI-device" ), this, - SLOT( connectToMidiDevice() ) ); - contextMenu.addSeparator(); - contextMenu.addAction( embed::getIconPixmap( "help" ), tr( "&Help" ), - this, SLOT( displayHelp() ) ); - contextMenu.exec( QCursor::pos() ); -} - - - - void knob::reset( void ) { setValue( m_initValue );