fundamental changes in plugin-architecture, added plugin-browser, bug-fixes - see ChangeLog for further details

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@18 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2005-10-20 13:02:26 +00:00
parent 58fe360793
commit f55c124be6
96 changed files with 5262 additions and 234 deletions

141
ChangeLog
View File

@@ -1,3 +1,144 @@
2005-10-19 Tobias Doerffel <tobydox@users.sourceforge.net>
* plugins/vestige/vestige.h:
* plugins/vestige/vestige.cpp:
added possibility of opening plugins instead of hardcoding them ;-)
* include/track.h:
renamed createTrack() and cloneTrack() to create() and clone()
* include/track_container.h:
* src/core/track_container.cpp:
receive drop-events -> add channel with instrument/preset
* src/audio/audio_jack.cpp:
removed usleep() out of loop in audioJACK::writeBufferToDev() since it
caused LMMS to hang e.g when removing a track
* src/core/plugin_browser.cpp:
show hand-cursor if over a plugin-description-widget
* src/widgets/pixmap_button.cpp:
if pixmap-button is set non-checkable, draw active-graphic if pressed
down and inactive one in normal state
* include/lmms_main_win.h:
* src/core/lmms_main_win.cpp:
own workspace for making wheelEvent(...) is now obsolete -> removed
* include/track_container.h:
* src/core/song_editor.cpp:
* src/core/track_container.cpp:
added own scroll-area for capturing special wheel-events where a
modifier-key (shift, control etc.) is pressed
* src/core/song_editor.cpp:
removed add-channel-button as it is obsolete after adding plugin-browser
* resources/:
improved icons such as project_*.png and sample-track-related icons
2005-10-18 Tobias Doerffel <tobydox@users.sourceforge.net>
* include/channel_track.h:
* src/tracks/channel_track.cpp:
- moved channelButton-implementation to channel_track.src
- added support for receiving drop-events, which makes channel-track
to load either the given instrument or the given preset
* src/core/plugin_browser.cpp:
* include/plugin_browser.h:
added cool plugin-browser, which displays all available instrument-
plugins which are draggable to a channel-window/button
* include/string_pair_drag.h:
* src/lib/string_pair_drag.cpp:
added drag'n'drop-implementation for dragging string-pairs (key/value)
which provides a standard-interface, although drag'n'drop has changed a
lot in Qt 4
* src/widgets/crystal_button.cpp:
made mouseMoveEvent()-method much more effective
* Makefile.am:
* buildtools/Makefile.am:
build buildtools in subdir instead of top-build-directory - solves
dependendy problems with bin2res
* src/core/file_browser.cpp:
do not depend on typeinfo of audioFileProcessor anymore by using
new setParameter()-method
* include/plugin.h:
added setParameter() and getParameter()-methods for making LMMS able to
set parameters of a specific plugin without knowing anything about it
2005-10-17 Tobias Doerffel <tobydox@users.sourceforge.net>
* buildtools/bin2res.cpp:
* include/embed.h:
* src/lib/embed.cpp:
- declaration of embedded-data-descriptor is now located in embed.h and
part of namespace embed
- added support for local embedded-resources which is important for
plugins containing their own images etc., so data and access-methods
are stored into namespace PLUGIN_NAME
* include/plugin.h:
* src/core/plugin.cpp:
added logo-field to descriptor-structure and simplified method for
getting descriptors of all plugins
* include/basic_filters.h:
removed Moog-2-filter as it is only very CPU-intensive without any
significant difference to sound of normal Moog-filter
2005-10-16 Tobias Doerffel <tobydox@users.sourceforge.net>
* src/lib/ladspa_manager.cpp:
skip not existing/unreadable directories when searching for plugins
* include/vestige.h:
* src/plugins/vestige.cpp:
make use of new instrument-play-handle
* include/channel_track.h:
* src/core/browser.cpp:
* src/core/song_editor.cpp:
* src/midi/midi_file.cpp:
* src/tracks/channel_track.cpp:
renamed loadPlugin() to loadInstrument()
* include/config_mgr.h:
* src/core/config_mgr.cpp:
added pluginDir()-method
* include/instrument_play_handle.h:
added another play-handle for playing instruments which do not
produce sound for each note
* src/plugins/:
renamed directory soundgenerators to plugins and modified all plugins
for working with revised plugin-system
* include/instrument.h:
* include/plugin.h:
* src/core/instrument.cpp:
* src/core/plugin.cpp:
splitted code from instrument up into class plugin and class instrument
and revised plugin-system
* include/instrument.h:
* src/core/instrument.cpp:
renamed files soundgenerator.* to instrument.* as well as class-name
2005-10-15 Tobias Doerffel <tobydox@users.sourceforge.net>
* include/vestige.h:
* src/soundgenerators/vestige.cpp:
new plugin "VeSTige" for handling VST-plugins - VERY experimental,
but at least, we get some sound out of these strange dll-files ;-)
2005-10-13 Tobias Doerffel <tobydox@users.sourceforge.net>
* src/audio/audio_jack.cpp:

View File

@@ -19,24 +19,23 @@ rpm: $(PACKAGE)-$(VERSION).tar.gz $(PACKAGE).spec
endif
noinst_PROGRAMS= bin2res
bin2res_SOURCES = buildtools/bin2res.cpp
SUBDIRS = artwork buildtools locale midi-maps plugins presets projects samples
INCLUDES = -I$(srcdir)/include -I.
bin_PROGRAMS = lmms
AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS)
%.moc: $(srcdir)/include/%.h
$(MOC) -o $@ $<
%.ts:
$(LUPDATE) $(lmms_SOURCES) -ts locale/$@
$(LUPDATE) $(lmms_SOURCES) `find plugins/ -type f -name *.cpp` -ts locale/$@
%.qm: %.ts
$(LRELEASE) $<
@@ -45,20 +44,18 @@ AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS)
lmms_MOC = \
./about_dialog.moc \
./arp_and_chords_tab_widget.moc \
./audio_file_processor.moc \
./bb_editor.moc \
./bb_track.moc \
./browser.moc \
./channel_track.moc \
./config_mgr.moc \
./crystal_button.moc \
./envelope_and_lfo_widget.moc \
./envelope_tab_widget.moc \
./export_project_dialog.moc \
./kmultitabbar.moc \
./file_browser.moc \
./group_box.moc \
./kmultitabbar.moc \
./knob.moc \
./ladspa_sine_1063.moc \
./lcd_spinbox.moc \
./led_checkbox.moc \
./lmms_main_win.moc \
@@ -69,6 +66,7 @@ lmms_MOC = \
./piano_roll.moc \
./piano_widget.moc \
./pixmap_button.moc \
./plugin_browser.moc \
./project_notes.moc \
./rename_dialog.moc \
./sample_buffer.moc \
@@ -77,7 +75,6 @@ lmms_MOC = \
./side_bar.moc \
./side_bar_widget.moc \
./song_editor.moc \
./sound_generator.moc \
./surround_area.moc \
./tab_bar.moc \
./tab_button.moc \
@@ -86,7 +83,6 @@ lmms_MOC = \
./timeline.moc \
./track_container.moc \
./track.moc \
./triple_oscillator.moc \
./visualization_widget.moc
@@ -94,8 +90,8 @@ BUILT_SOURCES = $(lmms_MOC)
lmms_EMBEDDED_RESOURCES = $(wildcard $(srcdir)/resources/*png AUTHORS COPYING)
./embedded_resources.h: $(lmms_EMBEDDED_RESOURCES) bin2res
$(top_builddir)/bin2res $(lmms_EMBEDDED_RESOURCES) > $@
./embedded_resources.h: $(lmms_EMBEDDED_RESOURCES)
$(top_builddir)/buildtools/bin2res $(lmms_EMBEDDED_RESOURCES) > $@
./embed.o: ./embedded_resources.h
@@ -113,11 +109,12 @@ lmms_SOURCES = \
$(srcdir)/src/core/about_dialog.cpp \
$(srcdir)/src/core/arp_and_chords_tab_widget.cpp \
$(srcdir)/src/core/bb_editor.cpp \
$(srcdir)/src/core/browser.cpp \
$(srcdir)/src/core/config_mgr.cpp \
$(srcdir)/src/core/envelope_and_lfo_widget.cpp \
$(srcdir)/src/core/envelope_tab_widget.cpp \
$(srcdir)/src/core/export_project_dialog.cpp \
$(srcdir)/src/core/file_browser.cpp \
$(srcdir)/src/core/instrument.cpp \
$(srcdir)/src/core/lmms_main_win.cpp \
$(srcdir)/src/core/main.cpp \
$(srcdir)/src/core/mixer.cpp \
@@ -126,11 +123,12 @@ lmms_SOURCES = \
$(srcdir)/src/core/note_play_handle.cpp \
$(srcdir)/src/core/piano_roll.cpp \
$(srcdir)/src/core/piano_widget.cpp \
$(srcdir)/src/core/plugin.cpp \
$(srcdir)/src/core/plugin_browser.cpp \
$(srcdir)/src/core/preset_preview_play_handle.cpp \
$(srcdir)/src/core/sample_play_handle.cpp \
$(srcdir)/src/core/setup_dialog.cpp \
$(srcdir)/src/core/song_editor.cpp \
$(srcdir)/src/core/sound_generator.cpp \
$(srcdir)/src/core/track.cpp \
$(srcdir)/src/core/track_container.cpp \
$(srcdir)/src/core/surround_area.cpp \
@@ -142,6 +140,7 @@ lmms_SOURCES = \
$(srcdir)/src/lib/mmp.cpp \
$(srcdir)/src/lib/oscillator.cpp \
$(srcdir)/src/lib/sample_buffer.cpp \
$(srcdir)/src/lib/string_pair_drag.cpp \
$(srcdir)/src/midi/midi_alsa_raw.cpp \
$(srcdir)/src/midi/midi_device.cpp \
$(srcdir)/src/midi/midi_file.cpp \
@@ -189,16 +188,14 @@ lmms_SOURCES = \
$(srcdir)/include/volume.h \
$(srcdir)/include/panning.h \
$(srcdir)/include/song_editor.h \
$(srcdir)/include/sound_generator.h \
$(srcdir)/include/audio_file_processor.h \
$(srcdir)/include/plugin.h \
$(srcdir)/include/instrument.h \
$(srcdir)/include/midi_time.h \
$(srcdir)/include/bb_editor.h \
$(srcdir)/include/piano_widget.h \
$(srcdir)/include/effect_board.h \
$(srcdir)/include/pixmap_button.h \
$(srcdir)/include/triple_oscillator.h \
$(srcdir)/include/settings.h \
$(srcdir)/include/plucked_string_synth.h \
$(srcdir)/include/rename_dialog.h \
$(srcdir)/include/export_project_dialog.h \
$(srcdir)/include/note_play_handle.h \
@@ -214,7 +211,8 @@ lmms_SOURCES = \
$(srcdir)/include/group_box.h \
$(srcdir)/include/tab_widget.h \
$(srcdir)/include/knob.h \
$(srcdir)/include/browser.h \
$(srcdir)/include/file_browser.h \
$(srcdir)/include/plugin_browser.h \
$(srcdir)/include/templates.h \
$(srcdir)/include/gui_templates.h \
$(srcdir)/include/surround_area.h \
@@ -248,7 +246,6 @@ lmms_SOURCES = \
$(srcdir)/include/preset_preview_play_handle.h \
$(srcdir)/include/sample_play_handle.h \
$(srcdir)/include/midi.h \
$(srcdir)/include/midi_out.h \
$(srcdir)/include/nstate_button.h \
$(srcdir)/include/midi_dummy.h \
$(srcdir)/include/midi_mapper.h \
@@ -259,7 +256,10 @@ lmms_SOURCES = \
$(srcdir)/include/text_float.h \
$(srcdir)/include/tempo_sync_knob.h \
$(srcdir)/include/setup_dialog.h \
$(srcdir)/include/empty_sg_plugin.h \
$(srcdir)/include/dummy_plugin.h \
$(srcdir)/include/dummy_instrument.h \
$(srcdir)/include/instrument_play_handle.h \
$(srcdir)/include/string_pair_drag.h \
$(srcdir)/include/ladspa_manager.h
@@ -296,18 +296,6 @@ if HAVE_LIBSF
LIB_SF_LDADD = -lsndfile
endif
lmms_LDADD = $(QT_LDADD) $(LIB_SDL_LDADD) $(LIB_ASOUND_LDADD) $(LIB_JACK_LDADD) $(LIB_SDL_SOUND_LDADD) $(LIB_VORBIS_LDADD) $(LIB_SRC_LDADD) $(LIB_SF_LDADD) -laudiofileprocessor -ldl
lmms_LDADD = $(QT_LDADD) $(LIB_SDL_LDADD) $(LIB_ASOUND_LDADD) $(LIB_JACK_LDADD) $(LIB_SDL_SOUND_LDADD) $(LIB_VORBIS_LDADD) $(LIB_SRC_LDADD) $(LIB_SF_LDADD) -lfst -ldl
lmms_LDFLAGS = -rdynamic -rpath $(pkglibdir)
SUBDIRS = artwork locale midi-maps presets projects samples
pkglib_LTLIBRARIES= libaudiofileprocessor.la libsine1063oscillator.la libmidiout.la libpluckedstringsynth.la libtripleoscillator.la
libaudiofileprocessor_la_SOURCES = src/soundgenerators/audio_file_processor.cpp
libsine1063oscillator_la_SOURCES = src/soundgenerators/ladspa_sine_1063.cpp
libmidiout_la_SOURCES = src/soundgenerators/midi_out.cpp
libpluckedstringsynth_la_SOURCES = src/soundgenerators/plucked_string_synth.cpp
libtripleoscillator_la_SOURCES = src/soundgenerators/triple_oscillator.cpp

29
README
View File

@@ -1,4 +1,4 @@
Linux MultiMedia Studio 0.1.2
Linux MultiMedia Studio 0.1.1
==============================
Copyright (c) 2004-2005 by Tobias Doerffel and others
@@ -41,13 +41,13 @@ Requirements
------------
The most important requirement is for sure a fast computer, so don't try to get
LMMS working on a pentium I with 60 MHz... ;-) So you should have at least
500 MHz, but for really enjoying LMMS less than 1 GHz makes no sense...
(LMMS is currently developed on a PIII 450 MHz...!!)
LMMS working on a pentium I with 60 MHz... ;-) Therefore you should have at
least 500 MHz, but for really enjoying LMMS less than 1 GHz makes no sense...
Required libraries are:
- Qt 3.2 or higher (tested up to 4.0.0) with devel-files
- Qt 3.0 (3.2 recommended) or higher (tested up to 4.0.0) with devel-files
Optional, but strongly recommended:
- libvorbis with devel-files
@@ -57,6 +57,7 @@ Optional, but strongly recommended:
- libsamplerate with devel-files
- libsndfile with devel-files
- JACK with devel-files
- libfst + header-files from Steinberg SDK
For compiling you should have an up to date GCC with g++.
LMMS has been (successfully) tested under Debian Sarge 3.1, Fedora Core 2-4,
@@ -83,16 +84,16 @@ can be found at
http://lmms.sourceforge.net
Before coding a new big feature, please always post your idea and suggestions
Details on development can be found at
http://lmms.sourceforge.net/development.php
or in the Wiki:
http://wiki.mindrules.net
Before coding a new big feature, please ALWAYS post your idea and suggestions
about your feature and about the actual implementation to the
LMMS-devel-mailinglist (lmms-devel@lists.sourceforge.net) and wait for replies!
Maybe there're different ideas, improvements, hints or maybe your feature is
not welcome/needed at the moment (but for sure this will be very seldom).
If you coded your feature, make sure, that it is running properly with the
newest available version of LMMS and that it also runs with different
configurations (e.g. disabled surround-support, missing package(s) etc.).
Important is also, that you comment your source so that other people can fix
bugs or improve your feature!

18
TODO
View File

@@ -1,18 +1,20 @@
- toolbar-redesign in song-editor, bb-editor and piano-roll!!!
- addchannel-toolbutton -> popup-menu with available soundgenerator-plugins
- complete toolbar-redesign in song-editor, bb-editor and piano-roll!!!
- dnd everywhere: presets, samples (afp/sample-track), TCO's, knob-values
- save/load parameters of VST-plugin
- move VST-code into separate class which can use several backends (libfst, dssi-vst and vst-server) -> add libfst/dssi-vst/vstserver-check to configure.in
- somehow avoid hidden plugin-descriptor-widgets if height of window is too small -> add scrollbar
- use drawLineF() for drawing notes in pattern::paintEvent() in qt4-version
- pattern freeze -> do not endless loop if looping-points are enabled
- solve problem with knob-control-precision
- built-in VST-support
- proper dlclos()ing of sg-plugins
- use own scrollview for capturing wheel-events
- add note-len- and note-alignment-selectbox to piano-roll
- only redraw region given by paint-event in pattern, bbTCO, sampleTCO etc.
- make LMMS an ALSA-sequencer-client
- use midi-maps
- process program-/channel-change-events from MIDI-files
- setup MIDI-channel and -program in MIDI-Out
- pre-listen when opening sample with QFileDialog
- level-meters in output-graph and channel-track
- panning-editing in piano-roll
- use midi-maps
- process program-/channel-change-events from MIDI-files
- setup MIDI-channel and -program in MIDI-Out
- speed up painting of sampleTCO
- save window-positions, -states and -sizes in files
- solve problems with different keyboard-layouts when playing channel-track with pc-keyboard -> use tr()

5
buildtools/Makefile.am Normal file
View File

@@ -0,0 +1,5 @@
AUTOMAKE_OPTIONS = foreign 1.4
noinst_PROGRAMS= bin2res
bin2res_SOURCES = bin2res.cpp

View File

@@ -97,7 +97,7 @@ int main( int argc, char * * argv )
e->cname = convertFileNameToCIdentifier( e->name );
embedded_data.push_back( e );
std::string s;
std::cout << "static const unsigned char " << e->cname <<
std::cout << "const unsigned char " << e->cname <<
"_data[] = {";
embedData( data, fsize, std::cout );
std::cout << std::endl << "};" << std::endl << std::endl;
@@ -106,7 +106,7 @@ int main( int argc, char * * argv )
if( embedded_data.size() > 0 )
{
std::cout << "static const unsigned char dummy_data[] ="
std::cout << "const unsigned char dummy_data[] ="
"{ 0x00 };" << std::endl << std::endl;
embed * dummy = new embed;
dummy->size = 1;
@@ -114,14 +114,15 @@ int main( int argc, char * * argv )
dummy->cname = convertFileNameToCIdentifier( "dummy" );
embedded_data.push_back( dummy );
std::cout << "#include <string.h>" << std::endl;
std::cout << "static struct embedDesc" << std::endl
<< "{" << std::endl
std::cout << "#include <string.h>" << std::endl << std::endl;
std::cout << "#include \"embed.h\"" << std::endl << std::endl;
std::cout << "embed::descriptor embed_vec[] = {" << std::endl;
/* << "{" << std::endl
<< " int size;" << std::endl
<< " const unsigned char * data;" <<
std::endl
<< " const char * name;" << std::endl
<< "} embed_vec[] = {" << std::endl;
<< "} embed_vec[] = {" << std::endl;*/
while( embedded_data.size() > 0 )
{
embed * e = embedded_data[0];
@@ -133,9 +134,9 @@ int main( int argc, char * * argv )
}
std::cout << " { 0, 0, 0 }" << std::endl << "};" << std::endl
<< std::endl
<< "static const embedDesc & findEmbeddedData( "
"const char * _name )" << std::endl
<< "{" << std::endl
<< "const embed::descriptor & "
"findEmbeddedData( const char * _name )"
<< std::endl << "{" << std::endl
<< " for( int i = 0; embed_vec[i].data; "
"i++ )" << std::endl
<< " {" << std::endl

View File

@@ -2,8 +2,8 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.50)
AC_INIT(lmms, 0.1.1-cvs20051013, tobydox@users.sourceforge.net)
AM_INIT_AUTOMAKE(lmms, 0.1.1-cvs20051013)
AC_INIT(lmms, 0.1.1-cvs20051019, tobydox@users.sourceforge.net)
AM_INIT_AUTOMAKE(lmms, 0.1.1-cvs20051019)
AM_CONFIG_HEADER(config.h)
@@ -22,7 +22,7 @@ gw_CHECK_QT
# checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([fcntl.h memory.h string.h sys/ioctl.h unistd.h stdlib.h dlfcn.h])
AC_CHECK_HEADERS([fcntl.h memory.h string.h sys/ioctl.h unistd.h stdlib.h dlfcn.h ladspa.h])
# checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -349,14 +349,23 @@ fi
AC_CONFIG_FILES([Makefile
artwork/Makefile
buildtools/Makefile
locale/Makefile
midi-maps/Makefile
plugins/Makefile
plugins/audio_file_processor/Makefile
plugins/ladspa_sine_1063/Makefile
plugins/midi_out/Makefile
plugins/plucked_string_synth/Makefile
plugins/triple_oscillator/Makefile
plugins/vestige/Makefile
presets/Makefile
presets/AudioFileProcessor/Makefile
presets/MIDI-Out/Makefile
presets/PluckedStringSynth/Makefile
presets/Sine1063Oscillator/Makefile
presets/TripleOscillator/Makefile
presets/VeSTige/Makefile
projects/Makefile
projects/cool_songs/Makefile
projects/covers/Makefile

View File

@@ -80,7 +80,7 @@ public:
private:
virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab,
Uint32 _frames,
float _master_output );
float _master_gain );
int FASTCALL setHWParams( Uint32 _sample_rate, Uint32 _channels,
snd_pcm_access_t _access );

