diff --git a/ChangeLog b/ChangeLog index 03fead3dd..460544ac5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,67 @@ +2006-08-07 Danny McRae + * include/oscillator.h: + * plugins/vibed/vibrating_string.h: + * plugins/vibed/vibrating_string.cpp: + clean up some things that were preventing the getNextSample + methods from being inlined + + * configure.in: + -made ladspa support default off + -must pass --with-ladspa to get it to build + + * Makefile.am: + * data/themes/default/add.png: + * data/themes/default/analysis.png: + * data/themes/default/ports.png: + * data/themes/default/uhoh.png: + * data/themes/default/unavailable_sound.png: + * data/themes/blue_scene/add.png: + * data/themes/blue_scene/analysis.png: + * data/themes/blue_scene/ports.png: + * data/themes/blue_scene/uhoh.png: + * data/themes/blue_scene/unavailable_sound.png: + * include/audio_port.h: + * include/effect_chain.h: + * include/effect_tab_widget.h: + * include/effect.h: + * include/engine.h: + * include/group_box.h: + * include/instrument_track.h: + * include/ladspa_2_lmms.h: + * include/ladspa_browser.h: + * include/ladspa_control.h: + * include/ladspa_control_dialog.h: + * include/ladspa_description.h: + * include/ladspa_manager.h: + * include/ladspa_port_dialog.h: + * include/main_window.h: + * include/rack_plugin.h: + * include/rack_view.h: + * include/select_ladspa_dialog.h: + * src/lmms_single_source.cpp: + * src/audio/audio_port.cpp: + * src/core/effect_chain.cpp: + * src/core/effect_tab_widget.cpp: + * src/core/effect.cpp: + * src/core/engine.cpp: + * src/core/ladspa_browser.cpp: + * src/core/ladspa_control.cpp: + * src/core/ladspa_port_dialog.cpp: + * src/core/main_window.cpp: + * src/core/mixer.cpp: + * src/core/select_ladspa_dialog.cpp: + * src/lib/ladspa_2_lmms.cpp: + * src/lib/ladspa_manager.cpp: + * src/tracks/instrument_track.cpp: + * src/widgets/group_box.cpp: + * src/widgets/ladspa_control.cpp: + * src/widgets/ladspa_description.cpp: + * src/widgets/rack_plugin.cpp: + * src/widgets/rack_view.cpp: + -added preliminary support for ladspa effects + -no load or save + -expect segfaults + 2006-08-07 Javier Serrano Polo * include/lcd_spinbox.h: diff --git a/Makefile.am b/Makefile.am index 7a2338b17..24f9129d7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,6 +58,7 @@ lmms_MOC = \ ./combobox.moc \ ./config_mgr.moc \ ./cpuload_widget.moc \ + ./effect_tab_widget.moc \ ./envelope_and_lfo_widget.moc \ ./envelope_tab_widget.moc \ ./export_project_dialog.moc \ @@ -67,6 +68,11 @@ lmms_MOC = \ ./kmultitabbar.moc \ ./kmultitabbar-qt3.moc \ ./knob.moc \ + ./ladspa_browser.moc \ + ./ladspa_control.moc \ + ./ladspa_control_dialog.moc \ + ./ladspa_description.moc \ + ./ladspa_port_dialog.moc \ ./lcd_spinbox.moc \ ./led_checkbox.moc \ ./main_window.moc \ @@ -82,11 +88,14 @@ lmms_MOC = \ ./pixmap_button.moc \ ./plugin_browser.moc \ ./project_notes.moc \ + ./rack_plugin.moc \ + ./rack_view.moc \ ./rubberband.moc \ ./qxembed.moc \ ./rename_dialog.moc \ ./sample_buffer.moc \ ./sample_track.moc \ + ./select_ladspa_dialog.moc \ ./setup_dialog.moc \ ./side_bar.moc \ ./side_bar_widget.moc \ @@ -130,6 +139,9 @@ lmms_SOURCES = \ $(srcdir)/src/core/automation_editor.cpp \ $(srcdir)/src/core/bb_editor.cpp \ $(srcdir)/src/core/config_mgr.cpp \ + $(srcdir)/src/core/effect_chain.cpp \ + $(srcdir)/src/core/effect_tab_widget.cpp \ + $(srcdir)/src/core/effect.cpp \ $(srcdir)/src/core/engine.cpp \ $(srcdir)/src/core/envelope_and_lfo_widget.cpp \ $(srcdir)/src/core/envelope_tab_widget.cpp \ @@ -137,6 +149,9 @@ lmms_SOURCES = \ $(srcdir)/src/core/file_browser.cpp \ $(srcdir)/src/core/import_filter.cpp \ $(srcdir)/src/core/instrument.cpp \ + $(srcdir)/src/core/ladspa_browser.cpp \ + $(srcdir)/src/core/ladspa_control_dialog.cpp \ + $(srcdir)/src/core/ladspa_port_dialog.cpp \ $(srcdir)/src/core/main_window.cpp \ $(srcdir)/src/core/main.cpp \ $(srcdir)/src/core/midi_tab_widget.cpp \ @@ -150,6 +165,7 @@ lmms_SOURCES = \ $(srcdir)/src/core/plugin_browser.cpp \ $(srcdir)/src/core/preset_preview_play_handle.cpp \ $(srcdir)/src/core/sample_play_handle.cpp \ + $(srcdir)/src/core/select_ladspa_dialog.cpp \ $(srcdir)/src/core/setup_dialog.cpp \ $(srcdir)/src/core/song_editor.cpp \ $(srcdir)/src/core/track.cpp \ @@ -162,6 +178,7 @@ lmms_SOURCES = \ $(srcdir)/src/lib/journalling_object.cpp \ $(srcdir)/src/lib/project_journal.cpp \ $(srcdir)/src/lib/embed.cpp \ + $(srcdir)/src/lib/ladspa_2_lmms.cpp \ $(srcdir)/src/lib/ladspa_manager.cpp \ $(srcdir)/src/lib/mmp.cpp \ $(srcdir)/src/lib/oscillator.cpp \ @@ -187,11 +204,15 @@ lmms_SOURCES = \ $(srcdir)/src/widgets/group_box.cpp \ $(srcdir)/src/widgets/kmultitabbar.cpp \ $(srcdir)/src/widgets/knob.cpp \ + $(srcdir)/src/widgets/ladspa_control.cpp \ + $(srcdir)/src/widgets/ladspa_description.cpp \ $(srcdir)/src/widgets/lcd_spinbox.cpp \ $(srcdir)/src/widgets/led_checkbox.cpp \ $(srcdir)/src/widgets/nstate_button.cpp \ $(srcdir)/src/widgets/pixmap_button.cpp \ $(srcdir)/src/widgets/project_notes.cpp \ + $(srcdir)/src/widgets/rack_plugin.cpp \ + $(srcdir)/src/widgets/rack_view.cpp \ $(srcdir)/src/widgets/rubberband.cpp \ $(srcdir)/src/widgets/qxembed.cpp \ $(srcdir)/src/widgets/rename_dialog.cpp \ @@ -323,6 +344,18 @@ lmms_SOURCES = \ $(srcdir)/include/project_journal.h \ $(srcdir)/include/import_filter.h \ $(srcdir)/include/engine.h \ + $(srcdir)/include/effect.h \ + $(srcdir)/include/effect_chain.h \ + $(srcdir)/include/effect_tab_widget.h \ + $(srcdir)/include/ladspa_2_lmms.h \ + $(srcdir)/include/ladspa_browser.h \ + $(srcdir)/include/ladspa_control.h \ + $(srcdir)/include/ladspa_control_dialog.h \ + $(srcdir)/include/ladspa_description.h \ + $(srcdir)/include/ladspa_port_dialog.h \ + $(srcdir)/include/rack_plugin.h \ + $(srcdir)/include/rack_view.h \ + $(srcdir)/include/select_ladspa_dialog.h \ $(srcdir)/include/qxembed.h diff --git a/configure.in b/configure.in index c434ef617..67a80ef38 100644 --- a/configure.in +++ b/configure.in @@ -203,10 +203,8 @@ AM_CONDITIONAL(VST_SUPPORT, test ! -z "$WINEGCC") # check for LADSPA-SDK -AC_ARG_WITH(src, - AS_HELP_STRING([--without-ladspa], - [disable support for LADSPA-support]), , - [ with_ladspa=yes ]) +AC_ARG_WITH(ladspa, + AS_HELP_STRING([--with-ladspa], [enable support for LADSPA]), [ with_ladspa=yes ], [ with_ladspa=no ]) AH_TEMPLATE(HAVE_LADSPA_H, [Define to 1 if you have the header file.]) if test "x$with_ladspa" = "xyes" ; then AC_CHECK_HEADER(ladspa.h, HAVE_LADSPA_H="true") @@ -214,7 +212,7 @@ fi if test ! -z "$HAVE_LADSPA_H" ; then AC_DEFINE(HAVE_LADSPA_H) fi - +#AM_CONDITIONAL(HAVE_LADSPA_H, test ! -z "$HAVE_LADSPA_H") # check for vorbis-lib AC_ARG_WITH(vorbis, @@ -663,6 +661,27 @@ else fi + + +if test -z "$HAVE_LADSPA_H" ; then + echo " ========================" + echo " === LMMS - WARNING =======================================================" + echo " ========================" + echo " =" + echo " = If you want support for LADSPA based effects, please pass" + echo " = " + echo " = --with-ladspa" + echo " = " + echo " = to configure, LADSPA support is still experimental." + echo " =" + with_warnings="true" +else + PLUGINS_TO_BUILD="$PLUGINS_TO_BUILD\n\t\* LADSPA for effects processing" +fi + + + + if test "x$with_vst" = "xno" ; then echo " ========================" echo " === LMMS - INFORMATION ===================================================" diff --git a/data/themes/blue_scene/add.png b/data/themes/blue_scene/add.png new file mode 100644 index 000000000..5ceca2754 Binary files /dev/null and b/data/themes/blue_scene/add.png differ diff --git a/data/themes/blue_scene/analysis.png b/data/themes/blue_scene/analysis.png new file mode 100644 index 000000000..60e24198a Binary files /dev/null and b/data/themes/blue_scene/analysis.png differ diff --git a/data/themes/blue_scene/ports.png b/data/themes/blue_scene/ports.png new file mode 100644 index 000000000..306fa8be5 Binary files /dev/null and b/data/themes/blue_scene/ports.png differ diff --git a/data/themes/blue_scene/uhoh.png b/data/themes/blue_scene/uhoh.png new file mode 100644 index 000000000..1966fc8dd Binary files /dev/null and b/data/themes/blue_scene/uhoh.png differ diff --git a/data/themes/blue_scene/unavailable_sound.png b/data/themes/blue_scene/unavailable_sound.png new file mode 100644 index 000000000..f4a18bc7c Binary files /dev/null and b/data/themes/blue_scene/unavailable_sound.png differ diff --git a/data/themes/default/add.png b/data/themes/default/add.png new file mode 100644 index 000000000..5ceca2754 Binary files /dev/null and b/data/themes/default/add.png differ diff --git a/data/themes/default/analysis.png b/data/themes/default/analysis.png new file mode 100644 index 000000000..60e24198a Binary files /dev/null and b/data/themes/default/analysis.png differ diff --git a/data/themes/default/ports.png b/data/themes/default/ports.png new file mode 100644 index 000000000..306fa8be5 Binary files /dev/null and b/data/themes/default/ports.png differ diff --git a/data/themes/default/uhoh.png b/data/themes/default/uhoh.png new file mode 100644 index 000000000..1966fc8dd Binary files /dev/null and b/data/themes/default/uhoh.png differ diff --git a/data/themes/default/unavailable_sound.png b/data/themes/default/unavailable_sound.png new file mode 100644 index 000000000..f4a18bc7c Binary files /dev/null and b/data/themes/default/unavailable_sound.png differ diff --git a/include/audio_port.h b/include/audio_port.h index e9a74435e..6bea8d718 100644 --- a/include/audio_port.h +++ b/include/audio_port.h @@ -38,6 +38,10 @@ #endif +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT +#include "effect_chain.h" +#endif #include "mixer.h" #include "effect_board.h" @@ -76,6 +80,13 @@ public: return( m_nextFxChannel ); } +#ifdef LADSPA_SUPPORT + inline effectChain * getEffects( void ) + { + return( m_effects ); + } +#endif + void setNextFxChannel( const fx_ch_t _chnl ) { m_nextFxChannel = _chnl; @@ -94,7 +105,10 @@ public: { NONE, FIRST, BOTH } m_bufferUsage; - + +#ifdef LADSPA_SUPPORT + inline bool processEffects( void ) { return( m_effects->processAudioBuffer( m_firstBuffer, m_frames ) ); }; +#endif private: surroundSampleFrame * m_firstBuffer; @@ -103,6 +117,11 @@ private: fx_ch_t m_nextFxChannel; QString m_name; + +#ifdef LADSPA_SUPPORT + effectChain * m_effects; + fpab_t m_frames; +#endif } ; diff --git a/include/effect.h b/include/effect.h new file mode 100644 index 000000000..616a53678 --- /dev/null +++ b/include/effect.h @@ -0,0 +1,162 @@ +/* + * effect.h - base class for effects + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _EFFECT_H +#define _EFFECT_H + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#include "engine.h" +#include "ladspa_2_lmms.h" +#include "mixer.h" +#include "ladspa_control.h" + + +typedef enum bufferRates +{ + CHANNEL_IN, + CHANNEL_OUT, + AUDIO_RATE_INPUT, + AUDIO_RATE_OUTPUT, + CONTROL_RATE_INPUT, + CONTROL_RATE_OUTPUT +} buffer_rate_t; + +typedef enum bufferData +{ + TOGGLED, + INTEGER, + FLOAT, + NONE +} buffer_data_t; + +typedef struct portDescription +{ + QString name; + ch_cnt_t proc; + Uint16 port_id; + Uint16 control_id; + buffer_rate_t rate; + buffer_data_t data_type; + LADSPA_Data max; + LADSPA_Data min; + LADSPA_Data def; + LADSPA_Data value; + LADSPA_Data * buffer; + ladspaControl * control; +} port_desc_t; + +typedef vvector multi_proc_t; + +class effect: public engineObject +{ +public: + effect( const ladspa_key_t & _key, engine * _engine ); + ~effect(); + + bool FASTCALL processAudioBuffer( surroundSampleFrame * _buf, const fpab_t _frames ); + void FASTCALL setControl( Uint16 _control, LADSPA_Data _data ); + + inline const multi_proc_t & getControls( void ) + { + return( m_controls ); + } + + inline ch_cnt_t getProcessorCount( void ) + { + return( m_processors ); + } + + inline void setRunning( void ) + { + m_bufferCount = 0; + m_running = TRUE; + }; + + inline void setBypass( bool _mode ) + { + m_bypass = _mode; + } + + inline bool isRunning( void ) + { + return( m_running ); + } + + inline void setTimeout( Uint32 _time_out ) + { + m_silenceTimeout = _time_out; + } + + inline void setWetDry( float _wet ) + { + m_wetDry = _wet; + } + + inline const QString & getName( void ) + { + return( m_name ); + } + + void FASTCALL setGate( float _level ); + +private: + ladspa_key_t m_key; + ladspa2LMMS * m_ladspa; + QString m_name; + + ch_cnt_t m_processors; + Uint16 m_effectChannels; + Uint16 m_portCount; + + const LADSPA_Descriptor * m_descriptor; + vvector m_handles; + + vvector m_ports; + multi_proc_t m_controls; + + effect * m_output; + + bool m_okay; + bool m_noRun; + bool m_running; + bool m_bypass; + + Uint32 m_bufferCount; + Uint32 m_silenceTimeout; + + float m_wetDry; + float m_gate; +}; + +#endif + +#endif diff --git a/include/effect_chain.h b/include/effect_chain.h new file mode 100644 index 000000000..59144b3c8 --- /dev/null +++ b/include/effect_chain.h @@ -0,0 +1,74 @@ +/* + * effect_chain.h - class for processing and effects chain + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _EFFECT_CHAIN_H +#define _EFFECT_CHAIN_H + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include "qt3support.h" + +#include "engine.h" +#include "effect.h" + +typedef vvector effect_list_t; + +class effectChain: public engineObject +{ +public: + effectChain( engine * _engine ); + ~effectChain(); + + void FASTCALL appendEffect( effect * _effect ); + bool FASTCALL processAudioBuffer( surroundSampleFrame * _buf, const fpab_t _frames ); + void FASTCALL swapEffects( effect * _eff1, effect * _eff2 ); + void setRunning( void ); + bool isRunning( void ); + + inline void setBypass( bool _mode ) + { + m_bypassed = _mode; + } + + inline const effect_list_t & getEffects( void ) + { + return( m_effects ); + } + +private: + effect_list_t m_effects; + + bool m_bypassed; + +}; + +#endif + +#endif + + + + + diff --git a/include/effect_tab_widget.h b/include/effect_tab_widget.h new file mode 100644 index 000000000..baeb566d1 --- /dev/null +++ b/include/effect_tab_widget.h @@ -0,0 +1,99 @@ +/* + * effect_tab_widget.h - tab-widget in channel-track-window for setting up + * effects + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _EFFECT_TAB_WIDGET_H +#define _EFFECT_TAB_WIDGET_H + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include +#include +#include +#include +#include +#include + +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "journalling_object.h" +#include "engine.h" +#include "rack_plugin.h" +#include "rack_view.h" + + +class instrumentTrack; +class groupBox; + + +class effectTabWidget : public QWidget, public journallingObject +{ + Q_OBJECT +public: + effectTabWidget( instrumentTrack * _channel_track ); + virtual ~effectTabWidget(); + + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "fx" ); + } + +private slots: + void addEffect( void ); + void setBypass( bool _state ); + +private: + instrumentTrack * m_instrumentTrack; + + groupBox * m_effectsGroupBox; + QPushButton * m_addButton; + + rackView * m_rack; + + friend class instrumentTrack; + +} ; + + +#endif + +#endif diff --git a/include/engine.h b/include/engine.h index df8301f6c..e40f56fe6 100644 --- a/include/engine.h +++ b/include/engine.h @@ -35,6 +35,10 @@ class pianoRoll; class projectNotes; class songEditor; +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT +class ladspa2LMMS; +#endif class engine { @@ -103,6 +107,13 @@ public: return( m_automationEditor ); } +#ifdef LADSPA_SUPPORT + inline ladspa2LMMS * getLADSPAManager( void ) + { + return( m_ladspaManager ); + } +#endif + void close( void ); float framesPerTact64th( void ) const @@ -124,7 +135,11 @@ private: pianoRoll * m_pianoRoll; projectNotes * m_projectNotes; projectJournal * m_projectJournal; - + +#ifdef LADSPA_SUPPORT + ladspa2LMMS * m_ladspaManager; +#endif + } ; diff --git a/include/group_box.h b/include/group_box.h index a9c1c4825..d53816383 100644 --- a/include/group_box.h +++ b/include/group_box.h @@ -39,6 +39,7 @@ #endif #include "pixmap_button.h" +#include "ladspa_manager.h" class QPixmap; @@ -62,6 +63,10 @@ public slots: void setState( bool _on, bool _anim = FALSE ); void animate( void ); +#ifdef LADSPA_SUPPORT +signals: + void toggled( bool _state ); +#endif protected: virtual void resizeEvent( QResizeEvent * _re ); diff --git a/include/instrument_track.h b/include/instrument_track.h index b33be9397..6d4ab7ed2 100755 --- a/include/instrument_track.h +++ b/include/instrument_track.h @@ -27,6 +27,8 @@ #ifndef _INSTRUMENT_TRACK_H #define _INSTRUMENT_TRACK_H +#include "ladspa_manager.h" + #include "qt3support.h" #ifdef QT4 @@ -70,6 +72,9 @@ class surroundArea; class flpImport; +#ifdef LADSPA_SUPPORT +class effectTabWidget; +#endif class instrumentTrack : public QWidget, public track, public midiEventProcessor @@ -170,6 +175,11 @@ public: { return( m_pianoWidget ); } + + inline audioPort * getAudioPort( void ) + { + return( m_audioPort ); + } public slots: @@ -239,7 +249,9 @@ private: envelopeTabWidget * m_envWidget; arpAndChordsTabWidget * m_arpWidget; midiTabWidget * m_midiWidget; - +#ifdef LADSPA_SUPPORT + effectTabWidget * m_effWidget; +#endif // test-piano at the bottom of every instrument-settings-window pianoWidget * m_pianoWidget; diff --git a/include/ladspa_2_lmms.h b/include/ladspa_2_lmms.h new file mode 100644 index 000000000..ab21c7df7 --- /dev/null +++ b/include/ladspa_2_lmms.h @@ -0,0 +1,86 @@ +/* + * ladspa_2_lmms.h - class that identifies and instantiates LADSPA effects + * for use with LMMS + * + * Copyright (c) 2005 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _LADSPA_2_LMMS_H +#define _LADSPA_2_LMMS_H + + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include "engine.h" + +class ladspa2LMMS: public ladspaManager +{ + +public: + + inline l_sortable_plugin_t getInstruments( void ) + { + return( m_instruments ); + } + + inline l_sortable_plugin_t getValidEffects( void ) + { + return( m_validEffects ); + } + + inline l_sortable_plugin_t getInvalidEffects( void ) + { + return( m_invalidEffects ); + } + + inline l_sortable_plugin_t getAnalysisTools( void ) + { + return( m_analysisTools ); + } + + inline l_sortable_plugin_t getOthers( void ) + { + return( m_otherPlugins ); + } + + QString getShortName( const ladspa_key_t & _key ); + +private: + ladspa2LMMS( engine * _engine ); + ~ladspa2LMMS(); + +// engine * m_engine; +// ladspaManager * m_ladspa; + + l_sortable_plugin_t m_instruments; + l_sortable_plugin_t m_validEffects; + l_sortable_plugin_t m_invalidEffects; + l_sortable_plugin_t m_analysisTools; + l_sortable_plugin_t m_otherPlugins; + + friend class engine; + +}; + +#endif + +#endif diff --git a/include/ladspa_browser.h b/include/ladspa_browser.h new file mode 100644 index 000000000..ec000fbdb --- /dev/null +++ b/include/ladspa_browser.h @@ -0,0 +1,75 @@ +/* + * ladspa_browser.h - dialog to display information about installed LADSPA + * plugins + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _LADSPA_BROWSER_H +#define _LADSPA_BROWSER_H + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + +#include "engine.h" + +class QComboBox; +class QLabel; +class QLineEdit; +class QSlider; + +class tabBar; + + +class ladspaBrowser : public QDialog, public engineObject +{ + Q_OBJECT +public: + ladspaBrowser( engine * _engine ); + virtual ~ladspaBrowser(); + + inline void labelWidget( QWidget * _w, const QString & _txt ); + +public slots: + void showPorts( const ladspa_key_t & _key ); + void testLADSPA( const ladspa_key_t & _key ); + +private: + tabBar * m_tabBar; + +} ; + +#endif + +#endif diff --git a/include/ladspa_control.h b/include/ladspa_control.h new file mode 100644 index 000000000..73f8acf7d --- /dev/null +++ b/include/ladspa_control.h @@ -0,0 +1,58 @@ +/* + * ladspa_control.h - widget for controlling a LADSPA port + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _LADSPA_CONTROL_H +#define _LADSPA_CONTROL_H + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include + +#include "engine.h" +#include "instrument_track.h" +#include "knob.h" +#include "led_checkbox.h" + +typedef struct portDescription port_desc_t; + + +class ladspaControl : public QWidget, public engineObject +{ + Q_OBJECT +public: + ladspaControl( QWidget * _parent, port_desc_t * _port, engine * _engine, instrumentTrack * _track ); + ~ladspaControl(); + + LADSPA_Data getValue( void ); + +private: + port_desc_t * m_port; + ledCheckBox * m_toggle; + knob * m_knob; +}; + +#endif + +#endif diff --git a/include/ladspa_manager.h b/include/ladspa_manager.h index 532697ba0..44e9df10c 100644 --- a/include/ladspa_manager.h +++ b/include/ladspa_manager.h @@ -58,82 +58,107 @@ #include "types.h" +#include "qt3support.h" +class engine; -typedef QPair ladspaKey; +const float NOHINT = -99342.2243f; + +typedef QPair ladspa_key_t; +typedef QPair sortable_plugin_t; +typedef vlist l_sortable_plugin_t; +typedef vlist l_ladspa_key_t; /* 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 +The can be retrieved by using ladspa_key_t. For example, to get the "Phase Modulated Voice" plug-in from the cmt library, you would perform the calls using: - ladspaKey( "cmt.so", "phasemod" ) + ladspa_key_t key( "cmt.so", "phasemod" ) as the plug-in key. */ +enum pluginType +{ + SOURCE, + TRANSFER, + VALID, + INVALID, + SINK, + OTHER +}; + +typedef struct ladspaManagerStorage +{ + LADSPA_Descriptor_Function descriptorFunction; + Uint32 index; + pluginType type; + Uint16 inputChannels; + Uint16 outputChannels; +} ladspaManagerDescription; + + 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 ); - } + + ladspaManager( engine * _engine ); + ~ladspaManager(); + l_sortable_plugin_t getSortedPlugins(); + ladspaManagerDescription * getDescription( const ladspa_key_t & + _plugin ); + /* 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 ); + QString FASTCALL getLabel( const ladspa_key_t & _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 ); + bool FASTCALL hasRealTimeDependency( const ladspa_key_t & _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 ); + bool FASTCALL isInplaceBroken( const ladspa_key_t & _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 ); + bool FASTCALL isRealTimeCapable( const ladspa_key_t & _plugin ); /* Returns the name of the plug-in */ - QString FASTCALL getName( const ladspaKey & _plugin ); + QString FASTCALL getName( const ladspa_key_t & _plugin ); /* Returns the the plug-in's author */ - QString FASTCALL getMaker( const ladspaKey & _plugin ); + QString FASTCALL getMaker( const ladspa_key_t & _plugin ); /* Returns the copyright for the plug-in */ - QString FASTCALL getCopyright( const ladspaKey & _plugin ); + QString FASTCALL getCopyright( const ladspa_key_t & _plugin ); /* This indicates the number of ports (input AND output) present on the plugin. */ - Uint32 FASTCALL getPortCount( const ladspaKey & _plugin ); + Uint32 FASTCALL getPortCount( const ladspa_key_t & _plugin ); /* Indicates that the port is an input. */ - bool FASTCALL isPortInput( const ladspaKey & _plugin, Uint32 _port ); + bool FASTCALL isPortInput( const ladspa_key_t & _plugin, Uint32 _port ); /* Indicates that the port is an output. */ - bool FASTCALL isPortOutput( const ladspaKey & _plugin, Uint32 _port ); + bool FASTCALL isPortOutput( const ladspa_key_t & _plugin, Uint32 _port ); /* Indicates that the port is an audio. */ - bool FASTCALL isPortAudio( const ladspaKey & _plugin, Uint32 _port ); + bool FASTCALL isPortAudio( const ladspa_key_t & _plugin, Uint32 _port ); /* Indicates that the port is an control. */ - bool FASTCALL isPortControl( const ladspaKey & _plugin, Uint32 _port ); + bool FASTCALL isPortControl( const ladspa_key_t & _plugin, Uint32 _port ); /* Indicates that any bounds specified should be interpreted as multiples of the sample rate. For instance, a frequency range from @@ -141,44 +166,44 @@ public: 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, + bool FASTCALL areHintsSampleRateDependent( const ladspa_key_t & _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 ); + float FASTCALL getLowerBound( const ladspa_key_t & _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 ); + float FASTCALL getUpperBound( const ladspa_key_t & _plugin, Uint32 _port ); /* Indicates whether the given port should be considered 0 or 1 boolean switch. */ - bool FASTCALL isPortToggled( const ladspaKey & _plugin, Uint32 _port ); + bool FASTCALL isPortToggled( const ladspa_key_t & _plugin, Uint32 _port ); /* Retrieves any default setting hints offered by the plug-in for the given port. */ - float FASTCALL getDefaultSetting( const ladspaKey & _plugin, + float FASTCALL getDefaultSetting( const ladspa_key_t & _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 ); + bool FASTCALL isLogarithmic( const ladspa_key_t & _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 ); + bool FASTCALL isInteger( const ladspa_key_t & _plugin, Uint32 _port ); /* Returns the name of the port. */ - QString FASTCALL getPortName( const ladspaKey & _plugin, Uint32 _port ); + QString FASTCALL getPortName( const ladspa_key_t & _plugin, Uint32 _port ); /* This may be used by the plugin developer to pass any custom @@ -187,13 +212,13 @@ public: writers will not use this facility as LADSPA_Handle should be used to hold instance data. */ const void * FASTCALL getImplementationData( - const ladspaKey & _plugin ); + const ladspa_key_t & _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 ); + const ladspa_key_t & _plugin ); /* The following methods are convenience functions for use during @@ -203,7 +228,7 @@ public: /* Returns a handle to an instantiation of the given plug-in. */ - LADSPA_Handle FASTCALL instantiate( const ladspaKey & _plugin, + LADSPA_Handle FASTCALL instantiate( const ladspa_key_t & _plugin, Uint32 _sample_rate ); /* This method calls a function pointer that connects a port on an @@ -223,7 +248,7 @@ public: connectPort() must be called at least once for each port before run() or runAdding() is called. */ - void FASTCALL connectPort( const ladspaKey & _plugin, + bool FASTCALL connectPort( const ladspa_key_t & _plugin, LADSPA_Handle _instance, Uint32 _port, LADSPA_Data * _data_location ); @@ -247,7 +272,7 @@ public: 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, + bool FASTCALL activate( const ladspa_key_t & _plugin, LADSPA_Handle _instance ); /* This method calls a function pointer that runs an instance of a @@ -260,7 +285,7 @@ public: 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, + bool FASTCALL run( const ladspa_key_t & _plugin, LADSPA_Handle _instance, Uint32 _sample_count ); /* This method calls a function pointer that runs an instance of a @@ -276,7 +301,7 @@ public: 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, + bool FASTCALL runAdding( const ladspa_key_t & _plugin, LADSPA_Handle _instance, Uint32 _sample_count ); @@ -289,7 +314,7 @@ public: 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, + bool FASTCALL setRunAddingGain( const ladspa_key_t & _plugin, LADSPA_Handle _instance, LADSPA_Data _gain ); @@ -306,7 +331,7 @@ public: 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, + bool FASTCALL deactivate( const ladspa_key_t & _plugin, LADSPA_Handle _instance ); /* Once an instance of a plugin has been finished with it can be @@ -316,27 +341,21 @@ public: 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, + bool FASTCALL cleanup( const ladspa_key_t & _plugin, LADSPA_Handle _instance ); private: void FASTCALL addPlugins( LADSPA_Descriptor_Function _descriptor_func, - const QString & _file ); + const QString & _file ); + Uint16 FASTCALL getPluginInputs( const LADSPA_Descriptor * _descriptor ); + Uint16 FASTCALL getPluginOutputs( const LADSPA_Descriptor * _descriptor ); - ladspaManager( void ); - ~ladspaManager(); - - - static ladspaManager * s_instanceOfMe; - - typedef struct ladspaManagerStorage - { - LADSPA_Descriptor_Function descriptorFunction; - Uint32 index; - } ladspaManagerDescription; - - typedef QMap ladspaManagerMapType; + typedef QMap + ladspaManagerMapType; ladspaManagerMapType m_ladspaManagerMap; + l_sortable_plugin_t m_sortedPlugins; + + friend class engine; } ; diff --git a/include/ladspa_port_dialog.h b/include/ladspa_port_dialog.h new file mode 100644 index 000000000..ff446d0b8 --- /dev/null +++ b/include/ladspa_port_dialog.h @@ -0,0 +1,61 @@ +/* + * ladspa_port_dialog.h - dialog to test a LADSPA plugin + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#ifndef _LADSPA_PORT_DIALOG_H +#define _LADSPA_PORT_DIALOG_H + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "ladspa_2_lmms.h" + + +class ladspaPortDialog : public QDialog, public engineObject +{ + Q_OBJECT +public: + ladspaPortDialog( const ladspa_key_t & _key, + engine * _engine ); + virtual ~ladspaPortDialog(); + +private: + ladspa_key_t m_key; + ladspa2LMMS * m_ladspa; + +}; + +#endif + +#endif + diff --git a/include/main_window.h b/include/main_window.h index f52212449..892fa93f9 100644 --- a/include/main_window.h +++ b/include/main_window.h @@ -50,6 +50,7 @@ #include "types.h" #include "engine.h" +#include "ladspa_manager.h" class QDomElement; @@ -118,6 +119,7 @@ public slots: void showSettingsDialog( void ); void aboutLMMS( void ); void help( void ); + void ladspaPluginBrowser( void ); void toggleAutomationEditorWin( void ); void toggleBBEditorWin( void ); void toggleSongEditorWin( void ); diff --git a/include/oscillator.h b/include/oscillator.h index 59749e613..3872ace55 100644 --- a/include/oscillator.h +++ b/include/oscillator.h @@ -185,10 +185,10 @@ private: float syncInit( sampleFrame * _ab, const fpab_t _frames, const ch_cnt_t _chnl ); - bool syncOk( float _osc_coeff ); + inline bool syncOk( float _osc_coeff ); - sample_t getSample( const float _sample ); - void FASTCALL recalcPhase( void ); + inline sample_t getSample( const float _sample ); + inline void FASTCALL recalcPhase( void ); } ; diff --git a/include/rack_plugin.h b/include/rack_plugin.h new file mode 100644 index 000000000..244cf6b48 --- /dev/null +++ b/include/rack_plugin.h @@ -0,0 +1,82 @@ +/* + * effect_tab_widget.h - tab-widget in channel-track-window for setting up + * effects + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#ifndef _RACK_PLUGIN_H +#define _RACK_PLUGIN_H + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include +#include +#include +#include + +#include "journalling_object.h" +#include "led_checkbox.h" +#include "instrument_track.h" +#include "embossed_font_label.h" +#include "effect.h" +#include "ladspa_control_dialog.h" + + +class knob; + + +class rackPlugin: public QWidget, public journallingObject +{ + Q_OBJECT + +public: + rackPlugin( QWidget * _parent, ladspa_key_t _key, instrumentTrack * _track, engine * _engine ); + ~rackPlugin(); + + QString nodeName( void ) const + { + return( "plugin" ); + } + +public slots: + void editControls( void ); + void bypassed( bool _state ); + void setWetDry( float _value ); + void setAutoQuit( float _value ); + void setGate( float _value ); + +private: + ledCheckBox * m_bypass; + knob * m_wetDry; + knob * m_autoQuit; + knob * m_gate; + QGroupBox * m_grouper; + QGroupBox * m_controls; + QLabel * m_label; + QPushButton * m_editButton; + effect * m_effect; + ladspaControlDialog * m_controlView; +}; + +#endif + +#endif diff --git a/include/rack_view.h b/include/rack_view.h new file mode 100644 index 000000000..36b677950 --- /dev/null +++ b/include/rack_view.h @@ -0,0 +1,65 @@ +/* + * right_frame.h - provides the display for the rackInsert instances + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#ifndef _RIGHT_FRAME_H +#define _RIGHT_FRAME_H + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include +#include +#include +#include +#include + +#include "types.h" +#include "engine.h" +#include "rack_plugin.h" +#include "instrument_track.h" + + +class rackView: public QWidget, public engineObject +{ + Q_OBJECT + +public: + rackView( QWidget * _parent, engine * _engine, instrumentTrack * _track ); + ~rackView(); + + void addPlugin( ladspa_key_t _key ); + +private: + QPtrList m_rackInserts; + int m_insertIndex; + + QVBoxLayout * m_mainLayout; + QScrollView * m_scrollView; + QVBox * m_rack; + + instrumentTrack * m_instrumentTrack; +}; + +#endif + +#endif diff --git a/plugins/vibed/vibrating_string.cpp b/plugins/vibed/vibrating_string.cpp index 31710bd06..bb38fc4c3 100644 --- a/plugins/vibed/vibrating_string.cpp +++ b/plugins/vibed/vibrating_string.cpp @@ -44,6 +44,7 @@ vibratingString::vibratingString( float _pitch, m_stringLoss( 1.0f - _string_loss ), m_state( 0.1f ) { + m_outsamp = bufferAllocator::alloc( m_oversample ); int string_length; string_length = static_cast( m_oversample *_sample_rate / diff --git a/plugins/vibed/vibrating_string.h b/plugins/vibed/vibrating_string.h index 149e091a3..1ba8d1d10 100644 --- a/plugins/vibed/vibrating_string.h +++ b/plugins/vibed/vibrating_string.h @@ -49,6 +49,7 @@ public: inline ~vibratingString( void ) { + bufferAllocator::free( m_outsamp ); bufferAllocator::free( m_impulse ); vibratingString::freeDelayLine( m_fromBridge ); vibratingString::freeDelayLine( m_toBridge ); @@ -56,15 +57,14 @@ public: inline sample_t nextSample( void ) { - sample_t outsamp[m_oversample]; sample_t ym0; sample_t ypM; for( Uint8 i = 0; i < m_oversample; i++) { // Output at pickup position - outsamp[i] = fromBridgeAccess( m_fromBridge, + m_outsamp[i] = fromBridgeAccess( m_fromBridge, m_pickupLoc ); - outsamp[i] += toBridgeAccess( m_toBridge, + m_outsamp[i] += toBridgeAccess( m_toBridge, m_pickupLoc ); // Sample traveling into "bridge" @@ -81,7 +81,7 @@ public: // Update and then increment pointer toBridgeUpdate( m_toBridge, -ypM ); } - return( outsamp[m_choice] ); + return( m_outsamp[m_choice] ); } private: @@ -104,6 +104,8 @@ private: int m_choice; float m_state; + sample_t * m_outsamp; + delayLine * FASTCALL initDelayLine( int _len, int _pick ); static void FASTCALL freeDelayLine( delayLine * _dl ); void FASTCALL resample( float *_src, diff --git a/src/audio/audio_port.cpp b/src/audio/audio_port.cpp index e1e898343..53c01520b 100644 --- a/src/audio/audio_port.cpp +++ b/src/audio/audio_port.cpp @@ -24,12 +24,17 @@ * */ +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT +#include "mixer.h" +#include "audio_device.h" +#include "config_mgr.h" +#endif #include "audio_port.h" #include "audio_device.h" #include "buffer_allocator.h" - audioPort::audioPort( const QString & _name, engine * _engine ) : engineObject( _engine ), m_bufferUsage( NONE ), @@ -47,6 +52,10 @@ audioPort::audioPort( const QString & _name, engine * _engine ) : eng()->getMixer()->framesPerAudioBuffer() ); eng()->getMixer()->addAudioPort( this ); setExtOutputEnabled( TRUE ); +#ifdef LADSPA_SUPPORT + m_frames = configManager::inst()->value( "mixer", "framesperaudiobuffer" ).toInt(); + m_effects = new effectChain( eng() ); +#endif } diff --git a/src/core/effect.cpp b/src/core/effect.cpp new file mode 100644 index 000000000..a041688df --- /dev/null +++ b/src/core/effect.cpp @@ -0,0 +1,383 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * effect.cpp - class for processing LADSPA effects + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include "qmessagebox.h" + +#include "effect.h" +#include "mixer.h" +#include "config_mgr.h" +#include "buffer_allocator.h" +#include "audio_device.h" +#include "ladspa_control.h" + + +effect::effect( const ladspa_key_t & _key, engine * _engine ) : + engineObject( _engine ), + m_key( _key ), + m_ladspa( _engine->getLADSPAManager() ), + m_output( NULL ), + m_okay( TRUE ), + m_noRun( FALSE ), + m_running( TRUE ), + m_bypass( FALSE ), + m_bufferCount( 0 ), + m_silenceTimeout( 10 ), + m_wetDry( 1.0f ), + m_gate( 0.0f ) +{ + if( m_ladspa->getDescription( _key ) == NULL ) + { + QMessageBox::warning( 0, "Effect", "Uknown LADSPA plugin requested: " + _key.first, QMessageBox::Ok, QMessageBox::NoButton ); + m_okay = FALSE; + return; + } + + m_name = m_ladspa->getShortName( _key ); + + // Calculate how many processing units are needed. + ch_cnt_t lmms_chnls = eng()->getMixer()->audioDev()->channels(); + m_effectChannels = m_ladspa->getDescription( _key )->inputChannels; + m_processors = lmms_chnls / m_effectChannels; + + // Categorize the ports, and create the buffers. + fpab_t buffer_size = configManager::inst()->value( "mixer", "framesperaudiobuffer" ).toInt(); + m_portCount = m_ladspa->getPortCount( _key ); + + for( ch_cnt_t proc = 0; proc < m_processors; proc++ ) + { + multi_proc_t ports; + for( Uint16 port = 0; port < m_portCount; port++ ) + { + port_desc_t * p = new portDescription; + + p->name = m_ladspa->getPortName( _key, port ); + p->proc = proc; + p->port_id = port; + + // Determine the port's category. + if( m_ladspa->isPortAudio( _key, port ) ) + { + // Nasty manual memory management--was having difficulty + // with some prepackaged plugins that were segfaulting + // during cleanup. It was easier to troubleshoot with the + // memory management all taking place in one file. + p->buffer = new LADSPA_Data[buffer_size]; + + if( p->name.upper().contains( "IN" ) && m_ladspa->isPortInput( _key, port ) ) + { + p->rate = CHANNEL_IN; + } + else if( p->name.upper().contains( "OUT" ) && m_ladspa->isPortOutput( _key, port ) ) + { + p->rate = CHANNEL_OUT; + } + else if( m_ladspa->isPortInput( _key, port ) ) + { + p->rate = AUDIO_RATE_INPUT; + } + else + { + p->rate = AUDIO_RATE_OUTPUT; + } + } + else + { + p->buffer = new LADSPA_Data; + + if( m_ladspa->isPortInput( _key, port ) ) + { + p->rate = CONTROL_RATE_INPUT; + } + else + { + p->rate = CONTROL_RATE_OUTPUT; + } + } + + if( m_ladspa->isPortToggled( _key, port ) ) + { + p->data_type = TOGGLED; + } + else if( m_ladspa->isInteger( _key, port ) ) + { + p->data_type = INTEGER; + } + else + { + p->data_type = FLOAT; + } + + // Get the range and default values. + p->max = m_ladspa->getUpperBound( _key, port ); + + if( p->max == NOHINT ) + { + p->max = 999999.0f; + } + else if( m_ladspa->areHintsSampleRateDependent( _key, port ) ) + { + p->max *= eng()->getMixer()->sampleRate(); + } + + p->min = m_ladspa->getLowerBound( _key, port ); + if( p->min == NOHINT ) + { + p->min = -999999.0f; + } + else if( m_ladspa->areHintsSampleRateDependent( _key, port ) ) + { + p->min *= eng()->getMixer()->sampleRate(); + } + + p->def = m_ladspa->getDefaultSetting( _key, port ); + if( p->def == NOHINT ) + { + if( p->data_type != TOGGLED ) + { + p->def = ( p->min + p->max ) / 2.0f; + } + else + { + p->def = 1.0f; + } + } + + p->value = p->def; + + + ports.append( p ); + + // For convenience, keep a separate list of the ports that are used + // to control the processors. + if( p->rate == AUDIO_RATE_INPUT || p->rate == CONTROL_RATE_INPUT ) + { + p->control_id = m_controls.count(); + m_controls.append( p ); + } + } + m_ports.append( ports ); + } + + // Instantiate the processing units. + m_descriptor = m_ladspa->getDescriptor( _key ); + if( m_descriptor == NULL ) + { + QMessageBox::warning( 0, "Effect", "Can't get LADSPA descriptor function: " + _key.first, QMessageBox::Ok, QMessageBox::NoButton ); + m_okay = FALSE; + return; + } + if( m_descriptor->run == NULL ) + { + QMessageBox::warning( 0, "Effect", "Plugin has no processor: " + _key.first, QMessageBox::Ok, QMessageBox::NoButton ); + m_noRun = TRUE; + } + for( ch_cnt_t proc = 0; proc < m_processors; proc++ ) + { + LADSPA_Handle effect = m_ladspa->instantiate( _key, eng()->getMixer()->sampleRate() ); + if( effect == NULL ) + { + QMessageBox::warning( 0, "Effect", "Can't get LADSPA instance: " + _key.first, QMessageBox::Ok, QMessageBox::NoButton ); + m_okay = FALSE; + return; + } + m_handles.append( effect ); + + } + + // Connect the ports. + for( ch_cnt_t proc = 0; proc < m_processors; proc++ ) + { + for( Uint16 port = 0; port < m_portCount; port++ ) + { + if( !m_ladspa->connectPort( _key, m_handles[proc], port, m_ports[proc][port]->buffer ) ) + { + QMessageBox::warning( 0, "Effect", "Failed to connect port: " + _key.first, QMessageBox::Ok, QMessageBox::NoButton ); + m_noRun = TRUE; + } + } + } + + // Activate the processing units. + for( ch_cnt_t proc = 0; proc < m_processors; proc++ ) + { + m_ladspa->activate( _key, m_handles[proc] ); + } +} + + + + +effect::~effect() +{ + if( !m_okay ) + { + return; + } + + for( ch_cnt_t proc = 0; proc < m_processors; proc++ ) + { + m_ladspa->deactivate( m_key, m_handles[proc] ); + m_ladspa->cleanup( m_key, m_handles[proc] ); + for( Uint16 port = 0; port < m_portCount; port++ ) + { + free( m_ports[proc][port]->buffer ); + free( m_ports[proc][port] ); + } + m_ports[proc].clear(); + } + m_ports.clear(); + m_handles.clear(); +} + + + + +bool FASTCALL effect::processAudioBuffer( surroundSampleFrame * _buf, const fpab_t _frames ) +{ + if( !m_okay || m_noRun || !m_running || m_bypass ) + { + return( FALSE ); + } + + // Copy the LMMS audio buffer to the LADSPA input buffer and initialize + // the control ports. Need to change this to handle non-in-place-broken + // plugins--would speed things up to use the same buffer for both + // LMMS and LADSPA. + ch_cnt_t channel = 0; + for( ch_cnt_t proc = 0; proc < m_processors; proc++) + { + for( Uint16 port = 0; port < m_portCount; port++ ) + { + switch( m_ports[proc][port]->rate ) + { + case CHANNEL_IN: + for( fpab_t frame = 0; frame < _frames; frame++ ) + { + m_ports[proc][port]->buffer[frame] = _buf[frame][channel]; + } + channel++; + break; + case AUDIO_RATE_INPUT: + m_ports[proc][port]->value = static_cast( m_ports[proc][port]->control->getValue() ); + // This only supports control rate ports, so the audio rates are + // treated as though they were control rate by setting the + // port buffer to all the same value. + for( fpab_t frame = 0; frame < _frames; frame++ ) + { + m_ports[proc][port]->buffer[frame] = m_ports[proc][port]->value; + } + break; + case CONTROL_RATE_INPUT: + m_ports[proc][port]->value = static_cast( m_ports[proc][port]->control->getValue() ); + m_ports[proc][port]->buffer[0] = m_ports[proc][port]->value; + break; + case CHANNEL_OUT: + case AUDIO_RATE_OUTPUT: + case CONTROL_RATE_OUTPUT: + break; + default: + break; + } + } + } + + // Process the buffers. + for( ch_cnt_t proc = 0; proc < m_processors; proc++ ) + { + (m_descriptor->run)(m_handles[proc], _frames); + } + + // Copy the LADSPA output buffers to the LMMS buffer. + double out_sum = 0.0; + channel = 0; + for( ch_cnt_t proc = 0; proc < m_processors; proc++) + { + for( Uint16 port = 0; port < m_portCount; port++ ) + { + switch( m_ports[proc][port]->rate ) + { + case CHANNEL_IN: + case AUDIO_RATE_INPUT: + case CONTROL_RATE_INPUT: + break; + case CHANNEL_OUT: + for( fpab_t frame = 0; frame < _frames; frame++ ) + { + _buf[frame][channel] = ( 1.0f - m_wetDry ) * _buf[frame][channel] + m_wetDry * m_ports[proc][port]->buffer[frame]; + out_sum += _buf[frame][channel] * _buf[frame][channel]; + } + channel++; + break; + case AUDIO_RATE_OUTPUT: + case CONTROL_RATE_OUTPUT: + break; + default: + break; + } + } + } + + // Check whether we need to continue processing input. + if( out_sum <= ( m_gate * _frames * channel ) ) + { + m_bufferCount++; + if( m_bufferCount > m_silenceTimeout ) + { + m_running = FALSE; + m_bufferCount = 0; + } + } + + return( m_running ); +} + + + +void FASTCALL effect::setControl( Uint16 _control, LADSPA_Data _value ) +{ + if( !m_okay ) + { + return; + } + m_controls[_control]->value = _value; +} + + + + +void FASTCALL effect::setGate( float _level ) +{ + m_gate = _level; +} + + + +#endif + +#endif diff --git a/src/core/effect_chain.cpp b/src/core/effect_chain.cpp new file mode 100644 index 000000000..ffd66eefa --- /dev/null +++ b/src/core/effect_chain.cpp @@ -0,0 +1,142 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * effect_chain.cpp - class for processing and effects chain + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include "effect_chain.h" + +effectChain::effectChain( engine * _engine ): + engineObject( _engine ), + m_bypassed( TRUE ) +{ +} + + + + +effectChain::~ effectChain() +{ + for( Uint32 eff = 0; eff < m_effects.count(); eff++ ) + { + free( m_effects[eff] ); + } + m_effects.clear(); +} + + + + +void FASTCALL effectChain::appendEffect( effect * _effect ) +{ + m_effects.append( _effect ); +} + + + + +bool FASTCALL effectChain::processAudioBuffer( surroundSampleFrame * _buf, const fpab_t _frames ) +{ + if( m_bypassed ) + { + return( FALSE ); + } + + bool more_effects = FALSE; + for( effect_list_t::iterator it = m_effects.begin(); it != m_effects.end(); it++ ) + { + more_effects |= (*it)->processAudioBuffer( _buf, _frames ); + } + return( more_effects ); +} + + + + +void effectChain::setRunning( void ) +{ + if( m_bypassed ) + { + return; + } + + for( effect_list_t::iterator it = m_effects.begin(); it != m_effects.end(); it++ ) + { + (*it)->setRunning(); + } +} + + + + +bool effectChain::isRunning( void ) +{ + if( m_bypassed ) + { + return( FALSE ); + } + + bool running = FALSE; + + for( effect_list_t::iterator it = m_effects.begin(); it != m_effects.end() || !running; it++ ) + { + running = (*it)->isRunning() && running; + } + return( running ); +} + + + + +void FASTCALL effectChain::swapEffects( effect * _eff1, effect * _eff2 ) +{ + Uint32 eff1_loc = m_effects.count(); + Uint32 eff2_loc = m_effects.count(); + + Uint32 count = 0; + for( effect_list_t::iterator it = m_effects.begin(); it != m_effects.end(); it++ ) + { + if( (*it) == _eff1 ) + { + eff1_loc = count; + } + if( (*it) == _eff2 ) + { + eff2_loc = count; + } + count++; + } + + if( eff1_loc < m_effects.count() && eff2_loc < m_effects.count() ) + { + m_effects[eff1_loc] = _eff2; + m_effects[eff2_loc] = _eff1; + } +} + +#endif + +#endif diff --git a/src/core/effect_tab_widget.cpp b/src/core/effect_tab_widget.cpp new file mode 100644 index 000000000..7b2b08e76 --- /dev/null +++ b/src/core/effect_tab_widget.cpp @@ -0,0 +1,131 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * effect_tab_widget.cpp - tab-widget in channel-track-window for setting up + * effects + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include +#include + +#endif + + +#include "effect_tab_widget.h" +#include "instrument_track.h" +#include "group_box.h" +#include "tooltip.h" +#include "embed.h" +#include "select_ladspa_dialog.h" +#include "rack_plugin.h" +#include "audio_port.h" + + +effectTabWidget::effectTabWidget( instrumentTrack * _instrument_track ) : + QWidget( _instrument_track->tabWidgetParent() ), + journallingObject( _instrument_track->eng() ), + m_instrumentTrack( _instrument_track ) +{ + m_effectsGroupBox = new groupBox( tr( "EFFECTS CHAIN" ), this, eng(), _instrument_track ); + connect( m_effectsGroupBox, SIGNAL( toggled( bool ) ), this, SLOT( setBypass( bool ) ) ); + m_effectsGroupBox->setGeometry( 2, 2, 242, 244 ); + + m_rack = new rackView( m_effectsGroupBox, eng(), _instrument_track ); + m_rack->move( 6, 22 ); + + m_addButton = new QPushButton( m_effectsGroupBox, "Add Effect" ); + m_addButton->setText( tr( "Add" ) ); + m_addButton->move( 75, 210 ); + connect( m_addButton, SIGNAL( clicked( void ) ), this, SLOT( addEffect( void ) ) ); +} + + + + +effectTabWidget::~effectTabWidget() +{ +} + + + + +void effectTabWidget::saveSettings( QDomDocument & _doc, QDomElement & _this ) +{ + _this.setAttribute( "fxdisabled", !m_effectsGroupBox->isActive() ); + +} + + + + +void effectTabWidget::loadSettings( const QDomElement & _this ) +{ + m_effectsGroupBox->setState( !_this.attribute( "fxdisabled" ).toInt() ); +} + + + + +void effectTabWidget::addEffect( void ) +{ + selectLADSPADialog sl( this, eng() ); + sl.exec(); + + if( sl.result() == QDialog::Rejected ) + { + return; + } + + ladspa_key_t key = sl.getSelection(); + m_rack->addPlugin( key ); +} + + + + +void effectTabWidget::setBypass( bool _state ) +{ + m_instrumentTrack->getAudioPort()->getEffects()->setBypass( !_state ); +} + +#include "effect_tab_widget.moc" + + +#endif + +#endif diff --git a/src/core/engine.cpp b/src/core/engine.cpp index 1f0bfefcc..50cffd05f 100644 --- a/src/core/engine.cpp +++ b/src/core/engine.cpp @@ -37,6 +37,10 @@ #include "project_notes.h" #include "song_editor.h" +#ifdef LADSPA_SUPPORT +#include "ladspa_2_lmms.h" +#endif + engine::engine( const bool _has_gui ) : m_hasGUI( _has_gui ), @@ -57,6 +61,10 @@ engine::engine( const bool _has_gui ) : m_pianoRoll = new pianoRoll( this ); m_automationEditor = new automationEditor( this ); +#ifdef LADSPA_SUPPORT + m_ladspaManager = new ladspa2LMMS( this ); +#endif + m_mixer->initDevices(); m_mainWindow->finalize(); diff --git a/src/core/ladspa_browser.cpp b/src/core/ladspa_browser.cpp new file mode 100644 index 000000000..5f7fd944c --- /dev/null +++ b/src/core/ladspa_browser.cpp @@ -0,0 +1,262 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * ladspa_browser.h - dialog to display information about installed LADSPA + * plugins + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + +#include "ladspa_browser.h" + +#include "tab_bar.h" +#include "tab_button.h" +#include "tab_widget.h" +#include "gui_templates.h" +#include "config_mgr.h" +#include "embed.h" +#include "debug.h" +#include "tooltip.h" +#include "ladspa_description.h" +#include "ladspa_port_dialog.h" +#include "effect.h" +#include "audio_device.h" +#include "buffer_allocator.h" +#include "effect_chain.h" + +inline void ladspaBrowser::labelWidget( QWidget * _w, const QString & _txt ) +{ + QLabel * title = new QLabel( _txt, _w ); + QFont f = title->font(); + f.setBold( TRUE ); + title->setFont( pointSize<12>( f ) ); + +#ifdef LMMS_DEBUG + assert( dynamic_cast( _w->layout() ) != NULL ); +#endif + dynamic_cast( _w->layout() )->addSpacing( 5 ); + dynamic_cast( _w->layout() )->addWidget( title ); + dynamic_cast( _w->layout() )->addSpacing( 10 ); +} + + + + +ladspaBrowser::ladspaBrowser( engine * _engine ) : + QDialog(), + engineObject( _engine ) +{ + setWindowIcon( embed::getIconPixmap( "setup_general" ) ); + setWindowTitle( tr( "LADSPA Plugin Browser" ) ); + setModal( TRUE ); + + QVBoxLayout * vlayout = new QVBoxLayout( this ); + vlayout->setSpacing( 0 ); + vlayout->setMargin( 0 ); + QWidget * settings = new QWidget( this ); + QHBoxLayout * hlayout = new QHBoxLayout( settings ); + hlayout->setSpacing( 0 ); + hlayout->setMargin( 0 ); + + m_tabBar = new tabBar( settings, QBoxLayout::TopToBottom ); + m_tabBar->setExclusive( TRUE ); + m_tabBar->setFixedWidth( 72 ); + + QWidget * ws = new QWidget( settings ); + ws->setFixedSize( 500, 400 ); + + QWidget * available = new QWidget( ws ); + available->setFixedSize( 500, 340 ); + QVBoxLayout * avl_layout = new QVBoxLayout( available ); + avl_layout->setSpacing( 0 ); + avl_layout->setMargin( 0 ); + labelWidget( available, tr( "Available Effects" ) ); + + ladspaDescription * available_list = new ladspaDescription(available, _engine, VALID ); + connect( available_list, SIGNAL( doubleClicked( const ladspa_key_t & ) ), + SLOT( showPorts( const ladspa_key_t & ) ) ); + avl_layout->addWidget( available_list ); + + + QWidget * unavailable = new QWidget( ws ); + unavailable->setFixedSize( 500, 340 ); + QVBoxLayout * unavl_layout = new QVBoxLayout( unavailable ); + unavl_layout->setSpacing( 0 ); + unavl_layout->setMargin( 0 ); + labelWidget( unavailable, tr( "Unavailable Effects" ) ); + + ladspaDescription * unavailable_list = new ladspaDescription(unavailable, _engine, INVALID ); + connect( unavailable_list, SIGNAL( doubleClicked( const ladspa_key_t & ) ), + SLOT( showPorts( const ladspa_key_t & ) ) ); + unavl_layout->addWidget( unavailable_list ); + + + QWidget * instruments = new QWidget( ws ); + instruments->setFixedSize( 500, 340 ); + QVBoxLayout * inst_layout = new QVBoxLayout( instruments ); + inst_layout->setSpacing( 0 ); + inst_layout->setMargin( 0 ); + labelWidget( instruments, tr( "Instruments" ) ); + + ladspaDescription * instruments_list = new ladspaDescription(instruments, _engine, SOURCE ); + connect( instruments_list, SIGNAL( doubleClicked( const ladspa_key_t & ) ), + SLOT( showPorts( const ladspa_key_t & ) ) ); + inst_layout->addWidget( instruments_list ); + + + QWidget * analysis = new QWidget( ws ); + analysis->setFixedSize( 500, 340 ); + QVBoxLayout * anal_layout = new QVBoxLayout( analysis ); + anal_layout->setSpacing( 0 ); + anal_layout->setMargin( 0 ); + labelWidget( analysis, tr( "Analysis Tools" ) ); + + ladspaDescription * analysis_list = new ladspaDescription(analysis, _engine, SINK ); + connect( analysis_list, SIGNAL( doubleClicked( const ladspa_key_t & ) ), + SLOT( showPorts( const ladspa_key_t & ) ) ); + anal_layout->addWidget( analysis_list ); + + + QWidget * other = new QWidget( ws ); + other->setFixedSize( 500, 340 ); + QVBoxLayout * other_layout = new QVBoxLayout( other ); + other_layout->setSpacing( 0 ); + other_layout->setMargin( 0 ); + labelWidget( other, tr( "Don't know" ) ); + + ladspaDescription * other_list = new ladspaDescription(other, _engine, OTHER ); + connect( other_list, SIGNAL( doubleClicked( const ladspa_key_t & ) ), + SLOT( showPorts( const ladspa_key_t & ) ) ); + other_layout->addWidget( other_list ); + +#ifndef QT4 +#define setIcon setPixmap +#endif + + m_tabBar->addTab( available, tr( "Available Effects" ), 0, FALSE, TRUE + )->setIcon( embed::getIconPixmap( "setup_audio" ) ); + m_tabBar->addTab( unavailable, tr( "Unavailable Effects" ), 1, FALSE, TRUE + )->setIcon( embed::getIconPixmap( + "unavailable_sound" ) ); + m_tabBar->addTab( instruments, tr( "Instruments" ), 2, FALSE, + TRUE )->setIcon( embed::getIconPixmap( + "setup_midi" ) ); + m_tabBar->addTab( analysis, tr( "Analysis Tools" ), 3, FALSE, TRUE + )->setIcon( embed::getIconPixmap( "analysis" ) ); + m_tabBar->addTab( other, tr( "Don't know" ), 4, TRUE, TRUE + )->setIcon( embed::getIconPixmap( "uhoh" ) ); + +#undef setIcon + + m_tabBar->setActiveTab( 0 ); + + hlayout->addWidget( m_tabBar ); + hlayout->addSpacing( 10 ); + hlayout->addWidget( ws ); + hlayout->addSpacing( 10 ); + hlayout->addStretch(); + + QWidget * buttons = new QWidget( this ); + QHBoxLayout * btn_layout = new QHBoxLayout( buttons ); + btn_layout->setSpacing( 0 ); + btn_layout->setMargin( 0 ); + + QPushButton * cancel_btn = new QPushButton( embed::getIconPixmap( + "cancel" ), + tr( "Close" ), + buttons ); + connect( cancel_btn, SIGNAL( clicked() ), this, SLOT( reject() ) ); + + btn_layout->addStretch(); + btn_layout->addSpacing( 10 ); + btn_layout->addWidget( cancel_btn ); + btn_layout->addSpacing( 10 ); + + vlayout->addWidget( settings ); + vlayout->addSpacing( 10 ); + vlayout->addWidget( buttons ); + vlayout->addSpacing( 10 ); + vlayout->addStretch(); + + show(); + + +} + + + + +ladspaBrowser::~ladspaBrowser() +{ +} + + + + +void ladspaBrowser::showPorts( const ladspa_key_t & _key ) +{ + ladspaPortDialog ports( _key, eng() ); + ports.exec(); +} + + + + +void ladspaBrowser::testLADSPA( const ladspa_key_t & _key ) +{ + effect * eff1 = new effect( _key, eng() ); + effect * eff2 = new effect( _key, eng() ); + effectChain chain( eng() ); + + chain.appendEffect( eff1 ); + chain.appendEffect( eff2 ); + + fpab_t buf_size = eng()->getMixer()->audioDev()->channels(); + surroundSampleFrame * buffer = bufferAllocator::alloc( buf_size ); + for( Uint8 i = 0; i < 100; i++ ) + { + chain.processAudioBuffer( buffer, buf_size ); + } + bufferAllocator::free( buffer ); +} + + + +#include "ladspa_browser.moc" + +#endif + +#endif diff --git a/src/core/ladspa_port_dialog.cpp b/src/core/ladspa_port_dialog.cpp new file mode 100644 index 000000000..f5bd96c82 --- /dev/null +++ b/src/core/ladspa_port_dialog.cpp @@ -0,0 +1,224 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * ladspa_port_dialog.cpp - dialog to test a LADSPA plugin + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "qt3support.h" + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#ifdef QT4 + +#include + +#else + +#include +#include + +#endif + +#include "ladspa_port_dialog.h" + +#include "embed.h" +#include "mixer.h" + + +ladspaPortDialog::ladspaPortDialog( const ladspa_key_t & _key, + engine * _engine ) : + QDialog(), + engineObject( _engine ), + m_key( _key ), + m_ladspa( _engine->getLADSPAManager() ) +{ + setWindowIcon( embed::getIconPixmap( "ports" ) ); + setWindowTitle( "Ports" ); + setModal( TRUE ); +// setFixedSize( 500, 500 ); + + QVBoxLayout * vlayout = new QVBoxLayout( this ); + vlayout->setSpacing( 0 ); + vlayout->setMargin( 0 ); + QWidget * settings = new QWidget( this ); + + Uint16 pc = m_ladspa->getPortCount( m_key ); + + QTable * display = new QTable( pc, 7, settings ); + + QStringList ports; + ports.append( tr( "Name" ) ); + ports.append( tr( "Rate" ) ); + ports.append( tr( "Direction" ) ); + ports.append( tr( "Type" ) ); + ports.append( tr( "Min < Default < Max" ) ); + ports.append( tr( "Logarithmic" ) ); + ports.append( tr( "SR Dependent" ) ); + + QStringList port_nums; + for(Uint16 row = 0; row < pc; row++) + { + port_nums.append( QString::number( row ) ); + Uint8 col = 0; + display->setText( row, col, m_ladspa->getPortName( m_key, row ) ); + col++; + + if( m_ladspa->isPortAudio( m_key, row ) ) + { + display->setText( row, col, tr( "Audio" ) ); + } + else + { + display->setText( row, col, tr( "Control" ) ); + } + col++; + + if( m_ladspa->isPortInput( m_key, row ) ) + { + display->setText( row, col, tr( "Input" ) ); + } + else + { + display->setText( row, col, tr( "Output" ) ); + } + col++; + + if( m_ladspa->isPortToggled( m_key, row ) ) + { + display->setText( row, col, tr( "Toggled" ) ); + } + else if( m_ladspa->isInteger( m_key, row ) ) + { + display->setText( row, col, tr( "Integer" ) ); + } + else + { + display->setText( row, col, tr( "Float" ) ); + } + col++; + + float min = m_ladspa->getLowerBound( m_key, row ); + float max = m_ladspa->getUpperBound( m_key, row ); + float def = m_ladspa->getDefaultSetting( m_key, row ); + QString range = ""; + + if( m_ladspa->areHintsSampleRateDependent( m_key, row ) ) + { + if( min != NOHINT ) + { + min *= eng()->getMixer()->sampleRate(); + } + if( max != NOHINT ) + { + max *= eng()->getMixer()->sampleRate(); + } + } + + if( min == NOHINT ) + { + range += "-Inf < "; + } + else if( m_ladspa->isInteger( m_key, row ) ) + { + range += QString::number( static_cast( min ) ) + " < "; + } + else + { + range += QString::number( min ) + " < "; + } + + if( def == NOHINT ) + { + range += "None < "; + } + else if( m_ladspa->isInteger( m_key, row ) ) + { + range += QString::number( static_cast( def ) ) + " < "; + } + else + { + range += QString::number( def ) + " < "; + } + + if( max == NOHINT ) + { + range += "Inf"; + } + else if( m_ladspa->isInteger( m_key, row ) ) + { + range += QString::number( static_cast( max ) ); + } + else + { + range += QString::number( max ); + } + + if( m_ladspa->isPortOutput( m_key, row ) || + m_ladspa->isPortToggled( m_key, row ) ) + { + range = ""; + } + display->setText( row, col, range ); + col++; + + if( m_ladspa->isLogarithmic( m_key, row ) ) + { + display->setText( row, col, tr( "Yes" ) ); + } + col++; + + if( m_ladspa->areHintsSampleRateDependent( m_key, row ) ) + { + display->setText( row, col, tr( "Yes" ) ); + } + col++; + } + + display->setColumnLabels( ports ); + display->setRowLabels( port_nums ); + display->setReadOnly( true ); + + for(Uint8 col = 0; col < ports.count(); col++ ) + { + display->adjustColumn( col ); + } + + vlayout->addWidget( settings ); + + setFixedSize( display->width(), display->height() ); + + show(); +} + + + +ladspaPortDialog::~ ladspaPortDialog() +{ +} + +#include "ladspa_port_dialog.moc" + +#endif + +#endif diff --git a/src/core/main_window.cpp b/src/core/main_window.cpp index c47a0f335..a43e82782 100644 --- a/src/core/main_window.cpp +++ b/src/core/main_window.cpp @@ -81,6 +81,10 @@ #include "project_journal.h" #include "automation_editor.h" +#ifdef LADSPA_SUPPORT +#include "ladspa_browser.h" +#endif + #if QT_VERSION >= 0x030100 QSplashScreen * mainWindow::s_splashScreen = NULL; @@ -527,13 +531,26 @@ void mainWindow::finalize( void ) help_menu->addAction( embed::getIconPixmap( "whatsthis" ), tr( "What's this?" ), this, SLOT( enterWhatsThisMode() ) ); + + +#ifdef LADSPA_SUPPORT +#ifdef QT4 + help_menu->addSeparator(); +#else + help_menu->insertSeparator(); +#endif + help_menu->addAction( embed::getIconPixmap( "help" ), tr( "LADSPA Plugins..." ), + this, SLOT( ladspaPluginBrowser() ) ); +#endif + + #ifdef QT4 help_menu->addSeparator(); #else help_menu->insertSeparator(); #endif help_menu->addAction( embed::getIconPixmap( "icon" ), tr( "About" ), - this, SLOT( aboutLMMS() ) ); + this, SLOT( aboutLMMS() ) ); // setup-dialog opened before? if( !configManager::inst()->value( "app", "configured" ).toInt() ) @@ -803,12 +820,25 @@ void mainWindow::aboutLMMS( void ) void mainWindow::help( void ) { QMessageBox::information( this, tr( "Help not available" ), - tr( "Currently there's no help " - "available in LMMS.\n" - "Please visit " - "http://wiki.mindrules.net " - "for documentation on LMMS." ), - QMessageBox::Ok ); + tr( "Currently there's no help " + "available in LMMS.\n" + "Please visit " + "http://wiki.mindrules.net " + "for documentation on LMMS." ), + QMessageBox::Ok ); +} + + + + +void mainWindow::ladspaPluginBrowser( void ) +{ + // moc for Qt 3.x doesn't recognize preprocessor directives, + // so we can't just block the whole thing out. +#ifdef LADSPA_SUPPORT + ladspaBrowser lb( eng() ); + lb.exec(); +#endif } diff --git a/src/core/mixer.cpp b/src/core/mixer.cpp index 9b12e94c6..d0269b837 100644 --- a/src/core/mixer.cpp +++ b/src/core/mixer.cpp @@ -278,10 +278,18 @@ const surroundSampleFrame * mixer::renderNextBuffer( void ) eng()->getSongEditor()->processNextBuffer(); +#ifdef LADSPA_SUPPORT + bool more_effects = FALSE; +#endif for( vvector::iterator it = m_audioPorts.begin(); it != m_audioPorts.end(); ++it ) { +#ifdef LADSPA_SUPPORT + more_effects |= ( *it )->processEffects(); + if( ( *it )->m_bufferUsage != audioPort::NONE || more_effects ) +#else if( ( *it )->m_bufferUsage != audioPort::NONE ) +#endif { processBuffer( ( *it )->firstBuffer(), ( *it )->nextFxChannel() ); diff --git a/src/lib/ladspa_2_lmms.cpp b/src/lib/ladspa_2_lmms.cpp new file mode 100644 index 000000000..ad572401f --- /dev/null +++ b/src/lib/ladspa_2_lmms.cpp @@ -0,0 +1,135 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * ladspa_2_lmms.cpp - class that identifies and instantiates LADSPA effects + * for use with LMMS + * + * Copyright (c) 2005 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include "ladspa_2_lmms.h" + + +ladspa2LMMS::ladspa2LMMS( engine * _engine ): + ladspaManager( _engine ) +{ + l_sortable_plugin_t plugins = getSortedPlugins(); + + for( l_sortable_plugin_t::iterator it = plugins.begin(); + it != plugins.end(); it++ ) + { + ladspa_key_t key = (*it).second; + ladspaManagerDescription * desc = getDescription( key ); + + if( desc->type == SOURCE ) + { + m_instruments.append( qMakePair( getName( key ), + key ) ); + } + else if( desc->type == TRANSFER && + ( desc->inputChannels == desc->outputChannels && + ( desc->inputChannels == 1 || + desc->inputChannels == 2 || + desc->inputChannels == 4 ) && + isRealTimeCapable( key ) ) ) + { + m_validEffects.append( qMakePair( getName( key ), + key ) ); + } + else if( desc->type == TRANSFER && + ( desc->inputChannels != desc->outputChannels || + ( desc->inputChannels != 1 && + desc->inputChannels != 2 && + desc->inputChannels != 4 ) || + !isRealTimeCapable( key ) ) ) + { + m_invalidEffects.append( qMakePair( getName( key ), + key ) ); + } + else if( desc->type == SINK ) + { + m_analysisTools.append( qMakePair( getName( key ), + key ) ); + } + else if( desc->type == OTHER ) + { + m_otherPlugins.append( qMakePair( getName( key ), + key ) ); + } + } +} + + + + +ladspa2LMMS::~ladspa2LMMS() +{ +} + + + +QString ladspa2LMMS::getShortName( const ladspa_key_t & _key ) +{ + QString name = getName( _key ); + + if( name.find( "(" ) > 0 ) + { + name = name.left( name.find( "(" ) ); + } + if( name.find( " - " ) > 0 ) + { + name = name.left( name.find( " - " ) ); + } + if( name.find( " " ) > 0 ) + { + name = name.left( name.find( " " ) ); + } + if( name.find( " with ", 0, FALSE ) > 0 ) + { + name = name.left( name.find( " with ", 0, FALSE ) ); + } + if( name.find( ",", 0, FALSE ) > 0 ) + { + name = name.left( name.find( ",", 0, FALSE ) ); + } + if( name.length() > 40 ) + { + Uint8 i = 40; + while( name[i] != ' ' && i != 0 ) + { + i--; + } + name = name.left( i ); + } + if( name.length() == 0 ) + { + name = "LADSPA Plugin"; + } + + return( name ); +} + +#endif + +#endif diff --git a/src/lib/ladspa_manager.cpp b/src/lib/ladspa_manager.cpp index bb080e925..f37151c72 100644 --- a/src/lib/ladspa_manager.cpp +++ b/src/lib/ladspa_manager.cpp @@ -53,10 +53,7 @@ -ladspaManager * ladspaManager::s_instanceOfMe = NULL; - - -ladspaManager::ladspaManager( void ) +ladspaManager::ladspaManager( engine * _engine ) { // TODO Need to move the search path definition to the config file to // have more control over where it tries to find the plugins. @@ -65,8 +62,13 @@ ladspaManager::ladspaManager( void ) split( ':' ); #else QStringList ladspaDirectories = QStringList::split( ':', - QString( getenv( "LADSPA_PATH" ) ) ); + QString( getenv( "LADSPA_PATH" ) ) ); #endif + + //*********DELETE THIS********* + ladspaDirectories.push_back( "/usr/lib/ladspa" ); + //*********DELETE THIS********* + // set default-directory if nothing is specified... if( ladspaDirectories.isEmpty() ) { @@ -91,51 +93,38 @@ ladspaManager::ladspaManager( void ) #endif for( QFileInfoList::iterator file = list.begin(); file != list.end(); ++file ) - { +{ #ifdef QT4 const QFileInfo & f = *file; #else const QFileInfo & f = **file; #endif QLibrary plugin_lib( f.absoluteFilePath() ); -/* pluginHandle = dlopen( f.absoluteFilePath(). -#ifdef QT4 - toAscii().constData(), -#else - ascii(), -#endif - RTLD_LAZY ); - if( pluginHandle ) - { - dlerror();*/ + if( plugin_lib.load() == TRUE ) { LADSPA_Descriptor_Function descriptorFunction = - ( LADSPA_Descriptor_Function ) plugin_lib.resolve( + ( LADSPA_Descriptor_Function ) plugin_lib.resolve( "ladspa_descriptor" ); - if( /*dlerror() == NULL &&*/ - descriptorFunction != NULL ) + if( descriptorFunction != NULL ) { #ifndef QT4 plugin_lib.setAutoUnload( FALSE ); #endif addPlugins( descriptorFunction, - f.fileName() ); + f.fileName() ); } -/* else - { - dlclose( ( void * ) - f.absoluteFilePath(). -#ifdef QT4 - toAscii().constData() -#else - ascii() -#endif - ); - }*/ } } } + + l_ladspa_key_t keys = m_ladspaManagerMap.keys(); + for( l_ladspa_key_t::iterator it = keys.begin(); + it != keys.end(); it++ ) + { + m_sortedPlugins.append( qMakePair( getName( *it ), *it ) ); + } + qHeapSort( m_sortedPlugins ); } @@ -143,20 +132,29 @@ ladspaManager::ladspaManager( void ) ladspaManager::~ladspaManager() { - // we trust in auto-unloading-mechanisms of OS -/* for( ladspaManagerMapType::Iterator it = m_ladspaManagerMap.begin(); - it != m_ladspaManagerMap.end(); ++it ) +} + + + + +ladspaManagerDescription * ladspaManager::getDescription( const ladspa_key_t & + _plugin ) +{ + if( m_ladspaManagerMap.contains( _plugin ) ) { - dlclose( it.value()->pluginHandle ); + return( m_ladspaManagerMap[_plugin] ); + } + else + { + return( NULL ); } - m_ladspaManagerMap.clear();*/ } void FASTCALL ladspaManager::addPlugins( - LADSPA_Descriptor_Function _descriptor_func, + LADSPA_Descriptor_Function _descriptor_func, const QString & _file ) { const LADSPA_Descriptor * descriptor; @@ -168,8 +166,29 @@ void FASTCALL ladspaManager::addPlugins( new ladspaManagerDescription; plugIn->descriptorFunction = _descriptor_func; plugIn->index = pluginIndex; + plugIn->inputChannels = getPluginInputs( descriptor ); + plugIn->outputChannels = getPluginOutputs( descriptor ); + + if( plugIn->inputChannels == 0 && plugIn->outputChannels > 0 ) + { + plugIn->type = SOURCE; + } + else if( plugIn->inputChannels > 0 && + plugIn->outputChannels > 0 ) + { + plugIn->type = TRANSFER; + } + else if( plugIn->inputChannels > 0 && + plugIn->outputChannels == 0 ) + { + plugIn->type = SINK; + } + else + { + plugIn->type = OTHER; + } - ladspaKey key( _file, QString( descriptor->Label ) ); + ladspa_key_t key( QString( descriptor->Label ), _file ); m_ladspaManagerMap[key] = plugIn; ++pluginIndex; } @@ -178,7 +197,63 @@ void FASTCALL ladspaManager::addPlugins( -QString FASTCALL ladspaManager::getLabel( const ladspaKey & _plugin ) +Uint16 FASTCALL ladspaManager::getPluginInputs( + const LADSPA_Descriptor * _descriptor ) +{ + Uint16 inputs = 0; + + for( Uint16 port = 0; port < _descriptor->PortCount; port++ ) + { + if( + LADSPA_IS_PORT_INPUT( _descriptor->PortDescriptors[port] ) && + LADSPA_IS_PORT_AUDIO( _descriptor->PortDescriptors[port] ) ) + { + QString name = QString( _descriptor->PortNames[port] ); + if( name.upper().contains( "IN" ) ) + { + inputs++; + } + } + } + return inputs; +} + + + + +Uint16 FASTCALL ladspaManager::getPluginOutputs( + const LADSPA_Descriptor * _descriptor ) +{ + Uint16 outputs = 0; + + for( Uint16 port = 0; port < _descriptor->PortCount; port++ ) + { + if( + LADSPA_IS_PORT_OUTPUT( _descriptor->PortDescriptors[port] ) && + LADSPA_IS_PORT_AUDIO( _descriptor->PortDescriptors[port] ) ) + { + QString name = QString( _descriptor->PortNames[port] ); + if( name.upper().contains( "OUT" ) ) + { + outputs++; + } + } + } + return outputs; +} + + + + +l_sortable_plugin_t ladspaManager::getSortedPlugins() +{ + return( m_sortedPlugins ); +} + + + + +QString FASTCALL ladspaManager::getLabel( const ladspa_key_t & _plugin ) { if( m_ladspaManagerMap.contains( _plugin ) ) { @@ -198,7 +273,7 @@ QString FASTCALL ladspaManager::getLabel( const ladspaKey & _plugin ) -bool FASTCALL ladspaManager::hasRealTimeDependency( const ladspaKey & _plugin ) +bool FASTCALL ladspaManager::hasRealTimeDependency( const ladspa_key_t & _plugin ) { if( m_ladspaManagerMap.contains( _plugin ) ) { @@ -218,7 +293,7 @@ bool FASTCALL ladspaManager::hasRealTimeDependency( const ladspaKey & _plugin ) -bool FASTCALL ladspaManager::isInplaceBroken( const ladspaKey & _plugin ) +bool FASTCALL ladspaManager::isInplaceBroken( const ladspa_key_t & _plugin ) { if( m_ladspaManagerMap.contains( _plugin ) ) { @@ -238,7 +313,7 @@ bool FASTCALL ladspaManager::isInplaceBroken( const ladspaKey & _plugin ) -bool FASTCALL ladspaManager::isRealTimeCapable( const ladspaKey & _plugin ) +bool FASTCALL ladspaManager::isRealTimeCapable( const ladspa_key_t & _plugin ) { if( m_ladspaManagerMap.contains( _plugin ) ) { @@ -258,7 +333,7 @@ bool FASTCALL ladspaManager::isRealTimeCapable( const ladspaKey & _plugin ) -QString FASTCALL ladspaManager::getName( const ladspaKey & _plugin ) +QString FASTCALL ladspaManager::getName( const ladspa_key_t & _plugin ) { if( m_ladspaManagerMap.contains( _plugin ) ) { @@ -278,7 +353,7 @@ QString FASTCALL ladspaManager::getName( const ladspaKey & _plugin ) -QString FASTCALL ladspaManager::getMaker( const ladspaKey & _plugin ) +QString FASTCALL ladspaManager::getMaker( const ladspa_key_t & _plugin ) { if( m_ladspaManagerMap.contains( _plugin ) ) { @@ -298,7 +373,7 @@ QString FASTCALL ladspaManager::getMaker( const ladspaKey & _plugin ) -QString FASTCALL ladspaManager::getCopyright( const ladspaKey & _plugin ) +QString FASTCALL ladspaManager::getCopyright( const ladspa_key_t & _plugin ) { if( m_ladspaManagerMap.contains( _plugin ) ) { @@ -318,7 +393,7 @@ QString FASTCALL ladspaManager::getCopyright( const ladspaKey & _plugin ) -Uint32 FASTCALL ladspaManager::getPortCount( const ladspaKey & _plugin ) +Uint32 FASTCALL ladspaManager::getPortCount( const ladspa_key_t & _plugin ) { if( m_ladspaManagerMap.contains( _plugin ) ) { @@ -338,7 +413,7 @@ Uint32 FASTCALL ladspaManager::getPortCount( const ladspaKey & _plugin ) -bool FASTCALL ladspaManager::isPortInput( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::isPortInput( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -362,7 +437,7 @@ bool FASTCALL ladspaManager::isPortInput( const ladspaKey & _plugin, -bool FASTCALL ladspaManager::isPortOutput( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::isPortOutput( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -386,7 +461,7 @@ bool FASTCALL ladspaManager::isPortOutput( const ladspaKey & _plugin, -bool FASTCALL ladspaManager::isPortAudio( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::isPortAudio( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -410,7 +485,7 @@ bool FASTCALL ladspaManager::isPortAudio( const ladspaKey & _plugin, -bool FASTCALL ladspaManager::isPortControl( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::isPortControl( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -435,7 +510,7 @@ bool FASTCALL ladspaManager::isPortControl( const ladspaKey & _plugin, bool FASTCALL ladspaManager::areHintsSampleRateDependent( - const ladspaKey & _plugin, + const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -459,7 +534,7 @@ bool FASTCALL ladspaManager::areHintsSampleRateDependent( -float FASTCALL ladspaManager::getLowerBound( const ladspaKey & _plugin, +float FASTCALL ladspaManager::getLowerBound( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -478,19 +553,19 @@ float FASTCALL ladspaManager::getLowerBound( const ladspaKey & _plugin, } else { - return( -999e-99 ); + return( NOHINT ); } } else { - return( -999e-99 ); + return( NOHINT ); } } -float FASTCALL ladspaManager::getUpperBound( const ladspaKey & _plugin, Uint32 _port ) +float FASTCALL ladspaManager::getUpperBound( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) && _port < getPortCount( _plugin ) ) @@ -504,23 +579,23 @@ float FASTCALL ladspaManager::getUpperBound( const ladspaKey & _plugin, descriptor->PortRangeHints[_port].HintDescriptor; if( LADSPA_IS_HINT_BOUNDED_ABOVE( hintDescriptor ) ) { - return( descriptor->PortRangeHints[_port].LowerBound ); + return( descriptor->PortRangeHints[_port].UpperBound ); } else { - return( -999e-99 ); + return( NOHINT ); } } else { - return( -999e-99 ); + return( NOHINT ); } } -bool FASTCALL ladspaManager::isPortToggled( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::isPortToggled( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -544,7 +619,7 @@ bool FASTCALL ladspaManager::isPortToggled( const ladspaKey & _plugin, -float FASTCALL ladspaManager::getDefaultSetting( const ladspaKey & _plugin, +float FASTCALL ladspaManager::getDefaultSetting( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -560,7 +635,7 @@ float FASTCALL ladspaManager::getDefaultSetting( const ladspaKey & _plugin, switch( hintDescriptor & LADSPA_HINT_DEFAULT_MASK ) { case LADSPA_HINT_DEFAULT_NONE: - return( -999e-99 ); + return( NOHINT ); case LADSPA_HINT_DEFAULT_MINIMUM: return( descriptor->PortRangeHints[_port]. LowerBound ); @@ -619,19 +694,19 @@ float FASTCALL ladspaManager::getDefaultSetting( const ladspaKey & _plugin, case LADSPA_HINT_DEFAULT_440: return( 440.0 ); default: - return( -999e-99 ); + return( NOHINT ); } } else { - return( -999e-99 ); + return( NOHINT ); } } -bool FASTCALL ladspaManager::isLogarithmic( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::isLogarithmic( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -655,7 +730,7 @@ bool FASTCALL ladspaManager::isLogarithmic( const ladspaKey & _plugin, -bool FASTCALL ladspaManager::isInteger( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::isInteger( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -679,7 +754,7 @@ bool FASTCALL ladspaManager::isInteger( const ladspaKey & _plugin, -QString FASTCALL ladspaManager::getPortName( const ladspaKey & _plugin, +QString FASTCALL ladspaManager::getPortName( const ladspa_key_t & _plugin, Uint32 _port ) { if( m_ladspaManagerMap.contains( _plugin ) @@ -703,7 +778,7 @@ QString FASTCALL ladspaManager::getPortName( const ladspaKey & _plugin, const void * FASTCALL ladspaManager::getImplementationData( - const ladspaKey & _plugin ) + const ladspa_key_t & _plugin ) { if( m_ladspaManagerMap.contains( _plugin ) ) { @@ -724,7 +799,7 @@ const void * FASTCALL ladspaManager::getImplementationData( const LADSPA_Descriptor * FASTCALL ladspaManager::getDescriptor( - const ladspaKey & _plugin ) + const ladspa_key_t & _plugin ) { if( m_ladspaManagerMap.contains( _plugin ) ) { @@ -744,7 +819,7 @@ const LADSPA_Descriptor * FASTCALL ladspaManager::getDescriptor( -LADSPA_Handle FASTCALL ladspaManager::instantiate( const ladspaKey & _plugin, +LADSPA_Handle FASTCALL ladspaManager::instantiate( const ladspa_key_t & _plugin, Uint32 _sample_rate ) { if( m_ladspaManagerMap.contains( _plugin ) ) @@ -766,7 +841,7 @@ LADSPA_Handle FASTCALL ladspaManager::instantiate( const ladspaKey & _plugin, -void FASTCALL ladspaManager::connectPort( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::connectPort( const ladspa_key_t & _plugin, LADSPA_Handle _instance, Uint32 _port, LADSPA_Data * _data_location ) @@ -783,14 +858,16 @@ void FASTCALL ladspaManager::connectPort( const ladspaKey & _plugin, { ( descriptor->connect_port ) ( _instance, _port, _data_location ); + return( TRUE ); } } + return( FALSE ); } -void FASTCALL ladspaManager::activate( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::activate( const ladspa_key_t & _plugin, LADSPA_Handle _instance ) { if( m_ladspaManagerMap.contains( _plugin ) ) @@ -803,14 +880,16 @@ void FASTCALL ladspaManager::activate( const ladspaKey & _plugin, if( descriptor->activate != NULL ) { ( descriptor->activate ) ( _instance ); + return( TRUE ); } } + return( FALSE ); } -void FASTCALL ladspaManager::run( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::run( const ladspa_key_t & _plugin, LADSPA_Handle _instance, Uint32 _sample_count ) { @@ -824,14 +903,16 @@ void FASTCALL ladspaManager::run( const ladspaKey & _plugin, if( descriptor->run != NULL ) { ( descriptor->run ) ( _instance, _sample_count ); + return( TRUE ); } } + return( FALSE ); } -void FASTCALL ladspaManager::runAdding( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::runAdding( const ladspa_key_t & _plugin, LADSPA_Handle _instance, Uint32 _sample_count ) { @@ -846,14 +927,16 @@ void FASTCALL ladspaManager::runAdding( const ladspaKey & _plugin, descriptor->set_run_adding_gain != NULL ) { ( descriptor->run_adding ) ( _instance, _sample_count ); + return( TRUE ); } } + return( FALSE ); } -void FASTCALL ladspaManager::setRunAddingGain( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::setRunAddingGain( const ladspa_key_t & _plugin, LADSPA_Handle _instance, LADSPA_Data _gain ) { @@ -869,14 +952,16 @@ void FASTCALL ladspaManager::setRunAddingGain( const ladspaKey & _plugin, { ( descriptor->set_run_adding_gain ) ( _instance, _gain ); + return( TRUE ); } } + return( FALSE ); } -void FASTCALL ladspaManager::deactivate( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::deactivate( const ladspa_key_t & _plugin, LADSPA_Handle _instance ) { if( m_ladspaManagerMap.contains( _plugin ) ) @@ -889,14 +974,16 @@ void FASTCALL ladspaManager::deactivate( const ladspaKey & _plugin, if( descriptor->deactivate != NULL ) { ( descriptor->deactivate ) ( _instance ); + return( TRUE ); } } + return( FALSE ); } -void FASTCALL ladspaManager::cleanup( const ladspaKey & _plugin, +bool FASTCALL ladspaManager::cleanup( const ladspa_key_t & _plugin, LADSPA_Handle _instance ) { if( m_ladspaManagerMap.contains( _plugin ) ) @@ -909,8 +996,10 @@ void FASTCALL ladspaManager::cleanup( const ladspaKey & _plugin, if( descriptor->cleanup != NULL ) { ( descriptor->cleanup ) ( _instance ); + return( TRUE ); } } + return( FALSE ); } diff --git a/src/lmms_single_source.cpp b/src/lmms_single_source.cpp index e65a093df..1dee75d45 100644 --- a/src/lmms_single_source.cpp +++ b/src/lmms_single_source.cpp @@ -1,6 +1,9 @@ #ifdef SINGLE_SOURCE_COMPILE #undef SINGLE_SOURCE_COMPILE #include "src/tracks/instrument_track.cpp" +#include "src/core/effect_tab_widget.cpp" +#include "src/core/ladspa_control_dialog.cpp" +#include "src/core/select_ladspa_dialog.cpp" #include "src/core/midi_tab_widget.cpp" #include "src/lib/string_pair_drag.cpp" #include "src/lib/buffer_allocator.cpp" @@ -10,9 +13,14 @@ #include "src/lib/base64.cpp" #include "src/lib/mmp.cpp" #include "src/lib/ladspa_manager.cpp" +#include "src/lib/ladspa_2_lmms.cpp" #include "src/lib/oscillator.cpp" #include "src/lib/clipboard.cpp" #include "src/lib/sample_buffer.cpp" +#include "src/core/effect_chain.cpp" +#include "src/core/effect.cpp" +#include "src/core/ladspa_browser.cpp" +#include "src/core/ladspa_port_dialog.cpp" #include "src/core/import_filter.cpp" #include "src/core/config_mgr.cpp" #include "src/core/envelope_and_lfo_widget.cpp" @@ -65,9 +73,11 @@ #include "src/tracks/pattern.cpp" #include "src/tracks/bb_track.cpp" #include "src/tracks/sample_track.cpp" +#include "src/widgets/ladspa_description.cpp" #include "src/widgets/project_notes.cpp" #include "src/widgets/led_checkbox.cpp" #include "src/widgets/knob.cpp" +#include "src/widgets/labeled_knob.cpp" #include "src/widgets/pixmap_button.cpp" #include "src/widgets/qxembed.cpp" #include "src/widgets/group_box.cpp" @@ -90,4 +100,8 @@ #include "src/widgets/automatable_button.cpp" #include "src/widgets/automatable_slider.cpp" #include "src/widgets/volume_knob.cpp" +#include "src/widgets/rack_plugin.cpp" +#include "src/widgets/rack_view.cpp" +#include "src/widgets/labeled_knob.cpp" +#include "src/widgets/ladspa_control.cpp" #endif diff --git a/src/tracks/instrument_track.cpp b/src/tracks/instrument_track.cpp index dcc992162..824500f67 100644 --- a/src/tracks/instrument_track.cpp +++ b/src/tracks/instrument_track.cpp @@ -26,6 +26,13 @@ */ +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT +#include "effect.h" +#include "effect_chain.h" +#include "effect_tab_widget.h" +#endif + #include "qt3support.h" #ifdef QT4 @@ -301,9 +308,17 @@ instrumentTrack::instrumentTrack( trackContainer * _tc ) : m_envWidget = new envelopeTabWidget( this ); m_arpWidget = new arpAndChordsTabWidget( this ); m_midiWidget = new midiTabWidget( this, m_midiPort ); +#ifdef LADSPA_SUPPORT + m_effWidget = new effectTabWidget( this ); +#endif m_tabWidget->addTab( m_envWidget, tr( "ENV/LFO/FILTER" ), 1 ); m_tabWidget->addTab( m_arpWidget, tr( "ARP/CHORD" ), 2 ); +#ifdef LADSPA_SUPPORT + m_tabWidget->addTab( m_effWidget, tr( "FX" ), 3 ); + m_tabWidget->addTab( m_midiWidget, tr( "MIDI" ), 4 ); +#else m_tabWidget->addTab( m_midiWidget, tr( "MIDI" ), 3 ); +#endif // setup piano-widget m_pianoWidget = new pianoWidget( this ); @@ -368,6 +383,7 @@ instrumentTrack::instrumentTrack( trackContainer * _tc ) : setFixedWidth( CHANNEL_WIDTH ); resize( sizeHint() ); #endif + } @@ -549,6 +565,10 @@ void instrumentTrack::processAudioBuffer( sampleFrame * _buf, return; } float v_scale = (float) getVolume() / DEFAULT_VOLUME; + +#ifdef LADSPA_SUPPORT + m_audioPort->getEffects()->setRunning(); +#endif // instruments using instrument-play-handles will call this method // without any knowledge about notes, so they pass NULL for _n, which diff --git a/src/widgets/group_box.cpp b/src/widgets/group_box.cpp index d08b5d9b6..669b29543 100644 --- a/src/widgets/group_box.cpp +++ b/src/widgets/group_box.cpp @@ -129,6 +129,9 @@ void groupBox::setState( bool _on, bool _anim ) m_animating = TRUE; animate(); } +#ifdef LADSPA_SUPPORT + emit( toggled( _on ) ); +#endif } diff --git a/src/widgets/ladspa_control.cpp b/src/widgets/ladspa_control.cpp new file mode 100644 index 000000000..d0f86403d --- /dev/null +++ b/src/widgets/ladspa_control.cpp @@ -0,0 +1,119 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * ladspa_control.cpp - widget for controlling a LADSPA port + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include + +#include "ladspa_control.h" +#include "effect.h" + + +ladspaControl::ladspaControl( QWidget * _parent, port_desc_t * _port, engine * _engine, instrumentTrack * _track ) : + QWidget( _parent, "ladspaControl" ), + engineObject( _engine ), + m_port( _port ), + m_toggle( NULL ), + m_knob( NULL ) +{ + switch( m_port->data_type ) + { + case TOGGLED: + m_toggle = new ledCheckBox( m_port->name, this, "", eng(), _track ); + setFixedSize( m_toggle->width(), m_toggle->height() ); + if( m_port->def == 1.0f ) + { + m_toggle->setChecked( TRUE ); + } + break; + case INTEGER: + m_knob = new knob( knobBright_26, this, m_port->name, eng(), _track); + m_knob->setLabel( m_port->name ); + m_knob->setRange( m_port->max, m_port->min, 1 + static_cast( m_port->max - m_port->min ) / 500 ); + m_knob->setInitValue( m_port->def ); + setFixedSize( m_knob->width(), m_knob->height() ); + m_knob->setHintText( tr( "Value:" ) + " ", "" ); +#ifdef QT4 + m_knob->setWhatsThis( +#else + QWhatsThis::add( m_knob, +#endif + tr( "Sorry, no help available." ) ); + break; + case FLOAT: + m_knob = new knob( knobBright_26, this, m_port->name, eng(), _track); + m_knob->setLabel( m_port->name ); + if( ( m_port->max - m_port->min ) < 500.0f ) + { + m_knob->setRange( m_port->min, m_port->max, 0.01 ); + } + else + { + m_knob->setRange( m_port->min, m_port->max, ( m_port->max - m_port->min ) / 500.0f ); + } + m_knob->setInitValue( m_port->def ); + m_knob->setHintText( tr( "Value:" ) + " ", "" ); +#ifdef QT4 + m_knob->setWhatsThis( +#else + QWhatsThis::add( m_knob, +#endif + tr( "Sorry, no help available." ) ); + setFixedSize( m_knob->width(), m_knob->height() ); + break; + default: + break; + } +} + + + + +ladspaControl::~ladspaControl() +{ +} + + + + +LADSPA_Data ladspaControl::getValue( void ) +{ + switch( m_port->data_type ) + { + case TOGGLED: + return( static_cast( m_toggle->isChecked() ) ); + default: + return( static_cast( m_knob->value() ) ); + } +} + + +#include "ladspa_control.moc" + +#endif + +#endif diff --git a/src/widgets/ladspa_description.cpp b/src/widgets/ladspa_description.cpp new file mode 100644 index 000000000..95aec77f3 --- /dev/null +++ b/src/widgets/ladspa_description.cpp @@ -0,0 +1,234 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * left_frame.cpp - presents the plugin selector portion of a ladspa rack + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include +#include + +#include "ladspa_description.h" +#include "mixer.h" +#include "audio_device.h" + + +pluginDescription::pluginDescription( QWidget * _parent, engine * _engine ): + QWidget( _parent, "pluginDescription" ), + m_ladspaManager( _engine->getLADSPAManager() ) +{ + m_boxer = new QVBoxLayout( this ); + m_grouper = new QGroupBox( 9, Qt::Vertical, tr( "Description" ), this ); + + m_label = new QLabel( m_grouper ); + m_label->setText( tr( "Label:" ) ); + + m_maker = new QLabel( m_grouper ); + m_maker->setText( tr( "Maker:" ) ); + + m_copyright = new QLabel( m_grouper ); + m_copyright->setText( tr( "Copyright:" ) ); + + m_requiresRealTime = new QLabel( m_grouper ); + m_requiresRealTime->setText( tr( "Requires Real Time:" ) ); + + m_realTimeCapable = new QLabel( m_grouper ); + m_realTimeCapable->setText( tr( "Real Time Capable:" ) ); + + m_inplaceBroken = new QLabel( m_grouper ); + m_inplaceBroken->setText( tr( "Inplace Broken:" ) ); + + m_channelsIn = new QLabel( m_grouper ); + m_channelsIn->setText( tr( "Channels In:" ) ); + + m_channelsOut = new QLabel( m_grouper ); + m_channelsOut->setText( tr( "Channels Out:" ) ); + + m_boxer->addWidget( m_grouper ); +} + + + + +pluginDescription::~pluginDescription() +{ +} + + + + +void pluginDescription::onHighlighted( const ladspa_key_t & _key ) +{ + m_label->setText( tr( "Name: " ) + + m_ladspaManager->getName( _key ) ); + m_maker->setText( tr( "Maker: " ) + + m_ladspaManager->getMaker( _key ) ); + m_copyright->setText( tr( "Copyright: " ) + + m_ladspaManager->getCopyright( _key ) ); + + if( m_ladspaManager->hasRealTimeDependency( _key ) ) + { + m_requiresRealTime->setText( tr( "Requires Real Time: Yes" ) ); + } + else + { + m_requiresRealTime->setText( tr( "Requires Real Time: No" ) ); + } + if( m_ladspaManager->isRealTimeCapable( _key ) ) + { + m_realTimeCapable->setText( tr( "Real Time Capable: Yes" ) ); + } + else + { + m_realTimeCapable->setText( tr( "Real Time Capable: No" ) ); + } + if( m_ladspaManager->isInplaceBroken( _key ) ) + { + m_inplaceBroken->setText( tr( "In Place Broken: Yes" ) ); + } + else + { + m_inplaceBroken->setText( tr( "In Place Broken: No" ) ); + } + QString chan = QString::number( m_ladspaManager->getDescription( + _key )->inputChannels ); + m_channelsIn->setText( tr( "Channels In: " ) + chan ); + chan = QString::number( m_ladspaManager->getDescription( + _key )->outputChannels ); + m_channelsOut->setText( tr( "Channels Out: " ) + chan ); +} + + + + + +ladspaDescription::ladspaDescription( QWidget * _parent, engine * _engine, pluginType _type ): + QWidget( _parent, "ladspaDescription" ) +{ + m_ladspaManager = _engine->getLADSPAManager(); + + setMinimumWidth( 200 ); + m_boxer = new QVBoxLayout( this ); + m_grouper = new QGroupBox( 1, Qt::Vertical, tr( "Plugins" ), this ); + + l_sortable_plugin_t plugins; + switch( _type ) + { + case SOURCE: + plugins = m_ladspaManager->getInstruments(); + break; + case TRANSFER: + plugins = m_ladspaManager->getValidEffects(); + break; + case VALID: + plugins = m_ladspaManager->getValidEffects(); + break; + case INVALID: + plugins = m_ladspaManager->getInvalidEffects(); + break; + case SINK: + plugins = m_ladspaManager->getAnalysisTools(); + break; + case OTHER: + plugins = m_ladspaManager->getOthers(); + break; + default: + break; + } + + for( l_sortable_plugin_t::iterator it = plugins.begin(); + it != plugins.end(); it++ ) + { + if( _type != VALID || m_ladspaManager->getDescription( (*it).second )->inputChannels <= _engine->getMixer()->audioDev()->channels() ) + { + m_pluginNames.append( (*it).first ); + m_pluginKeys.append( (*it).second ); + } + } + + m_pluginList = new QListBox( m_grouper ); + m_pluginList->insertStringList( m_pluginNames ); + connect( m_pluginList, SIGNAL( highlighted( int ) ), + SLOT( onHighlighted( int ) ) ); + connect( m_pluginList, SIGNAL( doubleClicked( QListBoxItem * ) ), + SLOT( onDoubleClicked( QListBoxItem * ) ) ); + m_boxer->addWidget( m_grouper ); + + m_pluginDescription = new pluginDescription( this, _engine ); + connect( this, SIGNAL( highlighted( const ladspa_key_t & ) ), + m_pluginDescription, + SLOT( onHighlighted( const ladspa_key_t & ) ) ); + m_boxer->addWidget( m_pluginDescription ); + + if( m_pluginList->numRows() > 0 ) + { + m_pluginList->setSelected( 0, true ); + m_currentSelection = m_pluginKeys[0]; + emit( highlighted( m_currentSelection ) ); + } +} + + + + +ladspaDescription::~ladspaDescription() +{ + delete m_pluginDescription; + delete m_pluginList; + delete m_grouper; + delete m_boxer; +} + + + + +void ladspaDescription::onHighlighted( int _pluginIndex ) +{ + m_currentSelection = m_pluginKeys[_pluginIndex]; + emit( highlighted( m_currentSelection ) ); +} + + + + +void ladspaDescription::onDoubleClicked( QListBoxItem * _item ) +{ +// m_currentSelection = m_pluginKeys[m_pluginList->index( _item )]; + emit( doubleClicked( m_currentSelection ) ); +} + + + + +void ladspaDescription::onAddButtonReleased() +{ + emit( addPlugin( m_currentSelection ) ); +} + + +#include "ladspa_description.moc" + +#endif + +#endif diff --git a/src/widgets/rack_plugin.cpp b/src/widgets/rack_plugin.cpp new file mode 100644 index 000000000..fb89f9153 --- /dev/null +++ b/src/widgets/rack_plugin.cpp @@ -0,0 +1,196 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * effect_tab_widget.cpp - tab-widget in channel-track-window for setting up + * effects + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#ifdef QT4 + +#include +#include +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include +#include + +#endif + +#include "rack_plugin.h" +#include "knob.h" +#include "tooltip.h" +#include "ladspa_2_lmms.h" +#include "ladspa_control_dialog.h" +#include "audio_port.h" + + +rackPlugin::rackPlugin( QWidget * _parent, ladspa_key_t _key, instrumentTrack * _track, engine * _engine ) : + QWidget( _parent, "rackPlugin" ), + journallingObject( _engine ) +{ + m_effect = new effect( _key, eng() ); + _track->getAudioPort()->getEffects()->appendEffect( m_effect ); + + setFixedSize( 210, 58 ); + setPaletteBackgroundColor( QColor( 99, 99, 99 ) ); + + m_grouper = new QGroupBox( 1, Qt::Vertical, "", this ); + m_grouper->setFixedSize( 210, 58 ); + + m_bypass = new ledCheckBox( "", this, tr( "Turn the effect off" ), eng(), _track ); + connect( m_bypass, SIGNAL( toggled( bool ) ), this, SLOT( bypassed( bool ) ) ); + m_bypass->setChecked( TRUE ); + m_bypass->move( 3, 3 ); +#ifdef QT4 + m_bypass->setWhatsThis( +#else + QWhatsThis::add( m_bypass, +#endif + tr( +"Toggles the effect on or off." ) ); + + m_wetDry = new knob( knobBright_26, this, tr( "Wet/Dry mix" ), eng(), _track ); + connect( m_wetDry, SIGNAL( valueChanged( float ) ), this, SLOT( setWetDry( float ) ) ); + m_wetDry->setLabel( tr( "W/D" ) ); + m_wetDry->setRange( 0.0f, 1.0f, 0.01f ); + m_wetDry->setInitValue( 1.0f ); + m_wetDry->move( 25, 3 ); + m_wetDry->setHintText( tr( "Wet Level:" ) + " ", "" ); +#ifdef QT4 + m_wetDry->setWhatsThis( +#else + QWhatsThis::add( m_wetDry, +#endif + tr( +"The wet/dry knob sets the ratio between the input signal and the effect that shows up in the output." ) ); + + m_autoQuit = new knob( knobBright_26, this, tr( "Decay" ), eng(), _track ); + connect( m_autoQuit, SIGNAL( valueChanged( float ) ), this, SLOT( setAutoQuit( float ) ) ); + m_autoQuit->setLabel( tr( "Decay" ) ); + m_autoQuit->setRange( 1, 100, 1 ); + m_autoQuit->setInitValue( 1 ); + m_autoQuit->move( 60, 3 ); + m_autoQuit->setHintText( tr( "Buffers:" ) + " ", "" ); +#ifdef QT4 + m_autoQuit->setWhatsThis( +#else + QWhatsThis::add( m_autoQuit, +#endif + tr( +"The decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values " +"will reduce the CPU overhead but run the risk of clipping the tail on delay effects." ) ); + + m_gate = new knob( knobBright_26, this, tr( "Decay" ), eng(), _track ); + connect( m_wetDry, SIGNAL( valueChanged( float ) ), this, SLOT( setGate( float ) ) ); + m_gate->setLabel( tr( "Gate" ) ); + m_gate->setRange( 0.0f, 1.0f, 0.01f ); + m_gate->setInitValue( 0.0f ); + m_gate->move( 95, 3 ); + m_gate->setHintText( tr( "Gate:" ) + " ", "" ); +#ifdef QT4 + m_gate->setWhatsThis( +#else + QWhatsThis::add( m_gate, +#endif + tr( +"The gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing " +"signals." ) ); + + m_editButton = new QPushButton( this, "Controls" ); + m_editButton->setText( tr( "Controls" ) ); + m_editButton->setGeometry( 140, 19, 50, 20 ); + connect( m_editButton, SIGNAL( clicked() ), this, SLOT( editControls() ) ); + + QString name = eng()->getLADSPAManager()->getShortName( _key ); + m_label = new QLabel( this ); + m_label->setText( name ); + QFont f = m_label->font(); + f.setBold( TRUE ); + m_label->setFont( pointSize<7>( f ) ); + m_label->setGeometry( 5, 38, 200, 20 ); + + m_controlView = new ladspaControlDialog( this, m_effect, eng(), _track ); +} + + + +rackPlugin::~rackPlugin() +{ +} + + + +void rackPlugin::editControls( void ) +{ + m_controlView->show(); + m_controlView->raise(); +} + + + + +void rackPlugin::bypassed( bool _state ) +{ + m_effect->setBypass( !_state ); +} + + + + +void rackPlugin::setWetDry( float _value ) +{ + m_effect->setWetDry( _value ); +} + + + +void rackPlugin::setAutoQuit( float _value ) +{ + m_effect->setTimeout( static_cast( _value ) ); +} + + + +void rackPlugin::setGate( float _value ) +{ + m_effect->setGate( _value ); +} + + +#include "rack_plugin.moc" + +#endif + +#endif diff --git a/src/widgets/rack_view.cpp b/src/widgets/rack_view.cpp new file mode 100644 index 000000000..f82629549 --- /dev/null +++ b/src/widgets/rack_view.cpp @@ -0,0 +1,83 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * right_frame.cpp - provides the display for the rackInsert instances + * + * Copyright (c) 2006 Danny McRae + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ladspa_manager.h" +#ifdef LADSPA_SUPPORT + +#include "rack_view.h" + + +rackView::rackView( QWidget * _parent, engine * _engine, instrumentTrack * _track ): + QWidget( _parent, "rackView" ), + engineObject( _engine ), + m_instrumentTrack( _track ) +{ + setFixedSize( 230, 180 ); + + m_mainLayout = new QVBoxLayout( this ); + m_scrollView = new QScrollView( this ); + m_scrollView->setFixedSize( 230, 180 ); + m_scrollView->setVScrollBarMode( QScrollView::AlwaysOn ); + m_mainLayout->addWidget( m_scrollView ); + + m_rack = new QVBox( m_scrollView->viewport() ); + m_scrollView->addChild( m_rack ); + + m_rackInserts.setAutoDelete( TRUE ); +} + + + +rackView::~rackView() +{ + m_rackInserts.setAutoDelete( TRUE ); + while( ! m_rackInserts.isEmpty() ) + { + m_rackInserts.removeFirst(); + } + + delete m_rack; + delete m_scrollView; + delete m_mainLayout; +} + + + + +void rackView::addPlugin( ladspa_key_t _key ) +{ + rackPlugin * plugin = new rackPlugin( m_rack, _key, m_instrumentTrack, eng() ); + m_rackInserts.append( plugin ); + m_rackInserts.current()->repaint(); + m_rackInserts.current()->show(); +} + + +#include "rack_view.moc" + +#endif + +#endif