From 959a7909c1adca430a63f783fd16687242a7be3d Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 12 Apr 2007 23:20:37 +0000 Subject: Merged with trunk R1705. Synced .po files with trunk. Fixed more editor operations to be type agnostic (ie not audio only). git-svn-id: svn://localhost/ardour2/branches/midi@1709 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/audiofilesource.h | 3 +- libs/ardour/ardour/audioregion.h | 2 + libs/ardour/ardour/configuration_vars.h | 1 - libs/ardour/ardour/coreaudiosource.h | 2 +- libs/ardour/ardour/diskstream.h | 1 + libs/ardour/ardour/playlist.h | 7 + libs/ardour/ardour/profile.h | 31 +++ libs/ardour/ardour/route.h | 4 +- libs/ardour/ardour/send.h | 2 +- libs/ardour/ardour/session.h | 4 + libs/ardour/ardour/sndfilesource.h | 2 + libs/ardour/ardour/source.h | 4 +- libs/ardour/audio_diskstream.cc | 10 +- libs/ardour/audiofilesource.cc | 104 +++++++++-- libs/ardour/audioregion.cc | 72 ++++--- libs/ardour/coreaudiosource.cc | 13 +- libs/ardour/diskstream.cc | 5 +- libs/ardour/globals.cc | 6 +- libs/ardour/insert.cc | 4 +- libs/ardour/ladspa_plugin.cc | 12 +- libs/ardour/midi_port.cc | 8 +- libs/ardour/panner.cc | 19 +- libs/ardour/playlist.cc | 23 ++- libs/ardour/region.cc | 5 +- libs/ardour/route.cc | 44 +++-- libs/ardour/session.cc | 6 +- libs/ardour/session_butler.cc | 2 +- libs/ardour/session_midi.cc | 18 -- libs/ardour/session_process.cc | 3 + libs/ardour/session_state.cc | 59 +++++- libs/ardour/session_time.cc | 1 + libs/ardour/session_transport.cc | 10 +- libs/ardour/sndfilesource.cc | 6 + libs/ardour/source.cc | 21 ++- libs/ardour/vst_plugin.cc | 5 +- libs/gtkmm2ext/SConscript | 1 + libs/gtkmm2ext/fastmeter.cc | 4 +- libs/gtkmm2ext/gtk_ui.cc | 10 +- libs/gtkmm2ext/gtkmm2ext/fastmeter.h | 2 +- libs/gtkmm2ext/gtkmm2ext/window_title.h | 44 +++++ libs/gtkmm2ext/window_title.cc | 26 +++ libs/pbd/SConscript | 1 + libs/pbd/pbd/shortpath.h | 8 + libs/pbd/shortpath.cc | 56 ++++++ libs/sigc++2/sigc++/adaptors/bind.h | 2 +- libs/sigc++2/sigc++/adaptors/retype.h | 2 +- libs/sigc++2/sigc++/functors/functor_trait.h | 6 +- libs/sigc++2/sigc++/functors/slot.h | 72 +++---- libs/sigc++2/sigc++/retype.h | 2 +- libs/sigc++2/sigc++/signal.h | 208 ++++++++++----------- .../generic_midi/generic_midi_control_protocol.cc | 66 +++++-- .../generic_midi/generic_midi_control_protocol.h | 4 +- libs/surfaces/generic_midi/midicontrollable.cc | 14 +- libs/surfaces/generic_midi/midicontrollable.h | 2 +- libs/surfaces/mackie/bcf_surface.cc | 78 +++----- libs/surfaces/mackie/mackie_control_protocol.cc | 65 ++++++- libs/surfaces/mackie/mackie_control_protocol.h | 22 ++- libs/surfaces/mackie/scripts/bcf-controls.csv | 22 +-- 58 files changed, 855 insertions(+), 381 deletions(-) create mode 100644 libs/ardour/ardour/profile.h create mode 100644 libs/gtkmm2ext/gtkmm2ext/window_title.h create mode 100644 libs/gtkmm2ext/window_title.cc create mode 100644 libs/pbd/pbd/shortpath.h create mode 100644 libs/pbd/shortpath.cc (limited to 'libs') diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h index 913cd7d5ed..149ceb7dc3 100644 --- a/libs/ardour/ardour/audiofilesource.h +++ b/libs/ardour/ardour/audiofilesource.h @@ -81,6 +81,7 @@ class AudioFileSource : public AudioSource { virtual void mark_capture_start (nframes_t) {} virtual void mark_capture_end () {} virtual void clear_capture_marks() {} + virtual bool one_of_several_channels () const { return false; } virtual int update_header (nframes_t when, struct tm&, time_t) = 0; virtual int flush_header () = 0; @@ -161,7 +162,7 @@ class AudioFileSource : public AudioSource { virtual void set_timeline_position (int64_t pos); virtual void set_header_timeline_position () = 0; - bool find (Glib::ustring& path, bool must_exist, bool& is_new); + bool find (Glib::ustring& path, bool must_exist, bool& is_new, uint16_t& chan); bool removable() const; bool writable() const { return _flags & Writable; } }; diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index 3b592a54ee..e25278cce9 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -89,6 +89,8 @@ class AudioRegion : public Region int set_state (const XMLNode&); static void set_default_fade (float steepness, nframes_t len); + bool fade_in_is_default () const; + bool fade_out_is_default () const; enum FadeShape { Linear, diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h index 674a9232b5..4f0bae1208 100644 --- a/libs/ardour/ardour/configuration_vars.h +++ b/libs/ardour/ardour/configuration_vars.h @@ -17,7 +17,6 @@ CONFIG_VARIABLE (bool, send_mtc, "send-mtc", false) CONFIG_VARIABLE (bool, send_mmc, "send-mmc", false) CONFIG_VARIABLE (bool, mmc_control, "mmc-control", false) CONFIG_VARIABLE (bool, midi_feedback, "midi-feedback", false) -CONFIG_VARIABLE (bool, midi_control, "midi-control", false) CONFIG_VARIABLE (uint8_t, mmc_device_id, "mmc-device-id", 0) /* control surfaces */ diff --git a/libs/ardour/ardour/coreaudiosource.h b/libs/ardour/ardour/coreaudiosource.h index 63c50d7cfb..ad21188531 100644 --- a/libs/ardour/ardour/coreaudiosource.h +++ b/libs/ardour/ardour/coreaudiosource.h @@ -52,7 +52,7 @@ class CoreAudioSource : public AudioFileSource { mutable nframes_t tmpbufsize; mutable Glib::Mutex _tmpbuf_lock; - void init (string str); + void init (); }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 10b3bbfe92..4809e17868 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -281,6 +281,7 @@ class Diskstream : public PBD::StatefulDestructible nframes_t file_frame; nframes_t playback_sample; nframes_t playback_distance; + bool commit_should_unlock; uint32_t _read_data_count; uint32_t _write_data_count; diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 54863b6fb0..b1612f39d5 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -141,6 +141,12 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f virtual bool destroy_region (boost::shared_ptr) = 0; + /* special case function used by UI selection objects, which have playlists that actually own the regions + within them. + */ + + void drop_regions (); + protected: friend class Session; @@ -180,6 +186,7 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f bool save_on_thaw; string last_save_reason; uint32_t in_set_state; + bool first_set_state; bool _hidden; bool _splicing; bool _nudging; diff --git a/libs/ardour/ardour/profile.h b/libs/ardour/ardour/profile.h new file mode 100644 index 0000000000..2ee47d39ea --- /dev/null +++ b/libs/ardour/ardour/profile.h @@ -0,0 +1,31 @@ +#ifndef __ardour_profile_h__ +#define __ardour_profile_h__ + +#include +#include + +namespace ARDOUR { + +class RuntimeProfile { + public: + enum Element { + SmallScreen, + LastElement + }; + + RuntimeProfile() { bits.resize (LastElement); } + ~RuntimeProfile() {} + + void set_small_screen() { bits[SmallScreen] = true; } + bool get_small_screen() const { return bits[SmallScreen]; } + + private: + boost::dynamic_bitset bits; + +}; + +extern RuntimeProfile* Profile; + +}; // namespace ARDOUR + +#endif /* __ardour_profile_h__ */ diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 70091ef85d..6247d79a27 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -169,9 +169,9 @@ class Route : public IO int copy_redirects (const Route&, Placement, uint32_t* err_streams = 0); int sort_redirects (uint32_t* err_streams = 0); - void clear_redirects (void *src); + void clear_redirects (Placement, void *src); void all_redirects_flip(); - void all_redirects_active (bool state); + void all_redirects_active (Placement, bool state); virtual nframes_t update_total_latency(); nframes_t signal_latency() const { return _own_latency; } diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h index d4c0572811..4e3c0fbe2d 100644 --- a/libs/ardour/ardour/send.h +++ b/libs/ardour/ardour/send.h @@ -38,7 +38,7 @@ class Send : public Redirect Send (Session&, Placement); Send (Session&, const XMLNode&); Send (const Send&); - ~Send (); + virtual ~Send (); uint32_t bit_slot() const { return bitslot; } diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 2022b21a05..a95b07a2e7 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -371,6 +371,7 @@ class Session : public PBD::StatefulDestructible void set_session_start (nframes_t start) { start_location->set_start(start); } void set_session_end (nframes_t end) { end_location->set_start(end); _end_location_is_free = false; } void use_rf_shuttle_speed (); + void allow_auto_play (bool yn); void request_transport_speed (float speed); void request_overwrite_buffer (Diskstream*); void request_diskstream_speed (Diskstream&, float speed); @@ -424,6 +425,8 @@ class Session : public PBD::StatefulDestructible int save_template (string template_name); int save_history (string snapshot_name = ""); int restore_history (string snapshot_name); + void remove_state (string snapshot_name); + void rename_state (string old_name, string new_name); static int rename_template (string old_name, string new_name); @@ -1004,6 +1007,7 @@ class Session : public PBD::StatefulDestructible volatile float _transport_speed; volatile float _desired_transport_speed; float _last_transport_speed; + bool auto_play_legal; nframes_t _last_slave_transport_frame; nframes_t maximum_output_latency; nframes_t last_stop_frame; diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h index 2fc3872887..916e9da49e 100644 --- a/libs/ardour/ardour/sndfilesource.h +++ b/libs/ardour/ardour/sndfilesource.h @@ -56,6 +56,8 @@ class SndFileSource : public AudioFileSource { bool set_destructive (bool yn); + bool one_of_several_channels () const; + static void setup_standard_crossfades (nframes_t sample_rate); static const AudioFileSource::Flag default_writable_flags; diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h index 45c91950fc..7b1179b81a 100644 --- a/libs/ardour/ardour/source.h +++ b/libs/ardour/ardour/source.h @@ -82,7 +82,9 @@ class Source : public PBD::StatefulDestructible time_t _timestamp; jack_nframes_t _length; - std::set > _playlists; + Glib::Mutex playlist_lock; + typedef std::map, uint32_t > PlaylistMap; + PlaylistMap _playlists; private: uint32_t _in_use; diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index eeaa095fbd..2c878fbd4d 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -526,6 +526,8 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_ return 0; } + commit_should_unlock = false; + check_record_status (transport_frame, nframes, can_record); nominally_recording = (can_record && re); @@ -544,7 +546,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_ if (!state_lock.trylock()) { return 1; } - + commit_should_unlock = true; adjust_capture_position = 0; for (chan = c->begin(); chan != c->end(); ++chan) { @@ -796,6 +798,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_ be called. unlock the state lock. */ + commit_should_unlock = false; state_lock.unlock(); } @@ -835,7 +838,10 @@ AudioDiskstream::commit (nframes_t nframes) || c->front()->capture_buf->read_space() >= disk_io_chunk_frames; } - state_lock.unlock(); + if (commit_should_unlock) { + state_lock.unlock(); + } + _processed = false; return need_butler; diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc index 1d10109aa1..84ccef905c 100644 --- a/libs/ardour/audiofilesource.cc +++ b/libs/ardour/audiofilesource.cc @@ -29,11 +29,13 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -91,15 +93,17 @@ AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags, SampleFo AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist) : AudioSource (s, node), _flags (Flag (Writable|CanRename)) - /* _channel is set in set_state() */ + /* _channel is set in set_state() or init() */ { /* constructor used for existing internal-to-session files. file must exist */ if (set_state (node)) { throw failed_constructor (); } + + string foo = _name; - if (init (_name, must_exist)) { + if (init (foo, must_exist)) { throw failed_constructor (); } } @@ -134,7 +138,7 @@ AudioFileSource::init (ustring pathstr, bool must_exist) _peaks_built = false; file_is_new = false; - if (!find (pathstr, must_exist, is_new)) { + if (!find (pathstr, must_exist, is_new, _channel)) { throw non_existent_source (); } @@ -244,7 +248,10 @@ AudioFileSource::set_state (const XMLNode& node) void AudioFileSource::mark_for_remove () { - if (!writable()) { + // This operation is not allowed for sources for destructive tracks or embedded files. + // Fortunately mark_for_remove() is never called for embedded files. This function + // must be fixed if that ever happens. + if (_flags & Destructive) { return; } @@ -359,19 +366,13 @@ AudioFileSource::move_to_trash (const ustring& trash_dir_name) } bool -AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew) +AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t& chan) { ustring::size_type pos; bool ret = false; isnew = false; - /* clean up PATH:CHANNEL notation so that we are looking for the correct path */ - - if ((pos = pathstr.find_last_of (':')) != ustring::npos) { - pathstr = pathstr.substr (0, pos); - } - if (pathstr[0] != '/') { /* non-absolute pathname: find pathstr in search path */ @@ -396,12 +397,60 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew) if (fullpath[fullpath.length()-1] != '/') { fullpath += '/'; } + fullpath += pathstr; + + /* i (paul) made a nasty design error by using ':' as a special character in + Ardour 0.99 .. this hack tries to make things sort of work. + */ - if (access (fullpath.c_str(), R_OK) == 0) { - keeppath = fullpath; - ++cnt; - } + if ((pos = pathstr.find_last_of (':')) != ustring::npos) { + + if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) { + + /* its a real file, no problem */ + + keeppath = fullpath; + ++cnt; + + } else { + + if (must_exist) { + + /* might be an older session using file:channel syntax. see if the version + without the :suffix exists + */ + + ustring shorter = pathstr.substr (0, pos); + fullpath = *i; + + if (fullpath[fullpath.length()-1] != '/') { + fullpath += '/'; + } + + fullpath += shorter; + + if (Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) { + chan = atoi (pathstr.substr (pos+1)); + pathstr = shorter; + keeppath = fullpath; + ++cnt; + } + + } else { + + /* new derived file (e.g. for timefx) being created in a newer session */ + + } + } + + } else { + + if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) { + keeppath = fullpath; + ++cnt; + } + } } if (cnt > 1) { @@ -418,7 +467,7 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew) isnew = true; } } - + _name = pathstr; _path = keeppath; ret = true; @@ -426,18 +475,31 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew) } else { /* external files and/or very very old style sessions include full paths */ + + /* ugh, handle ':' situation */ + + if ((pos = pathstr.find_last_of (':')) != ustring::npos) { + + ustring shorter = pathstr.substr (0, pos); + + if (Glib::file_test (shorter, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) { + chan = atoi (pathstr.substr (pos+1)); + pathstr = shorter; + } + } _path = pathstr; + if (is_embedded()) { _name = pathstr; } else { _name = pathstr.substr (pathstr.find_last_of ('/') + 1); } - - if (access (_path.c_str(), R_OK) != 0) { - /* file does not exist or we cannot read it */ + if (!Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) { + /* file does not exist or we cannot read it */ + if (must_exist) { error << string_compose(_("Filesource: cannot find required file (%1): %2"), _path, strerror (errno)) << endmsg; goto out; @@ -458,6 +520,7 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew) /* already exists */ ret = true; + } } @@ -575,6 +638,9 @@ AudioFileSource::safe_file_extension(ustring file) file.rfind(".maud")== ustring::npos && file.rfind(".vwe") == ustring::npos && file.rfind(".paf") == ustring::npos && +#ifdef HAVE_FLAC + file.rfind(".flac")== ustring::npos && +#endif // HAVE_FLAC #ifdef HAVE_COREAUDIO file.rfind(".mp3") == ustring::npos && file.rfind(".aac") == ustring::npos && diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 8bb40e9bcb..68b77a1199 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -332,12 +332,12 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff nframes_t buf_offset; nframes_t to_read; - /* precondition: caller has verified that we cover the desired section */ - - if (chan_n >= _sources.size()) { + if (muted()) { return 0; /* read nothing */ } - + + /* precondition: caller has verified that we cover the desired section */ + if (position < _position) { internal_offset = 0; buf_offset = _position - position; @@ -362,18 +362,30 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff mixdown_buffer += buf_offset; } - if (muted()) { - return 0; /* read nothing */ - } - _read_data_count = 0; - boost::shared_ptr src = audio_source(chan_n); - if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) { - return 0; /* "read nothing" */ - } + if (chan_n < n_channels()) { + + boost::shared_ptr src = audio_source(chan_n); + if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) { + + return 0; /* "read nothing" */ + } + + _read_data_count += src->read_data_count(); - _read_data_count += src->read_data_count(); + } else { + + /* track is N-channel, this region has less channels; silence the ones + we don't have. + */ + + memset (mixdown_buffer, 0, sizeof (Sample) * cnt); + + /* no fades required */ + + goto merge; + } /* fade in */ @@ -384,7 +396,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff /* see if this read is within the fade in */ if (internal_offset < fade_in_length) { - + nframes_t limit; limit = min (to_read, fade_in_length - internal_offset); @@ -458,13 +470,15 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude); } + merge: + if (!opaque()) { /* gack. the things we do for users. */ buf += buf_offset; - + for (nframes_t n = 0; n < to_read; ++n) { buf[n] += mixdown_buffer[n]; } @@ -827,6 +841,18 @@ AudioRegion::set_fade_out_active (bool yn) send_change (FadeOutActiveChanged); } +bool +AudioRegion::fade_in_is_default () const +{ + return _fade_in_shape == Linear && _fade_in.back()->when == 64; +} + +bool +AudioRegion::fade_out_is_default () const +{ + return _fade_out_shape == Linear && _fade_out.back()->when == 64; +} + void AudioRegion::set_default_fade_in () { @@ -938,7 +964,6 @@ AudioRegion::separate_by_channel (Session& session, vector r = RegionFactory::create (srcs, _start, _length, new_name, _layer, f); boost::shared_ptr ar = boost::dynamic_pointer_cast (r); - cerr << "new region name is " << ar->name() << endl; v.push_back (ar); @@ -1099,7 +1124,6 @@ AudioRegion::normalize_to (float target_dB) boost::shared_ptr pl (playlist()); if (pl) { - cerr << "Send modified\n"; pl->Modified(); } @@ -1130,14 +1154,16 @@ void AudioRegion::suspend_fade_in () { if (++_fade_in_disabled == 1) { - set_fade_in_active (false); + if (fade_in_is_default()) { + set_fade_in_active (false); + } } } void AudioRegion::resume_fade_in () { - if (_fade_in_disabled && --_fade_in_disabled == 0) { + if (--_fade_in_disabled == 0 && _fade_in_disabled) { set_fade_in_active (true); } } @@ -1146,14 +1172,16 @@ void AudioRegion::suspend_fade_out () { if (++_fade_out_disabled == 1) { - set_fade_out_active (false); + if (fade_out_is_default()) { + set_fade_out_active (false); + } } } void AudioRegion::resume_fade_out () { - if (_fade_out_disabled && --_fade_out_disabled == 0) { + if (--_fade_out_disabled == 0 &&_fade_out_disabled) { set_fade_out_active (true); } } @@ -1185,7 +1213,7 @@ AudioRegion::source_offset_changed () boost::shared_ptr AudioRegion::audio_source (uint32_t n) const { - // Guaranteed to succeed (use a static cast?) + // Guaranteed to succeed (use a static cast for speed?) return boost::dynamic_pointer_cast(source(n)); } diff --git a/libs/ardour/coreaudiosource.cc b/libs/ardour/coreaudiosource.cc index 572fd9ef81..703225e502 100644 --- a/libs/ardour/coreaudiosource.cc +++ b/libs/ardour/coreaudiosource.cc @@ -38,9 +38,10 @@ CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node) } CoreAudioSource::CoreAudioSource (Session& s, const string& path, int chn, Flag flags) - : AudioFileSource(s, path, flags), + /* files created this way are never writable or removable */ + : AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy))) { - channel = chn; + _channel = chn; init (); } @@ -60,8 +61,8 @@ CoreAudioSource::init () n_channels = file_asbd.NumberChannels(); cerr << "number of channels: " << n_channels << endl; - if (channel >= n_channels) { - error << string_compose("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number (%3)", n_channels, channel, name()) << endmsg; + if (_channel >= n_channels) { + error << string_compose("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number (%3)", n_channels, _channel, name()) << endmsg; throw failed_constructor(); } @@ -132,14 +133,14 @@ CoreAudioSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) con abl.mBuffers[0].mDataByteSize = tmpbufsize * sizeof(Sample); abl.mBuffers[0].mData = tmpbuf; - cerr << "channel: " << channel << endl; + cerr << "channel: " << _channel << endl; try { af.Read (real_cnt, &abl); } catch (CAXException& cax) { error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name); } - float *ptr = tmpbuf + channel; + float *ptr = tmpbuf + _channel; real_cnt /= n_channels; /* stride through the interleaved data */ diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index c8fd2e48bf..18aeb32931 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -114,6 +114,7 @@ Diskstream::init (Flag f) playback_distance = 0; _read_data_count = 0; _write_data_count = 0; + commit_should_unlock = false; pending_overwrite = false; overwrite_frame = 0; @@ -212,7 +213,9 @@ Diskstream::prepare () void Diskstream::recover () { - state_lock.unlock(); + if (commit_should_unlock) { + state_lock.unlock(); + } _processed = false; } diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index f5e841f00f..a310bd598f 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,7 @@ #include "i18n.h" ARDOUR::Configuration* ARDOUR::Config = 0; +ARDOUR::RuntimeProfile* ARDOUR::Profile = 0; ARDOUR::AudioLibrary* ARDOUR::Library = 0; #ifdef HAVE_LIBLO @@ -296,10 +298,12 @@ ARDOUR::init (ARDOUR::AudioEngine& engine, bool use_vst, bool try_optimization) Config->set_use_vst (use_vst); + Profile = new RuntimeProfile; + if (setup_midi (engine)) { return -1; } - + #ifdef HAVE_LIBLO if (setup_osc ()) { return -1; diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index e5d77c3951..956f693f13 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -493,9 +493,11 @@ PluginInsert::protect_automation () switch (al.automation_state()) { case Write: - case Touch: al.set_automation_state (Off); break; + case Touch: + al.set_automation_state (Play); + break; default: break; } diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index ba944f3c08..082d673fbc 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -195,6 +195,7 @@ LadspaPlugin::default_value (uint32_t port) float ret = 0.0f; bool bounds_given = false; bool sr_scaling = false; + bool earlier_hint = false; /* defaults - case 1 */ @@ -203,6 +204,7 @@ LadspaPlugin::default_value (uint32_t port) ret = prh[port].LowerBound; bounds_given = true; sr_scaling = true; + earlier_hint = true; } /* FIXME: add support for logarithmic defaults */ @@ -211,33 +213,41 @@ LadspaPlugin::default_value (uint32_t port) ret = prh[port].LowerBound * 0.75f + prh[port].UpperBound * 0.25f; bounds_given = true; sr_scaling = true; + earlier_hint = true; } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(prh[port].HintDescriptor)) { ret = prh[port].LowerBound * 0.50f + prh[port].UpperBound * 0.50f; bounds_given = true; sr_scaling = true; + earlier_hint = true; } else if (LADSPA_IS_HINT_DEFAULT_HIGH(prh[port].HintDescriptor)) { ret = prh[port].LowerBound * 0.25f + prh[port].UpperBound * 0.75f; bounds_given = true; sr_scaling = true; + earlier_hint = true; } else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(prh[port].HintDescriptor)) { ret = prh[port].UpperBound; bounds_given = true; sr_scaling = true; + earlier_hint = true; } else if (LADSPA_IS_HINT_DEFAULT_0(prh[port].HintDescriptor)) { ret = 0.0f; + earlier_hint = true; } else if (LADSPA_IS_HINT_DEFAULT_1(prh[port].HintDescriptor)) { ret = 1.0f; + earlier_hint = true; } else if (LADSPA_IS_HINT_DEFAULT_100(prh[port].HintDescriptor)) { ret = 100.0f; + earlier_hint = true; } else if (LADSPA_IS_HINT_DEFAULT_440(prh[port].HintDescriptor)) { ret = 440.0f; + earlier_hint = true; } else { /* no hint found */ @@ -290,7 +300,7 @@ LadspaPlugin::default_value (uint32_t port) /* defaults - case 5 */ - if (LADSPA_IS_HINT_SAMPLE_RATE(prh[port].HintDescriptor)) { + if (LADSPA_IS_HINT_SAMPLE_RATE(prh[port].HintDescriptor) && !earlier_hint) { if (bounds_given) { if (sr_scaling) { ret *= sample_rate; diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index d7ce12d411..8fbccf17f7 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -61,7 +61,7 @@ MidiPort::cycle_start (jack_nframes_t nframes) void* jack_buffer = jack_port_get_buffer(_port, nframes); const jack_nframes_t event_count - = jack_midi_get_event_count(jack_buffer, nframes); + = jack_midi_get_event_count(jack_buffer); assert(event_count < _buffer.capacity()); @@ -71,7 +71,7 @@ MidiPort::cycle_start (jack_nframes_t nframes) for (jack_nframes_t i=0; i < event_count; ++i) { // This will fail to compile if we change MidiEvent to our own class - jack_midi_event_get(static_cast(&ev), jack_buffer, i, nframes); + jack_midi_event_get(static_cast(&ev), jack_buffer, i); _buffer.push_back(ev); // Convert note ons with velocity 0 to proper note offs @@ -103,11 +103,11 @@ MidiPort::cycle_end() //if (event_count > 0) // cerr << "MIDIPort writing " << event_count << " events." << endl; - jack_midi_clear_buffer(jack_buffer, _nframes_this_cycle); + jack_midi_clear_buffer(jack_buffer); for (jack_nframes_t i=0; i < event_count; ++i) { const jack_midi_event_t& ev = _buffer[i]; assert(ev.time < _nframes_this_cycle); - jack_midi_event_write(jack_buffer, ev.time, ev.buffer, ev.size, _nframes_this_cycle); + jack_midi_event_write(jack_buffer, ev.time, ev.buffer, ev.size); } _nframes_this_cycle = 0; diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index 8e41e70687..e12857da93 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -666,10 +666,7 @@ Multi2dPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_co } pan = left * gain_coeff; - - for (; n < nframes; ++n) { - dst[n] += src[n] * pan; - } + Session::mix_buffers_with_gain(dst+n,src+n,nframes-n,pan); } else { @@ -679,20 +676,10 @@ Multi2dPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_co if ((pan *= gain_coeff) != 1.0f) { if (pan != 0.0f) { - - for (nframes_t n = 0; n < nframes; ++n) { - dst[n] += src[n] * pan; - } - + Session::mix_buffers_with_gain(dst,src,nframes,pan); } - - } else { - - for (nframes_t n = 0; n < nframes; ++n) { - dst[n] += src[n]; - } - + Session::mix_buffers_no_gain(dst,src,nframes); } #endif #ifdef CAN_INTERP diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 325ef27a18..0d743a5c9d 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -75,6 +75,7 @@ Playlist::Playlist (Session& sess, string nom, DataType type, bool hide) , _type(type) { init (hide); + first_set_state = false; _name = nom; } @@ -113,6 +114,7 @@ Playlist::Playlist (boost::shared_ptr other, string namestr, boo _edit_mode = other->_edit_mode; in_set_state = 0; + first_set_state = false; in_flush = false; in_partition = false; subcnt = 0; @@ -185,6 +187,7 @@ Playlist::Playlist (boost::shared_ptr other, nframes_t start, nf } in_set_state--; + first_set_state = false; /* this constructor does NOT notify others (session) */ } @@ -225,6 +228,7 @@ Playlist::init (bool hide) g_atomic_int_set (&ignore_state_changes, 0); pending_modified = false; pending_length = false; + first_set_state = true; _refcnt = 0; _hidden = hide; _splicing = false; @@ -515,10 +519,10 @@ Playlist::add_region_internal (boost::shared_ptr region, nframes_t posit old_length = _get_maximum_extent(); } - if (!in_set_state) { + if (!first_set_state) { boost::shared_ptr foo (shared_from_this()); region->set_playlist (boost::weak_ptr(foo)); - } + } region->set_position (position, this); @@ -581,6 +585,11 @@ Playlist::remove_region_internal (boost::shared_ptrregion) old_length = _get_maximum_extent(); } + if (!in_set_state) { + /* unset playlist */ + region->set_playlist (boost::weak_ptr()); + } + for (i = regions.begin(); i != regions.end(); ++i) { if (*i == region) { @@ -1181,6 +1190,14 @@ Playlist::region_changed (Change what_changed, boost::shared_ptr region) return save; } +void +Playlist::drop_regions () +{ + RegionLock rl (this); + regions.clear (); + all_regions.clear (); +} + void Playlist::clear (bool with_signals) { @@ -1412,7 +1429,7 @@ Playlist::set_state (const XMLNode& node) } in_set_state--; - + first_set_state = false; return 0; } diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 15609706b2..b972c20589 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -272,12 +272,15 @@ void Region::set_playlist (boost::weak_ptr wpl) { boost::shared_ptr old_playlist = (_playlist.lock()); + boost::shared_ptr pl (wpl.lock()); if (old_playlist == pl) { return; } + _playlist = pl; + if (pl) { if (old_playlist) { for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) { @@ -292,7 +295,7 @@ Region::set_playlist (boost::weak_ptr wpl) } else { if (old_playlist) { for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) { - (*i)->remove_playlist (_playlist); + (*i)->remove_playlist (old_playlist); } } } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 43c233e4d7..d37ae725af 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -113,7 +113,8 @@ Route::init () Route::~Route () { - clear_redirects (this); + clear_redirects (PreFader, this); + clear_redirects (PostFader, this); for (OrderKeys::iterator i = order_keys.begin(); i != order_keys.end(); ++i) { free ((void*)(i->first)); @@ -884,10 +885,13 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea return 0; } +/** Remove redirects with a given placement. + * @param p Placement of redirects to remove. + */ void -Route::clear_redirects (void *src) +Route::clear_redirects (Placement p, void *src) { - ChanCount old_rmo = redirect_max_outs; + const ChanCount old_rmo = redirect_max_outs; if (!_session.engine().connected()) { return; @@ -895,13 +899,22 @@ Route::clear_redirects (void *src) { Glib::RWLock::WriterLock lm (redirect_lock); - RedirectList::iterator i; - for (i = _redirects.begin(); i != _redirects.end(); ++i) { - (*i)->drop_references (); + RedirectList new_list; + + for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { + if ((*i)->placement() == p) { + /* it's the placement we want to get rid of */ + (*i)->drop_references (); + } else { + /* it's a different placement, so keep it */ + new_list.push_back (*i); + } } - _redirects.clear (); + + _redirects = new_list; } + /* FIXME: can't see how this test can ever fire */ if (redirect_max_outs != old_rmo) { reset_panner (); } @@ -1269,8 +1282,12 @@ Route::all_redirects_flip () } } +/** Set all redirects with a given placement to a given active state. + * @param p Placement of redirects to change. + * @param state New active state for those redirects. + */ void -Route::all_redirects_active (bool state) +Route::all_redirects_active (Placement p, bool state) { Glib::RWLock::ReaderLock lm (redirect_lock); @@ -1279,7 +1296,9 @@ Route::all_redirects_active (bool state) } for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - (*i)->set_active (state, this); + if ((*i)->placement() == p) { + (*i)->set_active (state, this); + } } } @@ -2263,8 +2282,9 @@ Route::protect_automation () { switch (gain_automation_state()) { case Write: - case Touch: set_gain_automation_state (Off); + case Touch: + set_gain_automation_state (Play); break; default: break; @@ -2272,9 +2292,11 @@ Route::protect_automation () switch (panner().automation_state ()) { case Write: - case Touch: panner().set_automation_state (Off); break; + case Touch: + panner().set_automation_state (Play); + break; default: break; } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 9d0b13fccd..d775e9c69b 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1909,7 +1909,7 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { if (dynamic_cast((*i).get()) == 0) { - if (!(*i)->hidden()) { + if (!(*i)->hidden() && (*i)->name() != _("master")) { bus_id++; } } @@ -1926,15 +1926,13 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ while (how_many) { do { - ++bus_id; - snprintf (bus_name, sizeof(bus_name), "Bus %" PRIu32, bus_id); if (route_by_name (bus_name) == 0) { break; } - } while (bus_id < (UINT_MAX-1)); + } while (++bus_id < (UINT_MAX-1)); try { shared_ptr bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO)); diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index 16c8d9cffa..afb284b0f4 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -248,7 +248,7 @@ Session::butler_thread_work () gettimeofday (&begin, 0); boost::shared_ptr dsl = diskstreams.reader (); - + for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) { boost::shared_ptr ds = *i; diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index 2a078565b5..7d20a05b45 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -451,24 +451,6 @@ Session::setup_midi_control () mtc_msg[10] = 0xf1; mtc_msg[12] = 0xf1; mtc_msg[14] = 0xf1; - - if (_mmc_port != 0) { - - Config->set_send_mmc (session_send_mmc); - - } else { - - mmc = 0; - session_send_mmc = false; - } - - if (_mtc_port != 0) { - - Config->set_send_mtc (session_send_mtc); - - } else { - session_send_mtc = false; - } } #if 0 diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 9b8b7f1d24..f0c4a29aa9 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -222,6 +222,9 @@ Session::commit_diskstreams (nframes_t nframes, bool &needs_butler) } /* force all diskstreams not handled by a Route to call do their stuff. + Note: the diskstreams that were handled by a route will just return zero + from this call, because they know they were processed. So in fact, this + also runs commit() for every diskstream. */ if ((dret = (*i)->process (_transport_frame, nframes, 0, actively_recording(), get_rec_monitors_input())) == 0) { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index aae5830b34..a588015eac 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -141,6 +141,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) insert_cnt = 0; _transport_speed = 0; _last_transport_speed = 0; + auto_play_legal = false; transport_sub_state = 0; _transport_frame = 0; last_stop_frame = 0; @@ -611,6 +612,48 @@ Session::remove_pending_capture_state () unlink (xml_path.c_str()); } +/** Rename a state file. + * @param snapshot_name Snapshot name. + */ +void +Session::rename_state (string old_name, string new_name) +{ + if (old_name == _current_snapshot_name || old_name == _name) { + /* refuse to rename the current snapshot or the "main" one */ + return; + } + + const string old_xml_path = _path + old_name + _statefile_suffix; + const string new_xml_path = _path + new_name + _statefile_suffix; + + if (rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) { + error << string_compose(_("could not rename snapshot %1 to %2"), old_name, new_name) << endmsg; + } +} + +/** Remove a state file. + * @param snapshot_name Snapshot name. + */ +void +Session::remove_state (string snapshot_name) +{ + if (snapshot_name == _current_snapshot_name || snapshot_name == _name) { + /* refuse to remove the current snapshot or the "main" one */ + return; + } + + const string xml_path = _path + snapshot_name + _statefile_suffix; + + /* make a backup copy of the state file */ + const string bak_path = xml_path + ".bak"; + if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) { + copy_file (xml_path, bak_path); + } + + /* and delete it */ + unlink (xml_path.c_str()); +} + int Session::save_state (string snapshot_name, bool pending) { @@ -636,10 +679,12 @@ Session::save_state (string snapshot_name, bool pending) if (!pending) { + /* proper save: use _statefile_suffix (.ardour in English) */ xml_path = _path; xml_path += snapshot_name; xml_path += _statefile_suffix; + /* make a backup copy of the old file */ bak_path = xml_path; bak_path += ".bak"; @@ -649,6 +694,7 @@ Session::save_state (string snapshot_name, bool pending) } else { + /* pending save: use _pending_suffix (.pending in English) */ xml_path = _path; xml_path += snapshot_name; xml_path += _pending_suffix; @@ -2751,6 +2797,9 @@ Session::cleanup_sources (Session::cleanup_report& rep) } } + char tmppath1[PATH_MAX+1]; + char tmppath2[PATH_MAX+1]; + for (vector::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) { used = false; @@ -2758,7 +2807,10 @@ Session::cleanup_sources (Session::cleanup_report& rep) for (set::iterator i = all_sources.begin(); i != all_sources.end(); ++i) { - if (spath == *i) { + realpath(spath.c_str(), tmppath1); + realpath((*i).c_str(), tmppath2); + + if (strcmp(tmppath1, tmppath2) == 0) { used = true; break; } @@ -3284,6 +3336,8 @@ Session::config_changed (const char* parameter_name) /* mark us ready to send */ next_quarter_frame_to_send = 0; } + } else { + session_send_mtc = false; } } else if (PARAM_IS ("send-mmc")) { @@ -3294,6 +3348,9 @@ Session::config_changed (const char* parameter_name) if (_mmc_port != 0) { session_send_mmc = Config->get_send_mmc(); + } else { + mmc = 0; + session_send_mmc = false; } } else if (PARAM_IS ("midi-feedback")) { diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc index 836958f667..281c3a3315 100644 --- a/libs/ardour/session_time.cc +++ b/libs/ardour/session_time.cc @@ -25,6 +25,7 @@ #include #include +#include #include #include diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 3ee74231e0..d9150d235a 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -646,7 +646,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w } } - if (transport_rolling() && !Config->get_auto_play() && !with_roll && !(synced_to_jack() && play_loop)) { + if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) { realtime_stop (false); } @@ -936,7 +936,7 @@ Session::post_transport () if (post_transport_work & PostTransportLocate) { - if (((Config->get_slave_source() == None && Config->get_auto_play()) && !_exporting) || (post_transport_work & PostTransportRoll)) { + if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) { start_transport (); } else { @@ -1261,3 +1261,9 @@ Session::update_latency_compensation_proxy (void* ignored) { update_latency_compensation (false, false); } + +void +Session::allow_auto_play (bool yn) +{ + auto_play_legal = yn; +} diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index d11afa736b..8f795db111 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -894,3 +894,9 @@ SndFileSource::get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& e ret |= (uint32_t) binfo->time_reference_low; return ret; } + +bool +SndFileSource::one_of_several_channels () const +{ + return _info.channels > 1; +} diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index c4cf1156cd..86afe4cb8d 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -132,7 +132,17 @@ Source::update_length (jack_nframes_t pos, jack_nframes_t cnt) void Source::add_playlist (boost::shared_ptr pl) { - _playlists.insert (pl); + std::pair res; + std::pair, uint32_t> newpair (pl, 1); + Glib::Mutex::Lock lm (playlist_lock); + + res = _playlists.insert (newpair); + + if (!res.second) { + /* it already existed, bump count */ + res.first->second++; + } + pl->GoingAway.connect (bind (mem_fun (*this, &Source::remove_playlist), boost::weak_ptr (pl))); } @@ -145,10 +155,15 @@ Source::remove_playlist (boost::weak_ptr wpl) return; } - std::set >::iterator x; + PlaylistMap::iterator x; + Glib::Mutex::Lock lm (playlist_lock); if ((x = _playlists.find (pl)) != _playlists.end()) { - _playlists.erase (x); + if (x->second > 1) { + x->second--; + } else { + _playlists.erase (x); + } } } diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc index ed78b0942d..afba6b5cfb 100644 --- a/libs/ardour/vst_plugin.cc +++ b/libs/ardour/vst_plugin.cc @@ -172,9 +172,8 @@ VSTPlugin::get_state() } else { - error << string_compose (_("cannot check VST chunk directory: %1"), - strerror (errno)) - << endmsg; + warning << string_compose (_("cannot check VST chunk directory: %1"), strerror (errno)) + << endmsg; return *root; } diff --git a/libs/gtkmm2ext/SConscript b/libs/gtkmm2ext/SConscript index 579ba5dd8e..504801aa03 100644 --- a/libs/gtkmm2ext/SConscript +++ b/libs/gtkmm2ext/SConscript @@ -56,6 +56,7 @@ tearoff.cc textviewer.cc utils.cc version.cc +window_title.cc """) gtkmm2ext.VersionBuild(['version.cc','gtkmm2ext/version.h'], []) diff --git a/libs/gtkmm2ext/fastmeter.cc b/libs/gtkmm2ext/fastmeter.cc index 253dad80a2..ab1e1472b3 100644 --- a/libs/gtkmm2ext/fastmeter.cc +++ b/libs/gtkmm2ext/fastmeter.cc @@ -50,7 +50,6 @@ FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o) hold_state = 0; current_peak = 0; current_level = 0; - current_user_level = -100.0f; set_events (BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK); @@ -413,10 +412,9 @@ FastMeter::horizontal_expose (GdkEventExpose* ev) } void -FastMeter::set (float lvl, float usrlvl) +FastMeter::set (float lvl) { current_level = lvl; - current_user_level = usrlvl; if (lvl > current_peak) { current_peak = lvl; diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc index 177e4f3dbb..903f56ba6f 100644 --- a/libs/gtkmm2ext/gtk_ui.cc +++ b/libs/gtkmm2ext/gtk_ui.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include "i18n.h" @@ -87,10 +88,11 @@ UI::UI (string namestr, int *argc, char ***argv, string rcfile) errors->text().set_editable (false); errors->text().set_name ("ErrorText"); - string title; - title = namestr; - title += ": Log"; - errors->set_title (title); + Glib::set_application_name(namestr); + + WindowTitle title(Glib::get_application_name()); + title += _("Log"); + errors->set_title (title.get_string()); errors->dismiss_button().set_name ("ErrorLogCloseButton"); errors->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), (Window *) errors)); diff --git a/libs/gtkmm2ext/gtkmm2ext/fastmeter.h b/libs/gtkmm2ext/gtkmm2ext/fastmeter.h index 775cb201cd..48bed3d150 100644 --- a/libs/gtkmm2ext/gtkmm2ext/fastmeter.h +++ b/libs/gtkmm2ext/gtkmm2ext/fastmeter.h @@ -35,7 +35,7 @@ class FastMeter : public Gtk::DrawingArea { FastMeter (long hold_cnt, unsigned long width, Orientation); virtual ~FastMeter (); - void set (float level, float user_level=0.0f); + void set (float level); void clear (); float get_level() { return current_level; } diff --git a/libs/gtkmm2ext/gtkmm2ext/window_title.h b/libs/gtkmm2ext/gtkmm2ext/window_title.h new file mode 100644 index 0000000000..1ce7d64b92 --- /dev/null +++ b/libs/gtkmm2ext/gtkmm2ext/window_title.h @@ -0,0 +1,44 @@ +#ifndef WINDOW_TITLE_INCLUDED +#define WINDOW_TITLE_INCLUDED + +#include + +namespace Gtkmm2ext { + +using std::string; + +/** + * \class The WindowTitle class can be used to maintain the + * consistancy of window titles between windows and dialogs. + * + * Each string element that is added to the window title will + * be separated by a hyphen. + */ +class WindowTitle +{ +public: + + /** + * \param title The first string/element of the window title + * which will may be the application name or the document + * name in a document based application. + */ + WindowTitle(const string& title); + + /** + * Add an string element to the window title. + */ + void operator+= (const string&); + + /// @return The window title string. + const string& get_string () { return m_title;} + +private: + + string m_title; + +}; + +} // Gtkmm2ext + +#endif // WINDOW_TITLE_INCLUDED diff --git a/libs/gtkmm2ext/window_title.cc b/libs/gtkmm2ext/window_title.cc new file mode 100644 index 0000000000..237be1ff0f --- /dev/null +++ b/libs/gtkmm2ext/window_title.cc @@ -0,0 +1,26 @@ +#include "gtkmm2ext/window_title.h" + +#include "i18n.h" + +namespace { + +// I don't know if this should be translated. +const char* const title_separator = X_(" - "); + +} // anonymous namespace + +namespace Gtkmm2ext { + +WindowTitle::WindowTitle(const string& title) + : m_title(title) +{ + +} + +void +WindowTitle::operator+= (const string& element) +{ + m_title = m_title + title_separator + element; +} + +} diff --git a/libs/pbd/SConscript b/libs/pbd/SConscript index 12664a1fca..3aaeb1bf1b 100644 --- a/libs/pbd/SConscript +++ b/libs/pbd/SConscript @@ -34,6 +34,7 @@ pathscanner.cc pool.cc pthread_utils.cc receiver.cc +shortpath.cc stacktrace.cc stateful.cc strreplace.cc diff --git a/libs/pbd/pbd/shortpath.h b/libs/pbd/pbd/shortpath.h new file mode 100644 index 0000000000..d126472e77 --- /dev/null +++ b/libs/pbd/pbd/shortpath.h @@ -0,0 +1,8 @@ +#ifndef __pbd_shortpath_h__ +#define __pbd_shortpath_h__ + +#include + +Glib::ustring short_path (const Glib::ustring& path, Glib::ustring::size_type target_characters); + +#endif /* __pbd_shortpath_h__ */ diff --git a/libs/pbd/shortpath.cc b/libs/pbd/shortpath.cc new file mode 100644 index 0000000000..59af8e4dcb --- /dev/null +++ b/libs/pbd/shortpath.cc @@ -0,0 +1,56 @@ +#include + +using namespace Glib; +using namespace std; + +ustring +short_path (const Glib::ustring& path, ustring::size_type target_characters) +{ + ustring::size_type last_sep; + ustring::size_type len = path.length(); + const char separator = '/'; + + if (len <= target_characters) { + return path; + } + + if ((last_sep = path.find_last_of (separator)) == ustring::npos) { + + /* just a filename, but its too long anyway */ + + if (target_characters > 3) { + return path.substr (0, target_characters - 3) + ustring ("..."); + } else { + /* stupid caller, just hand back the whole thing */ + return path; + } + } + + if (len - last_sep >= target_characters) { + + /* even the filename itself is too long */ + + if (target_characters > 3) { + return path.substr (last_sep+1, target_characters - 3) + ustring ("..."); + } else { + /* stupid caller, just hand back the whole thing */ + return path; + } + } + + uint32_t so_far = (len - last_sep); + uint32_t space_for = target_characters - so_far; + + if (space_for >= 3) { + ustring res = "..."; + res += path.substr (last_sep - space_for); + return res; + } else { + /* remove part of the end */ + ustring res = "..."; + res += path.substr (last_sep - space_for, len - last_sep + space_for - 3); + res += "..."; + return res; + + } +} diff --git a/libs/sigc++2/sigc++/adaptors/bind.h b/libs/sigc++2/sigc++/adaptors/bind.h index 81edaf7934..180a5f26e7 100644 --- a/libs/sigc++2/sigc++/adaptors/bind.h +++ b/libs/sigc++2/sigc++/adaptors/bind.h @@ -131,7 +131,7 @@ struct count_void * * @ingroup bind */ -template +template struct bind_functor; /** Adaptor that binds an argument to the wrapped functor. diff --git a/libs/sigc++2/sigc++/adaptors/retype.h b/libs/sigc++2/sigc++/adaptors/retype.h index 502959d3cd..01f71fcaa7 100644 --- a/libs/sigc++2/sigc++/adaptors/retype.h +++ b/libs/sigc++2/sigc++/adaptors/retype.h @@ -64,7 +64,7 @@ namespace sigc { * * @ingroup retype */ -template +template struct retype_functor : public adapts { diff --git a/libs/sigc++2/sigc++/functors/functor_trait.h b/libs/sigc++2/sigc++/functors/functor_trait.h index 656d010414..0b7475273f 100644 --- a/libs/sigc++2/sigc++/functors/functor_trait.h +++ b/libs/sigc++2/sigc++/functors/functor_trait.h @@ -27,14 +27,14 @@ namespace sigc { -/** nil struct type. - * The nil struct type is used as default template argument in the +/** nil_ struct type. + * The nil_ struct type is used as default template argument in the * unnumbered sigc::signal and sigc::slot templates. * * @ingroup signal * @ingroup slot */ -struct nil; +struct nil_; /** @defgroup functors Functors diff --git a/libs/sigc++2/sigc++/functors/slot.h b/libs/sigc++2/sigc++/functors/slot.h index 51294fe4d8..48c192a3c3 100644 --- a/libs/sigc++2/sigc++/functors/slot.h +++ b/libs/sigc++2/sigc++/functors/slot.h @@ -468,7 +468,7 @@ public: * * The template arguments determine the function signature of operator()(): * - @e T_return The return type of operator()(). - * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil means no argument. + * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil_ means no argument. * * To use simply assign the slot to the desired functor. If the functor * is not compatible with the parameter list defined with the template @@ -540,8 +540,8 @@ public: * * The template arguments determine the function signature of operator()(): * - @e T_return The return type of operator()(). - * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil means no argument. + * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil_ means no argument. * * To use simply assign the slot to the desired functor. If the functor * is not compatible with the parameter list defined with the template @@ -615,9 +615,9 @@ public: * * The template arguments determine the function signature of operator()(): * - @e T_return The return type of operator()(). - * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil means no argument. + * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil_ means no argument. * * To use simply assign the slot to the desired functor. If the functor * is not compatible with the parameter list defined with the template @@ -693,10 +693,10 @@ public: * * The template arguments determine the function signature of operator()(): * - @e T_return The return type of operator()(). - * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg4 Argument type used in the definition of operator()(). The default @p nil means no argument. + * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg4 Argument type used in the definition of operator()(). The default @p nil_ means no argument. * * To use simply assign the slot to the desired functor. If the functor * is not compatible with the parameter list defined with the template @@ -774,11 +774,11 @@ public: * * The template arguments determine the function signature of operator()(): * - @e T_return The return type of operator()(). - * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg4 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg5 Argument type used in the definition of operator()(). The default @p nil means no argument. + * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg4 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg5 Argument type used in the definition of operator()(). The default @p nil_ means no argument. * * To use simply assign the slot to the desired functor. If the functor * is not compatible with the parameter list defined with the template @@ -858,12 +858,12 @@ public: * * The template arguments determine the function signature of operator()(): * - @e T_return The return type of operator()(). - * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg4 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg5 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg6 Argument type used in the definition of operator()(). The default @p nil means no argument. + * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg4 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg5 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg6 Argument type used in the definition of operator()(). The default @p nil_ means no argument. * * To use simply assign the slot to the desired functor. If the functor * is not compatible with the parameter list defined with the template @@ -945,13 +945,13 @@ public: * * The template arguments determine the function signature of operator()(): * - @e T_return The return type of operator()(). - * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg4 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg5 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg6 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg7 Argument type used in the definition of operator()(). The default @p nil means no argument. + * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg4 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg5 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg6 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg7 Argument type used in the definition of operator()(). The default @p nil_ means no argument. * * To use simply assign the slot to the desired functor. If the functor * is not compatible with the parameter list defined with the template @@ -1037,13 +1037,13 @@ public: * * The template arguments determine the function signature of operator()(): * - @e T_return The return type of operator()(). - * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg4 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg5 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg6 Argument type used in the definition of operator()(). The default @p nil means no argument. - * - @e T_arg7 Argument type used in the definition of operator()(). The default @p nil means no argument. + * - @e T_arg1 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg2 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg3 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg4 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg5 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg6 Argument type used in the definition of operator()(). The default @p nil_ means no argument. + * - @e T_arg7 Argument type used in the definition of operator()(). The default @p nil_ means no argument. * * To use simply assign the slot to the desired functor. If the functor * is not compatible with the parameter list defined with the template @@ -1061,7 +1061,7 @@ public: * * @ingroup slot */ -template +template class slot : public slot7 { diff --git a/libs/sigc++2/sigc++/retype.h b/libs/sigc++2/sigc++/retype.h index 5df6622f84..069313573b 100644 --- a/libs/sigc++2/sigc++/retype.h +++ b/libs/sigc++2/sigc++/retype.h @@ -9,7 +9,7 @@ namespace SigC { -template +template struct retype_slot_functor : public ::sigc::adapts { diff --git a/libs/sigc++2/sigc++/signal.h b/libs/sigc++2/sigc++/signal.h index a89112cf9e..9c4e35442a 100644 --- a/libs/sigc++2/sigc++/signal.h +++ b/libs/sigc++2/sigc++/signal.h @@ -407,7 +407,7 @@ private: * This template implements the emit() function of signal0. * Template specializations are available to optimize signal * emission when no accumulator is used, i.e. the template - * argument @e T_accumulator is @p nil. + * argument @e T_accumulator is @p nil_. */ template struct signal_emit0 @@ -452,9 +452,9 @@ struct signal_emit0 * function for the case that no accumulator is used. */ template -struct signal_emit0 +struct signal_emit0 { - typedef signal_emit0 self_type; + typedef signal_emit0 self_type; typedef T_return result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -493,9 +493,9 @@ struct signal_emit0 * return type is @p void. */ template <> -struct signal_emit0 +struct signal_emit0 { - typedef signal_emit0 self_type; + typedef signal_emit0 self_type; typedef void result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -523,7 +523,7 @@ struct signal_emit0 * This template implements the emit() function of signal1. * Template specializations are available to optimize signal * emission when no accumulator is used, i.e. the template - * argument @e T_accumulator is @p nil. + * argument @e T_accumulator is @p nil_. */ template struct signal_emit1 @@ -577,9 +577,9 @@ struct signal_emit1 * function for the case that no accumulator is used. */ template -struct signal_emit1 +struct signal_emit1 { - typedef signal_emit1 self_type; + typedef signal_emit1 self_type; typedef T_return result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -620,9 +620,9 @@ struct signal_emit1 * return type is @p void. */ template -struct signal_emit1 +struct signal_emit1 { - typedef signal_emit1 self_type; + typedef signal_emit1 self_type; typedef void result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -652,7 +652,7 @@ struct signal_emit1 * This template implements the emit() function of signal2. * Template specializations are available to optimize signal * emission when no accumulator is used, i.e. the template - * argument @e T_accumulator is @p nil. + * argument @e T_accumulator is @p nil_. */ template struct signal_emit2 @@ -708,9 +708,9 @@ struct signal_emit2 * function for the case that no accumulator is used. */ template -struct signal_emit2 +struct signal_emit2 { - typedef signal_emit2 self_type; + typedef signal_emit2 self_type; typedef T_return result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -752,9 +752,9 @@ struct signal_emit2 * return type is @p void. */ template -struct signal_emit2 +struct signal_emit2 { - typedef signal_emit2 self_type; + typedef signal_emit2 self_type; typedef void result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -785,7 +785,7 @@ struct signal_emit2 * This template implements the emit() function of signal3. * Template specializations are available to optimize signal * emission when no accumulator is used, i.e. the template - * argument @e T_accumulator is @p nil. + * argument @e T_accumulator is @p nil_. */ template struct signal_emit3 @@ -843,9 +843,9 @@ struct signal_emit3 * function for the case that no accumulator is used. */ template -struct signal_emit3 +struct signal_emit3 { - typedef signal_emit3 self_type; + typedef signal_emit3 self_type; typedef T_return result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -888,9 +888,9 @@ struct signal_emit3 * return type is @p void. */ template -struct signal_emit3 +struct signal_emit3 { - typedef signal_emit3 self_type; + typedef signal_emit3 self_type; typedef void result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -922,7 +922,7 @@ struct signal_emit3 * This template implements the emit() function of signal4. * Template specializations are available to optimize signal * emission when no accumulator is used, i.e. the template - * argument @e T_accumulator is @p nil. + * argument @e T_accumulator is @p nil_. */ template struct signal_emit4 @@ -982,9 +982,9 @@ struct signal_emit4 * function for the case that no accumulator is used. */ template -struct signal_emit4 +struct signal_emit4 { - typedef signal_emit4 self_type; + typedef signal_emit4 self_type; typedef T_return result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -1028,9 +1028,9 @@ struct signal_emit4 * return type is @p void. */ template -struct signal_emit4 +struct signal_emit4 { - typedef signal_emit4 self_type; + typedef signal_emit4 self_type; typedef void result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -1063,7 +1063,7 @@ struct signal_emit4 * This template implements the emit() function of signal5. * Template specializations are available to optimize signal * emission when no accumulator is used, i.e. the template - * argument @e T_accumulator is @p nil. + * argument @e T_accumulator is @p nil_. */ template struct signal_emit5 @@ -1125,9 +1125,9 @@ struct signal_emit5 * function for the case that no accumulator is used. */ template -struct signal_emit5 +struct signal_emit5 { - typedef signal_emit5 self_type; + typedef signal_emit5 self_type; typedef T_return result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -1172,9 +1172,9 @@ struct signal_emit5 * return type is @p void. */ template -struct signal_emit5 +struct signal_emit5 { - typedef signal_emit5 self_type; + typedef signal_emit5 self_type; typedef void result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -1208,7 +1208,7 @@ struct signal_emit5 * This template implements the emit() function of signal6. * Template specializations are available to optimize signal * emission when no accumulator is used, i.e. the template - * argument @e T_accumulator is @p nil. + * argument @e T_accumulator is @p nil_. */ template struct signal_emit6 @@ -1272,9 +1272,9 @@ struct signal_emit6 * function for the case that no accumulator is used. */ template -struct signal_emit6 +struct signal_emit6 { - typedef signal_emit6 self_type; + typedef signal_emit6 self_type; typedef T_return result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -1320,9 +1320,9 @@ struct signal_emit6 * return type is @p void. */ template -struct signal_emit6 +struct signal_emit6 { - typedef signal_emit6 self_type; + typedef signal_emit6 self_type; typedef void result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -1357,7 +1357,7 @@ struct signal_emit6 * This template implements the emit() function of signal7. * Template specializations are available to optimize signal * emission when no accumulator is used, i.e. the template - * argument @e T_accumulator is @p nil. + * argument @e T_accumulator is @p nil_. */ template struct signal_emit7 @@ -1423,9 +1423,9 @@ struct signal_emit7 * function for the case that no accumulator is used. */ template -struct signal_emit7 +struct signal_emit7 { - typedef signal_emit7 self_type; + typedef signal_emit7 self_type; typedef T_return result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -1472,9 +1472,9 @@ struct signal_emit7 -struct signal_emit7 +struct signal_emit7 { - typedef signal_emit7 self_type; + typedef signal_emit7 self_type; typedef void result_type; typedef slot slot_type; typedef signal_impl::const_iterator_type iterator_type; @@ -1529,13 +1529,13 @@ struct signal_emit7 * * The following template arguments are used: * - @e T_return The desired return type for the emit() function (may be overridden by the accumulator). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. * * You should use the more convenient unnumbered sigc::signal template. * * @ingroup signal */ -template +template class signal0 : public signal_base { @@ -1575,7 +1575,7 @@ public: * During signal emission all slots that have been connected * to the signal are invoked unless they are manually set into * a blocking state. The parameters are passed on to the slots. - * If @e T_accumulated is not @p nil, an accumulator of this type + * If @e T_accumulated is not @p nil_, an accumulator of this type * is used to process the return values of the slot invocations. * Otherwise, the return value of the last slot invoked is returned. * @return The accumulated return values of the slot invocations. @@ -1638,13 +1638,13 @@ public: * The following template arguments are used: * - @e T_return The desired return type for the emit() function (may be overridden by the accumulator). * - @e T_arg1 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. * * You should use the more convenient unnumbered sigc::signal template. * * @ingroup signal */ -template +template class signal1 : public signal_base { @@ -1684,7 +1684,7 @@ public: * During signal emission all slots that have been connected * to the signal are invoked unless they are manually set into * a blocking state. The parameters are passed on to the slots. - * If @e T_accumulated is not @p nil, an accumulator of this type + * If @e T_accumulated is not @p nil_, an accumulator of this type * is used to process the return values of the slot invocations. * Otherwise, the return value of the last slot invoked is returned. * @param _A_a1 Argument to be passed on to the slots. @@ -1749,13 +1749,13 @@ public: * - @e T_return The desired return type for the emit() function (may be overridden by the accumulator). * - @e T_arg1 Argument type used in the definition of emit(). * - @e T_arg2 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. * * You should use the more convenient unnumbered sigc::signal template. * * @ingroup signal */ -template +template class signal2 : public signal_base { @@ -1795,7 +1795,7 @@ public: * During signal emission all slots that have been connected * to the signal are invoked unless they are manually set into * a blocking state. The parameters are passed on to the slots. - * If @e T_accumulated is not @p nil, an accumulator of this type + * If @e T_accumulated is not @p nil_, an accumulator of this type * is used to process the return values of the slot invocations. * Otherwise, the return value of the last slot invoked is returned. * @param _A_a1 Argument to be passed on to the slots. @@ -1862,13 +1862,13 @@ public: * - @e T_arg1 Argument type used in the definition of emit(). * - @e T_arg2 Argument type used in the definition of emit(). * - @e T_arg3 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. * * You should use the more convenient unnumbered sigc::signal template. * * @ingroup signal */ -template +template class signal3 : public signal_base { @@ -1908,7 +1908,7 @@ public: * During signal emission all slots that have been connected * to the signal are invoked unless they are manually set into * a blocking state. The parameters are passed on to the slots. - * If @e T_accumulated is not @p nil, an accumulator of this type + * If @e T_accumulated is not @p nil_, an accumulator of this type * is used to process the return values of the slot invocations. * Otherwise, the return value of the last slot invoked is returned. * @param _A_a1 Argument to be passed on to the slots. @@ -1977,13 +1977,13 @@ public: * - @e T_arg2 Argument type used in the definition of emit(). * - @e T_arg3 Argument type used in the definition of emit(). * - @e T_arg4 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. * * You should use the more convenient unnumbered sigc::signal template. * * @ingroup signal */ -template +template class signal4 : public signal_base { @@ -2023,7 +2023,7 @@ public: * During signal emission all slots that have been connected * to the signal are invoked unless they are manually set into * a blocking state. The parameters are passed on to the slots. - * If @e T_accumulated is not @p nil, an accumulator of this type + * If @e T_accumulated is not @p nil_, an accumulator of this type * is used to process the return values of the slot invocations. * Otherwise, the return value of the last slot invoked is returned. * @param _A_a1 Argument to be passed on to the slots. @@ -2094,13 +2094,13 @@ public: * - @e T_arg3 Argument type used in the definition of emit(). * - @e T_arg4 Argument type used in the definition of emit(). * - @e T_arg5 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. * * You should use the more convenient unnumbered sigc::signal template. * * @ingroup signal */ -template +template class signal5 : public signal_base { @@ -2140,7 +2140,7 @@ public: * During signal emission all slots that have been connected * to the signal are invoked unless they are manually set into * a blocking state. The parameters are passed on to the slots. - * If @e T_accumulated is not @p nil, an accumulator of this type + * If @e T_accumulated is not @p nil_, an accumulator of this type * is used to process the return values of the slot invocations. * Otherwise, the return value of the last slot invoked is returned. * @param _A_a1 Argument to be passed on to the slots. @@ -2213,13 +2213,13 @@ public: * - @e T_arg4 Argument type used in the definition of emit(). * - @e T_arg5 Argument type used in the definition of emit(). * - @e T_arg6 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. * * You should use the more convenient unnumbered sigc::signal template. * * @ingroup signal */ -template +template class signal6 : public signal_base { @@ -2259,7 +2259,7 @@ public: * During signal emission all slots that have been connected * to the signal are invoked unless they are manually set into * a blocking state. The parameters are passed on to the slots. - * If @e T_accumulated is not @p nil, an accumulator of this type + * If @e T_accumulated is not @p nil_, an accumulator of this type * is used to process the return values of the slot invocations. * Otherwise, the return value of the last slot invoked is returned. * @param _A_a1 Argument to be passed on to the slots. @@ -2334,13 +2334,13 @@ public: * - @e T_arg5 Argument type used in the definition of emit(). * - @e T_arg6 Argument type used in the definition of emit(). * - @e T_arg7 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used, i.e. signal emission returns the return value of the last slot invoked. * * You should use the more convenient unnumbered sigc::signal template. * * @ingroup signal */ -template +template class signal7 : public signal_base { @@ -2380,7 +2380,7 @@ public: * During signal emission all slots that have been connected * to the signal are invoked unless they are manually set into * a blocking state. The parameters are passed on to the slots. - * If @e T_accumulated is not @p nil, an accumulator of this type + * If @e T_accumulated is not @p nil_, an accumulator of this type * is used to process the return values of the slot invocations. * Otherwise, the return value of the last slot invoked is returned. * @param _A_a1 Argument to be passed on to the slots. @@ -2452,13 +2452,13 @@ public: * The template arguments determine the function signature of * the emit() function: * - @e T_return The desired return type of the emit() function. - * - @e T_arg1 Argument type used in the definition of emit(). The default @p nil means no argument. - * - @e T_arg2 Argument type used in the definition of emit(). The default @p nil means no argument. - * - @e T_arg3 Argument type used in the definition of emit(). The default @p nil means no argument. - * - @e T_arg4 Argument type used in the definition of emit(). The default @p nil means no argument. - * - @e T_arg5 Argument type used in the definition of emit(). The default @p nil means no argument. - * - @e T_arg6 Argument type used in the definition of emit(). The default @p nil means no argument. - * - @e T_arg7 Argument type used in the definition of emit(). The default @p nil means no argument. + * - @e T_arg1 Argument type used in the definition of emit(). The default @p nil_ means no argument. + * - @e T_arg2 Argument type used in the definition of emit(). The default @p nil_ means no argument. + * - @e T_arg3 Argument type used in the definition of emit(). The default @p nil_ means no argument. + * - @e T_arg4 Argument type used in the definition of emit(). The default @p nil_ means no argument. + * - @e T_arg5 Argument type used in the definition of emit(). The default @p nil_ means no argument. + * - @e T_arg6 Argument type used in the definition of emit(). The default @p nil_ means no argument. + * - @e T_arg7 Argument type used in the definition of emit(). The default @p nil_ means no argument. * * To specify an accumulator type the nested class signal::accumulated can be used. * @@ -2472,9 +2472,9 @@ public: * * @ingroup signal */ -template +template class signal - : public signal7 + : public signal7 { public: /** Convenience wrapper for the numbered sigc::signal# templates. @@ -2536,7 +2536,7 @@ public: signal() {} signal(const signal& src) - : signal7(src) {} + : signal7(src) {} }; @@ -2547,7 +2547,7 @@ public: */ template class signal - : public signal0 + : public signal0 { public: @@ -2567,7 +2567,7 @@ public: signal() {} signal(const signal& src) - : signal0(src) {} + : signal0(src) {} }; /** Convenience wrapper for the numbered sigc::signal1 template. @@ -2577,7 +2577,7 @@ public: */ template class signal - : public signal1 + : public signal1 { public: @@ -2597,7 +2597,7 @@ public: signal() {} signal(const signal& src) - : signal1(src) {} + : signal1(src) {} }; /** Convenience wrapper for the numbered sigc::signal2 template. @@ -2607,7 +2607,7 @@ public: */ template class signal - : public signal2 + : public signal2 { public: @@ -2627,7 +2627,7 @@ public: signal() {} signal(const signal& src) - : signal2(src) {} + : signal2(src) {} }; /** Convenience wrapper for the numbered sigc::signal3 template. @@ -2637,7 +2637,7 @@ public: */ template class signal - : public signal3 + : public signal3 { public: @@ -2657,7 +2657,7 @@ public: signal() {} signal(const signal& src) - : signal3(src) {} + : signal3(src) {} }; /** Convenience wrapper for the numbered sigc::signal4 template. @@ -2667,7 +2667,7 @@ public: */ template class signal - : public signal4 + : public signal4 { public: @@ -2687,7 +2687,7 @@ public: signal() {} signal(const signal& src) - : signal4(src) {} + : signal4(src) {} }; /** Convenience wrapper for the numbered sigc::signal5 template. @@ -2697,7 +2697,7 @@ public: */ template class signal - : public signal5 + : public signal5 { public: @@ -2717,7 +2717,7 @@ public: signal() {} signal(const signal& src) - : signal5(src) {} + : signal5(src) {} }; /** Convenience wrapper for the numbered sigc::signal6 template. @@ -2727,7 +2727,7 @@ public: */ template class signal - : public signal6 + : public signal6 { public: @@ -2747,7 +2747,7 @@ public: signal() {} signal(const signal& src) - : signal6(src) {} + : signal6(src) {} }; @@ -2780,12 +2780,12 @@ namespace SigC { * * The following template arguments are used: * - @e T_return The desired return type for the emit() function (may be overridden by the accumulator). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. * * @deprecated Use the unnumbered template sigc::signal instead. * @ingroup compat */ -template +template class Signal0 : public ::sigc::signal0 { @@ -2830,12 +2830,12 @@ public: * The following template arguments are used: * - @e T_return The desired return type for the emit() function (may be overridden by the accumulator). * - @e T_arg1 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. * * @deprecated Use the unnumbered template sigc::signal instead. * @ingroup compat */ -template +template class Signal1 : public ::sigc::signal1 { @@ -2881,12 +2881,12 @@ public: * - @e T_return The desired return type for the emit() function (may be overridden by the accumulator). * - @e T_arg1 Argument type used in the definition of emit(). * - @e T_arg2 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. * * @deprecated Use the unnumbered template sigc::signal instead. * @ingroup compat */ -template +template class Signal2 : public ::sigc::signal2 { @@ -2933,12 +2933,12 @@ public: * - @e T_arg1 Argument type used in the definition of emit(). * - @e T_arg2 Argument type used in the definition of emit(). * - @e T_arg3 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. * * @deprecated Use the unnumbered template sigc::signal instead. * @ingroup compat */ -template +template class Signal3 : public ::sigc::signal3 { @@ -2986,12 +2986,12 @@ public: * - @e T_arg2 Argument type used in the definition of emit(). * - @e T_arg3 Argument type used in the definition of emit(). * - @e T_arg4 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. * * @deprecated Use the unnumbered template sigc::signal instead. * @ingroup compat */ -template +template class Signal4 : public ::sigc::signal4 { @@ -3040,12 +3040,12 @@ public: * - @e T_arg3 Argument type used in the definition of emit(). * - @e T_arg4 Argument type used in the definition of emit(). * - @e T_arg5 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. * * @deprecated Use the unnumbered template sigc::signal instead. * @ingroup compat */ -template +template class Signal5 : public ::sigc::signal5 { @@ -3095,12 +3095,12 @@ public: * - @e T_arg4 Argument type used in the definition of emit(). * - @e T_arg5 Argument type used in the definition of emit(). * - @e T_arg6 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. * * @deprecated Use the unnumbered template sigc::signal instead. * @ingroup compat */ -template +template class Signal6 : public ::sigc::signal6 { @@ -3151,12 +3151,12 @@ public: * - @e T_arg5 Argument type used in the definition of emit(). * - @e T_arg6 Argument type used in the definition of emit(). * - @e T_arg7 Argument type used in the definition of emit(). - * - @e T_accumulator The accumulator type used for emission. The default @p nil means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. + * - @e T_accumulator The accumulator type used for emission. The default @p nil_ means that no accumulator should be used. Signal emission returns the return value of the last slot invoked. * * @deprecated Use the unnumbered template sigc::signal instead. * @ingroup compat */ -template +template class Signal7 : public ::sigc::signal7 { diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index 1a9570c6a2..3906b53e36 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -129,6 +129,30 @@ GenericMidiControlProtocol::start_learning (Controllable* c) return false; } + MIDIControllables::iterator tmp; + for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ) { + tmp = i; + ++tmp; + if (&(*i)->get_controllable() == c) { + delete (*i); + controllables.erase (i); + } + i = tmp; + } + + MIDIPendingControllables::iterator ptmp; + for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) { + ptmp = i; + ++ptmp; + if (&((*i).first)->get_controllable() == c) { + (*i).second.disconnect(); + delete (*i).first; + pending_controllables.erase (i); + } + i = ptmp; + } + + MIDIControllable* mc = 0; for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) { @@ -144,11 +168,12 @@ GenericMidiControlProtocol::start_learning (Controllable* c) { Glib::Mutex::Lock lm (pending_lock); - std::pair result; - result = pending_controllables.insert (mc); - if (result.second) { - c->LearningFinished.connect (bind (mem_fun (*this, &GenericMidiControlProtocol::learning_stopped), mc)); - } + + std::pair element; + element.first = mc; + element.second = c->LearningFinished.connect (bind (mem_fun (*this, &GenericMidiControlProtocol::learning_stopped), mc)); + + pending_controllables.push_back (element); } mc->learn_about_external_control (); @@ -161,10 +186,18 @@ GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc) Glib::Mutex::Lock lm (pending_lock); Glib::Mutex::Lock lm2 (controllables_lock); - MIDIControllables::iterator i = find (pending_controllables.begin(), pending_controllables.end(), mc); + MIDIPendingControllables::iterator tmp; - if (i != pending_controllables.end()) { - pending_controllables.erase (i); + for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) { + tmp = i; + ++tmp; + + if ( (*i).first == mc) { + (*i).second.disconnect(); + pending_controllables.erase(i); + } + + i = tmp; } controllables.insert (mc); @@ -181,18 +214,13 @@ GenericMidiControlProtocol::stop_learning (Controllable* c) relevant MIDIControllable and remove it from the pending list. */ - for (MIDIControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) { - if (&(*i)->get_controllable() == c) { - (*i)->stop_learning (); - dptr = *i; - pending_controllables.erase (i); - break; - } - } + for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) { + if (&((*i).first)->get_controllable() == c) { + (*i).first->stop_learning (); + dptr = (*i).first; + (*i).second.disconnect(); - for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) { - if (&(*i)->get_controllable() == c) { - controllables.erase (i); + pending_controllables.erase (i); break; } } diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h index 6fba16bccd..95aeb77cdb 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h @@ -49,7 +49,9 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { typedef std::set MIDIControllables; MIDIControllables controllables; - MIDIControllables pending_controllables; + + typedef std::list > MIDIPendingControllables; + MIDIPendingControllables pending_controllables; Glib::Mutex controllables_lock; Glib::Mutex pending_lock; diff --git a/libs/surfaces/generic_midi/midicontrollable.cc b/libs/surfaces/generic_midi/midicontrollable.cc index 7f6f889df5..7bf730b0f5 100644 --- a/libs/surfaces/generic_midi/midicontrollable.cc +++ b/libs/surfaces/generic_midi/midicontrollable.cc @@ -35,7 +35,7 @@ MIDIControllable::MIDIControllable (Port& p, Controllable& c, bool is_bistate) : controllable (c), _port (p), bistate (is_bistate) { setting = false; - last_written = 0; // got a better idea ? + last_value = 0; // got a better idea ? control_type = none; _control_description = "MIDI Control: none"; control_additional = (byte) -1; @@ -142,6 +142,8 @@ MIDIControllable::midi_sense_note (Parser &p, EventTwoBytes *msg, bool is_on) controllable.set_value (is_on ? 1 : 0); } } + + last_value = (MIDI::byte) (controllable.get_value() * 127.0); // to prevent feedback fights } void @@ -157,6 +159,8 @@ MIDIControllable::midi_sense_controller (Parser &, EventTwoBytes *msg) controllable.set_value (0); } } + + last_value = (MIDI::byte) (controllable.get_value() * 127.0); // to prevent feedback fights } } @@ -167,6 +171,7 @@ MIDIControllable::midi_sense_program_change (Parser &p, byte msg) if (!bistate) { controllable.set_value (msg/127.0); + last_value = (MIDI::byte) (controllable.get_value() * 127.0); // to prevent feedback fights } } @@ -178,6 +183,7 @@ MIDIControllable::midi_sense_pitchbend (Parser &p, pitchbend_t pb) /* XXX gack - get rid of assumption about typeof pitchbend_t */ controllable.set_value ((pb/(float) SHRT_MAX)); + last_value = (MIDI::byte) (controllable.get_value() * 127.0); // to prevent feedback fights } void @@ -292,7 +298,7 @@ MIDIControllable::send_feedback () if (setting || !feedback || control_type == none) { return; } - + msg[0] = (control_type & 0xF0) | (control_channel & 0xF); msg[1] = control_additional; msg[2] = (byte) (controllable.get_value() * 127.0f); @@ -307,11 +313,11 @@ MIDIControllable::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool force) MIDI::byte gm = (MIDI::byte) (controllable.get_value() * 127.0); - if (gm != last_written) { + if (gm != last_value) { *buf++ = (0xF0 & control_type) | (0xF & control_channel); *buf++ = control_additional; /* controller number */ *buf++ = gm; - last_written = gm; + last_value = gm; bufsize -= 3; } } diff --git a/libs/surfaces/generic_midi/midicontrollable.h b/libs/surfaces/generic_midi/midicontrollable.h index 7e0243971c..4bac325feb 100644 --- a/libs/surfaces/generic_midi/midicontrollable.h +++ b/libs/surfaces/generic_midi/midicontrollable.h @@ -67,7 +67,7 @@ class MIDIControllable : public Stateful PBD::Controllable& controllable; MIDI::Port& _port; bool setting; - MIDI::byte last_written; + MIDI::byte last_value; bool bistate; int midi_msg_id; /* controller ID or note number */ sigc::connection midi_sense_connection[2]; diff --git a/libs/surfaces/mackie/bcf_surface.cc b/libs/surfaces/mackie/bcf_surface.cc index 2aaa70fc3e..45b5ad85fa 100644 --- a/libs/surfaces/mackie/bcf_surface.cc +++ b/libs/surfaces/mackie/bcf_surface.cc @@ -615,19 +615,12 @@ void Mackie::BcfSurface::init_controls() group->add( *control ); group = groups["modifiers"]; - control = new Button ( 71, 1, "option", *group ); - buttons[0x47] = control; + control = new Button ( 80, 1, "option", *group ); + buttons[0x50] = control; controls.push_back( control ); controls_by_name["option"] = control; group->add( *control ); - group = groups["modifiers"]; - control = new Button ( 72, 1, "control", *group ); - buttons[0x48] = control; - controls.push_back( control ); - controls_by_name["control"] = control; - group->add( *control ); - group = groups["modifiers"]; control = new Button ( 73, 1, "cmd_alt", *group ); buttons[0x49] = control; @@ -663,13 +656,6 @@ void Mackie::BcfSurface::init_controls() controls_by_name["snapshot"] = control; group->add( *control ); - group = groups["automation"]; - control = new Button ( 78, 1, "touch", *group ); - buttons[0x4e] = control; - controls.push_back( control ); - controls_by_name["touch"] = control; - group->add( *control ); - group = groups["functions"]; control = new Button ( 79, 1, "redo", *group ); buttons[0x4f] = control; @@ -678,8 +664,8 @@ void Mackie::BcfSurface::init_controls() group->add( *control ); group = groups["functions"]; - control = new Button ( 80, 1, "marker", *group ); - buttons[0x50] = control; + control = new Button ( 71, 1, "marker", *group ); + buttons[0x47] = control; controls.push_back( control ); controls_by_name["marker"] = control; group->add( *control ); @@ -706,15 +692,15 @@ void Mackie::BcfSurface::init_controls() group->add( *control ); group = groups["transport"]; - control = new Button ( 84, 1, "frm_left", *group ); - buttons[0x54] = control; + control = new Button ( 91, 1, "frm_left", *group ); + buttons[0x5b] = control; controls.push_back( control ); controls_by_name["frm_left"] = control; group->add( *control ); group = groups["transport"]; - control = new Button ( 85, 1, "frm_right", *group ); - buttons[0x55] = control; + control = new Button ( 92, 1, "frm_right", *group ); + buttons[0x5c] = control; controls.push_back( control ); controls_by_name["frm_right"] = control; group->add( *control ); @@ -727,15 +713,15 @@ void Mackie::BcfSurface::init_controls() group->add( *control ); group = groups["transport"]; - control = new Button ( 44, 1, "punch_in", *group ); - buttons[0x2c] = control; + control = new Button ( 72, 1, "punch_in", *group ); + buttons[0x48] = control; controls.push_back( control ); controls_by_name["punch_in"] = control; group->add( *control ); group = groups["transport"]; - control = new Button ( 43, 1, "punch_out", *group ); - buttons[0x2b] = control; + control = new Button ( 78, 1, "punch_out", *group ); + buttons[0x4e] = control; controls.push_back( control ); controls_by_name["punch_out"] = control; group->add( *control ); @@ -755,15 +741,15 @@ void Mackie::BcfSurface::init_controls() group->add( *control ); group = groups["transport"]; - control = new Button ( 91, 1, "rewind", *group ); - buttons[0x5b] = control; + control = new Button ( 44, 1, "rewind", *group ); + buttons[0x2c] = control; controls.push_back( control ); controls_by_name["rewind"] = control; group->add( *control ); group = groups["transport"]; - control = new Button ( 92, 1, "ffwd", *group ); - buttons[0x5c] = control; + control = new Button ( 43, 1, "ffwd", *group ); + buttons[0x2b] = control; controls.push_back( control ); controls_by_name["ffwd"] = control; group->add( *control ); @@ -1196,7 +1182,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b } break; - case 0x47: // option + case 0x50: // option switch ( bs ) { case press: ls = mbh.option_press( button ); break; case release: ls = mbh.option_release( button ); break; @@ -1204,14 +1190,6 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b } break; - case 0x48: // control - switch ( bs ) { - case press: ls = mbh.control_press( button ); break; - case release: ls = mbh.control_release( button ); break; - case neither: break; - } - break; - case 0x49: // cmd_alt switch ( bs ) { case press: ls = mbh.cmd_alt_press( button ); break; @@ -1252,14 +1230,6 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b } break; - case 0x4e: // touch - switch ( bs ) { - case press: ls = mbh.touch_press( button ); break; - case release: ls = mbh.touch_release( button ); break; - case neither: break; - } - break; - case 0x4f: // redo switch ( bs ) { case press: ls = mbh.redo_press( button ); break; @@ -1268,7 +1238,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b } break; - case 0x50: // marker + case 0x47: // marker switch ( bs ) { case press: ls = mbh.marker_press( button ); break; case release: ls = mbh.marker_release( button ); break; @@ -1300,7 +1270,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b } break; - case 0x54: // frm_left + case 0x5b: // frm_left switch ( bs ) { case press: ls = mbh.frm_left_press( button ); break; case release: ls = mbh.frm_left_release( button ); break; @@ -1308,7 +1278,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b } break; - case 0x55: // frm_right + case 0x5c: // frm_right switch ( bs ) { case press: ls = mbh.frm_right_press( button ); break; case release: ls = mbh.frm_right_release( button ); break; @@ -1324,7 +1294,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b } break; - case 0x2c: // punch_in + case 0x48: // punch_in switch ( bs ) { case press: ls = mbh.punch_in_press( button ); break; case release: ls = mbh.punch_in_release( button ); break; @@ -1332,7 +1302,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b } break; - case 0x2b: // punch_out + case 0x4e: // punch_out switch ( bs ) { case press: ls = mbh.punch_out_press( button ); break; case release: ls = mbh.punch_out_release( button ); break; @@ -1356,7 +1326,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b } break; - case 0x5b: // rewind + case 0x2c: // rewind switch ( bs ) { case press: ls = mbh.rewind_press( button ); break; case release: ls = mbh.rewind_release( button ); break; @@ -1364,7 +1334,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b } break; - case 0x5c: // ffwd + case 0x2b: // ffwd switch ( bs ) { case press: ls = mbh.ffwd_press( button ); break; case release: ls = mbh.ffwd_release( button ); break; diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index 81d249588e..b1c8ef2ff8 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -1038,7 +1039,7 @@ void MackieControlProtocol::poll_automation() // Transport Buttons ///////////////////////////////////// -LedState MackieControlProtocol::rewind_press( Button & button ) +LedState MackieControlProtocol::frm_left_press( Button & button ) { // can use first_mark_before/after as well Location * loc = session->locations()->first_location_before ( @@ -1048,12 +1049,12 @@ LedState MackieControlProtocol::rewind_press( Button & button ) return on; } -LedState MackieControlProtocol::rewind_release( Button & button ) +LedState MackieControlProtocol::frm_left_release( Button & button ) { return off; } -LedState MackieControlProtocol::ffwd_press( Button & button ) +LedState MackieControlProtocol::frm_right_press( Button & button ) { // can use first_mark_before/after as well Location * loc = session->locations()->first_location_after ( @@ -1063,7 +1064,7 @@ LedState MackieControlProtocol::ffwd_press( Button & button ) return on; } -LedState MackieControlProtocol::ffwd_release( Button & button ) +LedState MackieControlProtocol::frm_right_release( Button & button ) { return off; } @@ -1112,6 +1113,36 @@ LedState MackieControlProtocol::record_release( Button & button ) return off; } +LedState MackieControlProtocol::rewind_press( Button & button ) +{ + session->request_transport_speed( -2.0 ); + return on; +} + +LedState MackieControlProtocol::rewind_release( Button & button ) +{ + if ( _transport_previously_rolling ) + session->request_transport_speed( 1.0 ); + else + session->request_stop(); + return off; +} + +LedState MackieControlProtocol::ffwd_press( Button & button ) +{ + session->request_transport_speed( 2.0 ); + return on; +} + +LedState MackieControlProtocol::ffwd_release( Button & button ) +{ + if ( _transport_previously_rolling ) + session->request_transport_speed( 1.0 ); + else + session->request_stop(); + return off; +} + /////////////////////////////////////////// // Session signals /////////////////////////////////////////// @@ -1198,6 +1229,8 @@ void MackieControlProtocol::notify_transport_state_changed() update_global_button( "stop", !session->transport_rolling() ); update_global_button( "loop", session->get_play_loop() ); + _transport_previously_rolling = session->transport_rolling(); + // rec is special because it's tristate Button * rec = reinterpret_cast( surface().controls_by_name["record"] ); mcu_port().write( builder.build_led( *rec, record_release( *rec ) ) ); @@ -1376,3 +1409,27 @@ LedState MackieControlProtocol::channel_right_release( Button & button ) { return off; } + +///////////////////////////////////// +// Functions +///////////////////////////////////// +LedState MackieControlProtocol::marker_press( Button & button ) +{ + // cut'n'paste from LocationUI::add_new_location() + string markername; + nframes_t where = session->audible_frame(); + session->locations()->next_available_name(markername,"mcu"); + Location *location = new Location (where, where, markername, Location::IsMark); + session->begin_reversible_command (_("add marker")); + XMLNode &before = session->locations()->get_state(); + session->locations()->add (location, true); + XMLNode &after = session->locations()->get_state(); + session->add_command (new MementoCommand(*(session->locations()), &before, &after)); + session->commit_reversible_command (); + return on; +} + +LedState MackieControlProtocol::marker_release( Button & button ) +{ + return off; +} diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h index d71979b463..de44075262 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.h +++ b/libs/surfaces/mackie/mackie_control_protocol.h @@ -124,11 +124,11 @@ class MackieControlProtocol void update_global_button( const std::string & name, Mackie::LedState ); // transport button handler methods from MackieButtonHandler - virtual Mackie::LedState rewind_press( Mackie::Button & ); - virtual Mackie::LedState rewind_release( Mackie::Button & ); + virtual Mackie::LedState frm_left_press( Mackie::Button & ); + virtual Mackie::LedState frm_left_release( Mackie::Button & ); - virtual Mackie::LedState ffwd_press( Mackie::Button & ); - virtual Mackie::LedState ffwd_release( Mackie::Button & ); + virtual Mackie::LedState frm_right_press( Mackie::Button & ); + virtual Mackie::LedState frm_right_release( Mackie::Button & ); virtual Mackie::LedState stop_press( Mackie::Button & ); virtual Mackie::LedState stop_release( Mackie::Button & ); @@ -154,7 +154,13 @@ class MackieControlProtocol virtual Mackie::LedState end_press( Mackie::Button & ); virtual Mackie::LedState end_release( Mackie::Button & ); - // bank switching button handler methods from MackieButtonHandler + virtual Mackie::LedState rewind_press( Mackie::Button & button ); + virtual Mackie::LedState rewind_release( Mackie::Button & button ); + + virtual Mackie::LedState ffwd_press( Mackie::Button & button ); + virtual Mackie::LedState ffwd_release( Mackie::Button & button ); + + // bank switching button handler methods from MackieButtonHandler virtual Mackie::LedState left_press( Mackie::Button & ); virtual Mackie::LedState left_release( Mackie::Button & ); @@ -172,6 +178,10 @@ class MackieControlProtocol virtual Mackie::LedState global_solo_press( Mackie::Button & ); virtual Mackie::LedState global_solo_release( Mackie::Button & ); + + // function buttons + virtual Mackie::LedState marker_press( Mackie::Button & ); + virtual Mackie::LedState marker_release( Mackie::Button & ); protected: // create instances of MackiePort, depending on what's found in ardour.rc @@ -302,6 +312,8 @@ class MackieControlProtocol bool _polling; struct pollfd * pfd; int nfds; + + bool _transport_previously_rolling; }; #endif // ardour_mackie_control_protocol_h diff --git a/libs/surfaces/mackie/scripts/bcf-controls.csv b/libs/surfaces/mackie/scripts/bcf-controls.csv index 6a6d66f6ac..e22965a906 100644 --- a/libs/surfaces/mackie/scripts/bcf-controls.csv +++ b/libs/surfaces/mackie/scripts/bcf-controls.csv @@ -49,30 +49,28 @@ button,1,,F15,1,0,0x44 button,1,,F16,1,0,0x45 # turn on/off all solos button,1,,global_solo,1,0,0x27 -button,1,modifiers,option,1,0,0x47 -button,1,modifiers,control,1,0,0x48 +button,1,modifiers,option,1,0,0x50 button,1,modifiers,cmd_alt,1,0,0x49 button,1,automation,on,1,1,0x4a button,1,automation,rec_ready,1,1,0x4b button,1,functions,undo,1,1,0x4c button,1,automation,snapshot,1,1,0x4d -button,1,automation,touch,1,1,0x4e button,1,functions,redo,1,1,0x4f -button,1,functions,marker,1,1,0x50 +button,1,functions,marker,1,1,0x47 button,1,functions,enter,1,1,0x51 button,1,functions,cancel,1,0,0x52 button,1,functions,mixer,1,0,0x53 -button,1,transport,frm_left,1,1,0x54 -button,1,transport,frm_right,1,1,0x55 + +# transport buttons +button,1,transport,frm_left,1,1,0x5b +button,1,transport,frm_right,1,1,0x5c button,1,transport,loop,1,1,0x46 -button,1,transport,punch_in,1,1,0x2c -button,1,transport,punch_out,1,1,0x2b +button,1,transport,punch_in,1,1,0x48 +button,1,transport,punch_out,1,1,0x4e button,1,transport,home,1,1,0x2a button,1,transport,end,1,1,0x29 - -# transport buttons -button,1,transport,"rewind",1,1,0x5b -button,1,transport,"ffwd",1,1,0x5c +button,1,transport,"rewind",1,1,0x2c +button,1,transport,"ffwd",1,1,0x2b button,1,transport,"stop",1,1,0x5d button,1,transport,"play",1,1,0x5e button,1,transport,"record",1,1,0x1f -- cgit v1.2.3