View File

@@ -68,7 +68,7 @@ public:
void FASTCALL writeBuffer( surroundSampleFrame * _ab, Uint32 _frames,
Uint32 _src_sample_rate,
float _master_output );
float _master_gain );
inline Uint32 sampleRate( void ) const
{
@@ -104,12 +104,12 @@ public:
protected:
virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab,
Uint32 _frames,
float _master_output ) = 0;
float _master_gain ) = 0;
// convert a given audio-buffer to a buffer in signed 16-bit samples
// returns num of bytes in outbuf
int FASTCALL convertToS16( surroundSampleFrame * _ab, Uint32 _frames,
float _master_output,
float _master_gain,
outputSampleType * _output_buffer,
bool _convert_endian = FALSE );

View File

@@ -64,7 +64,7 @@ public:
private:
virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab,
Uint32 _frames,
float _master_output );
float _master_gain );
bool startEncoding( void );
void finishEncoding( void );

View File

@@ -57,7 +57,7 @@ public:
private:
virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab,
Uint32 _frames,
float _master_output );
float _master_gain );
bool startEncoding( void );
void finishEncoding( void );

View File

@@ -91,7 +91,7 @@ public:
private:
virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab,
Uint32 _frames,
float _master_output );
float _master_gain );
void clearBuffer( void );

View File

@@ -75,7 +75,7 @@ public:
private:
virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab,
Uint32 _frames,
float _master_output );
float _master_gain );
int m_audioFD;

View File

@@ -63,7 +63,7 @@ public:
private:
virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab,
Uint32 _frames,
float _master_output );
float _master_gain );
typedef vvector<QPair<sampleFrame *, Uint32> > bufferVector;
bufferVector m_buffers;

View File

@@ -88,7 +88,7 @@ public:
private:
virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab,
Uint32 _frames,
float _master_output );
float _master_gain );
void clearBuffer( void );

View File

@@ -54,11 +54,9 @@ public:
NOTCH,
ALLPASS,
MOOG,
MOOG2,
SIMPLE_FLT_CNT,
DOUBLE_LOWPASS = 16+LOWPASS,
DOUBLE_MOOG = 16+MOOG,
DOUBLE_MOOG2 = 16+MOOG2
DOUBLE_MOOG = 16+MOOG
} ;
static inline filterTypes getFilterType( const int _idx )
@@ -127,7 +125,7 @@ public:
m_y4[_chnl] * ( 1.0f / 6.0f );
break;
}
case MOOG2:
/* case MOOG2:
case DOUBLE_MOOG2:
{
const float x1 = ( _in0 - m_r *
@@ -190,7 +188,7 @@ public:
out = m_oldx[_chnl];
break;
}
}*/
default:
// filter
@@ -251,7 +249,7 @@ public:
break;
}
case DOUBLE_MOOG2:
/* case DOUBLE_MOOG2:
{
if( m_subFilter == NULL )
{
@@ -276,7 +274,7 @@ public:
kfcr * kf ) );
m_r = 4 * _q * kacr;
break;
}
}*/
default:
{

View File

@@ -83,10 +83,10 @@ public:
protected:
void closeEvent( QCloseEvent * _ce );
void keyPressEvent (QKeyEvent * _ke);
void wheelEvent( QWheelEvent * _we );
void resizeEvent( QResizeEvent * _re );
virtual void closeEvent( QCloseEvent * _ce );
virtual void keyPressEvent( QKeyEvent * _ke );
virtual void resizeEvent( QResizeEvent * _re );
void updateBackground( void );

View File

@@ -105,6 +105,11 @@ public:
{
return( m_lmmsDataDir + LOCALE_PATH );
}
const QString & pluginDir( void ) const
{
return( m_lmmsPluginDir );
}
const QString & value( const QString & _class,
const QString & _attribute ) const;
@@ -148,6 +153,7 @@ private:
const QString m_lmmsRcFile;
QString m_lmmsWorkingDir;
QString m_lmmsDataDir;
QString m_lmmsPluginDir;
typedef vvector<QPair<QString, QString> > stringPairVector;
typedef QMap<QString, stringPairVector> settingsMap;

View File

@@ -0,0 +1,61 @@
/*
* dummy_instrument.h - instrument used as fallback if an instrument couldn't
* be loaded
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 _DUMMY_INSTRUMENT_H
#define _DUMMY_INSTRUMENT_H
#include "instrument.h"
class dummyInstrument : public instrument
{
public:
inline dummyInstrument( channelTrack * _channel_track ) :
instrument( _channel_track, "Dummy instrument" )
{
}
inline virtual ~dummyInstrument()
{
}
inline virtual void saveSettings( QDomDocument &, QDomElement & )
{
}
inline virtual void loadSettings( const QDomElement & )
{
}
inline virtual QString nodeName( void ) const
{
return( "dummyinstrument" );
}
} ;
#endif

61
include/dummy_plugin.h Normal file
View File

@@ -0,0 +1,61 @@
/*
* dummy_plugin.h - empty plugin which is used as fallback if a plugin wasn't
* found
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 _DUMMY_PLUGIN_H
#define _DUMMY_PLUGIN_H
#include "plugin.h"
class dummyPlugin : public plugin
{
public:
inline dummyPlugin( void ) :
plugin( "Dummy plugin", plugin::UNDEFINED )
{
}
inline virtual ~dummyPlugin()
{
}
inline virtual void saveSettings( QDomDocument &, QDomElement & )
{
}
inline virtual void loadSettings( const QDomElement & )
{
}
inline virtual QString nodeName( void ) const
{
return( "dummyplugin" );
}
} ;
#endif

View File

@@ -42,10 +42,31 @@
namespace embed
{
struct descriptor
{
int size;
const unsigned char * data;
const char * name;
} ;
QPixmap getIconPixmap( const char * _name, int _w = -1, int _h = -1 );
QString getText( const char * _name );
void loadTranslation( const QString & _tname );
}
#ifdef PLUGIN_NAME
namespace PLUGIN_NAME
{
QPixmap getIconPixmap( const char * _name, int _w = -1, int _h = -1 );
QString getText( const char * _name );
void loadTranslation( const QString & _tname );
}
#endif
#endif

View File

@@ -31,6 +31,12 @@
#include <config.h>
#endif
#ifdef HAVE_LADSPA_H
#define LADSPA_SUPPORT
#include <ladspa.h>
#include "qt3support.h"
#ifdef QT4
@@ -49,9 +55,10 @@
#endif
#include <ladspa.h>
#include "types.h"
typedef QPair<QString, QString> ladspaKey;
/* ladspaManager provides a database of LADSPA plug-ins. Upon instantiation,
@@ -188,7 +195,7 @@ public:
/* The following methods are convenience functions for use during
development. A real soundGenerator should use the getDescriptor()
development. A real instrument should use the getDescriptor()
method and implement the plug-in manipulations internally to avoid
the overhead associated with QMap lookups. */
@@ -326,5 +333,7 @@ private:
typedef QMap<ladspaKey, ladspaManagerDescription *> ladspaManagerMapType;
ladspaManagerMapType m_ladspaManagerMap;
};
#endif
#endif

View File

@@ -57,6 +57,7 @@
class audioDevice;
class midiDevice;
class lmmsMainWin;
class plugin;
const int DEFAULT_BUFFER_SIZE = 512;
@@ -174,7 +175,8 @@ public:
m_playHandlesToRemove.push_back( _ph );
}
void FASTCALL checkValidityOfPlayHandles( void );
void checkValidityOfPlayHandles( void );
inline int sampleRate( void )
@@ -319,7 +321,6 @@ private:
volatile bool m_quit;
audioDevice * m_audioDev;
audioDevice * m_oldAudioDev;
QString m_audioDevName;

133
include/plugin.h Normal file
View File

