From 3541af29df5bc48e2443588334e45961fba7fc53 Mon Sep 17 00:00:00 2001 From: Paul Giblock Date: Fri, 4 Apr 2008 06:39:00 +0000 Subject: [PATCH] initial controllers code git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@883 0778d3d1-df1d-0410-868b-ea421aaaa00d --- ChangeLog | 29 ++++++ Makefile.am | 3 + data/themes/Makefile.am | 5 +- data/themes/llama/background_artwork.png | Bin 0 -> 678 bytes include/automatable_model.h | 59 +++++++++++- include/automatable_model_templates.h | 1 + include/controller.h | 96 ++++++++++++++++++++ include/knob.h | 1 + src/core/controller.cpp | 110 +++++++++++++++++++++++ src/core/mixer.cpp | 1 + src/gui/widgets/knob.cpp | 13 ++- src/tracks/pattern.cpp | 4 +- 12 files changed, 315 insertions(+), 7 deletions(-) create mode 100644 data/themes/llama/background_artwork.png create mode 100644 include/controller.h create mode 100644 src/core/controller.cpp diff --git a/ChangeLog b/ChangeLog index c589e59793..d133fb4b47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2008-04-04 Paul Giblock + + * include/controller.h: + * src/core/controller.cpp: + * Makefile.am: + Add controller class to LMMS + + * include/knob.h: + * src/gui/widgets/knob.cpp: + Add Connect to Controller item to context menu for future dialog + + * include/automatable_model.h: + * include/automatable_model_templates.h: + - add controller pointer to class + - add value(int offset) function for sample-exact value fetching + - use controller in value() if set + + * src/tracks/pattern.cpp: + Change brightness of note volume-lines according to volume + + * src/core/mixer.cpp: + trigger controller's frame counter + + * data/themes/llama/background_artwork.png: + * data/themes/llama: + * data/themes/Makefile.am: + start a theme with my preferences + + 2008-04-03 Tobias Doerffel * include/song.h: diff --git a/Makefile.am b/Makefile.am index 10833bd6e6..dfbde9d0d4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -59,6 +59,7 @@ lmms_MOC = \ ./instrument_track.moc \ ./combobox.moc \ ./config_mgr.moc \ + ./controller.moc \ ./cpuload_widget.moc \ ./effect_control_dialog.moc \ ./effect_label.moc \ @@ -156,6 +157,7 @@ lmms_SOURCES = \ $(srcdir)/src/core/bb_track_container.cpp \ $(srcdir)/src/core/clipboard.cpp \ $(srcdir)/src/core/config_mgr.cpp \ + $(srcdir)/src/core/controller.cpp \ $(srcdir)/src/core/drumsynth.cpp \ $(srcdir)/src/core/effect_chain.cpp \ $(srcdir)/src/core/effect.cpp \ @@ -419,6 +421,7 @@ lmms_SOURCES = \ $(srcdir)/include/ladspa_control.h \ $(srcdir)/include/ladspa_control_view.h \ $(srcdir)/include/ladspa_base.h \ + $(srcdir)/include/controller.h \ $(THIRD_PARTY_CODE) diff --git a/data/themes/Makefile.am b/data/themes/Makefile.am index b00175d881..0d0a120edc 100644 --- a/data/themes/Makefile.am +++ b/data/themes/Makefile.am @@ -7,6 +7,9 @@ theme_blue_scene_DATA = blue_scene/*.png plugin_theme_blue_scenedir = $(lmmsdatadir)/themes/blue_scene/plugins plugin_theme_blue_scene_DATA = blue_scene/plugins/*.png +theme_llamadir = $(lmmsdatadir)/themes/llama +theme_llama_DATA = llama/*.png -EXTRA_DIST = $(theme_default_DATA) $(theme_blue_scene_DATA) $(plugin_theme_blue_scene_DATA) + +EXTRA_DIST = $(theme_default_DATA) $(theme_blue_scene_DATA) $(plugin_theme_blue_scene_DATA) $(theme_llama_DATA) diff --git a/data/themes/llama/background_artwork.png b/data/themes/llama/background_artwork.png new file mode 100644 index 0000000000000000000000000000000000000000..4aed538d7fc3a74a8c60dc26276f4c51c7909d27 GIT binary patch literal 678 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Y)RhkE%y{W;-5;PJdx@v7EBg%=7A840-^tmQ3=B-ho-U3d6}RrrzS!Ghz~hpbwLqb3 z!GEq7jlZ3eCeAHncs(aFvwl;>V->%&FAbHk*OO;0%Z!}%^4HDpwY#=Q=cex#&##^L z?dt5{Cs7rg^TlItuiaMsA+Dz6!?n_hjr-2l+i5>I`6}Y=TET7Px_bo;9G zO{NRNYEo`TOue%CZPe6^r}<$HTSBVq(@%c?cJ=rFdtrwst3;)i)$Qd|KDlw9(#MOe zh3W@pZ#^NGJ+=6~;y1N@OI=Es-f2tPChSp(IvKsZIPA|~`vc$hn@_&?@>OiMuiWGn z+5h8@&9+;x%CCC)_i($X?yOp`zDSEpe$-sC?($8$)O*|Bu2^$<@6-#wtyjG++2-$9 zI``Z+h#c$HQmfm`YYs8HJ>#_33J6@jxsnO2hVysB|4T1(<~6*sn)^05Aa?oYS}r8b z0nh)PS$^i)Tt(G)=fyZ)-LXHz9J14XHOq?P`fVJE8dh50(hp~VbjflYlDyx`p5nf^1k=UM}edddhC|I|<#%byB#2#E9b>#JJE h*5@1x&;5=3SHF8@&jr8!wG%+e&C}J-Wt~$(69AK=N`e3Y literal 0 HcmV?d00001 diff --git a/include/automatable_model.h b/include/automatable_model.h index 81b69363fa..f8a03acbee 100644 --- a/include/automatable_model.h +++ b/include/automatable_model.h @@ -31,8 +31,10 @@ #include "journalling_object.h" #include "level_object.h" #include "mv_base.h" +#include "controller.h" #include +#include @@ -102,11 +104,54 @@ public: return( static_cast( _v ) ); } - inline virtual T value( void ) const + inline virtual T value( void ) const + { + return value( 0 ); + } + + + inline virtual T value( int _frameOffset ) const { - return( m_value ); + T val; + if( m_controller != NULL ) + { + val = minValue() + + ( maxValue() - minValue() ) * + castValue( m_controller->currentValue( _frameOffset ) ); + + // New framebuffer, emit signal for all the signal based users + if( _frameOffset == 0 && val != m_value ) + { + // Sort of a hack, but this really is our intention + // + // Any model that wants sample-exactness must operate without relying + // on the dataChanged signal. This is primarily for updating the GUI + + //autoModel * that = const_cast( this ); + //emit that->dataChanged(); + } + } + else + { + val = m_value; + } + + return val; } + inline controller * getController( void ) const + { + return m_controller; + } + + inline void setController( controller * _c ) + { + m_controller = _c; + QObject::connect( m_controller, SIGNAL( valueChanged() ), + this, SIGNAL( dataChanged() ) ); + } + + inline virtual T initValue( void ) const { return( m_initValue ); @@ -200,12 +245,14 @@ protected: private: + controller * m_controller; T m_value; T m_initValue; T m_minValue; T m_maxValue; T m_step; int m_curLevel; + QPointer m_automationPattern; track * m_track; @@ -240,6 +287,14 @@ private: { return( level( attributeValue( _label ) ) ); } +/* +public slots: + + void changeData( void ) + { + emit dataChanged(); + } +*/ } ; diff --git a/include/automatable_model_templates.h b/include/automatable_model_templates.h index deafc969a8..3eef5a7dd8 100644 --- a/include/automatable_model_templates.h +++ b/include/automatable_model_templates.h @@ -45,6 +45,7 @@ automatableModel::automatableModel( ::model * _parent, bool _default_constructed ) : model( _parent, _default_constructed ), + m_controller( NULL ), m_value( _val ), m_initValue( _val ), m_minValue( _min ), diff --git a/include/controller.h b/include/controller.h new file mode 100644 index 0000000000..cb0098df45 --- /dev/null +++ b/include/controller.h @@ -0,0 +1,96 @@ +/* + * controller.h - declaration of class controller, which provides a + * standard for all controllers and controller plugins + * + * Copyright (c) 2008 Paul Giblock + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef _CONTROLLER_H +#define _CONTROLLER_H + +#include +#include + +#include "engine.h" +#include "mixer.h" + + +class controller : public QObject +{ + Q_OBJECT +public: + controller( void ); + + virtual ~controller(); + + virtual float currentValue( int _offset ); + + inline bool isSampleExact( void ) const + { + return m_sampleExact || engine::getMixer()->highQuality(); + } + + void setSampleExact( bool _exact ) + { + m_sampleExact = _exact; + } + + + static int runningFrames(); + static float runningTime(); + + static void triggerFrameCounter( void ); + static void resetFrameCounter( void ); + +private: + +protected: + + // The internal per-controller get-value function + virtual float value( int _offset ); + + float m_currentValue; + bool m_sampleExact; + + + static QVector s_controllers; + + static unsigned int s_frames; + + /* + + QString publicName(); +slots: + void trigger(); + + */ +signals: + // The value changed while the mixer isn't running (i.e: MIDI CC) + void valueChanged( void ); + + // Allow all attached models to unlink + void destroying( void ); + +}; + +#endif + diff --git a/include/knob.h b/include/knob.h index d075698e8d..9d6850533c 100644 --- a/include/knob.h +++ b/include/knob.h @@ -68,6 +68,7 @@ public slots: void pasteValue( void ); virtual void enterValue( void ); void connectToMidiDevice( void ); + void connectToController( void ); void displayHelp( void ); diff --git a/src/core/controller.cpp b/src/core/controller.cpp new file mode 100644 index 0000000000..44631c259c --- /dev/null +++ b/src/core/controller.cpp @@ -0,0 +1,110 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * controller.cpp - implementation of class controller which handles remote-control + * of automatableModels + * + * Copyright (c) 2008 Paul Giblock + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include + + +#include "song.h" +#include "engine.h" +#include "mixer.h" +#include "controller.h" + +unsigned int controller::s_frames = 0; +QVector controller::s_controllers; + +controller::controller( void ) +{ + s_controllers.append( this ); +} + + +controller::~controller() +{ + s_controllers.remove( s_controllers.indexOf( this ) ); + +} + + +// Get current value, with an offset into the current buffer for sample exactness +float controller::currentValue( int _offset ) +{ + if( _offset == 0 || isSampleExact() ) + { + m_currentValue = value( _offset ); + } + + return m_currentValue; +} + + +float controller::value( int _offset ) +{ + // 44100 frames/sec + return 0.5 + sinf((float)(runningFrames()) / 44100.0f) / 2; +} + + + +// Get position in frames +int controller::runningFrames() +{ + return s_frames; +} + +// Get position in seconds +float controller::runningTime() +{ + return s_frames / + engine::getMixer()->sampleRate() ; +} + + +void controller::triggerFrameCounter( void ) +{ + for( int i = 0; i < s_controllers.size(); ++i ) + { + emit s_controllers.at(i)->valueChanged(); + } + + s_frames += engine::getMixer()->framesPerPeriod(); + //emit s_signaler.triggerValueChanged(); +} + +void controller::resetFrameCounter( void ) +{ + s_frames = 0; +} + + + +#include "controller.moc" + + +#endif diff --git a/src/core/mixer.cpp b/src/core/mixer.cpp index 48ecc31d0e..8a618bcaeb 100644 --- a/src/core/mixer.cpp +++ b/src/core/mixer.cpp @@ -540,6 +540,7 @@ if( COND_NPH ) // and trigger LFOs envelopeAndLFOParameters::triggerLFO(); + controller::triggerFrameCounter(); const float new_cpu_load = timer.elapsed() / 10000.0f * sampleRate() / m_framesPerPeriod; diff --git a/src/gui/widgets/knob.cpp b/src/gui/widgets/knob.cpp index d2a43fdf83..8e3db12555 100644 --- a/src/gui/widgets/knob.cpp +++ b/src/gui/widgets/knob.cpp @@ -287,8 +287,8 @@ void knob::contextMenuEvent( QContextMenuEvent * ) SLOT( openInAutomationEditor() ) ); contextMenu.addSeparator(); } -/* contextMenu.addAction( tr( "Connect to MIDI-device" ), this, - SLOT( connectToMidiDevice() ) );*/ + contextMenu.addAction( tr( "Connect to controller..." ), this, + SLOT( connectToController() ) ); contextMenu.addSeparator(); contextMenu.addAction( embed::getIconPixmap( "help" ), tr( "&Help" ), this, SLOT( displayHelp() ) ); @@ -575,6 +575,15 @@ void knob::connectToMidiDevice( void ) } +void knob::connectToController( void ) +{ + // TODO[pg]: Display a dialog with list of controllers currently in the song + // in addition to any system MIDI controllers + + controller * c = new controller(); + + model()->setController( c ); +} void knob::displayHelp( void ) diff --git a/src/tracks/pattern.cpp b/src/tracks/pattern.cpp index d32eda4ffa..82331e3a16 100644 --- a/src/tracks/pattern.cpp +++ b/src/tracks/pattern.cpp @@ -1152,8 +1152,8 @@ void patternView::paintEvent( QPaintEvent * ) { Sint16 x1 = 2 * x_base + static_cast( ( *it )->pos() * ppt / 64 ); - Sint16 x2 = x1 + - static_cast( ( *it )->length() * ppt / 64 ); + Sint16 x2 = + static_cast( ( ( *it )->pos() + ( *it )->length() ) * ppt / 64 ); p.drawLine( x1, y_base + y_pos, x2, y_base + y_pos );