drag'n'drop for knobs

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@40 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2005-12-20 11:14:59 +00:00
parent 156ad36850
commit ffb654bc05
11 changed files with 275 additions and 106 deletions

View File

@@ -1,5 +1,8 @@
2005-12-19 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* 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)

1
TODO
View File

@@ -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

View File

@@ -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 <FLAC/stream_encoder.h> header file.])
AH_TEMPLATE(HAVE_FLAC_STREAM_DECODER_H, [Define to 1 if you have the <FLAC/stream_decoder.h> 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],

View File

@@ -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 );

View File

@@ -32,6 +32,7 @@
#include <QBitmap>
#include <Qt/QtXml>
#include <QFileInfo>
#include <QDropEvent>
#else

View File

@@ -31,6 +31,7 @@
#include <QPushButton>
#include <QKeyEvent>
#include <QMenu>
#include <Q3Header>
#else

View File

@@ -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() );

View File

@@ -37,6 +37,7 @@
#include <QFileDialog>
#include <QFileInfo>
#include <QFile>
#include <QBuffer>
#else
@@ -46,6 +47,7 @@
#include <qfiledialog.h>
#include <qfileinfo.h>
#include <qfile.h>
#include <qbuffer.h>
#if QT_VERSION < 0x030100
#include <qregexp.h>
@@ -68,6 +70,14 @@
#include <vorbis/vorbisfile.h>
#endif
#ifdef HAVE_FLAC_STREAM_ENCODER_H
#include <FLAC/stream_encoder.h>
#endif
#ifdef HAVE_FLAC_STREAM_DECODER_H
#include <FLAC/stream_decoder.h>
#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<QFile *>( _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<QBuffer *>( _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<QBuffer *>( _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<Uint32>( 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"

View File

@@ -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 ) ) )

View File

@@ -31,6 +31,7 @@
#include <QPushButton>
#include <QPainter>
#include <Qt/QtXml>
#include <QDropEvent>
#else

View File

@@ -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( "<font color=white><b>" +
QString( accessibleName() ) + "</b></font>", 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( "<font color=white><b>" +
QString( accessibleName() ) + "</b></font>", 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 );