@@ -0,0 +1,133 @@
/*
* plugin.h - class plugin, the base-class and generic interface for all plugins
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 _PLUGIN_H
#define _PLUGIN_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "qt3support.h"
#ifdef QT4
#include <QString>
#include <QVector>
#else
#include <qstring.h>
#include <qvaluevector.h>
#endif
#include "types.h"
#include "settings.h"
#include "embed.h"
#define STRINGIFY_PLUGIN_NAME(s) STR(s)
#define STR(PN) #PN
class QPixmap;
class plugin : public settings
{
public:
enum pluginTypes
{
INSTRUMENT, // instrument being used in channel-track
EFFECT, // effect-plugin for effect-board
IMPORT_FILTER, // filter for importing a file
EXPORT_FILTER, // filter for exporting a file
UNDEFINED = 255
} ;
// descriptor holds information about a plugin - every external plugin
// has to instantiate such a descriptor in an extern "C"-section so that
// the plugin-loader is able to access information about the plugin
struct descriptor
{
const char * name;
const char * public_name;
const char * description;
const char * author;
int version;
pluginTypes type;
embed::descriptor logo;
} ;
// contructor of a plugin
// _name: public name of plugin
// _type: one of the plugin-types defined above
plugin( const QString & _public_name, pluginTypes _type );
virtual ~plugin();
// returns the name, the plugin passed to plugin-constructor
inline const QString & publicName( void ) const
{
return( m_publicName );
}
// return type
inline pluginTypes type( void ) const
{
return( m_type );
}
// plugins can overload this for making other classes able to change
// settings of the plugin without knowing the actual class
virtual void FASTCALL setParameter( const QString & _param,
const QString & _value );
// plugins can overload this for making other classes able to query
// settings of the plugin without knowing the actual class
virtual QString FASTCALL getParameter( const QString & _param );
// returns an instance of a plugin whose name matches to given one
// if specified plugin couldn't be loaded, it creates a dummy-plugin
static plugin * FASTCALL instantiate( const QString & _plugin_name,
void * _data );
// fills given vector with descriptors for all available plugins
static void FASTCALL getDescriptorsOfAvailPlugins(
vvector<descriptor> & _plugin_descs );
private:
const QString m_publicName;
const pluginTypes m_type;
// pointer to instantiation-function in plugin
typedef plugin * ( * instantiationHook )( void * );
} ;
#endif

96
include/plugin_browser.h Normal file
View File

@@ -0,0 +1,96 @@
/*
* plugin_browser.h - include file for pluginBrowser
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 _PLUGIN_BROWSER_H
#define _PLUGIN_BROWSER_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "qt3support.h"
#ifdef QT4
#include <QVector>
#include <QPixmap>
#else
#include <qvaluevector.h>
#include <qpixmap.h>
#endif
#include "side_bar_widget.h"
#include "plugin.h"
class trackContainer;
class pluginBrowser : public sideBarWidget
{
Q_OBJECT
public:
pluginBrowser( QWidget * _parent );
virtual ~pluginBrowser();
private:
vvector<plugin::descriptor> m_pluginDescriptors;
QWidget * m_view;
} ;
class pluginDescWidget : public QWidget
{
public:
pluginDescWidget( const plugin::descriptor & _pd, QWidget * _parent );
virtual ~pluginDescWidget();
protected:
virtual void paintEvent( QPaintEvent * _pe );
virtual void mousePressEvent( QMouseEvent * _me );
virtual void mouseMoveEvent( QMouseEvent * _me );
virtual void mouseReleaseEvent( QMouseEvent * _me );
private:
const plugin::descriptor & m_pluginDescriptor;
QPixmap m_logo;
bool m_mouseOver;
} ;
#endif

View File

@@ -48,7 +48,7 @@ class sideBarWidget : public QWidget
public:
sideBarWidget( const QString & _title, const QPixmap & _icon,
QWidget * _parent );
~sideBarWidget();
virtual ~sideBarWidget();
inline const QPixmap & icon( void ) const
{
return( m_icon );
@@ -60,9 +60,9 @@ public:
protected:
void paintEvent( QPaintEvent * _pe );
void resizeEvent( QResizeEvent * _re );
inline void contextMenuEvent( QContextMenuEvent * )
virtual void paintEvent( QPaintEvent * _pe );
virtual void resizeEvent( QResizeEvent * _re );
inline virtual void contextMenuEvent( QContextMenuEvent * )
{
}

View File

@@ -229,7 +229,6 @@ protected:
protected slots:
void insertTact( void );
void removeTact( void );
void addChannelTrack( void );
void addBBTrack( void );
void addSampleTrack( void );
void scrolled( int _new_pos );

View File

@@ -0,0 +1,64 @@
/*
* string_pair_drag.h - class stringPairDrag which provides general support
* for drag'n'drop of string-pairs
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 _STRING_PAIR_DRAG_H
#define _STRING_PAIR_DRAG_H
#include "qt3support.h"
#ifdef QT4
#include <QDrag>
#else
#include <qdragobject.h>
#endif
class QPixmap;
class stringPairDrag : public
#ifdef QT4
QDrag
#else
QStoredDrag
#endif
{
public:
stringPairDrag( const QString & _key, const QString & _value,
const QPixmap & _icon, QWidget * _w );
~stringPairDrag();
static void processDragEnterEvent( QDragEnterEvent * _dee,
const QString & _allowed_keys );
static QString decodeKey( QDropEvent * _de );
static QString decodeValue( QDropEvent * _de );
} ;
#endif

View File

@@ -227,7 +227,7 @@ public:
public slots:
void changePosition( const midiTime & _new_pos = -1 );
void cloneTrack( void );
void deleteTrack( void );
void removeTrack( void );
void moveTrackUp( void );
void moveTrackDown( void );
void setMuted( bool _muted );
@@ -271,11 +271,10 @@ public:
track( trackContainer * _tc );
virtual ~track();
static track * FASTCALL createTrack( trackTypes _tt,
static track * FASTCALL create( trackTypes _tt, trackContainer * _tc );
static track * FASTCALL create( const QDomElement & _this,
trackContainer * _tc );
static track * FASTCALL createTrack( const QDomElement & _this,
trackContainer * _tc );
static track * FASTCALL cloneTrack( track * _track );
static track * FASTCALL clone( track * _track );
tact length( void ) const;

View File

@@ -93,10 +93,13 @@ public:
protected:
virtual void resizeEvent( QResizeEvent * );
virtual void dragEnterEvent( QDragEnterEvent * _dee );
virtual void dropEvent( QDropEvent * _de );
constTrackVector tracks( void ) const;
trackVector tracks( void );
virtual void resizeEvent( QResizeEvent * );
midiTime m_currentPosition;
@@ -106,16 +109,33 @@ protected slots:
private:
QScrollArea * m_scrollArea;
class scrollArea : public QScrollArea
{
public:
scrollArea( trackContainer * _parent );
virtual ~scrollArea();
protected:
virtual void wheelEvent( QWheelEvent * _we );
} ;
scrollArea * m_scrollArea;
typedef vvector<trackWidget *> trackWidgetVector;
trackWidgetVector m_trackWidgets;
float m_ppt;
friend class scrollArea;
signals:
void positionChanged( const midiTime & _pos );
} ;

View File

@@ -1,5 +1,6 @@
/*
* volume.h - declaration of some constants and types, concerning the volume of a note
* volume.h - declaration of some constants and types, concerning the volume
* of a note
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.sourceforge.net>

2
plugins/Makefile.am Normal file
View File

@@ -0,0 +1,2 @@
SUBDIRS = audio_file_processor ladspa_sine_1063 midi_out plucked_string_synth triple_oscillator vestige

View File

@@ -0,0 +1,34 @@
AUTOMAKE_OPTIONS = foreign 1.4
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/lib -I.
AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="audiofileprocessor"
%.moc: ./%.h
$(MOC) -o $@ $<
MOC_FILES = ./audio_file_processor.moc
BUILT_SOURCES = $(MOC_FILES) ./embedded_resources.h
EMBEDDED_RESOURCES = $(wildcard *png)
./embedded_resources.h: $(EMBEDDED_RESOURCES)
$(top_builddir)/buildtools/bin2res $(EMBEDDED_RESOURCES) > $@
EXTRA_DIST = $(EMBEDDED_RESOURCES)
CLEANFILES = $(MOC_FILES) ./embedded_resources.h
pkglib_LTLIBRARIES= libaudiofileprocessor.la
libaudiofileprocessor_la_SOURCES = audio_file_processor.cpp audio_file_processor.h
$(libaudiofileprocessor_la_SOURCES): ./embedded_resources.h

Binary file not shown.

View File

@@ -0,0 +1,628 @@
/*
* audio_file_processor.cpp - instrument for using audio-files
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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"
#ifdef QT4
#include <QPainter>
#include <QButtonGroup>
#include <QBitmap>
#include <Qt/QtXml>
#include <QFileInfo>
#else
#include <qpainter.h>
#include <qbuttongroup.h>
#include <qbitmap.h>
#include <qdom.h>
#include <qfileinfo.h>
#define isChecked isOn
#define setChecked setOn
#endif
#include "audio_file_processor.h"
#include "song_editor.h"
#include "channel_track.h"
#include "note_play_handle.h"
#include "paths.h"
#include "interpolation.h"
#include "buffer_allocator.h"
#include "pixmap_button.h"
#include "knob.h"
#include "tooltip.h"
#include "embed.cpp"
extern "C"
{
plugin::descriptor audiofileprocessor_plugin_descriptor =
{
STRINGIFY_PLUGIN_NAME( PLUGIN_NAME ),
"AudioFileProcessor",
QT_TRANSLATE_NOOP( "plugin",
"simple sampler with various settings for "
"using samples (e.g. drums) in a channel" ),
"Tobias Doerffel <tobydox@users.sf.net>",
0x0100,
plugin::INSTRUMENT,
PLUGIN_NAME::findEmbeddedData( "logo.png" )
} ;
}
QPixmap * audioFileProcessor::s_artwork = NULL;
audioFileProcessor::audioFileProcessor( channelTrack * _channel_track ) :
instrument( _channel_track,
audiofileprocessor_plugin_descriptor.public_name ),
specialBgHandlingWidget( PLUGIN_NAME::getIconPixmap( "artwork" ) ),
m_sampleBuffer( "" ),
m_drawMethod( sampleBuffer::LINE_CONNECT )
{
connect( &m_sampleBuffer, SIGNAL( sampleUpdated() ), this,
SLOT( sampleUpdated() ) );
if( s_artwork == NULL )
{
s_artwork = new QPixmap( PLUGIN_NAME::getIconPixmap(
"artwork" ) );
}
m_openAudioFileButton = new pixmapButton( this );
m_openAudioFileButton->setCheckable( FALSE );
m_openAudioFileButton->setCursor( QCursor( Qt::PointingHandCursor ) );
m_openAudioFileButton->move( 200, 90 );
m_openAudioFileButton->setActiveGraphic( embed::getIconPixmap(
"project_open_down" ) );
m_openAudioFileButton->setInactiveGraphic( embed::getIconPixmap(
"project_open" ) );
m_openAudioFileButton->setBgGraphic( getBackground(
m_openAudioFileButton ) );
connect( m_openAudioFileButton, SIGNAL( clicked() ), this,
SLOT( openAudioFile() ) );
toolTip::add( m_openAudioFileButton, tr( "Open other sample" ) );
#ifdef QT4
m_openAudioFileButton->setWhatsThis(
#else
QWhatsThis::add( m_openAudioFileButton,
#endif
tr( "Click here, if you want to open another audio-file. After "
"clicking on this button, a file-open-dialog appears "
"and you can select your file. Settings like Looping-"
"Mode, start- and end-point, amplify-value and so on "
"are not reset, so please don't wonder if your sample "
"doesn't sound like the original one..." ) );
m_reverseButton = new pixmapButton( this );
m_reverseButton->move( 160, 124 );
m_reverseButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"reverse_on" ) );
m_reverseButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"reverse_off" ) );
m_reverseButton->setBgGraphic( getBackground( m_reverseButton ) );
connect( m_reverseButton, SIGNAL( toggled( bool ) ), this,
SLOT( reverseBtnToggled( bool ) ) );
toolTip::add( m_reverseButton, tr( "Reverse sample" ) );
#ifdef QT4
m_reverseButton->setWhatsThis(
#else
QWhatsThis::add( m_reverseButton,
#endif
tr( "If you enable this button, the whole sample is reversed. "
"This is useful for cool effects, e.g. a reversed "
"crash." ) );
m_loopButton = new pixmapButton( this );
m_loopButton->move( 180, 124 );
m_loopButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
"loop_on" ) );
m_loopButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"loop_off" ) );
m_loopButton->setBgGraphic( getBackground( m_loopButton ) );
toolTip::add( m_loopButton,
tr( "Loop sample at start- and end-point" ) );
#ifdef QT4
m_loopButton->setWhatsThis(
#else
QWhatsThis::add( m_loopButton,
#endif
tr( "Here you can set, whether Looping-Mode is enabled. If "
"enabled, AudioFileProcessor loops between start- and "
"end-point of a sample until the whole note is played. "
"This is useful for things like string- and choir-"
"samples." ) );
m_ampKnob = new knob( knobDark_28, this, tr( "Amplify" ) );
m_ampKnob->setRange( 0, 500, 1.0f );
m_ampKnob->move( 6, 114 );
m_ampKnob->setValue( 100.0f, TRUE );
m_ampKnob->setHintText( tr( "Amplify:" )+" ", "%" );
m_ampKnob->setLabel( tr( "AMP" ) );
connect( m_ampKnob, SIGNAL( valueChanged( float ) ), this,
SLOT( ampKnobChanged( float ) ) );
#ifdef QT4
m_ampKnob->setWhatsThis(
#else
QWhatsThis::add( m_ampKnob,
#endif
tr( "With this knob you can set the amplify-ratio. When you "
"set a value of 100% your sample isn't changed. "
"Otherwise it will be amplified up or down (your "
"actual sample-file isn't touched!)" ) );
m_startKnob = new knob( knobDark_28, this, tr( "Start of sample" ) );
m_startKnob->setRange( 0, 1.0, 0.00001 );
m_startKnob->move( 46, 114 );
m_startKnob->setValue( 0.0, TRUE );
m_startKnob->setHintText( tr( "Startpoint:" )+" ", "" );
m_startKnob->setLabel( tr( "START" ) );
connect( m_startKnob, SIGNAL( valueChanged( float ) ), this,
SLOT( startKnobChanged( float ) ) );
#ifdef QT4
m_startKnob->setWhatsThis(
#else
QWhatsThis::add( m_startKnob,
#endif
tr( "With this knob you can set the point where "
"AudioFileProcessor should begin playing your sample. "
"If you enable Looping-Mode, this is the point to "
"which AudioFileProcessor returns if a note is longer "
"than the sample between start- and end-point." ) );
m_endKnob = new knob( knobDark_28, this, tr( "End of sample" ) );
m_endKnob->setRange( 0, 1.0, 0.00001 );
m_endKnob->move( 84, 114 );
m_endKnob->setValue( 1.0, TRUE );
m_endKnob->setHintText( tr( "Endpoint:" )+" ", "" );
m_endKnob->setLabel( tr( "END" ) );
connect( m_endKnob, SIGNAL( valueChanged( float ) ), this,
SLOT( endKnobChanged( float ) ) );
#ifdef QT4
m_endKnob->setWhatsThis(
#else
QWhatsThis::add( m_endKnob,
#endif
tr( "With this knob you can set the point where "
"AudioFileProcessor should stop playing your sample. "
"If you enable Looping-Mode, this is the point where "
"AudioFileProcessor returns if a note is longer than "
"the sample between start- and end-point." ) );
m_viewLinesPB = new pixmapButton( this );
m_viewLinesPB->move( 154, 158 );
m_viewLinesPB->setBgGraphic( getBackground( m_viewLinesPB ) );
if( m_drawMethod == sampleBuffer::LINE_CONNECT )
{
#ifdef QT4
m_viewLinesPB->setChecked( TRUE );
#else
m_viewLinesPB->setOn( TRUE );
#endif
}
connect( m_viewLinesPB, SIGNAL( toggled( bool ) ), this,
SLOT( lineDrawBtnToggled( bool ) ) );
#ifdef QT4
m_viewLinesPB->setWhatsThis(
#else
QWhatsThis::add( m_viewLinesPB,
#endif
tr( "Activate this button, if your sample should be drawn "
"with connected lines. This doesn't change the "
"sound itself. It just gives you another view to your "
"sample." ) );
m_viewDotsPB = new pixmapButton( this );
m_viewDotsPB->move( 204, 158 );
m_viewDotsPB->setBgGraphic( getBackground( m_viewDotsPB ) );
if( m_drawMethod == sampleBuffer::DOTS )
{
#ifdef QT4
m_viewDotsPB->setChecked( TRUE );
#else
m_viewDotsPB->setOn( TRUE );
#endif
}
connect( m_viewDotsPB, SIGNAL( toggled( bool ) ), this,
SLOT( dotDrawBtnToggled( bool ) ) );
#ifdef QT4
m_viewDotsPB->setWhatsThis(
#else
QWhatsThis::add( m_viewDotsPB,
#endif
tr( "Activate this button, if your sample should be drawn "
"with dots. This doesn't change the sound itself. "
"It just gives you another view to your sample." ) );
QButtonGroup * view_group = new QButtonGroup( this );
view_group->addButton( m_viewLinesPB );
view_group->addButton( m_viewDotsPB );
view_group->setExclusive( TRUE );
#ifndef QT4
view_group->hide();
setBackgroundMode( Qt::NoBackground );
#endif
}
audioFileProcessor::~audioFileProcessor()
{
}
void audioFileProcessor::saveSettings( QDomDocument & _doc,
QDomElement & _parent )
{
QDomElement afp_de = _doc.createElement( nodeName() );
afp_de.setAttribute( "src", m_sampleBuffer.audioFile() );
afp_de.setAttribute( "sframe", QString::number(
m_sampleBuffer.startFrame() /
(float)m_sampleBuffer.frames() ) );
afp_de.setAttribute( "eframe", QString::number(
m_sampleBuffer.endFrame() /
(float)m_sampleBuffer.frames() ) );
afp_de.setAttribute( "reversed", QString::number(
m_reverseButton->isChecked() ) );
afp_de.setAttribute( "looped", QString::number(
m_loopButton->isChecked() ) );
afp_de.setAttribute( "amp", QString::number( m_ampKnob->value() ) );
_parent.appendChild( afp_de );
}
void audioFileProcessor::loadSettings( const QDomElement & _this )
{
setAudioFile( _this.attribute( "src" ) );
setStartAndEndKnob( _this.attribute( "sframe" ).toFloat(),
_this.attribute( "eframe" ).toFloat() );
m_reverseButton->setChecked( _this.attribute( "reversed" ).toInt() );
m_loopButton->setChecked( _this.attribute( "looped" ).toInt() );
m_ampKnob->setValue( _this.attribute( "amp" ).toFloat() );
}
QString audioFileProcessor::nodeName( void ) const
{
return( audiofileprocessor_plugin_descriptor.name );
}
void audioFileProcessor::setParameter( const QString & _param,
const QString & _value )
{
if( _param == "audiofile" )
{
setAudioFile( _value );
}
}
Uint32 audioFileProcessor::getBeatLen( notePlayHandle * _n ) const
{
const float freq_factor = BASE_FREQ /
( getChannelTrack()->frequency( _n ) *
DEFAULT_SAMPLE_RATE /
mixer::inst()->sampleRate() );
return( static_cast<Uint32>( floorf( ( m_sampleBuffer.endFrame() -
m_sampleBuffer.startFrame() ) *
freq_factor ) ) );
}
void audioFileProcessor::setAudioFile( const QString & _audio_file )
{
// is current channel-name equal to previous-filename??
if( getChannelTrack()->name() ==
QFileInfo( m_sampleBuffer.audioFile() ).fileName() ||
m_sampleBuffer.audioFile() == "" )
{
// then set it to new one
getChannelTrack()->setName( QFileInfo( _audio_file
).fileName() );
}
// else we don't touch the channel-name, because the user named it self
m_sampleBuffer.setAudioFile( _audio_file );
setStartAndEndKnob( 0.0f, 1.0f );
}
void audioFileProcessor::playNote( notePlayHandle * _n )
{
const Uint32 frames = mixer::inst()->framesPerAudioBuffer();
sampleFrame * buf = bufferAllocator::alloc<sampleFrame>( frames );
// calculate frequency of note
const float note_freq = getChannelTrack()->frequency( _n ) /
( mixer::inst()->sampleRate() /
DEFAULT_SAMPLE_RATE );
if( m_sampleBuffer.play( buf, _n->totalFramesPlayed(),
frames, note_freq,
m_loopButton->isChecked(),
&_n->m_pluginData ) == TRUE )
{
getChannelTrack()->processAudioBuffer( buf, frames, _n );
}
bufferAllocator::free( buf );
}
void audioFileProcessor::deleteNotePluginData( notePlayHandle * _n )
{
if( _n->m_pluginData != NULL )
{
m_sampleBuffer.deleteResamplingData( &_n->m_pluginData );
}
}
void audioFileProcessor::paintEvent( QPaintEvent * )
{
#ifdef QT4
QPainter p( this );
#else
QPixmap pm( rect().size() );
pm.fill( this, rect().topLeft() );
QPainter p( &pm, this );
#endif
p.drawPixmap( 0, 0, *s_artwork );
QString file_name = "";
Uint16 idx = m_sampleBuffer.audioFile().length();
p.setFont( pointSize<8>( p.font() ) );
QFontMetrics fm( font() );
// simple algorithm for creating a text from the filename that
// matches in the white rectangle
#ifdef QT4
while( idx > 0 &&
fm.size( Qt::TextSingleLine, file_name + "..." ).width() < 225 )
#else
while( idx > 0 &&
fm.size( Qt::SingleLine, file_name + "..." ).width() < 225 )
#endif
{
file_name = m_sampleBuffer.audioFile()[--idx] + file_name;
}
if( idx > 0 )
{
file_name = "..." + file_name;
}
p.setPen( QColor( 255, 255, 255 ) );
p.drawText( 8, 84, file_name );
p.drawPixmap( 2, 172, m_graph );
p.setPen( QColor( 0xFF, 0xAA, 0x00 ) );
const QRect graph_rect( 4, 174, 241, 70 );
const Uint32 frames = tMax( m_sampleBuffer.frames(),
static_cast<Uint32>( 1 ) );
const Uint16 start_frame_x = m_sampleBuffer.startFrame() *
graph_rect.width() / frames;
const Uint16 end_frame_x = m_sampleBuffer.endFrame() *
( graph_rect.width() - 1 ) / frames;
p.drawLine( start_frame_x + graph_rect.x(), graph_rect.y(),
start_frame_x + graph_rect.x(),
graph_rect.height() + graph_rect.y() );
p.drawLine( end_frame_x + graph_rect.x(), graph_rect.y(),
end_frame_x + graph_rect.x(),
graph_rect.height() + graph_rect.y() );
#ifndef QT4
bitBlt( this, rect().topLeft(), &pm );
#endif
}
void audioFileProcessor::sampleUpdated( void )
{
m_graph = QPixmap( 245, 75 );
copyBlt( &m_graph, 0, 0, s_artwork, 2, 172, m_graph.width(),
m_graph.height() );
QPainter p( &m_graph );
m_sampleBuffer.drawWaves( p, QRect( 2, 2, m_graph.width() - 4,
m_graph.height() - 4 ),
m_drawMethod );
update();
}
void audioFileProcessor::reverseBtnToggled( bool _on )
{
m_sampleBuffer.setReversed( _on );
songEditor::inst()->setModified();
}
void audioFileProcessor::lineDrawBtnToggled( bool _on )
{
if( _on )
{
m_drawMethod = sampleBuffer::LINE_CONNECT;
sampleUpdated();
}
}
void audioFileProcessor::dotDrawBtnToggled( bool _on )
{
if( _on )
{
m_drawMethod = sampleBuffer::DOTS;
sampleUpdated();
}
}
void audioFileProcessor::ampKnobChanged( float _val )
{
m_sampleBuffer.setAmplification( _val/100.0f );
}
void audioFileProcessor::setStartAndEndKnob( float _s, float _e )
{
// because the signal-handlers of valuechanges of start- and end-knob
// do range checking, depending on value of the other knob, we have to
// disconnect the signal-handlers, set then the values, connect again
// and then let the changes take effect...
m_startKnob->disconnect();
m_endKnob->disconnect();
m_startKnob->setValue( _s );
m_endKnob->setValue( _e );
connect( m_startKnob, SIGNAL( valueChanged( float ) ), this,
SLOT( startKnobChanged( float ) ) );
connect( m_endKnob, SIGNAL( valueChanged( float ) ), this,
SLOT( endKnobChanged( float ) ) );
m_startKnob->setValue( _s );
m_endKnob->setValue( _e );
}
void audioFileProcessor::startKnobChanged( float _new_value )
{
if( _new_value < m_endKnob->value() )
{
m_sampleBuffer.setStartFrame( static_cast<Uint32>( _new_value *
m_sampleBuffer.frames() ) );
}
else
{
m_startKnob->setValue( m_endKnob->value() - 0.01 );
}
update();
}
void audioFileProcessor::endKnobChanged( float _new_value )
{
if( _new_value > m_startKnob->value() )
{
m_sampleBuffer.setEndFrame( static_cast<Uint32>( _new_value *
m_sampleBuffer.frames() ) - 1 );
}
else
{
m_endKnob->setValue( m_startKnob->value() + 0.01 );
}
update();
}
void audioFileProcessor::openAudioFile( void )
{
QString af = m_sampleBuffer.openAudioFile();
if( af != "" )
{
setAudioFile( af );
songEditor::inst()->setModified();
}
}
extern "C"
{
// neccessary for getting instance out of shared lib
plugin * lmms_plugin_main( void * _data )
{
return( new audioFileProcessor(
static_cast<channelTrack *>( _data ) ) );
}
}
#undef isChecked
#undef isOn
#include "audio_file_processor.moc"

View File

@@ -0,0 +1,116 @@
/*
* audio_file_processor.h - declaration of class audioFileProcessor
* (instrument-plugin for using audio-files)
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 _AUDIO_FILE_PROCESSOR_H
#define _AUDIO_FILE_PROCESSOR_H
#include "qt3support.h"
#ifdef QT4
#include <QPixmap>
#else
#include <qpixmap.h>
#endif
#include "instrument.h"
#include "sample_buffer.h"
#include "spc_bg_hndl_widget.h"
class knob;
class pixmapButton;
class audioFileProcessor : public instrument, public specialBgHandlingWidget
{
Q_OBJECT
public:
audioFileProcessor( channelTrack * _channel_track );
virtual ~audioFileProcessor();
virtual void FASTCALL playNote( notePlayHandle * _n );
virtual void FASTCALL deleteNotePluginData( notePlayHandle * _n );
virtual void FASTCALL saveSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void FASTCALL loadSettings( const QDomElement & _this );
virtual void FASTCALL setParameter( const QString & _param,
const QString & _value );
virtual QString nodeName( void ) const;
virtual Uint32 FASTCALL getBeatLen( notePlayHandle * _n ) const;
public slots:
void setAudioFile( const QString & _audio_file );
protected slots:
void openAudioFile( void );
void reverseBtnToggled( bool _on );
void ampKnobChanged( float _new_value );
void startKnobChanged( float _new_value );
void endKnobChanged( float _new_value );
void lineDrawBtnToggled( bool _on );
void dotDrawBtnToggled( bool _on );
void sampleUpdated( void );
protected:
void paintEvent( QPaintEvent * );
private:
static QPixmap * s_artwork;
sampleBuffer m_sampleBuffer;
sampleBuffer::drawMethods m_drawMethod;
QPixmap m_graph;
knob * m_ampKnob;
knob * m_startKnob;
knob * m_endKnob;
pixmapButton * m_openAudioFileButton;
pixmapButton * m_viewLinesPB;
pixmapButton * m_viewDotsPB;
pixmapButton * m_reverseButton;
pixmapButton * m_loopButton;
void updateSample( void );
void FASTCALL setStartAndEndKnob( float _s, float _e );
} ;
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,33 @@
AUTOMAKE_OPTIONS = foreign 1.4
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/lib -I.
AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="pluckedstringsynth"
%.moc: ./%.h
$(MOC) -o $@ $<
MOC_FILES = ./plucked_string_synth.moc
BUILT_SOURCES = $(MOC_FILES) ./embedded_resources.h
EMBEDDED_RESOURCES = $(wildcard *png)
./embedded_resources.h: $(EMBEDDED_RESOURCES)
$(top_builddir)/buildtools/bin2res $(EMBEDDED_RESOURCES) > $@
EXTRA_DIST = $(EMBEDDED_RESOURCES)
CLEANFILES = $(MOC_FILES) ./embedded_resources.h
pkglib_LTLIBRARIES= libpluckedstringsynth.la
libpluckedstringsynth_la_SOURCES = plucked_string_synth.cpp plucked_string_synth.h
$(libpluckedstringsynth_la_SOURCES): ./embedded_resources.h

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,274 @@
/*
* plucked_string_synth.cpp - instrument which uses the Karplus-Strong-algorithm
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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"
#ifdef QT4
#include <Qt/QtXml>
#include <QMap>
#else
#include <qdom.h>
#include <qmap.h>
#endif
#include "plucked_string_synth.h"
#include "channel_track.h"
#include "note_play_handle.h"
#include "templates.h"
#include "buffer_allocator.h"
#include "knob.h"
#include "embed.cpp"
extern "C"
{
plugin::descriptor pluckedstringsynth_plugin_descriptor =
{
STRINGIFY_PLUGIN_NAME( PLUGIN_NAME ),
"PluckedStringSynth",
QT_TRANSLATE_NOOP( "plugin",
"cheap synthesis of guitar/harp-like sounds" ),
"Tobias Doerffel <tobydox@users.sf.net>",
0x0100,
plugin::INSTRUMENT,
PLUGIN_NAME::findEmbeddedData( "logo.png" )
} ;
}
// TODO: make this synth stereo for better better spacial (room) feeling and
// add distortion
pluckedStringSynth::pluckedStringSynth( channelTrack * _channel_track ) :
instrument( _channel_track,
pluckedstringsynth_plugin_descriptor.public_name )
{
m_pickKnob = new knob( knobDark_28, this, tr( "Pick position" ) );
m_pickKnob->setRange( 0.0f, 0.5f, 0.005f );
m_pickKnob->setValue( 0.0f, TRUE );
m_pickKnob->move( 86, 134 );
m_pickKnob->setHintText( tr( "Pick position:" ) + " ", "" );
m_pickupKnob = new knob( knobDark_28, this, tr( "Pickup position" ) );
m_pickupKnob->setRange( 0.0f, 0.5f, 0.005f );
m_pickupKnob->setValue( 0.05f, TRUE );
m_pickupKnob->move( 138, 134 );
m_pickupKnob->setHintText( tr( "Pickup position:" ) + " ", "" );
#ifdef QT4
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap(
"artwork" ) );
setPalette( pal );
#else
setErasePixmap( PLUGIN_NAME::getIconPixmap( "artwork" ) );
#endif
}
pluckedStringSynth::~pluckedStringSynth()
{
}
void pluckedStringSynth::saveSettings( QDomDocument & _doc,
QDomElement & _parent )
{
QDomElement pss_de = _doc.createElement( nodeName() );
pss_de.setAttribute( "pick", QString::number( m_pickKnob->value() ) );
pss_de.setAttribute( "pickup", QString::number(
m_pickupKnob->value() ) );
_parent.appendChild( pss_de );
}
void pluckedStringSynth::loadSettings( const QDomElement & _this )
{
m_pickKnob->setValue( _this.attribute( "pick" ).toFloat() );
m_pickupKnob->setValue( _this.attribute( "pickup" ).toFloat() );
}
QString pluckedStringSynth::nodeName( void ) const
{
return( pluckedstringsynth_plugin_descriptor.name );
}
void pluckedStringSynth::playNote( notePlayHandle * _n )
{
if ( _n->totalFramesPlayed() == 0 )
{
float freq = getChannelTrack()->frequency( _n );
_n->m_pluginData = new pluckSynth( freq, m_pickKnob->value(),
m_pickupKnob->value() );
}
const Uint32 frames = mixer::inst()->framesPerAudioBuffer();
sampleFrame * buf = bufferAllocator::alloc<sampleFrame>( frames );
pluckSynth * ps = static_cast<pluckSynth *>( _n->m_pluginData );
for( Uint32 frame = 0; frame < frames; ++frame )
{
const sampleType cur = ps->nextStringSample();
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
{
buf[frame][chnl] = cur;
}
}
getChannelTrack()->processAudioBuffer( buf, frames, _n );
bufferAllocator::free( buf );
}
void pluckedStringSynth::deleteNotePluginData( notePlayHandle * _n )
{
delete static_cast<pluckSynth *>( _n->m_pluginData );
}
pluckSynth::delayLine * FASTCALL pluckSynth::initDelayLine( int _len )
{
delayLine * dl = new pluckSynth::delayLine[_len];
dl->length = _len;
if( _len > 0 )
{
dl->data = new sampleType[_len];
}
else
{
dl->data = NULL;
}
dl->pointer = dl->data;
dl->end = dl->data + _len - 1;
return( dl );
}
void FASTCALL pluckSynth::freeDelayLine( delayLine * _dl )
{
if( _dl && _dl->data )
{
delete[] _dl->data;
}
_dl->data = NULL;
delete[] _dl;
}
pluckSynth::pluckSynth( float _pitch, float _pick, float _pickup )
{
const float AMP = 1.5f;
int rail_length = static_cast<int>( mixer::inst()->sampleRate() / 2 /
_pitch ) + 1;
// Round pick position to nearest spatial sample.
// A pick position at x = 0 is not allowed.
int pick_sample = static_cast<int>( tMax<float>( rail_length * _pick,
1.0f ) );
float initial_shape[rail_length];
m_upperRail = pluckSynth::initDelayLine( rail_length );
m_lowerRail = pluckSynth::initDelayLine( rail_length );
//#define METALLIC_PLUCK
#ifdef METALLIC_PLUCK
for ( int i = 0; i < rail_length; i++ )
{
initial_shape[i] = rand() * AMP / RAND_MAX;
}
initial_shape[pick_sample] = 0.5;
initial_shape[pick_sample+1] = 0.5;
#else
float upslope = AMP / pick_sample;
const float downslope = AMP / ( rail_length - pick_sample - 1 );
for( int i = 0; i < pick_sample; i++ )
{
initial_shape[i] = upslope * i;
}
for( int i = pick_sample; i < rail_length; i++ )
{
initial_shape[i] = downslope * ( rail_length - 1 - i );
}
#endif
// Initial conditions for the ideal plucked string.
// "Past history" is measured backward from the end of the array.
pluckSynth::setDelayLine( m_lowerRail, initial_shape, 0.5f );
pluckSynth::setDelayLine( m_upperRail, initial_shape, 0.5f );
m_pickupLoc = static_cast<int>( _pickup * rail_length );
}
extern "C"
{
// neccessary for getting instance out of shared lib
plugin * lmms_plugin_main( void * _data )
{
return( new pluckedStringSynth(
static_cast<channelTrack *>( _data ) ) );
}
}

View File

@@ -0,0 +1,216 @@
/*
* plucked_string_sytn.h - declaration of class pluckedStringSynth which
* is a synth for plucked string-sounds
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 _PLUCKED_STRING_SYNTH_H
#define _PLUCKED_STRING_SYNTH_H
#include "instrument.h"
class knob;
class notePlayHandle;
// the actual synth
class pluckSynth
{
public:
pluckSynth( float _pitch, float _pick, float _pickup );
inline ~pluckSynth( void )
{
pluckSynth::freeDelayLine( m_upperRail );
pluckSynth::freeDelayLine( m_lowerRail );
}
inline sampleType nextStringSample( void )
{
// Output at pickup position
sampleType outsamp = rgDlAccess( m_upperRail, m_pickupLoc );
outsamp += lgDlAccess( m_lowerRail, m_pickupLoc );
// Sample traveling into "bridge"
sampleType ym0 = lgDlAccess( m_lowerRail, 1 );
// Sample to "nut"
sampleType ypM = rgDlAccess( m_upperRail,
m_upperRail->length - 2 );
// String state update
// Decrement pointer and then update
rgDlUpdate( m_upperRail, -bridgeReflection( ym0 ) );
// Update and then increment pointer
lgDlUpdate( m_lowerRail, -ypM );
return( outsamp );
}
private:
struct delayLine
{
sampleType * data;
int length;
sampleType * pointer;
sampleType * end;
} ;
delayLine * m_upperRail;
delayLine * m_lowerRail;
int m_pickupLoc;
static delayLine * FASTCALL initDelayLine( int _len );
static void FASTCALL freeDelayLine( delayLine * _dl );
static inline void setDelayLine( delayLine * _dl, float * _values,
float _scale )
{
for( int i = 0; i < _dl->length; ++i )
{
_dl->data[i] = _scale * _values[i];
}
}
/* lgDlUpdate(dl, insamp);
* Places "nut-reflected" sample from upper delay-line into
* current lower delay-line pointer position (which represents
* x = 0 position). The pointer is then incremented (i.e. the
* wave travels one sample to the left), turning the previous
* position into an "effective" x = L position for the next
* iteration. */
static inline void lgDlUpdate( delayLine * _dl, sampleType _insamp )
{
register sampleType * ptr = _dl->pointer;
*ptr = _insamp;
++ptr;
if( ptr > _dl->end )
{
ptr = _dl->data;
}
_dl->pointer = ptr;
}
/* rgDlUpdate(dl, insamp);
* Decrements current upper delay-line pointer position (i.e.
* the wave travels one sample to the right), moving it to the
* "effective" x = 0 position for the next iteration. The
* "bridge-reflected" sample from lower delay-line is then placed
* into this position. */
static inline void rgDlUpdate( delayLine * _dl, sampleType _insamp )
{
register sampleType * ptr = _dl->pointer;
--ptr;
if( ptr < _dl->data )
{
ptr = _dl->end;
}
*ptr = _insamp;
_dl->pointer = ptr;
}
/* dlAccess(dl, position);
* Returns sample "position" samples into delay-line's past.
* Position "0" points to the most recently inserted sample. */
static inline sampleType dlAccess( delayLine * _dl, int _position )
{
sampleType * outpos = _dl->pointer + _position;
while( outpos < _dl->data )
{
outpos += _dl->length;
}
while( outpos > _dl->end )
{
outpos -= _dl->length;
}
return( *outpos );
}
/*
* Right-going delay line:
* -->---->---->---
* x=0
* (pointer)
* Left-going delay line:
* --<----<----<---
* x=0
* (pointer)
*/
/* rgDlAccess(dl, position);
* Returns spatial sample at position "position", where position zero
* is equal to the current upper delay-line pointer position (x = 0).
* In a right-going delay-line, position increases to the right, and
* delay increases to the right => left = past and right = future. */
static inline sampleType rgDlAccess( delayLine * _dl, int _position )
{
return( dlAccess( _dl, _position ) );
}
/* lgDlAccess(dl, position);
* Returns spatial sample at position "position", where position zero
* is equal to the current lower delay-line pointer position (x = 0).
* In a left-going delay-line, position increases to the right, and
* delay DEcreases to the right => left = future and right = past. */
static inline sampleType lgDlAccess( delayLine * _dl, int _position )
{
return( dlAccess( _dl, _position ) );
}
static inline sampleType bridgeReflection( sampleType _insamp )
{
static sampleType state = 0.0f; // filter memory
// Implement a one-pole lowpass with feedback coefficient = 0.5
return( state = state*0.5f + _insamp*0.5f );
}
} ;
class pluckedStringSynth : public instrument
{
public:
pluckedStringSynth(channelTrack * _channel_track );
virtual ~pluckedStringSynth();
virtual void FASTCALL playNote( notePlayHandle * _n );
virtual void FASTCALL deleteNotePluginData( notePlayHandle * _n );
virtual void FASTCALL saveSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void FASTCALL loadSettings( const QDomElement & _this );
virtual QString nodeName( void ) const;
private:
knob * m_pickKnob;
knob * m_pickupKnob;
} ;
#endif

