diff --git a/ChangeLog b/ChangeLog index e71a8dbc5..bf222c17b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2005-10-13 Tobias Doerffel + + * src/audio/audio_jack.cpp: + do not fill up buffers if JACK-transport is not rolling but at the same + time always handle frame-syncing-var in JACK-callback, even if JACK- + transport is not rolling - fixes several bugs like lockups when + removing tracks while JACK-server is pausing... + + * src/widgets/knob.cpp: + fixed bug which caused hidden mouse-cursor forever when pressing right + mouse-button while left one is pressed + + * src/lib/ladspa_manager.cpp: + use /usr/lib/ladspa as default-directory if env-var LADSPA_PATH is not + set + + * src/soundgenerators/*.cpp: + removed obsolete defaultSettings()-method from each soundgenerator + +2005-10-13 Dany McRae + + * include/ladspa_manager.h + * include/ladspa_sine_1063.h + * src/lib/ladspa_manager.cpp: + * src/soundgenerators/ladspa_sine_1063.cpp: + added LADSPA-support and a simple soundgenerator for testing-purposes + 2005-10-12 Dany McRae * Makefile.am: diff --git a/Makefile.am b/Makefile.am index 6a336da2b..8ec5213bf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,6 +58,7 @@ lmms_MOC = \ ./kmultitabbar.moc \ ./group_box.moc \ ./knob.moc \ + ./ladspa_sine_1063.moc \ ./lcd_spinbox.moc \ ./led_checkbox.moc \ ./lmms_main_win.moc \ @@ -137,6 +138,7 @@ lmms_SOURCES = \ $(srcdir)/src/lib/buffer_allocator.cpp \ $(srcdir)/src/lib/clipboard.cpp \ $(srcdir)/src/lib/embed.cpp \ + $(srcdir)/src/lib/ladspa_manager.cpp \ $(srcdir)/src/lib/mmp.cpp \ $(srcdir)/src/lib/oscillator.cpp \ $(srcdir)/src/lib/sample_buffer.cpp \ @@ -257,7 +259,8 @@ lmms_SOURCES = \ $(srcdir)/include/text_float.h \ $(srcdir)/include/tempo_sync_knob.h \ $(srcdir)/include/setup_dialog.h \ - $(srcdir)/include/empty_sg_plugin.h + $(srcdir)/include/empty_sg_plugin.h \ + $(srcdir)/include/ladspa_manager.h EXTRA_DIST = $(lmms_EMBEDDED_RESOURCES) @@ -300,10 +303,11 @@ SUBDIRS = artwork locale midi-maps presets projects samples -pkglib_LTLIBRARIES= libaudiofileprocessor.la libmidiout.la libpluckedstringsynth.la libtripleoscillator.la +pkglib_LTLIBRARIES= libaudiofileprocessor.la libsine1063oscillator.la libmidiout.la libpluckedstringsynth.la libtripleoscillator.la libaudiofileprocessor_la_SOURCES = src/soundgenerators/audio_file_processor.cpp +libsine1063oscillator_la_SOURCES = src/soundgenerators/ladspa_sine_1063.cpp libmidiout_la_SOURCES = src/soundgenerators/midi_out.cpp libpluckedstringsynth_la_SOURCES = src/soundgenerators/plucked_string_synth.cpp libtripleoscillator_la_SOURCES = src/soundgenerators/triple_oscillator.cpp diff --git a/TODO b/TODO index 9565199f4..d97492ddd 100644 --- a/TODO +++ b/TODO @@ -1,10 +1,12 @@ +- toolbar-redesign in song-editor, bb-editor and piano-roll!!! +- addchannel-toolbutton -> popup-menu with available soundgenerator-plugins +- solve problem with knob-control-precision +- built-in VST-support - proper dlclos()ing of sg-plugins - use own scrollview for capturing wheel-events - add note-len- and note-alignment-selectbox to piano-roll - only redraw region given by paint-event in pattern, bbTCO, sampleTCO etc. -- make usable with Qt4 - make LMMS an ALSA-sequencer-client -- adchannel-toolbutton -> popup-menu with available soundgenerator-plugins - pre-listen when opening sample with QFileDialog - level-meters in output-graph and channel-track - panning-editing in piano-roll @@ -13,7 +15,7 @@ - setup MIDI-channel and -program in MIDI-Out - speed up painting of sampleTCO - save window-positions, -states and -sizes in files -- solve problems with different keyboard-layouts when playing channel-track with pc-keyboard +- solve problems with different keyboard-layouts when playing channel-track with pc-keyboard -> use tr() - balance env+lfo - autosave every 1 minute - audioDummy: always wait until the stuff normally would have been written (=simulate blocking IO) @@ -23,9 +25,11 @@ - dynamic pitch-change - make piano-roll use the global clipboard?? - add languages: - - Dutch - Italian - - ...any other welcome + - Swedish + - Norwegian + - Greece + - ... @@ -37,7 +41,6 @@ Things to be done anytime in the future - FLP-Import - classical note-edit-window -> also ability of printing and maybe later scanning & recognition of notes - add FLAC as export-format? -- support of LADSPA for all plugins - better commented source... - optimize, optimize, optimize..... diff --git a/configure.in b/configure.in index 347cd4ca2..31ed5a8d2 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-cvs20051012, tobydox@users.sourceforge.net) -AM_INIT_AUTOMAKE(lmms, 0.1.1-cvs20051012) +AC_INIT(lmms, 0.1.1-cvs20051013, tobydox@users.sourceforge.net) +AM_INIT_AUTOMAKE(lmms, 0.1.1-cvs20051013) AM_CONFIG_HEADER(config.h) @@ -355,6 +355,7 @@ AC_CONFIG_FILES([Makefile presets/AudioFileProcessor/Makefile presets/MIDI-Out/Makefile presets/PluckedStringSynth/Makefile + presets/Sine1063Oscillator/Makefile presets/TripleOscillator/Makefile projects/Makefile projects/cool_songs/Makefile diff --git a/include/ladspa_manager.h b/include/ladspa_manager.h new file mode 100644 index 000000000..c514e3453 --- /dev/null +++ b/include/ladspa_manager.h @@ -0,0 +1,330 @@ +/* + * ladspa_manager.h - declaration of class ladspaManager + * a class to manage loading and instantiation + * of ladspa plugins + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Danny McRae + * + * 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 _LADSPA_MANAGER_H +#define _LADSPA_MANAGER_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include + +#else + +#include +#include +#include +#include + +#endif + +#include +#include "types.h" + +typedef QPair ladspaKey; + +/* ladspaManager provides a database of LADSPA plug-ins. Upon instantiation, +it loads all of the plug-ins found in the LADSPA_PATH environmental variable +and stores their access descriptors according in a dictionary keyed on +the filename the plug-in was loaded from and the label of the plug-in. + +The can be retrieved by using ladspaKey. For example, to get the +"Phase Modulated Voice" plug-in from the cmt library, you would perform the +calls using: + + ladspaKey( "cmt.so", "phasemod" ) + +as the plug-in key. */ + +class ladspaManager +{ +public: + /* Provides access to the single instance of the class. */ + static inline ladspaManager * inst( void ) + { + if( s_instanceOfMe == NULL ) + { + s_instanceOfMe = new ladspaManager(); + } + return( s_instanceOfMe ); + } + + /* This identifier can be used as a unique, case-sensitive + identifier for the plugin type within the plugin file. Plugin + types should be identified by file and label rather than by index + or plugin name, which may be changed in new plugin + versions. Labels must not contain white-space characters. */ + QString FASTCALL getLabel( const ladspaKey & _plugin ); + + /* Indicates that the plugin has a real-time dependency + (e.g. listens to a MIDI device) and so its output must not + be cached or subject to significant latency. */ + bool FASTCALL hasRealTimeDependency( const ladspaKey & _plugin ); + + /* Indicates that the plugin may cease to work correctly if the + host elects to use the same data location for both input and output + (see connectPort). */ + bool FASTCALL isInplaceBroken( const ladspaKey & _plugin ); + + /* Indicates that the plugin is capable of running not only in a + conventional host but also in a 'hard real-time' environment. */ + bool FASTCALL isRealTimeCapable( const ladspaKey & _plugin ); + + /* Returns the name of the plug-in */ + QString FASTCALL getName( const ladspaKey & _plugin ); + + /* Returns the the plug-in's author */ + QString FASTCALL getMaker( const ladspaKey & _plugin ); + + /* Returns the copyright for the plug-in */ + QString FASTCALL getCopyright( const ladspaKey & _plugin ); + + /* This indicates the number of ports (input AND output) present on + the plugin. */ + Uint32 FASTCALL getPortCount( const ladspaKey & _plugin ); + + + /* Indicates that the port is an input. */ + bool FASTCALL isPortInput( const ladspaKey & _plugin, Uint32 _port ); + + /* Indicates that the port is an output. */ + bool FASTCALL isPortOutput( const ladspaKey & _plugin, Uint32 _port ); + + /* Indicates that the port is an audio. */ + bool FASTCALL isPortAudio( const ladspaKey & _plugin, Uint32 _port ); + + /* Indicates that the port is an control. */ + bool FASTCALL isPortControl( const ladspaKey & _plugin, Uint32 _port ); + + /* Indicates that any bounds specified should be interpreted as + multiples of the sample rate. For instance, a frequency range from + 0Hz to the Nyquist frequency (half the sample rate) could be requested + by this hint in conjunction with LowerBound = 0 and UpperBound = 0.5. + Hosts that support bounds at all must support this hint to retain meaning. */ + bool FASTCALL areHintsSampleRateDependent( const ladspaKey & _plugin, + Uint32 _port ); + + /* Returns the lower boundary value for the given port. If + no lower bound is provided by the plug-in, returns -999e-99. When + areHintsSampleRateDependent() is also true then this value should be + multiplied by the relevant sample rate. */ + float FASTCALL getLowerBound( const ladspaKey & _plugin, Uint32 _port ); + + /* Returns the upper boundary value for the given port. If + no upper bound is provided by the plug-in, returns -999e-99. When + areHintsSampleRateDependent() is also true then this value should be + multiplied by the relevant sample rate. */ + float FASTCALL getUpperBound( const ladspaKey & _plugin, Uint32 _port ); + + /* Indicates whether the given port should be considered 0 or 1 + boolean switch. */ + bool FASTCALL isPortToggled( const ladspaKey & _plugin, Uint32 _port ); + + /* Retrieves any default setting hints offered by the plug-in for + the given port. */ + float FASTCALL getDefaultSetting( const ladspaKey & _plugin, + Uint32 _port ); + + + /* Indicates that it is likely that the user will find it more + intuitive to view values using a logarithmic scale. This is + particularly useful for frequencies and gains. */ + bool FASTCALL isLogarithmic( const ladspaKey & _plugin, Uint32 _port ); + + + /* Indicates that a user interface would probably wish to provide a + stepped control taking only integer values. Any bounds set should be + slightly wider than the actual integer range required to avoid floating + point rounding errors. For instance, the integer set {0,1,2,3} might + be described as [-0.1, 3.1]. */ + bool FASTCALL isInteger( const ladspaKey & _plugin, Uint32 _port ); + + /* Returns the name of the port. */ + QString FASTCALL getPortName( const ladspaKey & _plugin, Uint32 _port ); + + + /* This may be used by the plugin developer to pass any custom + implementation data into an instantiate call. It must not be used + or interpreted by the host. It is expected that most plugin + writers will not use this facility as LADSPA_Handle should be + used to hold instance data. */ + const void * FASTCALL getImplementationData( const ladspaKey & _plugin ); + + + /* Returns a pointer to the plug-in's descriptor from which control + of the plug-in is accessible */ + const LADSPA_Descriptor * FASTCALL getDescriptor( const ladspaKey & _plugin ); + + + /* The following methods are convenience functions for use during + development. A real soundGenerator should use the getDescriptor() + method and implement the plug-in manipulations internally to avoid + the overhead associated with QMap lookups. */ + + + /* Returns a handle to an instantiation of the given plug-in. */ + LADSPA_Handle FASTCALL instantiate( const ladspaKey & _plugin, + Uint32 _sample_rate ); + + /* This method calls a function pointer that connects a port on an + instantiated plugin to a memory location at which a block of data + for the port will be read/written. The data location is expected + to be an array of LADSPA_Data for audio ports or a single + LADSPA_Data value for control ports. Memory issues will be + managed by the host. The plugin must read/write the data at these + locations every time run() or runAdding() is called and the data + present at the time of this connection call should not be + considered meaningful. + + connectPort() may be called more than once for a plugin instance + to allow the host to change the buffers that the plugin is + reading or writing. These calls may be made before or after + activate() or deactivate() calls. + + connectPort() must be called at least once for each port before + run() or runAdding() is called. */ + void FASTCALL connectPort( const ladspaKey & _plugin, + LADSPA_Handle _instance, + Uint32 _port, + LADSPA_Data * _data_location ); + + /* This method calls a function pointer that initialises a plugin + instance and activates it for use. This is separated from + instantiate() to aid real-time support and so that hosts can + reinitialise a plugin instance by calling deactivate() and then + activate(). In this case the plugin instance must reset all state + information dependent on the history of the plugin instance + except for any data locations provided by connectPort() and any + gain set by setRunAddingGain(). If there is nothing for + activate() to do then the plugin writer may provide a NULL rather + than an empty function. + + When present, hosts must call this function once before run() (or + runAdding()) is called for the first time. This call should be + made as close to the run() call as possible and indicates to + real-time plugins that they are now live. Plugins should not rely + on a prompt call to run() after activate(). activate() may not be + called again unless deactivate() is called first. Note that + connectPort() may be called before or after a call to + activate(). */ + void FASTCALL activate( const ladspaKey & _plugin, LADSPA_Handle _instance ); + + /* This method calls a function pointer that runs an instance of a + plugin for a block. Two parameters are required: the first is a + handle to the particular instance to be run and the second + indicates the block size (in samples) for which the plugin + instance may run. + + Note that if an activate() function exists then it must be called + before run() or run_adding(). If deactivate() is called for a + plugin instance then the plugin instance may not be reused until + activate() has been called again. */ + void FASTCALL run( const ladspaKey & _plugin, LADSPA_Handle _instance, + Uint32 _sample_count ); + + /* This method calls a function pointer that runs an instance of a + plugin for a block. This has identical behaviour to run() except + in the way data is output from the plugin. When run() is used, + values are written directly to the memory areas associated with + the output ports. However when runAdding() is called, values + must be added to the values already present in the memory + areas. Furthermore, output values written must be scaled by the + current gain set by setRunAddingGain() (see below) before + addition. + + runAdding() is optional. When it is not provided by a plugin, + this function pointer must be set to NULL. When it is provided, + the function setRunAddingGain() must be provided also. */ + void FASTCALL runAdding( const ladspaKey & _plugin, LADSPA_Handle _instance, + Uint32 _sample_count ); + + /* This method calls a function pointer that sets the output gain for + use when runAdding() is called (see above). If this function is + never called the gain is assumed to default to 1. Gain + information should be retained when activate() or deactivate() + are called. + + This function should be provided by the plugin if and only if the + runAdding() function is provided. When it is absent this + function pointer must be set to NULL. */ + void FASTCALL setRunAddingGain( const ladspaKey & _plugin, LADSPA_Handle _instance, + LADSPA_Data _gain ); + + /* This is the counterpart to activate() (see above). If there is + nothing for deactivate() to do then the plugin writer may provide + a NULL rather than an empty function. + + Hosts must deactivate all activated units after they have been + run() (or run_adding()) for the last time. This call should be + made as close to the last run() call as possible and indicates to + real-time plugins that they are no longer live. Plugins should + not rely on prompt deactivation. Note that connect_port() may be + called before or after a call to deactivate(). + + Deactivation is not similar to pausing as the plugin instance + will be reinitialised when activate() is called to reuse it. */ + void FASTCALL deactivate( const ladspaKey & _plugin, LADSPA_Handle _instance ); + + /* Once an instance of a plugin has been finished with it can be + deleted using the following function. The instance handle passed + ceases to be valid after this call. + + If activate() was called for a plugin instance then a + corresponding call to deactivate() must be made before cleanup() + is called. */ + void FASTCALL cleanup( const ladspaKey & _plugin, LADSPA_Handle _instance ); + +private: + void FASTCALL addPlugins( void * _plugin_handle, + LADSPA_Descriptor_Function _descriptor_func, + const QString & _file ); + + ladspaManager( void ); + ~ladspaManager(); + + + static ladspaManager * s_instanceOfMe; + + typedef struct ladspaManagerStorage + { + void * pluginHandle; + LADSPA_Descriptor_Function descriptorFunction; + Uint32 index; + } ladspaManagerDescription; + + typedef QMap ladspaManagerMapType; + ladspaManagerMapType m_ladspaManagerMap; +}; + +#endif diff --git a/src/audio/audio_jack.cpp b/src/audio/audio_jack.cpp index 01e05d127..a0619f25c 100644 --- a/src/audio/audio_jack.cpp +++ b/src/audio/audio_jack.cpp @@ -218,24 +218,29 @@ void audioJACK::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames, { m_bufMutex.lock(); - vvector bufs; - for( Uint8 chnl = 0; chnl < channels(); ++chnl ) + jack_transport_state_t ts = jack_transport_query( m_client, NULL ); + if( ts == JackTransportRolling ) { - sampleType * buf = bufferAllocator::alloc( - _frames ); - for( Uint32 frame = 0; frame < _frames; ++frame ) + vvector bufs; + for( Uint8 chnl = 0; chnl < channels(); ++chnl ) { - buf[frame] = _ab[frame][chnl] * _master_output; + sampleType * buf = bufferAllocator::alloc( + _frames ); + for( Uint32 frame = 0; frame < _frames; ++frame ) + { + buf[frame] = _ab[frame][chnl] * _master_output; + } + bufset b = { buf, _frames } ; + bufs.push_back( b ); } - bufset b = { buf, _frames } ; - bufs.push_back( b ); + m_bufferSets.push_back( bufs ); } - m_bufferSets.push_back( bufs ); + m_frameSync += _frames; m_bufMutex.unlock(); - // now wait until data has been collected by processCallback() + // now wait until data has been collected/skipped by processCallback() while( m_frameSync > m_jackBufSize ) { #ifdef HAVE_UNISTD_H @@ -261,6 +266,16 @@ int audioJACK::processCallback( jack_nframes_t _nframes, void * _udata ) NULL ); if( ts != JackTransportRolling ) { + // always decrease frame-sync-var as we would do it if running + // in normal mode, so that the mixer-thread does up + if( _nframes < _this->m_frameSync ) + { + _this->m_frameSync -= _nframes; + } + else + { + _this->m_frameSync = 0; + } return( 0 ); } diff --git a/src/lib/ladspa_manager.cpp b/src/lib/ladspa_manager.cpp new file mode 100644 index 000000000..8d8d0afa0 --- /dev/null +++ b/src/lib/ladspa_manager.cpp @@ -0,0 +1,844 @@ +/* + * ladspa_manager.cpp - a class to manage loading and instantiation + * of ladspa plugins + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Danny McRae + * + * 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. + * + */ + + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + +#include +#include +#include + + +#include "ladspa_manager.h" + + +ladspaManager * ladspaManager::s_instanceOfMe = NULL; + + +ladspaManager::ladspaManager( void ) +{ + LADSPA_Descriptor_Function descriptorFunction; + void * pluginHandle; + + // TODO Need to move the search path definition to the config file to have + // more control over where it tries to find the plugins. + QStringList ladspaDirectories = QStringList::split( QString( ":" ), + QString( getenv( "LADSPA_PATH" ) ) ); + // set default-directory if nothing is specified... + if( ladspaDirectories.isEmpty() ) + { + ladspaDirectories.push_back( "/usr/lib/ladspa" ); + } + for( QStringList::iterator it = ladspaDirectories.begin(); + it != ladspaDirectories.end(); ++it ) + { + QDir directory( ( *it ) ); + const QFileInfoList * list = directory.entryInfoList(); + + for( QFileInfoList::iterator file = list->begin(); + file != list->end(); ++file ) + { + pluginHandle = dlopen( ( *file )->absFilePath().latin1(), + RTLD_LAZY ); + if( pluginHandle ) + { + dlerror(); + descriptorFunction + = ( LADSPA_Descriptor_Function ) + dlsym( pluginHandle, + "ladspa_descriptor" ); + if( dlerror() == NULL && descriptorFunction ) + { + addPlugins( pluginHandle, + descriptorFunction, + ( *file )->fileName() ); + } + else + { + dlclose( ( void * ) + ( *file )->absFilePath().latin1() + ); + } + } + } + } +} + + + + +ladspaManager::~ladspaManager() +{ + for( ladspaManagerMapType::Iterator it = m_ladspaManagerMap.begin(); + it != m_ladspaManagerMap.end(); ++it ) + { + dlclose( it.data()->pluginHandle ); + } + m_ladspaManagerMap.clear(); +} + + + + +void FASTCALL ladspaManager::addPlugins( void * _plugin_handle, + LADSPA_Descriptor_Function _descriptor_func, + const QString & _file ) +{ + const LADSPA_Descriptor * descriptor; + long pluginIndex = 0; + + while( ( descriptor = _descriptor_func( pluginIndex ) ) != NULL ) + { + ladspaManagerDescription * plugIn = + new ladspaManagerDescription; + plugIn->pluginHandle = _plugin_handle; + plugIn->descriptorFunction = _descriptor_func; + plugIn->index = pluginIndex; + + ladspaKey key( _file, QString( descriptor->Label ) ); + m_ladspaManagerMap[key] = plugIn; + ++pluginIndex; + } +} + + + + +QString FASTCALL ladspaManager::getLabel( const ladspaKey & _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( QString( descriptor->Label ) ); + } + else + { + return( QString( "" ) ); + } +} + + + + +bool FASTCALL ladspaManager::hasRealTimeDependency( const ladspaKey & _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( LADSPA_IS_REALTIME( descriptor->Properties ) ); + } + else + { + return( FALSE ); + } +} + + + + +bool FASTCALL ladspaManager::isInplaceBroken( const ladspaKey & _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( LADSPA_IS_INPLACE_BROKEN( descriptor->Properties ) ); + } + else + { + return( FALSE ); + } +} + + + + +bool FASTCALL ladspaManager::isRealTimeCapable( const ladspaKey & _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( LADSPA_IS_HARD_RT_CAPABLE( descriptor->Properties ) ); + } + else + { + return( FALSE ); + } +} + + + + +QString FASTCALL ladspaManager::getName( const ladspaKey & _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( QString( descriptor->Name ) ); + } + else + { + return( QString( "" ) ); + } +} + + + + +QString FASTCALL ladspaManager::getMaker( const ladspaKey & _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( QString( descriptor->Maker ) ); + } + else + { + return( QString( "" ) ); + } +} + + + + +QString FASTCALL ladspaManager::getCopyright( const ladspaKey & _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( QString( descriptor->Copyright ) ); + } + else + { + return( QString( "" ) ); + } +} + + + + +Uint32 FASTCALL ladspaManager::getPortCount( const ladspaKey & _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( descriptor->PortCount ); + } + else + { + return( 0 ); + } +} + + + + +bool FASTCALL ladspaManager::isPortInput( const ladspaKey & _plugin, + Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + + return( LADSPA_IS_PORT_INPUT + ( descriptor->PortDescriptors[_port] ) ); + } + else + { + return( FALSE ); + } +} + + + + +bool FASTCALL ladspaManager::isPortOutput( const ladspaKey & _plugin, + Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + + return( LADSPA_IS_PORT_OUTPUT + ( descriptor->PortDescriptors[_port] ) ); + } + else + { + return( FALSE ); + } +} + + + + +bool FASTCALL ladspaManager::isPortAudio( const ladspaKey & _plugin, Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + + return( LADSPA_IS_PORT_AUDIO + ( descriptor->PortDescriptors[_port] ) ); + } + else + { + return( FALSE ); + } +} + + + + +bool FASTCALL ladspaManager::isPortControl( const ladspaKey & _plugin, + Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + + return( LADSPA_IS_PORT_CONTROL + ( descriptor->PortDescriptors[_port] ) ); + } + else + { + return( FALSE ); + } +} + + + + +bool FASTCALL ladspaManager::areHintsSampleRateDependent( + const ladspaKey & _plugin, + Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + LADSPA_PortRangeHintDescriptor hintDescriptor + = descriptor->PortRangeHints[_port].HintDescriptor; + return( LADSPA_IS_HINT_SAMPLE_RATE + ( hintDescriptor ) ); + } + else + { + return( FALSE ); + } +} + + + + +float FASTCALL ladspaManager::getLowerBound( const ladspaKey & _plugin, + Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + LADSPA_PortRangeHintDescriptor hintDescriptor + = descriptor->PortRangeHints[_port].HintDescriptor; + if( LADSPA_IS_HINT_BOUNDED_BELOW + ( hintDescriptor ) ) + { + return( descriptor->PortRangeHints[_port].LowerBound ); + } + else + { + return( -999e-99 ); + } + } + else + { + return( -999e-99 ); + } +} + + + + +float FASTCALL ladspaManager::getUpperBound( const ladspaKey & _plugin, Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + LADSPA_PortRangeHintDescriptor hintDescriptor + = descriptor->PortRangeHints[_port].HintDescriptor; + if( LADSPA_IS_HINT_BOUNDED_ABOVE + ( hintDescriptor ) ) + { + return( descriptor->PortRangeHints[_port].LowerBound ); + } + else + { + return( -999e-99 ); + } + } + else + { + return( -999e-99 ); + } +} + + + + +bool FASTCALL ladspaManager::isPortToggled( const ladspaKey & _plugin, + Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + LADSPA_PortRangeHintDescriptor hintDescriptor + = descriptor->PortRangeHints[_port].HintDescriptor; + return( LADSPA_IS_HINT_TOGGLED + ( hintDescriptor ) ); + } + else + { + return( FALSE ); + } +} + + + + +float FASTCALL ladspaManager::getDefaultSetting( const ladspaKey & _plugin, + Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + LADSPA_PortRangeHintDescriptor hintDescriptor + = descriptor->PortRangeHints[_port].HintDescriptor; + switch( hintDescriptor & LADSPA_HINT_DEFAULT_MASK ) + { + case LADSPA_HINT_DEFAULT_NONE: + return( -999e-99 ); + case LADSPA_HINT_DEFAULT_MINIMUM: + return( descriptor->PortRangeHints[_port].LowerBound ); + case LADSPA_HINT_DEFAULT_LOW: + if( LADSPA_IS_HINT_LOGARITHMIC + ( hintDescriptor )) + { + return( exp( log( descriptor->PortRangeHints[_port].LowerBound ) + * 0.75 + + log( descriptor->PortRangeHints[_port].UpperBound ) + * 0.25 ) ); + } + else + { + return( descriptor->PortRangeHints[_port].LowerBound + * 0.75 + + descriptor->PortRangeHints[_port].UpperBound + * 0.25 ); + } + case LADSPA_HINT_DEFAULT_MIDDLE: + if( LADSPA_IS_HINT_LOGARITHMIC + ( hintDescriptor ) ) + { + return( sqrt( descriptor->PortRangeHints[_port].LowerBound + * descriptor->PortRangeHints[_port].UpperBound ) ); + } + else + { + return( 0.5 * ( descriptor->PortRangeHints[_port].LowerBound + + descriptor->PortRangeHints[_port].UpperBound ) ); + } + case LADSPA_HINT_DEFAULT_HIGH: + if( LADSPA_IS_HINT_LOGARITHMIC + ( hintDescriptor ) ) + { + return( exp( log( descriptor->PortRangeHints[_port].LowerBound ) + * 0.25 + + log( descriptor->PortRangeHints[_port].UpperBound ) + * 0.75 ) ); + } + else + { + return( descriptor->PortRangeHints[_port].LowerBound + * 0.25 + + descriptor->PortRangeHints[_port].UpperBound + * 0.75 ); + } + case LADSPA_HINT_DEFAULT_MAXIMUM: + return( descriptor->PortRangeHints[_port].UpperBound ); + case LADSPA_HINT_DEFAULT_0: + return( 0.0 ); + case LADSPA_HINT_DEFAULT_1: + return( 1.0 ); + case LADSPA_HINT_DEFAULT_100: + return( 100.0 ); + case LADSPA_HINT_DEFAULT_440: + return( 440.0 ); + default: + return( -999e-99 ); + } + } + else + { + return( -999e-99 ); + } +} + + + + +bool FASTCALL ladspaManager::isLogarithmic( const ladspaKey & _plugin, + Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + LADSPA_PortRangeHintDescriptor hintDescriptor + = descriptor->PortRangeHints[_port].HintDescriptor; + return( LADSPA_IS_HINT_LOGARITHMIC + ( hintDescriptor ) ); + } + else + { + return( FALSE ); + } +} + + + + +bool FASTCALL ladspaManager::isInteger( const ladspaKey & _plugin, + Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + LADSPA_PortRangeHintDescriptor hintDescriptor + = descriptor->PortRangeHints[_port].HintDescriptor; + return( LADSPA_IS_HINT_INTEGER + ( hintDescriptor ) ); + } + else + { + return( FALSE ); + } +} + + + + +QString FASTCALL ladspaManager::getPortName( const ladspaKey & _plugin, + Uint32 _port ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + + return( QString( descriptor->PortNames[_port] ) ); + } + else + { + return( QString( "" ) ); + } +} + + + + +const void * FASTCALL ladspaManager::getImplementationData( const ladspaKey & + _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( descriptor->ImplementationData ); + } + else + { + return( NULL ); + } +} + + + + +const LADSPA_Descriptor * FASTCALL ladspaManager::getDescriptor( + const ladspaKey & _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( descriptor ); + } + else + { + return( NULL ); + } +} + + + + +LADSPA_Handle FASTCALL ladspaManager::instantiate( const ladspaKey & _plugin, + Uint32 _sample_rate ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + return( ( descriptor->instantiate ) ( descriptor, _sample_rate ) ); + } + else + { + return( NULL ); + } +} + + + + +void FASTCALL ladspaManager::connectPort( const ladspaKey & _plugin, + LADSPA_Handle _instance, + Uint32 _port, + LADSPA_Data * _data_location ) +{ + if( m_ladspaManagerMap.contains( _plugin ) + && _port < getPortCount( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + if( descriptor->connect_port != NULL ) + { + ( descriptor->connect_port ) ( _instance, _port, _data_location ); + } + } +} + + + + +void FASTCALL ladspaManager::activate( const ladspaKey & _plugin, + LADSPA_Handle _instance ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + if( descriptor->activate != NULL ) + { + ( descriptor->activate ) ( _instance ); + } + } +} + + + + +void FASTCALL ladspaManager::run( const ladspaKey & _plugin, LADSPA_Handle _instance, + Uint32 _sample_count ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + if( descriptor->run != NULL ) + { + ( descriptor->run ) ( _instance, _sample_count ); + } + } +} + + + + +void FASTCALL ladspaManager::runAdding( const ladspaKey & _plugin, + LADSPA_Handle _instance, + Uint32 _sample_count ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + if( descriptor->run_adding!=NULL + && descriptor->set_run_adding_gain!=NULL ) + { + ( descriptor->run_adding ) ( _instance, _sample_count ); + } + } +} + + + + +void FASTCALL ladspaManager::setRunAddingGain( const ladspaKey & _plugin, + LADSPA_Handle _instance, + LADSPA_Data _gain ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + if( descriptor->run_adding!=NULL + && descriptor->set_run_adding_gain!=NULL ) + { + ( descriptor->set_run_adding_gain ) ( _instance, _gain ); + } + } +} + + + + +void FASTCALL ladspaManager::deactivate( const ladspaKey & _plugin, + LADSPA_Handle _instance ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + if( descriptor->deactivate != NULL ) + { + ( descriptor->deactivate ) ( _instance ); + } + } +} + + + + +void FASTCALL ladspaManager::cleanup( const ladspaKey & _plugin, + LADSPA_Handle _instance ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) + { + LADSPA_Descriptor_Function descriptorFunction + = m_ladspaManagerMap[_plugin]->descriptorFunction; + const LADSPA_Descriptor * descriptor + = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); + if( descriptor->cleanup != NULL ) + { + ( descriptor->cleanup ) ( _instance ); + } + } +} + diff --git a/src/widgets/knob.cpp b/src/widgets/knob.cpp index 7fbfb9eb4..f840098b5 100644 --- a/src/widgets/knob.cpp +++ b/src/widgets/knob.cpp @@ -162,8 +162,6 @@ void knob::setHintText( const QString & _txt_before, { m_hintTextBeforeValue = _txt_before; m_hintTextAfterValue = _txt_after; -/* toolTip::add( this, m_hintTextBeforeValue + QString::number( value() ) + - m_hintTextAfterValue );*/ } @@ -253,8 +251,6 @@ void knob::valueChange( void ) { recalcAngle(); update(); -/* toolTip::add( this, m_hintTextBeforeValue + QString::number( value() ) + - m_hintTextAfterValue );*/ if( m_tracking ) { emit valueChanged( value() ); @@ -474,22 +470,25 @@ void knob::mouseMoveEvent( QMouseEvent * _me ) //! Mouse Release Event handler -void knob::mouseReleaseEvent( QMouseEvent * _me ) +void knob::mouseReleaseEvent( QMouseEvent * /* _me*/ ) { - m_scrollMode = ScrNone; - buttonReleased(); + if( m_scrollMode != ScrNone ) + { + m_scrollMode = ScrNone; + buttonReleased(); + } switch( m_scrollMode ) { case ScrMouse: - setPosition( _me->pos() ); + //setPosition( _me->pos() ); m_direction = 0; m_mouseOffset = 0; - emit sliderReleased (); + emit sliderReleased(); break; case ScrDirect: - setPosition( _me->pos() ); + //setPosition( _me->pos() ); m_direction = 0; m_mouseOffset = 0; break; @@ -527,9 +526,6 @@ void knob::wheelEvent( QWheelEvent * _me ) QPoint( m_knobPixmap->width() + 2, 0 ) ); s_textFloat->setVisibilityTimeOut( 1000 ); -/* toolTip::add( this, m_hintTextBeforeValue+QString::number( value() ) + - m_hintTextAfterValue );*/ - if( value() != m_prevValue ) { emit sliderMoved( value() ); @@ -727,6 +723,12 @@ 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() );