2008-06-02 21:41:35 +00:00
/*
2015-10-04 14:51:05 -04:00
Copyright ( C ) 2000 - 2007 Paul Davis
2008-06-02 21:41:35 +00:00
This program is free software ; you can redistribute it and / or modify
2011-03-30 12:36:53 +00:00
it under the terms of the GNU General Public License as published by
2008-06-02 21:41:35 +00:00
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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# ifndef __pbd_controllable_h__
# define __pbd_controllable_h__
# include <string>
# include <set>
2009-12-11 03:18:17 +00:00
# include <map>
2008-06-02 21:41:35 +00:00
2013-10-16 23:30:28 -04:00
# include "pbd/libpbd_visibility.h"
2009-12-19 20:26:31 +00:00
# include "pbd/signals.h"
2012-07-25 17:48:55 +00:00
# include <glibmm/threads.h>
2008-06-02 21:41:35 +00:00
2009-02-25 18:26:51 +00:00
# include "pbd/statefuldestructible.h"
2008-06-02 21:41:35 +00:00
2014-07-27 11:28:23 +01:00
using std : : min ;
using std : : max ;
2008-06-02 21:41:35 +00:00
class XMLNode ;
namespace PBD {
2016-04-12 17:03:44 +02:00
/** This is a pure virtual class to represent a scalar control.
2015-10-21 22:30:13 -04:00
*
* Note that it contains no storage / state for the controllable thing that it
* represents . Derived classes must provide set_value ( ) / get_value ( ) methods ,
* which will involve ( somehow ) an actual location to store the value .
*
* In essence , this is an interface , not a class .
*
* Without overriding upper ( ) and lower ( ) , a derived class will function
* as a control whose value can range between 0 and 1.0 .
2016-01-02 04:58:23 -05:00
*
2015-10-21 22:30:13 -04:00
*/
2013-10-16 23:30:28 -04:00
class LIBPBD_API Controllable : public PBD : : StatefulDestructible {
2017-07-25 20:15:12 +02:00
public :
2009-12-30 16:48:58 +00:00
enum Flag {
Toggle = 0x1 ,
2011-03-04 00:35:01 +00:00
GainLike = 0x2 ,
2016-04-09 16:14:18 -04:00
RealTime = 0x4 ,
NotAutomatable = 0x8 ,
2009-12-30 16:48:58 +00:00
} ;
Controllable ( const std : : string & name , Flag f = Flag ( 0 ) ) ;
2008-06-02 21:41:35 +00:00
virtual ~ Controllable ( ) { Destroyed ( this ) ; }
2012-01-21 16:38:56 +00:00
/* We express Controllable values in one of three ways:
* 1. ` user ' - - - as presented to the user ( e . g . dB , Hz , etc . )
* 2. ` interface ' - - - as used in some cases for the UI representation
* ( in order to make controls behave logarithmically ) .
* 3. ` internal ' - - - as passed to a processor , track , plugin , or whatever .
*
2017-01-22 12:02:28 +01:00
* Note that in some cases user and internal may be the same
2012-01-21 16:38:56 +00:00
* ( and interface different ) e . g . frequency , which is presented
* to the user and passed to the processor in linear terms , but
* which needs log scaling in the interface .
*
2017-01-22 12:02:28 +01:00
* In other cases , user and interface may be the same ( and internal different )
2012-01-21 16:38:56 +00:00
* e . g . gain , which is presented to the user in log terms ( dB )
* but passed to the processor as a linear quantity .
2011-02-15 01:42:48 +00:00
*/
2016-01-02 04:58:23 -05:00
/* Within an application, various Controllables might be considered to
* be " grouped " in a way that implies that setting 1 of them also
* modifies others in the group .
*/
enum GroupControlDisposition {
2016-01-21 12:04:20 -05:00
InverseGroup , /* set all controls in the same "group" as this one */
2016-01-02 04:58:23 -05:00
NoGroup , /* set only this control */
2016-03-14 10:41:33 -04:00
UseGroup , /* use group settings to decide which group controls are altered */
ForGroup /* this setting is being done *for* the group
( i . e . UseGroup was set in the callchain
somewhere ) .
*/
2016-01-02 04:58:23 -05:00
} ;
/** Get and Set `internal' value
*
* All derived classes must implement this .
2017-07-26 22:57:43 +02:00
*
* Basic derived classes will ignore @ param group_override ,
* but more sophisticated children , notably those that
* proxy the value setting logic via an object that is aware of group
* relationships between this control and others , will find it useful .
*/
virtual void set_value ( double , GroupControlDisposition group_override ) = 0 ;
2010-07-27 14:09:16 +00:00
virtual double get_value ( void ) const = 0 ;
2008-06-02 21:41:35 +00:00
2017-02-06 16:41:15 +01:00
/** This is used when saving state. By default it just calls
* get_value ( ) , but a class with more complex semantics might override
* this to save some value that differs from what get_value ( ) would
* return .
*/
virtual double get_save_value ( ) const { return get_value ( ) ; }
2014-07-18 08:47:45 -05:00
/** Conversions between `internal', 'interface', and 'user' values */
virtual double internal_to_interface ( double i ) const { return ( i - lower ( ) ) / ( upper ( ) - lower ( ) ) ; } //by default, the interface range is just a linear interpolation between lower and upper values
virtual double interface_to_internal ( double i ) const { return lower ( ) + i * ( upper ( ) - lower ( ) ) ; }
2015-10-21 08:09:40 -04:00
/** Get and Set `interface' value (typically, fraction of knob travel) */
2014-07-18 08:47:45 -05:00
virtual float get_interface ( ) const { return ( internal_to_interface ( get_value ( ) ) ) ; }
2016-01-02 04:58:23 -05:00
virtual void set_interface ( float fraction ) { fraction = min ( max ( 0.0f , fraction ) , 1.0f ) ; set_value ( interface_to_internal ( fraction ) , NoGroup ) ; }
2014-07-18 08:47:45 -05:00
virtual std : : string get_user_string ( ) const { return std : : string ( ) ; }
2009-12-19 20:26:31 +00:00
PBD : : Signal0 < void > LearningFinished ;
static PBD : : Signal3 < void , PBD : : Controllable * , int , int > CreateBinding ;
static PBD : : Signal1 < void , PBD : : Controllable * > DeleteBinding ;
2008-06-02 21:41:35 +00:00
2009-12-19 20:26:31 +00:00
static PBD : : Signal1 < bool , PBD : : Controllable * > StartLearning ;
static PBD : : Signal1 < void , PBD : : Controllable * > StopLearning ;
2008-06-02 21:41:35 +00:00
2009-12-19 20:26:31 +00:00
static PBD : : Signal1 < void , Controllable * > Destroyed ;
2015-10-05 16:17:49 +02:00
2017-07-02 15:28:51 +02:00
static PBD : : Signal1 < void , boost : : weak_ptr < PBD : : Controllable > > GUIFocusChanged ;
2016-03-11 10:34:51 -05:00
PBD : : Signal2 < void , bool , PBD : : Controllable : : GroupControlDisposition > Changed ;
2008-06-02 21:41:35 +00:00
2009-10-15 18:56:11 +00:00
int set_state ( const XMLNode & , int version ) ;
2017-06-12 02:25:20 +02:00
virtual XMLNode & get_state ( ) ;
2008-06-02 21:41:35 +00:00
2009-02-18 23:54:41 +00:00
std : : string name ( ) const { return _name ; }
2009-12-30 16:48:58 +00:00
bool touching ( ) const { return _touching ; }
2017-07-26 22:57:43 +02:00
PBD : : Signal0 < void > TouchChanged ;
2008-06-02 21:41:35 +00:00
2009-12-30 16:48:58 +00:00
bool is_toggle ( ) const { return _flags & Toggle ; }
bool is_gain_like ( ) const { return _flags & GainLike ; }
2017-07-26 22:57:43 +02:00
virtual double lower ( ) const { return 0.0 ; }
virtual double upper ( ) const { return 1.0 ; }
virtual double normal ( ) const { return 0.0 ; } //the default value
2010-04-06 16:57:35 +00:00
2009-12-30 16:48:58 +00:00
Flag flags ( ) const { return _flags ; }
void set_flags ( Flag f ) ;
2008-06-02 21:41:35 +00:00
static Controllable * by_id ( const PBD : : ID & ) ;
static Controllable * by_name ( const std : : string & ) ;
2017-07-26 22:57:43 +02:00
static const std : : string xml_node_name ;
2016-01-02 04:58:23 -05:00
2017-07-25 20:15:12 +02:00
protected :
2017-07-26 22:57:43 +02:00
void set_touching ( bool yn ) {
if ( _touching = = yn ) { return ; }
_touching = yn ;
TouchChanged ( ) ; /* EMIT SIGNAL */
}
2017-07-25 20:15:12 +02:00
private :
2008-06-02 21:41:35 +00:00
std : : string _name ;
2014-07-18 08:47:45 -05:00
std : : string _units ;
2009-12-30 16:48:58 +00:00
Flag _flags ;
2009-02-18 23:54:41 +00:00
bool _touching ;
2008-06-02 21:41:35 +00:00
2009-12-17 18:24:23 +00:00
static void add ( Controllable & ) ;
2009-12-22 20:21:43 +00:00
static void remove ( Controllable * ) ;
2008-06-02 21:41:35 +00:00
typedef std : : set < PBD : : Controllable * > Controllables ;
2017-07-26 22:57:43 +02:00
static Glib : : Threads : : RWLock registry_lock ;
2008-06-02 21:41:35 +00:00
static Controllables registry ;
} ;
/* a utility class for the occasions when you need but do not have
2017-07-26 22:57:43 +02:00
* a Controllable
*/
2015-10-04 14:51:05 -04:00
class LIBPBD_API IgnorableControllable : public Controllable
2008-06-02 21:41:35 +00:00
{
2017-07-26 22:57:43 +02:00
public :
2009-12-30 16:48:58 +00:00
IgnorableControllable ( ) : PBD : : Controllable ( " ignoreMe " ) { }
2009-12-11 03:18:17 +00:00
~ IgnorableControllable ( ) { }
2015-10-04 14:51:05 -04:00
2016-01-02 04:58:23 -05:00
void set_value ( double /*v*/ , PBD : : Controllable : : GroupControlDisposition /* group_override */ ) { }
2010-07-27 14:09:16 +00:00
double get_value ( ) const { return 0.0 ; }
2008-06-02 21:41:35 +00:00
} ;
}
# endif /* __pbd_controllable_h__ */