View File

@@ -0,0 +1,33 @@
AUTOMAKE_OPTIONS = foreign 1.4
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/lib -I.
AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="tripleoscillator"
%.moc: ./%.h
$(MOC) -o $@ $<
MOC_FILES = ./triple_oscillator.moc
BUILT_SOURCES = $(MOC_FILES) ./embedded_resources.h
EMBEDDED_RESOURCES = $(wildcard *png)
./embedded_resources.h: $(EMBEDDED_RESOURCES)
$(top_builddir)/buildtools/bin2res $(EMBEDDED_RESOURCES) > $@
EXTRA_DIST = $(EMBEDDED_RESOURCES)
CLEANFILES = $(MOC_FILES) ./embedded_resources.h
pkglib_LTLIBRARIES= libtripleoscillator.la
libtripleoscillator_la_SOURCES = triple_oscillator.cpp triple_oscillator.h
$(libtripleoscillator_la_SOURCES): ./embedded_resources.h

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,167 @@
/*
* triple_oscillator.h - declaration of class tripleOscillator a powerful
* instrument-plugin with 3 oscillators
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 _TRIPLE_OSCILLATOR_H
#define _TRIPLE_OSCILLATOR_H
#include "instrument.h"
#include "oscillator.h"
#include "sample_buffer.h"
class knob;
class pixmapButton;
class notePlayHandle;
const int NUM_OF_OSCILLATORS = 3;
class tripleOscillator : public instrument
{
Q_OBJECT
public:
tripleOscillator( channelTrack * _channel ) FASTCALL;
virtual ~tripleOscillator();
virtual void FASTCALL playNote( notePlayHandle * _n );
virtual void FASTCALL deleteNotePluginData( notePlayHandle * _n );
virtual void FASTCALL saveSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void FASTCALL loadSettings( const QDomElement & _this );
virtual QString nodeName( void ) const;
protected slots:
// Slots for Osc 1
void osc01SinWaveCh( bool _on );
void osc01TriangleWaveCh( bool _on );
void osc01SawWaveCh( bool _on );
void osc01SquareWaveCh( bool _on );
void osc01MoogSawWaveCh( bool _on );
void osc01ExpWaveCh( bool _on );
void osc01WhiteNoiseCh( bool _on );
void osc01UserDefWaveCh( bool _on );
void osc01UserDefWaveDblClick( void );
// Slots for Osc 2
void osc02SinWaveCh( bool _on );
void osc02TriangleWaveCh( bool _on );
void osc02SawWaveCh( bool _on );
void osc02SquareWaveCh( bool _on );
void osc02MoogSawWaveCh( bool _on );
void osc02ExpWaveCh( bool _on );
void osc02WhiteNoiseCh( bool _on );
void osc02UserDefWaveCh( bool _on );
void osc02UserDefWaveDblClick( void );
// Slots for Osc 3
void osc03SinWaveCh( bool _on );
void osc03TriangleWaveCh( bool _on );
void osc03SawWaveCh( bool _on );
void osc03SquareWaveCh( bool _on );
void osc03MoogSawWaveCh( bool _on );
void osc03ExpWaveCh( bool _on );
void osc03WhiteNoiseCh( bool _on );
void osc03UserDefWaveCh( bool _on );
void osc03UserDefWaveDblClick( void );
// modulation-type-button slots
void fm1BtnToggled( bool _on );
void am1BtnToggled( bool _on );
void mix1BtnToggled( bool _on );
void sync1BtnToggled( bool _on );
void fm2BtnToggled( bool _on );
void am2BtnToggled( bool _on );
void mix2BtnToggled( bool _on );
void sync2BtnToggled( bool _on );
private:
channelTrack * m_channelTrack;
struct oscillatorData
{
oscillator::waveShapes waveShape;
knob * volKnob;
knob * panKnob;
knob * coarseKnob;
knob * fineLKnob;
knob * fineRKnob;
knob * phaseOffsetKnob;
knob * stereoPhaseDetuningKnob;
pixmapButton * sinWaveBtn;
pixmapButton * triangleWaveBtn;
pixmapButton * sawWaveBtn;
pixmapButton * sqrWaveBtn;
pixmapButton * moogSawWaveBtn;
pixmapButton * expWaveBtn;
pixmapButton * whiteNoiseWaveBtn;
pixmapButton * usrWaveBtn;
sampleBuffer m_sampleBuffer;
} m_osc[NUM_OF_OSCILLATORS];
struct oscPtr
{
oscillator * oscLeft;
oscillator * oscRight;
} ;
void FASTCALL doSinWaveBtn( oscillatorData * _osc );
void FASTCALL doTriangleWaveBtn( oscillatorData * _osc );
void FASTCALL doSawWaveBtn( oscillatorData * _osc );
void FASTCALL doSqrWaveBtn( oscillatorData * _osc );
void FASTCALL doMoogSawWaveBtn( oscillatorData * _osc );
void FASTCALL doExpWaveBtn( oscillatorData * _osc );
void FASTCALL doWhiteNoiseWaveBtn( oscillatorData * _osc );
void FASTCALL doUsrWaveBtn( oscillatorData * _osc );
pixmapButton * FASTCALL getModulationButton(
oscillator::modulationAlgos _modulation_algo, int _n );
void FASTCALL setModulationAlgo(
oscillator::modulationAlgos _new_modulation_algo, int _n );
oscillator::modulationAlgos FASTCALL getModulationAlgo( int _n );
pixmapButton * m_fm1OscBtn;
pixmapButton * m_am1OscBtn;
pixmapButton * m_mix1OscBtn;
pixmapButton * m_sync1OscBtn;
pixmapButton * m_fm2OscBtn;
pixmapButton * m_am2OscBtn;
pixmapButton * m_mix2OscBtn;
pixmapButton * m_sync2OscBtn;
oscillator::modulationAlgos m_modulationAlgo1;
oscillator::modulationAlgos m_modulationAlgo2;
} ;
#endif

View File

@@ -0,0 +1,35 @@
AUTOMAKE_OPTIONS = foreign 1.4
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/lib -I.
AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="vestige"
%.moc: ./%.h
$(MOC) -o $@ $<
MOC_FILES = ./vestige.moc
BUILT_SOURCES = $(MOC_FILES) ./embedded_resources.h
EMBEDDED_RESOURCES = $(wildcard *png)
./embedded_resources.h: $(EMBEDDED_RESOURCES)
$(top_builddir)/buildtools/bin2res $(EMBEDDED_RESOURCES) > $@
EXTRA_DIST = $(EMBEDDED_RESOURCES)
CLEANFILES = $(MOC_FILES) ./embedded_resources.h
pkglib_LTLIBRARIES= libvestige.la
libvestige_la_SOURCES = vestige.cpp vestige.h
# libvestige_la_LIBADD = -lfst
$(libvestige_la_SOURCES): ./embedded_resources.h

BIN
plugins/vestige/artwork.png Normal file

Binary file not shown.

BIN
plugins/vestige/logo.png Normal file

Binary file not shown.

860
plugins/vestige/vestige.cpp Normal file
View File

@@ -0,0 +1,860 @@
/*
* vestige.cpp - instrument-plugin for hosting VST-plugins
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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"
#ifdef QT4
#include <Qt/QtXml>
#include <QMessageBox>
#include <QFileDialog>
#include <QFileInfo>
#include <QDir>
#include <QCursor>
#else
#include <qdom.h>
#include <qmessagebox.h>
#include <qfiledialog.h>
#include <qfileinfo.h>
#include <qdir.h>
#include <qcursor.h>
#endif
#include "vestige.h"
#include "channel_track.h"
#include "note_play_handle.h"
#include "buffer_allocator.h"
#include "mixer.h"
#include "song_editor.h"
#include "instrument_play_handle.h"
#include "pixmap_button.h"
#include "tooltip.h"
#include "spc_bg_hndl_widget.h"
#include "embed.cpp"
extern "C"
{
plugin::descriptor vestige_plugin_descriptor =
{
STRINGIFY_PLUGIN_NAME( PLUGIN_NAME ),
"VeSTige",
QT_TRANSLATE_NOOP( "plugin",
"experimental VST-hoster for using VST-plugins "
"within LMMS" ),
"Tobias Doerffel <tobydox@users.sf.net>",
0x0100,
plugin::INSTRUMENT,
PLUGIN_NAME::findEmbeddedData( "logo.png" )
} ;
}
bool vestigeInstrument::s_initialized = FALSE;
bool vestigeInstrument::s_threadAdopted = FALSE;
QPixmap * vestigeInstrument::s_artwork = NULL;
vestigeInstrument::vestigeInstrument( channelTrack * _channel_track ) :
instrument( _channel_track, vestige_plugin_descriptor.public_name ),
specialBgHandlingWidget( PLUGIN_NAME::getIconPixmap( "artwork" ) ),
m_handle( NULL ),
m_fst( NULL )
{
if( s_artwork == NULL )
{
s_artwork = new QPixmap( PLUGIN_NAME::getIconPixmap(
"artwork" ) );
}
#ifdef QT4
QPalette pal;
pal.setBrush( backgroundRole(), *s_artwork);
setPalette( pal );
#else
setErasePixmap( *s_artwork );
#endif
m_openPluginButton = new pixmapButton( this );
m_openPluginButton->setCheckable( FALSE );
m_openPluginButton->setCursor( PointingHandCursor );
m_openPluginButton->move( 200, 70 );
m_openPluginButton->setActiveGraphic( embed::getIconPixmap(
"project_open_down" ) );
m_openPluginButton->setInactiveGraphic( embed::getIconPixmap(
"project_open" ) );
m_openPluginButton->setBgGraphic( getBackground(
m_openPluginButton ) );
connect( m_openPluginButton, SIGNAL( clicked() ), this,
SLOT( openPlugin() ) );
toolTip::add( m_openPluginButton, tr( "Open other VST-plugin" ) );
#ifdef QT4
m_openPluginButton->setWhatsThis(
#else
QWhatsThis::add( m_openPluginButton,
#endif
tr( "Click here, if you want to open another VST-plugin. After "
"clicking on this button, a file-open-dialog appears "
"and you can select your file." ) );
if( s_initialized == FALSE )
{
if( fst_init( fst_signal_handler ) )
{
// TODO: message-box
return;
}
s_initialized = TRUE;
}
// now we need a play-handle which cares for calling play()
instrumentPlayHandle * iph = new instrumentPlayHandle( this );
mixer::inst()->addPlayHandle( iph );
}
vestigeInstrument::~vestigeInstrument()
{
// this single call automates the rest of cleanup like trashing our
// play-handle and so on
invalidate();
closePlugin();
}
void vestigeInstrument::loadSettings( const QDomElement & _this )
{
}
void vestigeInstrument::saveSettings( QDomDocument & _doc,
QDomElement & _parent )
{
QDomElement vst_de = _doc.createElement( nodeName() );
_parent.appendChild( vst_de );
}
QString vestigeInstrument::nodeName( void ) const
{
return( vestige_plugin_descriptor.name );
}
void vestigeInstrument::setParameter( const QString & _param,
const QString & _value )
{
if( _param == "plugin" )
{
closePlugin();
m_plugin = _value;
if( ( m_handle = fst_load(
#ifdef QT4
m_plugin.constData().toAscii()
#else
m_plugin.ascii()
#endif
) ) == NULL )
{
QMessageBox::information( this,
tr( "Failed loading plugin" ),
tr( "The VST-plugin %1 couldn't be "
"loaded for some reason." ).arg(
m_plugin ),
QMessageBox::Ok );
return;
}
if( ( m_fst = fst_instantiate( m_handle, hostCallback,
this ) ) == NULL )
{
QMessageBox::information( this,
tr( "Failed instantiating plugin" ),
tr( "Couldn't create an instance of "
"VST-plugin %1 for some "
"reason." ).arg( m_plugin ),
QMessageBox::Ok );
fst_unload( m_handle );
m_handle = NULL;
return;
}
// set sample-rate and blocksize
m_fst->plugin->dispatcher( m_fst->plugin, effSetSampleRate, 0,
0, NULL, mixer::inst()->sampleRate() );
m_fst->plugin->dispatcher( m_fst->plugin, effSetBlockSize, 0,
mixer::inst()->framesPerAudioBuffer(),
NULL, 0.0f );
// set program to zero
m_fst->plugin->dispatcher( m_fst->plugin, effSetProgram, 0, 0,
NULL, 0.0f );
// resume
m_fst->plugin->dispatcher( m_fst->plugin, effMainsChanged, 0,
1, NULL, 0.0f );
/* if( fst_run_editor( m_fst ) )
{
printf( "VeSTige: cannot create editor\n" );
}*/
int vst_version = m_fst->plugin->dispatcher( m_fst->plugin,
effGetVstVersion, 0, 0,
NULL, 0.0f );
if( vst_version < 2 )
{
QMessageBox::information( this,
tr( "VST-plugin too old" ),
tr( "The version of VST-plugin %1 "
"is smaller than 2, which "
"isn't supported." ).arg(
m_plugin ),
QMessageBox::Ok );
return;
}
/* printf("WID:%d %d\n", (int)fst_get_XID( m_fst ),
(int)QWidget::find( fst_get_XID( m_fst ) ) );*/
//printf("%d\n", m_fst->plugin->numParams);
}
}
void vestigeInstrument::play( void )
{
// the very first time, we have to adopt fst-thread
if( !s_threadAdopted )
{
fst_adopt_thread();
s_threadAdopted = TRUE;
}
if( m_handle == NULL || m_fst == NULL )
{
return;
}
// first we gonna post all MIDI-events we enqueued so far
if( m_midiEvents.size() )
{
// since MIDI-events are not received immediately, we have
// to have them stored somewhere even after dispatcher-call,
// so we create static copies of the data and post them
static VstEvents events;
static vvector<VstMidiEvent> cur_events;
cur_events = m_midiEvents;
m_midiEvents.clear();
for( csize i = 0; i < cur_events.size(); ++i )
{
events.events[i] = (VstEvent *) &cur_events[i];
}
events.numEvents = cur_events.size();
events.reserved = 0;
m_fst->plugin->dispatcher( m_fst->plugin, effProcessEvents,
0, 0, &events, 0.0f );
}
// now we're ready to fetch sound from VST-plugin
const Uint32 frames = mixer::inst()->framesPerAudioBuffer();
int ch_in = m_fst->plugin->numInputs;
int ch_out = m_fst->plugin->numOutputs;
float * ins[ch_in];
float * outs[ch_out];
for( int i = 0; i < ch_in; ++i )
{
ins[i] = bufferAllocator::alloc<float>( frames );
}
for( int i = 0; i < ch_out; ++i )
{
outs[i] = bufferAllocator::alloc<float>( frames );
}
if( m_fst->plugin->flags & effFlagsCanReplacing )
{
m_fst->plugin->processReplacing( m_fst->plugin, ins, outs,
frames );
}
else
{
printf("normal process\n");
//mixer::inst()->clearAudioBuffer( buf, frames );
m_fst->plugin->process( m_fst->plugin, ins, outs, frames );
printf("normal process done\n");
}
for( int i = 0; i < ch_in; ++i )
{
bufferAllocator::free( ins[i] );
}
// got our data, now we just have to merge the 1/2 out-buffers
sampleFrame * buf = bufferAllocator::alloc<sampleFrame>( frames );
Uint8 chnls = tMax<Uint8>( ch_out, DEFAULT_CHANNELS );
if( chnls != DEFAULT_CHANNELS )
{
mixer::inst()->clearAudioBuffer( buf, frames );
}
for( Uint32 f = 0; f < frames; ++f )
{
for( Uint8 chnl = 0; chnl < chnls; ++chnl )
{
buf[f][chnl] = outs[chnl][f];
}
}
for( int i = 0; i < ch_out; ++i )
{
bufferAllocator::free( outs[i] );
}
getChannelTrack()->processAudioBuffer( buf, frames, NULL );
bufferAllocator::free( buf );
}
void vestigeInstrument::playNote( notePlayHandle * _n )
{
if( _n->totalFramesPlayed() == 0 )
{
enqueueEvent( midiEvent( NOTE_ON, 0, _n->key(),
_n->getVolume() ), _n->framesAhead() );
}
}
void vestigeInstrument::deleteNotePluginData( notePlayHandle * _n )
{
enqueueEvent( midiEvent( NOTE_OFF, 0, _n->key(), 0 ) );
}
void vestigeInstrument::openPlugin( void )
{
#ifdef QT4
QFileDialog ofd( NULL, tr( "Open VST-plugin" ) );
#else
QFileDialog ofd( QString::null, QString::null, NULL, "", TRUE );
ofd.setWindowTitle( tr( "Open VST-plugin" ) );
#endif
QString dir;
if( m_plugin != "" )
{
#ifdef QT4
dir = QFileInfo( m_plugin ).absolutePath();
#else
dir = QFileInfo( m_plugin ).dirPath( TRUE );
#endif
}
else
{
dir = QDir::home().path();
}
// change dir to position of previously opened file
ofd.setDirectory( dir );
ofd.setFileMode( QFileDialog::ExistingFiles );
// set filters
#ifdef QT4
QStringList types;
types << tr( "DLL-files (*.dll)" )
<< tr( "EXE-files (*.exe)" )
;
ofd.setFilters( types );
#else
ofd.addFilter( tr( "DLL-files (*.dll)" ) );
ofd.addFilter( tr( "EXE-files (*.exe)" ) );
ofd.setSelectedFilter( tr( "DLL-files (*.dll)" ) );
#endif
if( m_plugin != "" )
{
// select previously opened file
ofd.selectFile( QFileInfo( m_plugin ).fileName() );
}
if ( ofd.exec () == QDialog::Accepted )
{
if( ofd.selectedFiles().isEmpty() )
{
return;
}
setParameter( "plugin", ofd.selectedFiles()[0] );
}
}
void vestigeInstrument::paintEvent( QPaintEvent * )
{
#ifdef QT4
QPainter p( this );
#else
QPixmap pm( rect().size() );
pm.fill( this, rect().topLeft() );
QPainter p( &pm, this );
#endif
p.drawPixmap( 0, 0, *s_artwork );
QString plugin_name = ( m_handle != NULL && m_fst != NULL ) ?
QString( m_handle->name ) + " " +
QString::number( m_fst->plugin->dispatcher(
m_fst->plugin,
effGetVendorVersion,
0, 0, NULL, 0.0f ) ):
tr( "No VST-plugin loaded" );
QFont f = p.font();
f.setBold( TRUE );
p.setFont( pointSize<10>( f ) );
p.setPen( QColor( 0, 0, 0 ) );
p.drawText( 20, 80, plugin_name );
if( m_handle != NULL && m_fst != NULL )
{
p.setPen( QColor( 64, 128, 64 ) );
f.setBold( FALSE );
p.setFont( pointSize<8>( f ) );
char buf[1024];
m_fst->plugin->dispatcher( m_fst->plugin, effGetVendorString,
0, 0, buf, 0 );
p.drawText( 20, 94, tr( "by" ) + " " + QString( buf ) );
}
#ifndef QT4
bitBlt( this, rect().topLeft(), &pm );
#endif
}
void vestigeInstrument::closePlugin( void )
{
if( m_fst != NULL && m_handle != NULL )
{
//fst_destroy_editor( m_fst );
printf( "closing VST-plugin" );
fst_close( m_fst );
printf( "unloading VST-plugin" );
fst_unload( m_handle );
m_fst = NULL;
m_handle = NULL;
}
}
void vestigeInstrument::enqueueEvent( const midiEvent & _e,
Uint32 _frames_ahead )
{
if( m_handle == NULL || m_fst == NULL )
{
return;
}
VstMidiEvent event;
event.type = kVstMidiType;
event.byteSize = 24;
event.deltaFrames = _frames_ahead;
event.flags = 0;
event.detune = 0;
event.noteLength = 0;
event.noteOffset = 0;
event.noteOffVelocity = 0;
event.reserved1 = 0;
event.reserved2 = 0;
event.midiData[0] = _e.m_type + _e.m_channel;
event.midiData[1] = _e.key();
event.midiData[2] = _e.velocity();
event.midiData[3] = 0;
m_midiEvents.push_back( event );
}
#define DEBUG_CALLBACKS
#ifdef DEBUG_CALLBACKS
#define SHOW_CALLBACK printf
#else
#define SHOW_CALLBACK(...)
#endif
long vestigeInstrument::hostCallback( AEffect * _effect, long _opcode,
long _index, long _value, void * _ptr,
float _opt )
{
static VstTimeInfo _timeInfo;
SHOW_CALLBACK( "host-callback, opcode = %d", (int) _opcode );
switch( _opcode )
{
case audioMasterAutomate:
SHOW_CALLBACK( "amc: audioMasterAutomate\n" );
// index, value, returns 0
_effect->setParameter( _effect, _index, _opt );
return( 0 );
case audioMasterVersion:
SHOW_CALLBACK( "amc: audioMasterVersion\n" );
// vst version, currently 2 (0 for older)
return( 2 );
case audioMasterCurrentId:
SHOW_CALLBACK( "amc: audioMasterCurrentId\n" );
// returns the unique id of a plug that's currently
// loading
return( 0 );
case audioMasterIdle:
SHOW_CALLBACK ("amc: audioMasterIdle\n");
// call application idle routine (this will
// call effEditIdle for all open editors too)
_effect->dispatcher( _effect, effEditIdle, 0, 0, NULL,
0.0f );
return( 0 );
case audioMasterPinConnected:
SHOW_CALLBACK( "amc: audioMasterPinConnected\n" );
// inquire if an input or output is beeing connected;
// index enumerates input or output counting from zero:
// value is 0 for input and != 0 otherwise. note: the
// return value is 0 for <true> such that older versions
// will always return true.
return( 1 );
case audioMasterWantMidi:
SHOW_CALLBACK( "amc: audioMasterWantMidi\n" );
// <value> is a filter which is currently ignored
return( 0 );
case audioMasterGetTime:
SHOW_CALLBACK( "amc: audioMasterGetTime\n" );
// returns const VstTimeInfo* (or 0 if not supported)
// <value> should contain a mask indicating which
// fields are required (see valid masks above), as some
// items may require extensive conversions
memset( &_timeInfo, 0, sizeof( _timeInfo ) );
//tstate = jack_transport_query (jackvst->client, &jack_pos);
_timeInfo.samplePos = 0;
_timeInfo.sampleRate = mixer::inst()->sampleRate();
_timeInfo.flags = 0;
_timeInfo.tempo = songEditor::inst()->getBPM();
_timeInfo.timeSigNumerator = 4;//(long) floor (jack_pos.beats_per_bar);
_timeInfo.timeSigDenominator = 4;//(long) floor (jack_pos.beat_type);
_timeInfo.flags |= (kVstBarsValid|kVstTempoValid);
// if (tstate == JackTransportRolling) {
_timeInfo.flags |= kVstTransportPlaying;
// }
return( (long)&_timeInfo );
case audioMasterProcessEvents:
SHOW_CALLBACK( "amc: audioMasterProcessEvents\n" );
// VstEvents* in <ptr>
return( 0 );
case audioMasterSetTime:
SHOW_CALLBACK( "amc: audioMasterSetTime\n" );
// VstTimenfo* in <ptr>, filter in <value>, not
// supported
case audioMasterTempoAt:
SHOW_CALLBACK( "amc: audioMasterTempoAt\n" );
// returns tempo (in bpm * 10000) at sample frame
// location passed in <value>
return( 0 );
case audioMasterGetNumAutomatableParameters:
SHOW_CALLBACK( "amc: audioMasterGetNumAutomatable"
"Parameters\n" );
return( 0 );
case audioMasterGetParameterQuantization:
SHOW_CALLBACK( "amc: audioMasterGetParameter\n"
"Quantization\n" );
// returns the integer value for +1.0 representation,
// or 1 if full single float precision is maintained
// in automation. parameter index in <value> (-1: all,
// any)
return( 0 );
case audioMasterIOChanged:
SHOW_CALLBACK( "amc: audioMasterIOChanged\n" );
// numInputs and/or numOutputs has changed
return( 0 );
case audioMasterNeedIdle:
SHOW_CALLBACK( "amc: audioMasterNeedIdle\n" );
// plug needs idle calls (outside its editor window)
return( 0 );
case audioMasterSizeWindow:
// TODO using lmms-main-window-size
SHOW_CALLBACK( "amc: audioMasterSizeWindow\n" );
// index: width, value: height
return( 0 );
case audioMasterGetSampleRate:
// TODO using mixer-call
SHOW_CALLBACK( "amc: audioMasterGetSampleRate\n" );
return( 0 );
case audioMasterGetBlockSize:
// TODO using mixer-call
SHOW_CALLBACK( "amc: audioMasterGetBlockSize\n" );
return( 0 );
case audioMasterGetInputLatency:
// TODO using mixer-call
SHOW_CALLBACK( "amc: audioMasterGetInputLatency\n" );
return( 0 );
case audioMasterGetOutputLatency:
// TODO using mixer-call
SHOW_CALLBACK( "amc: audioMasterGetOutputLatency\n" );
return( 0 );
case audioMasterGetPreviousPlug:
SHOW_CALLBACK( "amc: audioMasterGetPreviousPlug\n" );
// input pin in <value> (-1: first to come), returns
// cEffect*
return( 0 );
case audioMasterGetNextPlug:
SHOW_CALLBACK( "amc: audioMasterGetNextPlug\n" );
// output pin in <value> (-1: first to come), returns
// cEffect*
return( 0 );
case audioMasterWillReplaceOrAccumulate:
SHOW_CALLBACK( "amc: audioMasterWillReplaceOr"
"Accumulate\n" );
// returns: 0: not supported, 1: replace, 2: accumulate
return( 0 );
case audioMasterGetCurrentProcessLevel:
SHOW_CALLBACK( "amc: audioMasterGetCurrentProcess"
"Level\n" );
// returns: 0: not supported,
// 1: currently in user thread (gui)
// 2: currently in audio thread (where process is
// called)
// 3: currently in 'sequencer' thread (midi, timer etc)
// 4: currently offline processing and thus in user
// thread
// other: not defined, but probably pre-empting user
// thread.
return( 0 );
case audioMasterGetAutomationState:
SHOW_CALLBACK( "amc: audioMasterGetAutomationState\n" );
// returns 0: not supported, 1: off, 2:read, 3:write,
// 4:read/write offline
return( 0 );
case audioMasterOfflineStart:
SHOW_CALLBACK( "amc: audioMasterOfflineStart\n" );
return( 0 );
case audioMasterOfflineRead:
SHOW_CALLBACK( "amc: audioMasterOfflineRead\n" );
// ptr points to offline structure, see below.
// return 0: error, 1 ok
return( 0 );
case audioMasterOfflineWrite:
SHOW_CALLBACK( "amc: audioMasterOfflineWrite\n" );
// same as read
return( 0 );
case audioMasterOfflineGetCurrentPass:
SHOW_CALLBACK( "amc: audioMasterOfflineGetCurrent"
"Pass\n" );
return( 0 );
case audioMasterOfflineGetCurrentMetaPass:
SHOW_CALLBACK( "amc: audioMasterOfflineGetCurrentMeta"
"Pass\n");
return( 0 );
case audioMasterSetOutputSampleRate:
SHOW_CALLBACK( "amc: audioMasterSetOutputSample"
"Rate\n" );
// for variable i/o, sample rate in <opt>
return( 0 );
case audioMasterGetSpeakerArrangement:
SHOW_CALLBACK( "amc: audioMasterGetSpeaker"
"Arrangement\n" );
// (long)input in <value>, output in <ptr>
return( 0 );
case audioMasterGetVendorString:
SHOW_CALLBACK( "amc: audioMasterGetVendorString\n" );
// fills <ptr> with a string identifying the vendor
// (max 64 char)
strcpy( (char *) _ptr, "LAD");
return( 0 );
case audioMasterGetProductString:
SHOW_CALLBACK( "amc: audioMasterGetProductString\n" );
// fills <ptr> with a string with product name
// (max 64 char)
strcpy( (char *) _ptr, "VeSTige" );
return( 0 );
case audioMasterGetVendorVersion:
SHOW_CALLBACK( "amc: audioMasterGetVendorVersion\n" );
// TODO
// returns vendor-specific version
return( 1000 );
case audioMasterVendorSpecific:
SHOW_CALLBACK( "amc: audioMasterVendorSpecific\n" );
// no definition, vendor specific handling
return( 0 );
case audioMasterSetIcon:
SHOW_CALLBACK( "amc: audioMasterSetIcon\n" );
// TODO
// void* in <ptr>, format not defined yet
return( 0 );
case audioMasterCanDo:
SHOW_CALLBACK( "amc: audioMasterCanDo\n" );
// string in ptr, see below
return( 0 );
case audioMasterGetLanguage:
SHOW_CALLBACK( "amc: audioMasterGetLanguage\n" );
// TODO
// see enum
return( 0 );
case audioMasterOpenWindow:
SHOW_CALLBACK( "amc: audioMasterOpenWindow\n" );
// TODO
// returns platform specific ptr
return( 0 );
case audioMasterCloseWindow:
SHOW_CALLBACK( "amc: audioMasterCloseWindow\n" );
// TODO
// close window, platform specific handle in <ptr>
return( 0 );
case audioMasterGetDirectory:
SHOW_CALLBACK( "amc: audioMasterGetDirectory\n" );
// TODO
// get plug directory, FSSpec on MAC, else char*
return( 0 );
case audioMasterUpdateDisplay:
SHOW_CALLBACK( "amc: audioMasterUpdateDisplay\n" );
// something has changed, update 'multi-fx' display
_effect->dispatcher( _effect, effEditIdle, 0, 0, NULL,
0.0f );
return( 0 );
case audioMasterBeginEdit:
SHOW_CALLBACK( "amc: audioMasterBeginEdit\n" );
// begin of automation session (when mouse down),
// parameter index in <index>
return( 0 );
case audioMasterEndEdit:
SHOW_CALLBACK( "amc: audioMasterEndEdit\n" );
// end of automation session (when mouse up),
// parameter index in <index>
return( 0 );
case audioMasterOpenFileSelector:
SHOW_CALLBACK( "amc: audioMasterOpenFileSelector\n" );
// open a fileselector window with VstFileSelect*
// in <ptr>
return( 0 );
default:
SHOW_CALLBACK( "VST master dispatcher: undefed: "
"%d, %d\n", (int) _opcode,
effKeysRequired );
break;
}
return( 0 );
}
extern "C"
{
// neccessary for getting instance out of shared lib
plugin * lmms_plugin_main( void * _data )
{
return( new vestigeInstrument( static_cast<channelTrack *>( _data ) ) );
}
}
#include "vestige.moc"

110
plugins/vestige/vestige.h Normal file
View File

@@ -0,0 +1,110 @@
/*
* vestige.h - instrument VeSTige for hosting VST-plugins
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 _VESTIGE_H
#define _VESTIGE_H
#include "instrument.h"
#include "midi.h"
#ifdef QT4
#include <QVector>
#else
#include <qvector.h>
#endif
#include <fst.h>
#include <vst/aeffectx.h>
#include "spc_bg_hndl_widget.h"
class pixmapButton;
class QPixmap;
class vestigeInstrument : public instrument, public specialBgHandlingWidget
{
Q_OBJECT
public:
vestigeInstrument( channelTrack * _channel_track );
virtual ~vestigeInstrument();
virtual void play( void );
virtual void FASTCALL playNote( notePlayHandle * _n );
virtual void FASTCALL deleteNotePluginData( notePlayHandle * _n );
virtual void FASTCALL saveSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void FASTCALL loadSettings( const QDomElement & _this );
virtual QString nodeName( void ) const;
virtual void FASTCALL setParameter( const QString & _param,
const QString & _value );
protected slots:
void openPlugin( void );
protected:
virtual void paintEvent( QPaintEvent * _pe );
private:
void closePlugin( void );
void enqueueEvent( const midiEvent & _e, Uint32 _frames_ahead = 0 );
static long hostCallback( AEffect *, long, long, long, void *, float );
static bool s_initialized;
static bool s_threadAdopted;
static QPixmap * s_artwork;
FSTHandle * m_handle;
FST * m_fst;
vvector<VstMidiEvent> m_midiEvents;
pixmapButton * m_openPluginButton;
QString m_plugin;
} ;
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -175,13 +175,13 @@ int audioALSA::handleError( int _err )
void audioALSA::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames,
float _master_output )
float _master_gain )
{
outputSampleType * outbuf = bufferAllocator::alloc<outputSampleType>(
_frames * channels() );
bufferAllocator::autoCleaner<> ac( outbuf );
convertToS16( _ab, _frames, _master_output, outbuf,
convertToS16( _ab, _frames, _master_gain, outbuf,
m_littleEndian != isLittleEndian() );
Uint32 frame = 0;

View File

@@ -70,7 +70,7 @@ audioDevice::~audioDevice()
void audioDevice::writeBuffer( surroundSampleFrame * _ab, Uint32 _frames,
Uint32 _src_sample_rate, float _master_output )
Uint32 _src_sample_rate, float _master_gain )
{
// make sure, no other thread is accessing device
lock();
@@ -82,12 +82,12 @@ void audioDevice::writeBuffer( surroundSampleFrame * _ab, Uint32 _frames,
_frames * channels() );
resample( _ab, _frames, temp, _src_sample_rate, m_sampleRate );
writeBufferToDev( temp, _frames * m_sampleRate /
_src_sample_rate, _master_output );
_src_sample_rate, _master_gain );
bufferAllocator::free( temp );
}
else
{
writeBufferToDev( _ab, _frames, _master_output );
writeBufferToDev( _ab, _frames, _master_gain );
}
// release lock
unlock();
@@ -240,7 +240,7 @@ LP_FILTER_COEFFS[tap] * lp_hist[( oldest + tap ) % LP_FILTER_TAPS][chnl];
int FASTCALL audioDevice::convertToS16( surroundSampleFrame * _ab,
Uint32 _frames, float _master_output,
Uint32 _frames, float _master_gain,
outputSampleType * _output_buffer,
bool _convert_endian )
{
@@ -251,7 +251,7 @@ int FASTCALL audioDevice::convertToS16( surroundSampleFrame * _ab,
( _output_buffer + frame * channels() )[chnl] =
static_cast<outputSampleType>(
mixer::clip( _ab[frame][chnl] *
_master_output ) *
_master_gain ) *
OUTPUT_SAMPLE_MULTIPLIER );
}
}

View File

@@ -186,7 +186,7 @@ bool audioFileOgg::startEncoding( void )
void FASTCALL audioFileOgg::writeBufferToDev( surroundSampleFrame * _ab,
Uint32 _frames,
float _master_output )
float _master_gain )
{
int eos = 0;
@@ -197,7 +197,7 @@ void FASTCALL audioFileOgg::writeBufferToDev( surroundSampleFrame * _ab,
{
for( Uint8 chnl = 0; chnl < channels(); ++chnl )
{
buffer[chnl][frame] = _ab[frame][chnl] * _master_output;
buffer[chnl][frame] = _ab[frame][chnl] * _master_gain;
}
}

View File

@@ -88,11 +88,11 @@ bool audioFileWave::startEncoding( void )
void FASTCALL audioFileWave::writeBufferToDev( surroundSampleFrame * _ab,
Uint32 _frames,
float _master_output )
float _master_gain )
{
outputSampleType * outbuf = bufferAllocator::alloc<outputSampleType>(
_frames * channels() );
int bytes = convertToS16( _ab, _frames, _master_output, outbuf,
int bytes = convertToS16( _ab, _frames, _master_gain, outbuf,
!isLittleEndian() );
writeData( outbuf, bytes );

View File

@@ -214,7 +214,7 @@ audioJACK::~audioJACK()
void audioJACK::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames,
float _master_output )
float _master_gain )
{
m_bufMutex.lock();
@@ -228,7 +228,7 @@ void audioJACK::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames,
_frames );
for( Uint32 frame = 0; frame < _frames; ++frame )
{
buf[frame] = _ab[frame][chnl] * _master_output;
buf[frame] = _ab[frame][chnl] * _master_gain;
}
bufset b = { buf, _frames } ;
bufs.push_back( b );
@@ -246,7 +246,10 @@ void audioJACK::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames,
#ifdef HAVE_UNISTD_H
#ifdef HAVE_USLEEP
// just wait and give cpu-time to other processes
usleep( 200 );
// tobydox 20051019: causes LMMS to hang up when locking
// several other mutexes, so skip it
//usleep( 200 );
#endif
#endif
}
@@ -264,6 +267,8 @@ int audioJACK::processCallback( jack_nframes_t _nframes, void * _udata )
#endif
jack_transport_state_t ts = jack_transport_query( _this->m_client,
NULL );
_this->m_bufMutex.lock();
if( ts != JackTransportRolling )
{
// always decrease frame-sync-var as we would do it if running
@@ -276,6 +281,7 @@ int audioJACK::processCallback( jack_nframes_t _nframes, void * _udata )
{
_this->m_frameSync = 0;
}
_this->m_bufMutex.unlock();
return( 0 );
}
@@ -289,7 +295,6 @@ int audioJACK::processCallback( jack_nframes_t _nframes, void * _udata )
_this->m_outputPorts[ch], _nframes );
}
_this->m_bufMutex.lock();
jack_nframes_t done = 0;
while( done < _nframes )

View File

@@ -278,11 +278,11 @@ QString audioOSS::probeDevice( void )
void audioOSS::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames,
float _master_output )
float _master_gain )
{
outputSampleType * outbuf = bufferAllocator::alloc<outputSampleType>(
_frames * channels() );
int bytes = convertToS16( _ab, _frames, _master_output, outbuf,
int bytes = convertToS16( _ab, _frames, _master_gain, outbuf,
m_convertEndian );
write( m_audioFD, outbuf, bytes );

View File

@@ -125,10 +125,10 @@ audioSDL::~audioSDL()
void audioSDL::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames,
float _master_output )
float _master_gain )
{
m_bufMutex.lock();
convertToS16( _ab, _frames, _master_output, m_buffer,
convertToS16( _ab, _frames, _master_gain, m_buffer,
m_convertEndian );
m_bufMutex.unlock();
// before returning make sure, callback was called, so we're synced

View File

@@ -294,14 +294,6 @@ void bbEditor::keyPressEvent( QKeyEvent * _ke )
void bbEditor::wheelEvent( QWheelEvent * _we )
{
lmmsMainWin::inst()->workspace()->wheelEvent( _we );
}
void bbEditor::resizeEvent( QResizeEvent * _re )
{
updateBackground();

View File

@@ -163,10 +163,19 @@ configManager::configManager( void ) :
m_lmmsDataDir( qApp->applicationDirPath().section( '/', 0, -2 ) +
"/share/lmms/" ),
#else
// hardcode since qt 3.0 doesn't know something like
// applicationDirPath and implmeneting own function would be senseless
// since real support for qt 3.0 is senseless too ;-)
// hardcode since qt < 3.2 doesn't know something like
// applicationDirPath and implementing own function would be senseless
// since real support for qt < 3.2 is senseless too ;-)
m_lmmsDataDir( "/usr/share/lmms" ),
#endif
#if QT_VERSION >= 0x030200
m_lmmsPluginDir( qApp->applicationDirPath().section( '/', 0, -2 ) +
"/lib/lmms/" ),
#else
// hardcode since qt < 3.2 doesn't know something like
// applicationDirPath and implementing own function would be senseless
// since real support for qt < 3.2 is senseless too ;-)
m_lmmsPluginDir( "/usr/lib/lmms" ),
#endif
m_currentPage( 0 )
{

View File

@@ -153,10 +153,7 @@ envelopeTabWidget::envelopeTabWidget( channelTrack * _channel_track,
m_filterComboBox->addItem( tr( "Notch" ) );
m_filterComboBox->addItem( tr( "Allpass" ) );
m_filterComboBox->addItem( tr( "Moog" ) );
m_filterComboBox->addItem( tr( "Moog 2" ) );
m_filterComboBox->addItem( tr( "2x LowPass" ) );
m_filterComboBox->addItem( tr( "2x Moog" ) );
m_filterComboBox->addItem( tr( "2x Moog 2" ) );
#ifdef QT4
m_filterComboBox->setWhatsThis(

93
src/core/instrument.cpp Normal file
View File

@@ -0,0 +1,93 @@
/*
* instrument.cpp - base-class for all instrument-plugins (synths, samplers etc)
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 "instrument.h"
#include "channel_track.h"
#include "dummy_instrument.h"
instrument::instrument( channelTrack * _channel_track, const QString & _name ) :
QWidget( _channel_track->pluginParent() ),
plugin( _name, INSTRUMENT ),
m_channelTrack( _channel_track ),
m_valid( TRUE )
{
setFixedSize( 250, 250 );
}
instrument::~instrument()
{
}
void instrument::play( void )
{
}
void instrument::playNote( notePlayHandle * )
{
}
void instrument::deleteNotePluginData( notePlayHandle * )
{
}
Uint32 instrument::beatLen( notePlayHandle * ) const
{
return( 0 );
}
instrument * instrument::instantiate( const QString & _plugin_name,
channelTrack * _channel_track )
{
plugin * p = plugin::instantiate( _plugin_name, _channel_track );
// check whether instantiated plugin is an instrument
if( dynamic_cast<instrument *>( p ) != NULL )
{
// everything ok, so return pointer
return( dynamic_cast<instrument *>( p ) );
}
// not quite... so delete plugin and return dummy instrument
delete p;
return( new dummyInstrument( _channel_track ) );
}

View File

@@ -163,6 +163,7 @@ int main( int argc, char * * argv )
e->show();
e->exportBtnClicked();
}
return( app.exec() );
}

View File

@@ -211,27 +211,6 @@ void mixer::run( void )
// while we're acting...
m_safetySyncMutex.lock();
/* following code is faster but unstable since using iterators
while deleting from vector is dangerous and often leads to
undefined results...
playHandleVector::iterator it = m_playHandles.begin();
while( it != m_playHandles.end() )
{
if( ( *it )->done() )
{
// delete all play-handles which have
// played completely now
delete *it;
m_playHandles.erase( it );
}
else
{
// play all uncompletely-played play-handles...
( *it )->play();
++it;
}
}*/
csize idx = 0;
while( idx < m_playHandles.size() )
{

175
src/core/plugin.cpp Normal file
View File

@@ -0,0 +1,175 @@
/*
* plugin.cpp - implemenation of plugin-class including plugin-loader
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#include "qt3support.h"
#ifdef QT4
#include <QMessageBox>
#include <QDir>
#else
#include <qmessagebox.h>
#include <qdir.h>
#endif
#include "plugin.h"
#include "mixer.h"
#include "config_mgr.h"
#include "dummy_plugin.h"
plugin::plugin( const QString & _public_name, pluginTypes _type ) :
settings(),
m_publicName( _public_name ),
m_type( _type )
{
}
plugin::~plugin()
{
}
void plugin::setParameter( const QString &, const QString & )
{
}
QString plugin::getParameter( const QString & )
{
return( "" );
}
plugin * plugin::instantiate( const QString & _plugin_name, void * _data )
{
#ifdef HAVE_DLFCN_H
void * handle = dlopen( QString( "lib" + _plugin_name + ".so" ).
#ifdef QT4
toAscii().constData()
#else
ascii()
#endif
, RTLD_LAZY );
if( handle == NULL )
{
QMessageBox::information( NULL,
mixer::tr( "Plugin not found" ),
mixer::tr( "The %1-plugin wasn't found!"
).arg( _plugin_name ),
QMessageBox::Ok |
QMessageBox::Default );
return( new dummyPlugin() );
}
dlerror();
instantiationHook inst_hook = ( instantiationHook )( dlsym( handle,
"lmms_plugin_main" ) );
char * error = dlerror();
if( error != NULL )
{
printf( "%s\n", error );
QMessageBox::information( NULL,
mixer::tr( "Error while loading plugin" ),
mixer::tr( "Failed loading plugin \"%1\"!"
).arg( _plugin_name ),
QMessageBox::Ok |
QMessageBox::Default );
return( new dummyPlugin() );
}
plugin * inst = inst_hook( _data );
//dlclose( handle );
return( inst );
#endif
return( new dummyPlugin() );
}
void plugin::getDescriptorsOfAvailPlugins( vvector<descriptor> & _plugin_descs )
{
QDir directory( configManager::inst()->pluginDir() );
const QFileInfoList * list = directory.entryInfoList( "*.so" );
if( list == NULL )
{
return;
}
for( QFileInfoList::iterator file = list->begin();
file != list->end(); ++file )
{
void * handle = dlopen( ( *file )->absFilePath().latin1(),
RTLD_LAZY );
char * msg = dlerror();
if( msg != NULL || handle == NULL )
{
printf( "plugin-loader: %s\n", msg );
continue;
}
void * foo = dlsym( handle, "lmms_plugin_main" );
msg = dlerror();
if( msg != NULL || foo == NULL )
{
printf( "plugin-loader: %s\n", msg );
continue;
}
QString desc_name = ( *file )->fileName().mid( 3 ).section(
'.', 0, 0 ) + "_plugin_descriptor";
descriptor * plugin_desc =
(descriptor *) dlsym( handle, desc_name.ascii() );
msg = dlerror();
if( msg != NULL || plugin_desc == NULL )
{
printf( "plugin-loader: %s\n", msg );
continue;
}
_plugin_descs.push_back( *plugin_desc );
//dlclose( handle );
}
}

248
src/core/plugin_browser.cpp Normal file
View File

@@ -0,0 +1,248 @@
/*
* plugin_browser.cpp - implementation of the plugin-browser
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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"
#ifdef QT4
#include <QLabel>
#include <QPainter>
/*#include <QScrollArea>*/
#include <QCursor>
#else
#include <qlabel.h>
#include <qpainter.h>
/*#include <qscrollview.h>*/
#include <qcursor.h>
#endif
#include "plugin_browser.h"
#include "embed.h"
#include "debug.h"
#include "gui_templates.h"
#include "string_pair_drag.h"
pluginBrowser::pluginBrowser( QWidget * _parent ) :
sideBarWidget( tr( "Instrument plugins" ),
embed::getIconPixmap( "plugins" ), _parent )
{
setWindowTitle( tr( "Plugin browser" ) );
m_view = new QWidget( contentParent() );
//m_view->setFrameShape( QFrame::NoFrame );
addContentWidget( m_view );
QVBoxLayout * view_layout = new QVBoxLayout( m_view, 5, 10 );
QLabel * hint = new QLabel( tr( "You can drag an instrument-plugin "
"into either the Song-Editor, the "
"Beat+Bassline Editor or just into a "
"channel-window or on the "
"corresponding channel-button." ),
m_view );
hint->setFont( pointSize<8>( hint->font() ) );
hint->setAlignment( hint->alignment() | WordBreak );
view_layout->addWidget( hint );
plugin::getDescriptorsOfAvailPlugins( m_pluginDescriptors );
for( vvector<plugin::descriptor>::iterator it =
m_pluginDescriptors.begin();
it != m_pluginDescriptors.end(); ++it )
{
pluginDescWidget * p = new pluginDescWidget( *it, m_view );
p->show();
view_layout->addWidget( p );
}
view_layout->addStretch();
show();
}
pluginBrowser::~pluginBrowser()
{
}
pluginDescWidget::pluginDescWidget( const plugin::descriptor & _pd,
QWidget * _parent ) :
QWidget( _parent ),
m_pluginDescriptor( _pd ),
m_logo(),
m_mouseOver( FALSE )
{
m_logo.loadFromData( _pd.logo.data, _pd.logo.size );
setFixedHeight( 60 );
setMouseTracking( TRUE );
#ifndef QT4
setBackgroundMode( Qt::NoBackground );
#endif
setCursor( PointingHandCursor );
}
pluginDescWidget::~pluginDescWidget()
{
}
void pluginDescWidget::paintEvent( QPaintEvent * )
{
QColor fill_color( 192, 192, 192 );
if( m_mouseOver )
{
fill_color = QColor( 224, 224, 224 );
}
#ifdef QT4
QPainter p( this );
p.fillRect( rect(), fill_color );
#else
// create pixmap for whole widget
QPixmap pm( rect().size() );
pm.fill( fill_color );
// and a painter for it
QPainter p( &pm );
#endif
p.setPen( QColor( 64, 64, 64 ) );
p.drawRect( rect() );
p.drawPixmap( 4, 4, m_logo );
QFont f = pointSize<8>( p.font() );
f.setBold( TRUE );
p.setFont( f );
p.drawText( 58, 14, m_pluginDescriptor.public_name );
f.setBold( FALSE );
p.setFont( pointSize<7>( f ) );
QStringList words = QStringList::split( ' ',
plugin::tr( m_pluginDescriptor.description ) );
for( QStringList::iterator it = words.begin(); it != words.end(); ++it )
{
if( ( *it ).contains( '-' ) )
{
QStringList splitted_word = QStringList::split( '-',
*it );
QStringList::iterator orig_it = it;
for( QStringList::iterator it2 = splitted_word.begin();
it2 != splitted_word.end(); ++it2 )
{
if( it2 == splitted_word.fromLast() )
{
words.insert( it, *it2 );
}
else
{
words.insert( it, *it2 + "-" );
++it;
}
}
words.erase( orig_it );
--it;
}
}
int y = 26;
int avail_width = width() - 58 - 5;
QString s;
for( QStringList::iterator it = words.begin(); it != words.end(); ++it )
{
if( p.fontMetrics().width( s + *it + " " ) >= avail_width )
{
p.drawText( 58, y, s );
y += 10;
s = "";
}
s += *it;
if( ( *it ).right( 1 ) != "-" )
{
s += " ";
}
}
p.drawText( 58, y, s );
#ifndef QT4
// blit drawn pixmap to actual widget
bitBlt( this, rect().topLeft(), &pm );
#endif
}
void pluginDescWidget::mousePressEvent( QMouseEvent * _me )
{
if( _me->button() == Qt::LeftButton )
{
new stringPairDrag( "plugin", m_pluginDescriptor.name, m_logo,
this );
m_mouseOver = FALSE;
update();
}
}
void pluginDescWidget::mouseMoveEvent( QMouseEvent * _me )
{
bool new_mouse_over = rect().contains( _me->pos() );
if( new_mouse_over != m_mouseOver )
{
m_mouseOver = new_mouse_over;
update();
}
}
void pluginDescWidget::mouseReleaseEvent( QMouseEvent * _me )
{
mouseMoveEvent( _me );
}
#include "plugin_browser.moc"

View File

@@ -115,7 +115,7 @@ presetPreviewPlayHandle::presetPreviewPlayHandle(
multimediaProject mmp( _preset_file );
if( s_globalChannelTrack == NULL )
{
track * t = track::createTrack( track::CHANNEL_TRACK,
track * t = track::create( track::CHANNEL_TRACK,
blindTrackContainer::inst() );
s_globalChannelTrack = dynamic_cast<channelTrack *>( t );
#ifdef LMMS_DEBUG

View File

@@ -351,16 +351,6 @@ songEditor::songEditor() :
/* edit_tb->setPaletteBackgroundPixmap( embed::getIconPixmap(
"toolbar_bg" ) );
edit_tb->setErasePixmap( embed::getIconPixmap( "toolbar_bg" ) );*/
#ifdef QT4
a = edit_tb->addAction( embed::getIconPixmap( "add_channel_track" ), "",
this, SLOT( addChannelTrack() ) );
a->setToolTip( tr( "Add channel-track" ) );
#else
m_addChannelTrackButton = new QToolButton( embed::getIconPixmap(
"add_channel_track" ), "", "",
this, SLOT( addChannelTrack() ),
edit_tb );
#endif
#ifdef QT4
a = edit_tb->addAction( embed::getIconPixmap( "add_bb_track" ), "",
this, SLOT( addBBTrack() ) );
@@ -414,7 +404,6 @@ songEditor::songEditor() :
toolTip::add( m_playButton, tr( "Play/pause song (Space)" ) );
toolTip::add( m_stopButton, tr( "Stop playing song (Space)" ) );
toolTip::add( m_addChannelTrackButton, tr( "Add channel-track" ) );
toolTip::add( m_addBBTrackButton, tr( "Add beat/bassline" ) );
toolTip::add( m_addSampleTrackButton, tr( "Add sample-track" ) );
toolTip::add( m_insertTactButton, tr( "Insert tact at current tact "
@@ -609,7 +598,6 @@ void songEditor::scrolled( int _new_pos )
void songEditor::wheelEvent( QWheelEvent * _we )
{
_we->accept();
if( m_controlPressed )
{
if( _we->delta() > 0 )
@@ -636,6 +624,12 @@ void songEditor::wheelEvent( QWheelEvent * _we )
m_leftRightScroll->setValue( m_leftRightScroll->value() -
_we->delta() / 30 );
}
else
{
_we->ignore();
return;
}
_we->accept();
}
@@ -1290,24 +1284,9 @@ void songEditor::removeTact( void )
void songEditor::addChannelTrack( void )
{
channelTrack * t = dynamic_cast< channelTrack * >(
track::createTrack( track::CHANNEL_TRACK, this ) );
#ifdef LMMS_DEBUG
assert( t != NULL );
#endif
t->loadPlugin( "tripleoscillator" );
t->toggledChannelButton( TRUE );
t->show();
}
void songEditor::addBBTrack( void )
{
track * t = track::createTrack( track::BB_TRACK, this );
track * t = track::create( track::BB_TRACK, this );
if( dynamic_cast<bbTrack *>( t ) != NULL )
{
dynamic_cast<bbTrack *>( t )->clickedTrackLabel();
@@ -1319,7 +1298,7 @@ void songEditor::addBBTrack( void )
void songEditor::addSampleTrack( void )
{
(void) track::createTrack( track::SAMPLE_TRACK, this );
(void) track::create( track::SAMPLE_TRACK, this );
}
@@ -1435,14 +1414,14 @@ void songEditor::createNewProject( void )
clearProject();
track * t;
t = track::createTrack( track::CHANNEL_TRACK, this );
dynamic_cast< channelTrack * >( t )->loadPlugin(
t = track::create( track::CHANNEL_TRACK, this );
dynamic_cast< channelTrack * >( t )->loadInstrument(
"tripleoscillator" );
track::createTrack( track::SAMPLE_TRACK, this );
t = track::createTrack( track::CHANNEL_TRACK, bbEditor::inst() );
dynamic_cast< channelTrack * >( t )->loadPlugin(
track::create( track::SAMPLE_TRACK, this );
t = track::create( track::CHANNEL_TRACK, bbEditor::inst() );
dynamic_cast< channelTrack * >( t )->loadInstrument(
"tripleoscillator" );
track::createTrack( track::BB_TRACK, this );
track::create( track::BB_TRACK, this );
setBPM( DEFAULT_BPM );
m_masterVolumeSlider->setValue( 100 );

View File

@@ -607,10 +607,10 @@ trackWidget::trackWidget( track * _track, QWidget * _parent ) :
"", &m_trackOperationsWidget );
deltr_btn->setGeometry( 1, 1+TRACK_OP_BTN_HEIGHT, TRACK_OP_BTN_WIDTH,
TRACK_OP_BTN_HEIGHT );
connect( deltr_btn, SIGNAL( clicked() ), this, SLOT( deleteTrack() ) );
connect( deltr_btn, SIGNAL( clicked() ), this, SLOT( removeTrack() ) );
connect( deltr_btn, SIGNAL( clicked() ), deltr_btn,
SLOT( clearFocus() ) );
toolTip::add( deltr_btn, tr( "Delete this track" ) );
toolTip::add( deltr_btn, tr( "Remove this track" ) );
QPushButton * muptr_btn = new QPushButton( embed::getIconPixmap(
"arp_up_on", 12, 12 ),
@@ -718,7 +718,7 @@ void trackWidget::cloneTrack( void )
void trackWidget::deleteTrack( void )
void trackWidget::removeTrack( void )
{
m_track->getTrackContainer()->removeTrack( m_track );
}
@@ -873,7 +873,7 @@ track::~track()
track * FASTCALL track::createTrack( trackTypes _tt, trackContainer * _tc )
track * FASTCALL track::create( trackTypes _tt, trackContainer * _tc )
{
switch( _tt )
{
@@ -891,10 +891,10 @@ track * FASTCALL track::createTrack( trackTypes _tt, trackContainer * _tc )
track * FASTCALL track::createTrack( const QDomElement & _this,
track * FASTCALL track::create( const QDomElement & _this,
trackContainer * _tc )
{
track * t = createTrack( static_cast<trackTypes>( _this.attribute(
track * t = create( static_cast<trackTypes>( _this.attribute(
"type" ).toInt() ), _tc );
#ifdef LMMS_DEBUG
assert( t != NULL );
@@ -906,13 +906,13 @@ track * FASTCALL track::createTrack( const QDomElement & _this,
track * FASTCALL track::cloneTrack( track * _track )
track * FASTCALL track::clone( track * _track )
{
QDomDocument doc;
QDomElement parent = doc.createElement( "clone" );
_track->saveSettings( doc, parent );
QDomElement e = parent.firstChild().toElement();
return( createTrack( e, _track->getTrackContainer() ) );
return( create( e, _track->getTrackContainer() ) );
}

View File

@@ -51,7 +51,9 @@
#include "lmms_main_win.h"
#include "mixer.h"
#include "song_editor.h"
#include "string_pair_drag.h"
#include "channel_track.h"
#include "mmp.h"
@@ -69,15 +71,9 @@ trackContainer::trackContainer() :
lmmsMainWin::inst()->workspace()->addWindow( this );
#endif
m_scrollArea = new QScrollArea( this );
m_scrollArea->setFrameStyle( QFrame::NoFrame );
m_scrollArea->setHorizontalScrollBarPolicy(
#ifdef QT4
Qt::ScrollBarAlwaysOff
#else
QScrollArea::AlwaysOff
#endif
);
m_scrollArea = new scrollArea( this );
setAcceptDrops( TRUE );
}
@@ -157,7 +153,7 @@ void trackContainer::loadSettings( const QDomElement & _this )
if( node.isElement() )
{
track::createTrack( node.toElement(), this );
track::create( node.toElement(), this );
}
node = node.nextSibling();
}
@@ -176,7 +172,7 @@ void trackContainer::loadSettings( const QDomElement & _this )
void trackContainer::cloneTrack( track * _track )
{
track::cloneTrack( _track );
track::clone( _track );
}
@@ -372,6 +368,41 @@ void trackContainer::resizeEvent( QResizeEvent * )
void trackContainer::dragEnterEvent( QDragEnterEvent * _dee )
{
stringPairDrag::processDragEnterEvent( _dee, "preset,plugin" );
}
void trackContainer::dropEvent( QDropEvent * _de )
{
QString type = stringPairDrag::decodeKey( _de );
QString value = stringPairDrag::decodeValue( _de );
if( type == "plugin" )
{
channelTrack * ct = dynamic_cast<channelTrack *>(
track::create( track::CHANNEL_TRACK,
this ) );
ct->loadInstrument( value );
ct->toggledChannelButton( TRUE );
}
else if( type == "preset" )
{
multimediaProject mmp( value );
channelTrack * ct = dynamic_cast<channelTrack *>(
track::create( track::CHANNEL_TRACK,
this ) );
ct->loadTrackSpecificSettings( mmp.content().firstChild().
toElement() );
ct->toggledChannelButton( TRUE );
}
}
void trackContainer::updateScrollArea( void )
{
m_scrollArea->resize( tMax( m_scrollArea->parentWidget()->width() -
@@ -384,6 +415,45 @@ void trackContainer::updateScrollArea( void )
trackContainer::scrollArea::scrollArea( trackContainer * _parent ) :
QScrollArea( _parent )
{
setFrameStyle( QFrame::NoFrame );
setHorizontalScrollBarPolicy(
#ifdef QT4
Qt::ScrollBarAlwaysOff
#else
QScrollArea::AlwaysOff
#endif
);
}
trackContainer::scrollArea::~scrollArea()
{
}
void trackContainer::scrollArea::wheelEvent( QWheelEvent * _we )
{
// always pass wheel-event to parent-widget (song-editor
// bb-editor etc.) because they might want to use it for zooming
// or scrolling left/right if a modifier-key is pressed, otherwise
// they do not accept it and we pass it up to QScrollArea
dynamic_cast<trackContainer *>( parentWidget() )->wheelEvent( _we );
if( !_we->isAccepted() )
{
QScrollArea::wheelEvent( _we );
}
}
#include "track_container.moc"
#undef setValue

View File

@@ -188,7 +188,7 @@ void * bufferAllocator::allocBytes( Uint32 _bytes )
}
// nothing so far, so we'll alloc a new (aligned) buf
// got nothing so far, so we'll alloc a new (aligned) buf
bufDesc d = { FALSE, new char[_bytes + BUFFER_ALIGN], NULL, _bytes, 0 };
d.buf = (void *)( (size_t) d.origPtr + ( BUFFER_ALIGN -
( (size_t) d.origPtr &

View File

@@ -43,9 +43,15 @@
#include "config_mgr.h"
#ifndef PLUGIN_NAME
namespace embed
#else
namespace PLUGIN_NAME
#endif
{
#include "embedded_resources.h"
@@ -55,10 +61,10 @@ QPixmap getIconPixmap( const char * _name, int _w, int _h )
{
QString name = QString( _name ) + ".png";
#ifdef QT4
const embedDesc & e = findEmbeddedData(
const embed::descriptor & e = findEmbeddedData(
name.toAscii().constData() );
#else
const embedDesc & e = findEmbeddedData( name.ascii() );
const embed::descriptor & e = findEmbeddedData( name.ascii() );
#endif
// not found?
if( QString( e.name ) != name )
@@ -88,13 +94,12 @@ QPixmap getIconPixmap( const char * _name, int _w, int _h )
QString getText( const char * _name )
{
const embedDesc & e = findEmbeddedData( _name );
const embed::descriptor & e = findEmbeddedData( _name );
return( QString::fromLatin1( (const char *) e.data, e.size ) );
}
void loadTranslation( const QString & _tname )
{
QTranslator * t = new QTranslator( 0 );
@@ -103,9 +108,10 @@ void loadTranslation( const QString & _tname )
#if QT_VERSION >= 0x030100
#ifdef QT4
const embedDesc & e = findEmbeddedData( name.toAscii().constData() );
const embed::descriptor & e = findEmbeddedData(
name.toAscii().constData() );
#else
const embedDesc & e = findEmbeddedData( name.ascii() );
const embed::descriptor & e = findEmbeddedData( name.ascii() );
#endif
// not found?
if( QString( e.name ) != name )
@@ -126,3 +132,4 @@ void loadTranslation( const QString & _tname )
}

View File

@@ -23,26 +23,31 @@
*/
#include "ladspa_manager.h"
#ifdef LADSPA_SUPPORT
#ifdef QT4
#include <QDir>
#include <QFileInfo>
#include <QPair>
#else
#include <qdir.h>
#include <qfileinfo.h>
#include <qpair.h>
#endif
#include <ladspa.h>
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#include <math.h>
#include "ladspa_manager.h"
ladspaManager * ladspaManager::s_instanceOfMe = NULL;
@@ -55,19 +60,25 @@ ladspaManager::ladspaManager( void )
// TODO Need to move the search path definition to the config file to have
// more control over where it tries to find the plugins.
QStringList ladspaDirectories = QStringList::split( QString( ":" ),
QStringList ladspaDirectories = QStringList::split( ':',
QString( getenv( "LADSPA_PATH" ) ) );
// set default-directory if nothing is specified...
if( ladspaDirectories.isEmpty() )
{
ladspaDirectories.push_back( "/usr/lib/ladspa" );
ladspaDirectories.push_back( "/usr/local/lib/ladspa" );
}
for( QStringList::iterator it = ladspaDirectories.begin();
it != ladspaDirectories.end(); ++it )
{
QDir directory( ( *it ) );
const QFileInfoList * list = directory.entryInfoList();
// if directory doesn't exist or isn't readable, we get NULL which
// would crash LMMS...
if( list == NULL )
{
continue;
}
for( QFileInfoList::iterator file = list->begin();
file != list->end(); ++file )
{
@@ -842,3 +853,6 @@ void FASTCALL ladspaManager::cleanup( const ladspaKey & _plugin,
}
}
#endif

View File

@@ -0,0 +1,112 @@
/*
* string_pair_drag.cpp - class stringPairDrag which provides general support
* for drag'n'drop of string-pairs
*
* Linux MultiMedia Studio
* Copyright (c) 2004-2005 Tobias Doerffel <tobydox@users.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 "string_pair_drag.h"
stringPairDrag::stringPairDrag( const QString & _key, const QString & _value,
const QPixmap & _icon, QWidget * _w ) :
#ifdef QT4
QDrag( _w )
#else
QStoredDrag( "lmms/stringpair", _w )
#endif
{
setPixmap( _icon );
QString txt = _key + ":" + _value;
#ifdef QT4
QMimeData * m = new QMimeData();
m->setData( "lmms/stringpair", txt.toAscii() );
setMimeData( m );
start( /*Qt::CopyAction*/ Qt::IgnoreAction );
#else
setEncodedData( txt.utf8() );
drag();
#endif
}
stringPairDrag::~stringPairDrag()
{
// TODO: do we have to delete anything???
}
void stringPairDrag::processDragEnterEvent( QDragEnterEvent * _dee,
const QString & _allowed_keys )
{
#ifdef QT4
if( !_dee->mimeData()->hasFormat( "lmms/stringpair" ) )
{
return;
}
QString txt = _dee->mimeData()->data();
#else
QString txt = _dee->encodedData( "lmms/stringpair" );
#endif
bool accepted = QStringList::split( ',', _allowed_keys ).contains(
txt.section( ':', 0, 0 ) );
#ifdef QT4
if( accepted )
{
_dee->acceptProposedAction();
}
#else
_dee->accept( accepted );
#endif
}
QString stringPairDrag::decodeKey( QDropEvent * _de )
{
#ifdef QT4
return( QString( _de->mimeData()->data() ).section( ':', 0, 0 ) );
#else
return( QString( _de->encodedData( "lmms/stringpair" ) ).section(
':', 0, 0 ) );
#endif
}
QString stringPairDrag::decodeValue( QDropEvent * _de )
{
#ifdef QT4
return( QString( _de->mimeData()->data() ).section( ':', 1, 1 ) );
#else
return( QString( _de->encodedData( "lmms/stringpair" ) ).section(
':', 1, 1 ) );
#endif
}

View File

@@ -29,6 +29,7 @@
#include <QPainter>
#include <QMouseEvent>
#else
#include <qpainter.h>
@@ -87,9 +88,9 @@ void pixmapButton::paintEvent( QPaintEvent * )
}
#ifdef QT4
if( isChecked() )
if( isChecked() || isDown() )
#else
if( isOn() )
if( isOn() || isDown() )
#endif
{
if( m_activePixmap != NULL )