diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2013-07-31 20:11:15 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2013-07-31 20:11:15 -0400 |
commit | 6a436fd826d1c9d88b60287696cc0836ccce35aa (patch) | |
tree | 460a08b4d46359b6b168ece26f592c75fc2fe41f /libs | |
parent | bb59def1ca8a21f915cf636dd1e54957df981656 (diff) | |
parent | 4dc74ae2ea13d2e5a8b481961d507df1ff98df97 (diff) |
fix merge conflict from master
Diffstat (limited to 'libs')
41 files changed, 1317 insertions, 234 deletions
diff --git a/libs/ardour/ardour/iec1ppmdsp.h b/libs/ardour/ardour/iec1ppmdsp.h new file mode 100644 index 0000000000..58dea97555 --- /dev/null +++ b/libs/ardour/ardour/iec1ppmdsp.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> + Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __IEC1PPMDSP_H +#define __IEC1PPMDSP_H + + +class Iec1ppmdsp +{ +public: + + Iec1ppmdsp (void); + ~Iec1ppmdsp (void); + + void process (float *p, int n); + float read (void); + void reset (); + + static void init (float fsamp); + +private: + + float _z1; // filter state + float _z2; // filter state + float _m; // max value since last read() + bool _res; // flag to reset m + + static float _w1; // attack filter coefficient + static float _w2; // attack filter coefficient + static float _w3; // release filter coefficient + static float _g; // gain factor +}; + + +#endif diff --git a/libs/ardour/ardour/iec2ppmdsp.h b/libs/ardour/ardour/iec2ppmdsp.h new file mode 100644 index 0000000000..3574a8bd3f --- /dev/null +++ b/libs/ardour/ardour/iec2ppmdsp.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> + Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __IEC2PPMDSP_H +#define __IEC2PPMDSP_H + + +class Iec2ppmdsp +{ +public: + + Iec2ppmdsp (void); + ~Iec2ppmdsp (void); + + void process (float *p, int n); + float read (void); + void reset (); + + static void init (float fsamp); + +private: + + float _z1; // filter state + float _z2; // filter state + float _m; // max value since last read() + bool _res; // flag to reset m + + static float _w1; // attack filter coefficient + static float _w2; // attack filter coefficient + static float _w3; // release filter coefficient + static float _g; // gain factor +}; + + +#endif diff --git a/libs/ardour/kmeterdsp.h b/libs/ardour/ardour/kmeterdsp.h index 9c2309e09c..eca3c76695 100644 --- a/libs/ardour/kmeterdsp.h +++ b/libs/ardour/ardour/kmeterdsp.h @@ -1,6 +1,6 @@ /* Copyright (C) 2008-2011 Fons Adriaensen <fons@linuxaudio.org> - Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org> + Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,9 +29,10 @@ public: void process (float *p, int n); float read (); - static void init (int fsamp); void reset (); + static void init (int fsamp); + private: float _z1; // filter state diff --git a/libs/ardour/ardour/meter.h b/libs/ardour/ardour/meter.h index 31ebc76179..a4ad8ecff4 100644 --- a/libs/ardour/ardour/meter.h +++ b/libs/ardour/ardour/meter.h @@ -23,7 +23,11 @@ #include "ardour/types.h" #include "ardour/processor.h" #include "pbd/fastlog.h" -#include "kmeterdsp.h" + +#include "ardour/kmeterdsp.h" +#include "ardour/iec1ppmdsp.h" +#include "ardour/iec2ppmdsp.h" +#include "ardour/vumeterdsp.h" namespace ARDOUR { @@ -71,6 +75,9 @@ public: /** Compute peaks */ void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool); + void activate () { } + void deactivate () { } + ChanCount input_streams () const { return current_meters; } ChanCount output_streams () const { return current_meters; } @@ -104,7 +111,11 @@ private: std::vector<float> _visible_peak_power; std::vector<float> _max_peak_signal; std::vector<float> _max_peak_power; + std::vector<Kmeterdsp *> _kmeter; + std::vector<Iec1ppmdsp *> _iec1meter; + std::vector<Iec2ppmdsp *> _iec2meter; + std::vector<Vumeterdsp *> _vumeter; MeterType _meter_type; }; diff --git a/libs/ardour/ardour/process_thread.h b/libs/ardour/ardour/process_thread.h index 0c197e9fb2..f96595fbbf 100644 --- a/libs/ardour/ardour/process_thread.h +++ b/libs/ardour/ardour/process_thread.h @@ -45,7 +45,8 @@ public: */ static BufferSet& get_silent_buffers (ChanCount count = ChanCount::ZERO); - static BufferSet& get_scratch_buffers (ChanCount count = ChanCount::ZERO); + static BufferSet& get_scratch_buffers (ChanCount count = ChanCount::ZERO, bool silence = false); + static BufferSet& get_route_buffers (ChanCount count = ChanCount::ZERO, bool silence = false); static BufferSet& get_mix_buffers (ChanCount count = ChanCount::ZERO); static gain_t* gain_automation_buffer (); static gain_t* send_gain_automation_buffer (); diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h index f87781c8a9..a1008df6a6 100644 --- a/libs/ardour/ardour/rc_configuration_vars.h +++ b/libs/ardour/ardour/rc_configuration_vars.h @@ -148,9 +148,12 @@ CONFIG_VARIABLE (bool, super_rapid_clock_update, "super-rapid-clock-update", fal /* metering */ CONFIG_VARIABLE (float, meter_hold, "meter-hold", 100.0f) -CONFIG_VARIABLE (float, meter_falloff, "meter-falloff", 32.0f) +CONFIG_VARIABLE (float, meter_falloff, "meter-falloff", 13.3f) +CONFIG_VARIABLE (VUMeterStandard, meter_vu_standard, "meter-vu-standard", MeteringVUstandard) CONFIG_VARIABLE (MeterLineUp, meter_line_up_level, "meter-line-up-level", MeteringLineUp18) +CONFIG_VARIABLE (MeterLineUp, meter_line_up_din, "meter-line-up-din", MeteringLineUp15) CONFIG_VARIABLE (float, meter_peak, "meter-peak", 0.0f) +CONFIG_VARIABLE (bool, meter_style_led, "meter-style-led", true) /* miscellany */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 85866f99a5..1044d9a2dc 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -200,7 +200,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void process (pframes_t nframes); BufferSet& get_silent_buffers (ChanCount count = ChanCount::ZERO); - BufferSet& get_scratch_buffers (ChanCount count = ChanCount::ZERO); + BufferSet& get_scratch_buffers (ChanCount count = ChanCount::ZERO, bool silence = true ); + BufferSet& get_route_buffers (ChanCount count = ChanCount::ZERO, bool silence = true); BufferSet& get_mix_buffers (ChanCount count = ChanCount::ZERO); bool have_rec_enabled_track () const; @@ -813,6 +814,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void send_mmc_locate (framepos_t); int send_full_time_code (framepos_t); + void send_song_position_pointer (framepos_t); bool step_editing() const { return (_step_editors > 0); } diff --git a/libs/ardour/ardour/session_configuration_vars.h b/libs/ardour/ardour/session_configuration_vars.h index ebeebbe1fd..5e93c01b79 100644 --- a/libs/ardour/ardour/session_configuration_vars.h +++ b/libs/ardour/ardour/session_configuration_vars.h @@ -64,3 +64,4 @@ CONFIG_VARIABLE (bool, show_rec_on_meterbridge, "show-rec-on-meterbridge", true) CONFIG_VARIABLE (bool, show_mute_on_meterbridge, "show-mute-on-meterbridge", false) CONFIG_VARIABLE (bool, show_solo_on_meterbridge, "show-solo-on-meterbridge", false) CONFIG_VARIABLE (bool, show_name_on_meterbridge, "show-name-on-meterbridge", true) +CONFIG_VARIABLE (uint32_t, meterbridge_label_height, "meterbridge-label-height", 0) diff --git a/libs/ardour/ardour/thread_buffers.h b/libs/ardour/ardour/thread_buffers.h index cd0b76511a..9d92454887 100644 --- a/libs/ardour/ardour/thread_buffers.h +++ b/libs/ardour/ardour/thread_buffers.h @@ -38,6 +38,7 @@ public: BufferSet* silent_buffers; BufferSet* scratch_buffers; + BufferSet* route_buffers; BufferSet* mix_buffers; gain_t* gain_automation_buffer; gain_t* send_gain_automation_buffer; diff --git a/libs/ardour/ardour/ticker.h b/libs/ardour/ardour/ticker.h index 23d2ef2fe6..da728a5d54 100644 --- a/libs/ardour/ardour/ticker.h +++ b/libs/ardour/ardour/ticker.h @@ -42,7 +42,7 @@ class MidiClockTicker : public SessionHandlePtr, boost::noncopyable { public: MidiClockTicker (); - virtual ~MidiClockTicker() {}; + virtual ~MidiClockTicker() {} void tick (const framepos_t& transport_frames); @@ -77,6 +77,7 @@ private: void send_start_event (pframes_t offset); void send_continue_event (pframes_t offset); void send_stop_event (pframes_t offset); + void send_position_event (framepos_t transport_position, pframes_t offset); }; } diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 05d6d0b27d..2115149872 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -178,10 +178,17 @@ namespace ARDOUR { }; enum MeterType { - MeterMaxSignal = 0x01, - MeterMaxPeak = 0x02, - MeterPeak = 0x04, - MeterKrms = 0x08 + MeterMaxSignal = 0x001, + MeterMaxPeak = 0x002, + MeterPeak = 0x004, + MeterKrms = 0x008, + MeterK20 = 0x010, + MeterK14 = 0x020, + MeterIEC1DIN = 0x040, + MeterIEC1NOR = 0x080, + MeterIEC2BBC = 0x100, + MeterIEC2EBU = 0x200, + MeterVU = 0x400 }; enum TrackMode { @@ -376,6 +383,13 @@ namespace ARDOUR { MeteringRoute ///< meter what is going through the route }; + enum VUMeterStandard { + MeteringVUfrench, // 0VU = -2dBu + MeteringVUamerican, // 0VU = 0dBu + MeteringVUstandard, // 0VU = +4dBu + MeteringVUeight // 0VU = +8dBu + }; + enum MeterLineUp { MeteringLineUp24, MeteringLineUp20, @@ -583,6 +597,7 @@ std::istream& operator>>(std::istream& o, ARDOUR::HeaderFormat& sf); std::istream& operator>>(std::istream& o, ARDOUR::AutoConnectOption& sf); std::istream& operator>>(std::istream& o, ARDOUR::EditMode& sf); std::istream& operator>>(std::istream& o, ARDOUR::MonitorModel& sf); +std::istream& operator>>(std::istream& o, ARDOUR::VUMeterStandard& sf); std::istream& operator>>(std::istream& o, ARDOUR::MeterLineUp& sf); std::istream& operator>>(std::istream& o, ARDOUR::PFLPosition& sf); std::istream& operator>>(std::istream& o, ARDOUR::AFLPosition& sf); @@ -605,6 +620,7 @@ std::ostream& operator<<(std::ostream& o, const ARDOUR::HeaderFormat& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::AutoConnectOption& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::EditMode& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::MonitorModel& sf); +std::ostream& operator<<(std::ostream& o, const ARDOUR::VUMeterStandard& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::MeterLineUp& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::PFLPosition& sf); std::ostream& operator<<(std::ostream& o, const ARDOUR::AFLPosition& sf); diff --git a/libs/ardour/ardour/vumeterdsp.h b/libs/ardour/ardour/vumeterdsp.h new file mode 100644 index 0000000000..86487e8e8e --- /dev/null +++ b/libs/ardour/ardour/vumeterdsp.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> + Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __VUMETERDSP_H +#define __VUMETERDSP_H + + +class Vumeterdsp +{ +public: + + Vumeterdsp (void); + ~Vumeterdsp (void); + + void process (float *p, int n); + float read (void); + void reset (); + + static void init (float fsamp); + +private: + + float _z1; // filter state + float _z2; // filter state + float _m; // max value since last read() + bool _res; // flag to reset m + + static float _w; // lowpass filter coefficient + static float _g; // gain factor +}; + + +#endif diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 4b33bbd4c6..6de833aeb4 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -353,7 +353,7 @@ AudioTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_fram _silent = false; _amp->apply_gain_automation(false); - BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers ()); + BufferSet& bufs = _session.get_route_buffers (n_process_buffers ()); fill_buffers_with_input (bufs, _input, nframes); diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index 9c86b87415..3636ebf941 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -1824,7 +1824,6 @@ AUPlugin::do_save_preset (string preset_name) CFPropertyListRef propertyList; vector<Glib::ustring> v; Glib::ustring user_preset_path; - bool ret = true; std::string m = maker(); std::string n = name(); @@ -1843,12 +1842,12 @@ AUPlugin::do_save_preset (string preset_name) if (g_mkdir_with_parents (user_preset_path.c_str(), 0775) < 0) { error << string_compose (_("Cannot create user plugin presets folder (%1)"), user_preset_path) << endmsg; - return false; + return string(); } DEBUG_TRACE (DEBUG::AudioUnits, "get current preset\n"); if (unit->GetAUPreset (propertyList) != noErr) { - return false; + return string(); } // add the actual preset name */ @@ -1863,7 +1862,7 @@ AUPlugin::do_save_preset (string preset_name) if (save_property_list (propertyList, user_preset_path)) { error << string_compose (_("Saving plugin state to %1 failed"), user_preset_path) << endmsg; - ret = false; + return string(); } CFRelease(propertyList); diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc index e224186bd2..65540d4e3d 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -189,7 +189,7 @@ AudioSource::touch_peakfile () struct utimbuf tbuf; tbuf.actime = statbuf.st_atime; - tbuf.modtime = time ((time_t) 0); + tbuf.modtime = time ((time_t*) 0); g_utime (peakpath.c_str(), &tbuf); } diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc index 495ff0b4c3..ab181d2956 100644 --- a/libs/ardour/enums.cc +++ b/libs/ardour/enums.cc @@ -62,6 +62,7 @@ setup_enum_writer () ColorMode _ColorMode; MeterFalloff _MeterFalloff; MeterHold _MeterHold; + VUMeterStandard _VUMeterStandard; MeterLineUp _MeterLineUp; EditMode _EditMode; RegionPoint _RegionPoint; @@ -177,6 +178,13 @@ setup_enum_writer () REGISTER_ENUM (MeterMaxPeak); REGISTER_ENUM (MeterPeak); REGISTER_ENUM (MeterKrms); + REGISTER_ENUM (MeterK20); + REGISTER_ENUM (MeterK14); + REGISTER_ENUM (MeterIEC1DIN); + REGISTER_ENUM (MeterIEC1NOR); + REGISTER_ENUM (MeterIEC2BBC); + REGISTER_ENUM (MeterIEC2EBU); + REGISTER_ENUM (MeterVU); REGISTER (_MeterType); REGISTER_ENUM (Normal); @@ -215,6 +223,12 @@ setup_enum_writer () REGISTER_ENUM (MeterHoldLong); REGISTER (_MeterHold); + REGISTER_ENUM (MeteringVUfrench); + REGISTER_ENUM (MeteringVUamerican); + REGISTER_ENUM (MeteringVUstandard); + REGISTER_ENUM (MeteringVUeight); + REGISTER (_VUMeterStandard); + REGISTER_ENUM (MeteringLineUp24); REGISTER_ENUM (MeteringLineUp20); REGISTER_ENUM (MeteringLineUp18); @@ -668,6 +682,20 @@ std::ostream& operator<<(std::ostream& o, const MonitorModel& var) return o << s; } +std::istream& operator>>(std::istream& o, VUMeterStandard& var) +{ + std::string s; + o >> s; + var = (VUMeterStandard) string_2_enum (s, var); + return o; +} + +std::ostream& operator<<(std::ostream& o, const VUMeterStandard& var) +{ + std::string s = enum_2_string (var); + return o << s; +} + std::istream& operator>>(std::istream& o, MeterLineUp& var) { std::string s; diff --git a/libs/ardour/iec1ppmdsp.cc b/libs/ardour/iec1ppmdsp.cc new file mode 100644 index 0000000000..bed825048f --- /dev/null +++ b/libs/ardour/iec1ppmdsp.cc @@ -0,0 +1,100 @@ +/* + Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> + Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <math.h> +#include "ardour/iec1ppmdsp.h" + + +float Iec1ppmdsp::_w1; +float Iec1ppmdsp::_w2; +float Iec1ppmdsp::_w3; +float Iec1ppmdsp::_g; + + +Iec1ppmdsp::Iec1ppmdsp (void) : + _z1 (0), + _z2 (0), + _m (0), + _res (true) +{ +} + + +Iec1ppmdsp::~Iec1ppmdsp (void) +{ +} + + +void Iec1ppmdsp::process (float *p, int n) +{ + float z1, z2, m, t; + + z1 = _z1; + z2 = _z2; + m = _res ? 0: _m; + _res = false; + + n /= 4; + while (n--) + { + z1 *= _w3; + z2 *= _w3; + t = fabsf (*p++); + if (t > z1) z1 += _w1 * (t - z1); + if (t > z2) z2 += _w2 * (t - z2); + t = fabsf (*p++); + if (t > z1) z1 += _w1 * (t - z1); + if (t > z2) z2 += _w2 * (t - z2); + t = fabsf (*p++); + if (t > z1) z1 += _w1 * (t - z1); + if (t > z2) z2 += _w2 * (t - z2); + t = fabsf (*p++); + if (t > z1) z1 += _w1 * (t - z1); + if (t > z2) z2 += _w2 * (t - z2); + t = z1 + z2; + if (t > m) m = t; + } + + _z1 = z1 + 1e-10f; + _z2 = z2 + 1e-10f; + _m = m; +} + + +float Iec1ppmdsp::read (void) +{ + _res = true; + return _g * _m; +} + +void Iec1ppmdsp::reset () +{ + _z1 = _z2 = _m = .0f; + _res = true; +} + +void Iec1ppmdsp::init (float fsamp) +{ + _w1 = 450.0f / fsamp; + _w2 = 1300.0f / fsamp; + _w3 = 1.0f - 5.4f / fsamp; + _g = 0.5108f; +} + +/* vi:set ts=8 sts=8 sw=4: */ diff --git a/libs/ardour/iec2ppmdsp.cc b/libs/ardour/iec2ppmdsp.cc new file mode 100644 index 0000000000..76862cccd2 --- /dev/null +++ b/libs/ardour/iec2ppmdsp.cc @@ -0,0 +1,100 @@ +/* + Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> + Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <math.h> +#include "ardour/iec2ppmdsp.h" + + +float Iec2ppmdsp::_w1; +float Iec2ppmdsp::_w2; +float Iec2ppmdsp::_w3; +float Iec2ppmdsp::_g; + + +Iec2ppmdsp::Iec2ppmdsp (void) : + _z1 (0), + _z2 (0), + _m (0), + _res (true) +{ +} + + +Iec2ppmdsp::~Iec2ppmdsp (void) +{ +} + + +void Iec2ppmdsp::process (float *p, int n) +{ + float z1, z2, m, t; + + z1 = _z1; + z2 = _z2; + m = _res ? 0: _m; + _res = false; + + n /= 4; + while (n--) + { + z1 *= _w3; + z2 *= _w3; + t = fabsf (*p++); + if (t > z1) z1 += _w1 * (t - z1); + if (t > z2) z2 += _w2 * (t - z2); + t = fabsf (*p++); + if (t > z1) z1 += _w1 * (t - z1); + if (t > z2) z2 += _w2 * (t - z2); + t = fabsf (*p++); + if (t > z1) z1 += _w1 * (t - z1); + if (t > z2) z2 += _w2 * (t - z2); + t = fabsf (*p++); + if (t > z1) z1 += _w1 * (t - z1); + if (t > z2) z2 += _w2 * (t - z2); + t = z1 + z2; + if (t > m) m = t; + } + + _z1 = z1 + 1e-10f; + _z2 = z2 + 1e-10f; + _m = m; +} + + +float Iec2ppmdsp::read (void) +{ + _res = true; + return _g * _m; +} + +void Iec2ppmdsp::reset () +{ + _z1 = _z2 = _m = .0f; + _res = true; +} + +void Iec2ppmdsp::init (float fsamp) +{ + _w1 = 200.0f / fsamp; + _w2 = 860.0f / fsamp; + _w3 = 1.0f - 4.0f / fsamp; + _g = 0.5141f; +} + +/* vi:set ts=8 sts=8 sw=4: */ diff --git a/libs/ardour/kmeterdsp.cc b/libs/ardour/kmeterdsp.cc index afd0f71719..181378cf76 100644 --- a/libs/ardour/kmeterdsp.cc +++ b/libs/ardour/kmeterdsp.cc @@ -1,6 +1,6 @@ /* Copyright (C) 2008-2011 Fons Adriaensen <fons@linuxaudio.org> - Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org> + Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,12 +17,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - #include <math.h> -#include "kmeterdsp.h" +#include "ardour/kmeterdsp.h" + float Kmeterdsp::_omega; + Kmeterdsp::Kmeterdsp (void) : _z1 (0), _z2 (0), @@ -36,6 +37,10 @@ Kmeterdsp::~Kmeterdsp (void) { } +void Kmeterdsp::init (int fsamp) +{ + _omega = 9.72f / fsamp; // ballistic filter coefficient +} void Kmeterdsp::process (float *p, int n) { @@ -44,45 +49,37 @@ void Kmeterdsp::process (float *p, int n) // p : pointer to sample buffer // n : number of samples to process - float s, t, z1, z2; + float s, z1, z2; // Get filter state. z1 = _z1; z2 = _z2; - // Process n samples. Find digital peak value for this - // period and perform filtering. The second filter is - // evaluated only every 4th sample - this is just an - // optimisation. - t = 0; + // Perform filtering. The second filter is evaluated + // only every 4th sample - this is just an optimisation. n /= 4; // Loop is unrolled by 4. while (n--) { s = *p++; s *= s; - if (t < s) t = s; // Update digital peak. z1 += _omega * (s - z1); // Update first filter. s = *p++; s *= s; - if (t < s) t = s; // Update digital peak. z1 += _omega * (s - z1); // Update first filter. s = *p++; s *= s; - if (t < s) t = s; // Update digital peak. z1 += _omega * (s - z1); // Update first filter. s = *p++; s *= s; - if (t < s) t = s; // Update digital peak. z1 += _omega * (s - z1); // Update first filter. z2 += 4 * _omega * (z1 - z2); // Update second filter. } - t = sqrtf (t); // Save filter state. The added constants avoid denormals. _z1 = z1 + 1e-20f; _z2 = z2 + 1e-20f; - s = sqrtf (2 * z2); + s = sqrtf (2.0f * z2); if (_flag) // Display thread has read the rms value. { @@ -96,7 +93,6 @@ void Kmeterdsp::process (float *p, int n) } } - /* Returns highest _rms value since last call */ float Kmeterdsp::read () { @@ -105,15 +101,10 @@ float Kmeterdsp::read () return rv; } -void Kmeterdsp::init (int fsamp) -{ - _omega = 9.72f / fsamp; // ballistic filter coefficient -} - void Kmeterdsp::reset () { - _z1 = _z2 = _rms = 0.0; - _flag=false; + _z1 = _z2 = _rms = .0f; + _flag = false; } -/* vi:set ts=8 sts=8 sw=8: */ +/* vi:set ts=8 sts=8 sw=4: */ diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index 82bf97264f..38d0d8b944 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -574,7 +574,7 @@ LadspaPlugin::connect_and_run (BufferSet& bufs, cycles_t then = get_cycles (); BufferSet& silent_bufs = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1)); - BufferSet& scratch_bufs = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1)); + BufferSet& scratch_bufs = _session.get_scratch_buffers(ChanCount(DataType::AUDIO, 1)); uint32_t audio_in_index = 0; uint32_t audio_out_index = 0; diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 2f46db75a6..d44f9351c4 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -1652,7 +1652,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs, } } else if (!valid) { // Nothing we understand or care about, connect to scratch - _ev_buffers[port_index] = silent_bufs.get_lv2_midi( + _ev_buffers[port_index] = scratch_bufs.get_lv2_midi( (flags & PORT_INPUT), 0, (flags & PORT_EVENT)); } buf = lv2_evbuf_get_buffer(_ev_buffers[port_index]); diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc index 3d1ab61bbc..490b75dcb2 100644 --- a/libs/ardour/meter.cc +++ b/libs/ardour/meter.cc @@ -40,13 +40,24 @@ PeakMeter::PeakMeter (Session& s, const std::string& name) : Processor (s, string_compose ("meter-%1", name)) { Kmeterdsp::init(s.nominal_frame_rate()); + Iec1ppmdsp::init(s.nominal_frame_rate()); + Iec2ppmdsp::init(s.nominal_frame_rate()); + Vumeterdsp::init(s.nominal_frame_rate()); + _pending_active = true; + _meter_type = MeterPeak; } PeakMeter::~PeakMeter () { while (_kmeter.size() > 0) { delete (_kmeter.back()); + delete (_iec1meter.back()); + delete (_iec2meter.back()); + delete (_vumeter.back()); _kmeter.pop_back(); + _iec1meter.pop_back(); + _iec2meter.pop_back(); + _vumeter.pop_back(); } } @@ -97,9 +108,18 @@ PeakMeter::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_fr // Meter audio in to the rest of the peaks for (uint32_t i = 0; i < n_audio; ++i, ++n) { _peak_signal[n] = compute_peak (bufs.get_audio(i).data(), nframes, _peak_signal[n]); - if (_meter_type & MeterKrms) { + if (_meter_type & (MeterKrms | MeterK20 | MeterK14)) { _kmeter[i]->process(bufs.get_audio(i).data(), nframes); } + if (_meter_type & (MeterIEC1DIN | MeterIEC1NOR)) { + _iec1meter[i]->process(bufs.get_audio(i).data(), nframes); + } + if (_meter_type & (MeterIEC2BBC | MeterIEC2EBU)) { + _iec2meter[i]->process(bufs.get_audio(i).data(), nframes); + } + if (_meter_type & MeterVU) { + _vumeter[i]->process(bufs.get_audio(i).data(), nframes); + } } // Zero any excess peaks @@ -119,6 +139,9 @@ PeakMeter::reset () for (size_t n = 0; n < _kmeter.size(); ++n) { _kmeter[n]->reset(); + _iec1meter[n]->reset(); + _iec2meter[n]->reset(); + _vumeter[n]->reset(); } } @@ -129,6 +152,16 @@ PeakMeter::reset_max () _max_peak_power[i] = -INFINITY; _max_peak_signal[i] = 0; } + + const size_t n_midi = min (_peak_signal.size(), (size_t) current_meters.n_midi()); + + for (size_t n = 0; n < _peak_signal.size(); ++n) { + if (n < n_midi) { + _visible_peak_power[n] = 0; + } else { + _visible_peak_power[n] = -INFINITY; + } + } } bool @@ -155,24 +188,20 @@ PeakMeter::configure_io (ChanCount in, ChanCount out) void PeakMeter::reflect_inputs (const ChanCount& in) { - current_meters = in; - - const size_t limit = min (_peak_signal.size(), (size_t) current_meters.n_total ()); - const size_t n_midi = min (_peak_signal.size(), (size_t) current_meters.n_midi()); - const size_t n_audio = current_meters.n_audio(); - - for (size_t n = 0; n < limit; ++n) { - if (n < n_midi) { - _visible_peak_power[n] = 0; - } else { - _visible_peak_power[n] = -INFINITY; + for (uint32_t i = in.n_total(); i < current_meters.n_total(); ++i) { + if (i < _peak_signal.size()) { + _peak_signal[i] = 0.0f; } } - - for (size_t n = 0; n < n_audio; ++n) { - _kmeter[n]->reset(); + for (uint32_t i = in.n_audio(); i < current_meters.n_audio(); ++i) { + if (i >= _kmeter.size()) continue; + _kmeter[i]->reset(); + _iec1meter[i]->reset(); + _iec2meter[i]->reset(); + _vumeter[i]->reset(); } + current_meters = in; reset_max(); ConfigurationChanged (in, in); /* EMIT SIGNAL */ @@ -206,12 +235,27 @@ PeakMeter::reset_max_channels (const ChanCount& chn) /* alloc/free other audio-only meter types. */ while (_kmeter.size() > n_audio) { delete (_kmeter.back()); + delete (_iec1meter.back()); + delete (_iec2meter.back()); + delete (_vumeter.back()); _kmeter.pop_back(); + _iec1meter.pop_back(); + _iec2meter.pop_back(); + _vumeter.pop_back(); } while (_kmeter.size() < n_audio) { _kmeter.push_back(new Kmeterdsp()); + _iec1meter.push_back(new Iec1ppmdsp()); + _iec2meter.push_back(new Iec2ppmdsp()); + _vumeter.push_back(new Vumeterdsp()); } assert(_kmeter.size() == n_audio); + assert(_iec1meter.size() == n_audio); + assert(_iec2meter.size() == n_audio); + assert(_vumeter.size() == n_audio); + + reset(); + reset_max(); } /** To be driven by the Meter signal from IO. @@ -226,11 +270,26 @@ PeakMeter::meter () return; } - assert(_visible_peak_power.size() == _peak_signal.size()); + // TODO block this thread while PeakMeter::reset_max_channels() is + // reallocating channels. + // (may happen with Session > New: old session not yet closed, + // meter-thread still active while new one is initializing and + // maybe on other occasions, too) + if ( (_visible_peak_power.size() != _peak_signal.size()) + || (_max_peak_power.size() != _peak_signal.size()) + || (_max_peak_signal.size() != _peak_signal.size()) + ) { + return; + } const size_t limit = min (_peak_signal.size(), (size_t) current_meters.n_total ()); const size_t n_midi = min (_peak_signal.size(), (size_t) current_meters.n_midi()); + /* 0.01f ^= 100 Hz update rate */ + const float midi_meter_falloff = Config->get_meter_falloff() * 0.01f; + /* kmeters: 24dB / 2 sec */ + const float audio_meter_falloff = (_meter_type & (MeterK20 | MeterK14)) ? 0.12f : midi_meter_falloff; + for (size_t n = 0; n < limit; ++n) { /* grab peak since last read */ @@ -241,11 +300,11 @@ PeakMeter::meter () if (n < n_midi) { _max_peak_power[n] = -INFINITY; // std::max (new_peak, _max_peak_power[n]); // XXX _max_peak_signal[n] = 0; - if (Config->get_meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) { + if (midi_meter_falloff == 0.0f || new_peak > _visible_peak_power[n]) { ; } else { - /* empirical WRT to falloff times , 0.01f ^= 100 Hz update rate */ - new_peak = _visible_peak_power[n] - sqrt(_visible_peak_power[n] * Config->get_meter_falloff() * 0.01f * 0.0002f); + /* empirical algorithm WRT to audio falloff times */ + new_peak = _visible_peak_power[n] - sqrt(_visible_peak_power[n] * midi_meter_falloff * 0.0002f); if (new_peak < (1.0 / 512.0)) new_peak = 0; } _visible_peak_power[n] = new_peak; @@ -268,47 +327,72 @@ PeakMeter::meter () _max_peak_power[n] = std::max (new_peak, _max_peak_power[n]); - if (Config->get_meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) { + if (audio_meter_falloff == 0.0f || new_peak > _visible_peak_power[n]) { _visible_peak_power[n] = new_peak; } else { // do falloff - new_peak = _visible_peak_power[n] - (Config->get_meter_falloff() * 0.01f); - _visible_peak_power[n] = std::max (new_peak, (float)-INFINITY); + new_peak = _visible_peak_power[n] - (audio_meter_falloff); + _visible_peak_power[n] = std::max (new_peak, -INFINITY); } } } +#define CHECKSIZE(MTR) (n < MTR.size() + n_midi && n >= n_midi) + float PeakMeter::meter_level(uint32_t n, MeterType type) { switch (type) { case MeterKrms: + case MeterK20: + case MeterK14: + { + const uint32_t n_midi = current_meters.n_midi(); + if (CHECKSIZE(_kmeter)) { + return accurate_coefficient_to_dB (_kmeter[n - n_midi]->read()); + } + } + break; + case MeterIEC1DIN: + case MeterIEC1NOR: + { + const uint32_t n_midi = current_meters.n_midi(); + if (CHECKSIZE(_iec1meter)) { + return accurate_coefficient_to_dB (_iec1meter[n - n_midi]->read()); + } + } + break; + case MeterIEC2BBC: + case MeterIEC2EBU: { - const uint32_t n_midi = current_meters.n_midi(); - if ((n - n_midi) < _kmeter.size() && (n - n_midi) >= 0) { -#if 0 - return fast_coefficient_to_dB (_kmeter[n-n_midi]->read()); -#else - return accurate_coefficient_to_dB (_kmeter[n-n_midi]->read()); -#endif + const uint32_t n_midi = current_meters.n_midi(); + if (CHECKSIZE(_iec2meter)) { + return accurate_coefficient_to_dB (_iec2meter[n - n_midi]->read()); } - return minus_infinity(); } + break; + case MeterVU: + { + const uint32_t n_midi = current_meters.n_midi(); + if (CHECKSIZE(_vumeter)) { + return accurate_coefficient_to_dB (_vumeter[n - n_midi]->read()); + } + } + break; case MeterPeak: return peak_power(n); case MeterMaxSignal: if (n < _max_peak_signal.size()) { return _max_peak_signal[n]; - } else { - return minus_infinity(); } + break; default: case MeterMaxPeak: if (n < _max_peak_power.size()) { return _max_peak_power[n]; - } else { - return minus_infinity(); } + break; } + return minus_infinity(); } void @@ -320,12 +404,31 @@ PeakMeter::set_type(MeterType t) _meter_type = t; - if (t & MeterKrms) { + if (t & (MeterKrms | MeterK20 | MeterK14)) { const size_t n_audio = current_meters.n_audio(); for (size_t n = 0; n < n_audio; ++n) { _kmeter[n]->reset(); } } + if (t & (MeterIEC1DIN | MeterIEC1NOR)) { + const size_t n_audio = current_meters.n_audio(); + for (size_t n = 0; n < n_audio; ++n) { + _iec1meter[n]->reset(); + } + } + if (t & (MeterIEC2BBC | MeterIEC2EBU)) { + const size_t n_audio = current_meters.n_audio(); + for (size_t n = 0; n < n_audio; ++n) { + _iec2meter[n]->reset(); + } + } + if (t & MeterVU) { + const size_t n_audio = current_meters.n_audio(); + for (size_t n = 0; n < n_audio; ++n) { + _vumeter[n]->reset(); + } + } + TypeChanged(t); } diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 7c4ae24a2a..415ae6210f 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -352,7 +352,7 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame return dret; } - BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers()); + BufferSet& bufs = _session.get_route_buffers (n_process_buffers()); fill_buffers_with_input (bufs, _input, nframes); diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index 998a03e3aa..d519dbd7a7 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -448,7 +448,7 @@ PluginInsert::silence (framecnt_t nframes) } for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) { - (*i)->connect_and_run (_session.get_silent_buffers ((*i)->get_info()->n_inputs), in_map, out_map, nframes, 0); + (*i)->connect_and_run (_session.get_scratch_buffers ((*i)->get_info()->n_inputs, true), in_map, out_map, nframes, 0); } } diff --git a/libs/ardour/po/de.po b/libs/ardour/po/de.po index 579d5257e2..564cafd434 100644 --- a/libs/ardour/po/de.po +++ b/libs/ardour/po/de.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-06-11 08:49-0400\n" -"PO-Revision-Date: 2013-02-05 19:52+0100\n" +"POT-Creation-Date: 2013-07-17 11:09+0200\n" +"PO-Revision-Date: 2013-07-23 15:04+0200\n" "Last-Translator: Edgar Aichinger <edogawa@aon.at>\n" "Language-Team: German <ardour-dev@lists.ardour.org>\n" "Language: de\n" @@ -218,7 +218,7 @@ msgstr "" msgid "Connect session to engine" msgstr "Verbinde Projekt mit Engine" -#: audioengine.cc:844 +#: audioengine.cc:843 msgid "" "a port with the name \"%1\" already exists: check for duplicated track/bus " "names" @@ -226,7 +226,7 @@ msgstr "" "Ein Port mit Namen \"%1\" existiert bereits: Prüfen Sie auf doppelte Spur/" "Busnamen" -#: audioengine.cc:846 session.cc:1698 +#: audioengine.cc:845 session.cc:1698 msgid "" "No more JACK ports are available. You will need to stop %1 and restart JACK " "with more ports if you need this many tracks." @@ -234,35 +234,35 @@ msgstr "" "Keine JACK-Ports mehr verfügbar. Wenn Sie so viele Spuren benötigen, müssen " "Sie %1 stoppen und JACK mit mehr Ports neu starten." -#: audioengine.cc:849 +#: audioengine.cc:848 msgid "AudioEngine: cannot register port \"%1\": %2" msgstr "AudioEngine: kann Port \"%1\": %2 nicht registrieren" -#: audioengine.cc:879 +#: audioengine.cc:878 msgid "unable to create port: %1" msgstr "kann Port: %1 nicht erzeugen" -#: audioengine.cc:933 +#: audioengine.cc:932 msgid "connect called before engine was started" msgstr "Aufruf von connect vor dem Start der Engine" -#: audioengine.cc:959 +#: audioengine.cc:958 msgid "AudioEngine: cannot connect %1 (%2) to %3 (%4)" msgstr "AudioEngine: kann %1 (%2) nicht mit %3 (%4) verbinden" -#: audioengine.cc:974 audioengine.cc:1005 +#: audioengine.cc:973 audioengine.cc:1004 msgid "disconnect called before engine was started" msgstr "Aufruf von disconnect vor dem Start der Engine" -#: audioengine.cc:1053 +#: audioengine.cc:1052 msgid "get_port_by_name() called before engine was started" msgstr "Aufruf von get_port_by_name() vor dem Start der Engine" -#: audioengine.cc:1105 +#: audioengine.cc:1104 msgid "get_ports called before engine was started" msgstr "Aufruf von get_ports vor dem Start der Engine" -#: audioengine.cc:1428 +#: audioengine.cc:1427 msgid "failed to connect to JACK" msgstr "Verbindung zu JACK fehlgeschlagen" @@ -316,8 +316,8 @@ msgstr "AudioSource: kann Pfad für Peaks (b) \"%1\" nicht öffnen (%2)" msgid "" "AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)" msgstr "" -"AudioSource[%1]: peak read - kann %2 Samples bei Offset %3 von %4 nicht lesen" -"(%5)" +"AudioSource[%1]: peak read - kann %2 Samples bei Offset %3 von %4 nicht " +"lesen(%5)" #: audiosource.cc:667 msgid "%1: could not write read raw data for peak computation (%2)" @@ -971,21 +971,21 @@ msgstr "R" msgid "%d" msgstr "%d" -#: ladspa_plugin.cc:87 +#: ladspa_plugin.cc:88 msgid "LADSPA: module has no descriptor function." msgstr "LADSPA: Modul hat keine Beschreibungsfunktion" -#: ladspa_plugin.cc:92 +#: ladspa_plugin.cc:93 msgid "LADSPA: plugin has gone away since discovery!" msgstr "LADSPA: Plugin ist nicht mehr auffindbar!" -#: ladspa_plugin.cc:99 +#: ladspa_plugin.cc:100 msgid "LADSPA: \"%1\" cannot be used, since it cannot do inplace processing" msgstr "" "LADSPA: \"%1\" kann nicht verwendet werdeen, da es kein \"inplace processing" "\" beherrscht" -#: ladspa_plugin.cc:296 +#: ladspa_plugin.cc:297 msgid "" "illegal parameter number used with plugin \"%1\". This may indicate a change " "in the plugin design, and presets may be invalid" @@ -993,35 +993,35 @@ msgstr "" "Falsche Parameterzahl für Plugin \"%1\". Das auf eine Änderung im Plugin-" "Design hindeuten, und Presets sind eventuell ungültig" -#: ladspa_plugin.cc:373 ladspa_plugin.cc:418 +#: ladspa_plugin.cc:376 ladspa_plugin.cc:426 msgid "Bad node sent to LadspaPlugin::set_state" msgstr "Schlechter Knoten an LadspaPlugin::set_state gesendet" -#: ladspa_plugin.cc:386 ladspa_plugin.cc:431 +#: ladspa_plugin.cc:391 ladspa_plugin.cc:440 msgid "LADSPA: no ladspa port number" msgstr "LADSPA: keine LADSPA-Portnummer" -#: ladspa_plugin.cc:392 ladspa_plugin.cc:437 +#: ladspa_plugin.cc:397 ladspa_plugin.cc:446 msgid "LADSPA: no ladspa port data" msgstr "LADSPA: keine LADSPA-Portdaten" -#: ladspa_plugin.cc:707 +#: ladspa_plugin.cc:717 msgid "LADSPA: cannot load module from \"%1\"" msgstr "LADSPA: kann Modul nicht aus \"%1\" laden" -#: ladspa_plugin.cc:817 +#: ladspa_plugin.cc:827 msgid "Could not locate HOME. Preset not removed." msgstr "Konnte HOME nicht eruieren. Preset nicht entfernt." -#: ladspa_plugin.cc:854 ladspa_plugin.cc:860 +#: ladspa_plugin.cc:864 ladspa_plugin.cc:870 msgid "Could not create %1. Preset not saved. (%2)" msgstr "Konnte %1 nicht erzeugen. Preset nicht gesichert. (%2)" -#: ladspa_plugin.cc:867 +#: ladspa_plugin.cc:877 msgid "Error saving presets file %1." msgstr "Fehler beim Sichern der Preset-Datei %1." -#: ladspa_plugin.cc:905 +#: ladspa_plugin.cc:915 msgid "Could not locate HOME. Preset not saved." msgstr "Konnte HOME nicht eruieren. Preset nicht gesichert." @@ -1368,23 +1368,39 @@ msgstr "" "Konnte die Wiedergabeliste nicht aus den Quelldaten des Projekts " "konstruieren!" +#: plugin.cc:324 +msgid "" +"Plugin presets are not supported in this build of %1. Consider paying for a " +"full version" +msgstr "" +"Pluginpresets werden in diesem %1-Binärpaket nicht unterstützt. Erwägen Sie, " +"für die Vollversion zu bezahlen" + +#: plugin.cc:398 +msgid "" +"Saving plugin settings is not supported in this build of %1. Consider paying " +"for the full version" +msgstr "" +"Das Speichern von Pluginpresets werden in diesem %1-Binärpaket nicht " +"unterstützt. Erwägen Sie, für die Vollversion zu bezahlen" + #: plugin_insert.cc:599 msgid "programming error: " msgstr "Programmierfehler:" -#: plugin_insert.cc:908 +#: plugin_insert.cc:914 msgid "XML node describing plugin is missing the `type' field" msgstr "Dem XML-Knoten zur Beschreibung des Plugins fehlt das \"type\"-Feld" -#: plugin_insert.cc:923 +#: plugin_insert.cc:929 msgid "unknown plugin type %1 in plugin insert state" msgstr "Unbekannter Plugintyp %1 im Einfüge-Status des Plugins" -#: plugin_insert.cc:951 +#: plugin_insert.cc:957 msgid "Plugin has no unique ID field" msgstr "Das Plugin hat kein Feld für die eindeutige ID" -#: plugin_insert.cc:960 +#: plugin_insert.cc:966 msgid "" "Found a reference to a plugin (\"%1\") that is unknown.\n" "Perhaps it was removed or moved since it was last used." @@ -1392,15 +1408,15 @@ msgstr "" "Referenz auf ein unbekanntes Plugin (\"%1\") gefunden.\n" "Vielleicht wurde es seit der letzten Verwendung entfernt oder verschoben." -#: plugin_insert.cc:1076 +#: plugin_insert.cc:1082 msgid "PluginInsert: Auto: no ladspa port number" msgstr "PluginInsert: Auto: keine LADSPA Portnummer" -#: plugin_insert.cc:1083 +#: plugin_insert.cc:1089 msgid "PluginInsert: Auto: port id out of range" msgstr "PluginInsert: Auto: Port-ID Bereichsüberschreitung" -#: plugin_insert.cc:1119 +#: plugin_insert.cc:1125 msgid "PluginInsert: automatable control %1 not found - ignored" msgstr "" "PluginInsert: automatisierbares Kontrollelement %1 nicht gefunden - ignoriert" @@ -1550,23 +1566,23 @@ msgstr "Import: Fehler in src_new() : %1" msgid "return %1" msgstr "Rückgabewert: %1" -#: route.cc:1100 route.cc:2550 +#: route.cc:1101 route.cc:2557 msgid "unknown Processor type \"%1\"; ignored" msgstr "unbekannter Prozessortyp \"%1\"; ignoriert" -#: route.cc:1112 +#: route.cc:1113 msgid "processor could not be created. Ignored." msgstr "Prozessor konnte nicht erzeugt werden. Ignoriert." -#: route.cc:1983 route.cc:2203 +#: route.cc:1986 route.cc:2210 msgid "Bad node sent to Route::set_state() [%1]" msgstr "Schlechter Knoten an Route::set_state() gesendet [%1]" -#: route.cc:2042 +#: route.cc:2045 msgid "Pannable state found for route (%1) without a panner!" msgstr "Pannerziel-Status für Route (%1) ohne Panner gefunden!" -#: route.cc:2106 route.cc:2110 route.cc:2317 route.cc:2321 +#: route.cc:2113 route.cc:2117 route.cc:2324 route.cc:2328 msgid "badly formed order key string in state file! [%1] ... ignored." msgstr "" "schlecht geformte Zeichenkette für den Schlüssel der Sortierreihenfolge in " @@ -1857,18 +1873,17 @@ msgstr "Session: kann quarter-frame MTC-Nachricht nicht senden (%1)" msgid "Session: cannot create Playlist from XML description." msgstr "Session: kann Wiedergabeliste nicht aus der XML-Beschreibung erzeugen" -#: session_process.cc:135 +#: session_process.cc:133 msgid "Session: error in no roll for %1" msgstr "Session: Fehler in no_roll für %1" -#: session_process.cc:1160 +#: session_process.cc:1158 msgid "Programming error: illegal event type in process_event (%1)" msgstr "Programmierfehler: illegaler Ereignistyp in process_event (%1)" #: session_state.cc:139 -#, fuzzy msgid "Could not use path %1 (%2)" -msgstr "Konnte Pfad %1 nicht benutzen (%s)" +msgstr "Konnte Pfad %1 nicht benutzen (%2)" #: session_state.cc:267 msgid "solo cut control (dB)" @@ -2406,7 +2421,7 @@ msgstr "" msgid "attempt to write a non-writable audio file source (%1)" msgstr "Versuch, in eine schreibgeschützte Audio-Dateiquelle zu schreiben (%1)" -#: sndfilesource.cc:396 utils.cc:497 utils.cc:521 utils.cc:535 utils.cc:554 +#: sndfilesource.cc:396 utils.cc:507 utils.cc:531 utils.cc:545 utils.cc:564 msgid "programming error: %1 %2" msgstr "Programmierfehler: %1 %2" @@ -2672,11 +2687,11 @@ msgstr "M-Clock" msgid "LTC" msgstr "LTC" -#: utils.cc:589 +#: utils.cc:599 msgid "programming error: unknown native header format: %1" msgstr "Programmierfehler: unbekanntes natives Dateikopfformat: %1" -#: utils.cc:604 +#: utils.cc:614 msgid "cannot open directory %1 (%2)" msgstr "kann Verzeichnis %1 nicht öffnen (%2)" diff --git a/libs/ardour/process_thread.cc b/libs/ardour/process_thread.cc index e10ccf160c..d4a3d2f390 100644 --- a/libs/ardour/process_thread.cc +++ b/libs/ardour/process_thread.cc @@ -90,7 +90,7 @@ ProcessThread::get_silent_buffers (ChanCount count) } BufferSet& -ProcessThread::get_scratch_buffers (ChanCount count) +ProcessThread::get_scratch_buffers (ChanCount count, bool silence) { ThreadBuffers* tb = _private_thread_buffers.get(); assert (tb); @@ -105,6 +105,41 @@ ProcessThread::get_scratch_buffers (ChanCount count) sb->set_count (sb->available()); } + if (silence) { + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + for (uint32_t i = 0; i < sb->count().get(*t); ++i) { + sb->get(*t, i).clear(); + } + } + } + + return *sb; +} + +BufferSet& +ProcessThread::get_route_buffers (ChanCount count, bool silence) +{ + ThreadBuffers* tb = _private_thread_buffers.get(); + assert (tb); + + BufferSet* sb = tb->route_buffers; + assert (sb); + + if (count != ChanCount::ZERO) { + assert(sb->available() >= count); + sb->set_count (count); + } else { + sb->set_count (sb->available()); + } + + if (silence) { + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + for (uint32_t i = 0; i < sb->count().get(*t); ++i) { + sb->get(*t, i).clear(); + } + } + } + return *sb; } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 797481b7b8..671a00319d 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -101,6 +101,9 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type) , _custom_meter_position_noted (false) , _last_custom_meter_was_at_end (false) { + if (is_master()) { + _meter_type = MeterK20; + } processor_max_streams.reset(); } @@ -568,7 +571,7 @@ void Route::monitor_run (framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick) { assert (is_monitor()); - BufferSet& bufs (_session.get_scratch_buffers (n_process_buffers())); + BufferSet& bufs (_session.get_route_buffers (n_process_buffers())); passthru (bufs, start_frame, end_frame, nframes, declick); } @@ -594,7 +597,7 @@ Route::passthru (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, void Route::passthru_silence (framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick) { - BufferSet& bufs (_session.get_silent_buffers (n_process_buffers())); + BufferSet& bufs (_session.get_route_buffers (n_process_buffers(), true)); bufs.set_count (_input->n_ports()); write_out_of_band_data (bufs, start_frame, end_frame, nframes); @@ -3017,7 +3020,7 @@ Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, */ } - BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers()); + BufferSet& bufs = _session.get_route_buffers (n_process_buffers()); fill_buffers_with_input (bufs, _input, nframes); @@ -3056,7 +3059,7 @@ Route::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, in _silent = false; - BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers()); + BufferSet& bufs = _session.get_route_buffers (n_process_buffers()); fill_buffers_with_input (bufs, _input, nframes); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 476682158f..9817f17069 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -4174,12 +4174,19 @@ Session::get_silent_buffers (ChanCount count) } BufferSet& -Session::get_scratch_buffers (ChanCount count) +Session::get_scratch_buffers (ChanCount count, bool silence) { - return ProcessThread::get_scratch_buffers (count); + return ProcessThread::get_scratch_buffers (count, silence); } BufferSet& +Session::get_route_buffers (ChanCount count, bool silence) +{ + return ProcessThread::get_route_buffers (count, silence); +} + + +BufferSet& Session::get_mix_buffers (ChanCount count) { return ProcessThread::get_mix_buffers (count); diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index 5b5554be7c..e4fd58dedc 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -44,6 +44,7 @@ #include "ardour/midi_ui.h" #include "ardour/session.h" #include "ardour/slave.h" +#include "ardour/ticker.h" #include "i18n.h" @@ -580,6 +581,19 @@ Session::mmc_step_timeout () return true; } +/*********************************************************************** + OUTBOUND SYSTEM COMMON STUFF +**********************************************************************/ + + +void +Session::send_song_position_pointer (framepos_t t) +{ + if (midi_clock) { + midi_clock->position_changed (t); + } +} + int Session::start_midi_thread () { diff --git a/libs/ardour/thread_buffers.cc b/libs/ardour/thread_buffers.cc index 34f6f9828b..fd3160bb15 100644 --- a/libs/ardour/thread_buffers.cc +++ b/libs/ardour/thread_buffers.cc @@ -30,6 +30,7 @@ using namespace std; ThreadBuffers::ThreadBuffers () : silent_buffers (new BufferSet) , scratch_buffers (new BufferSet) + , route_buffers (new BufferSet) , mix_buffers (new BufferSet) , gain_automation_buffer (0) , send_gain_automation_buffer (0) @@ -64,6 +65,7 @@ ThreadBuffers::ensure_buffers (ChanCount howmany) scratch_buffers->ensure_buffers (*t, count, size); mix_buffers->ensure_buffers (*t, count, size); silent_buffers->ensure_buffers (*t, count, size); + route_buffers->ensure_buffers (*t, count, size); } delete [] gain_automation_buffer; diff --git a/libs/ardour/ticker.cc b/libs/ardour/ticker.cc index 5d078952a1..4f66128943 100644 --- a/libs/ardour/ticker.cc +++ b/libs/ardour/ticker.cc @@ -40,7 +40,8 @@ MidiClockTicker::MidiClockTicker () { } -void MidiClockTicker::set_session (Session* s) +void +MidiClockTicker::set_session (Session* s) { SessionHandlePtr::set_session (s); @@ -59,12 +60,14 @@ MidiClockTicker::session_going_away () _midi_port = 0; } -void MidiClockTicker::update_midi_clock_port() +void +MidiClockTicker::update_midi_clock_port() { _midi_port = MIDI::Manager::instance()->midi_clock_output_port(); } -void MidiClockTicker::transport_state_changed() +void +MidiClockTicker::transport_state_changed() { if (_session->exporting()) { /* no midi clock during export, for now */ @@ -80,8 +83,8 @@ void MidiClockTicker::transport_state_changed() framepos_t position = _session->transport_frame(); DEBUG_TRACE (PBD::DEBUG::MidiClock, - string_compose ("Transport state change @ %4, speed: %1 position: %2 play loop: %3\n", speed, position, _session->get_play_loop(), position) - ); + string_compose ("Transport state change @ %4, speed: %1 position: %2 play loop: %3\n", speed, position, _session->get_play_loop(), position) + ); if (speed == 1.0f) { _last_tick = position; @@ -109,19 +112,27 @@ void MidiClockTicker::transport_state_changed() return; send_stop_event(0); + send_position_event (position, 0); } tick (position); } -void MidiClockTicker::position_changed (framepos_t position) +void +MidiClockTicker::position_changed (framepos_t position) { - DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Position change: %1\n", position)); + const double speed = _session->transport_speed(); + DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Transport Position Change: %1, speed: %2\n", position, speed)); + + if (speed == 0.0f && Config->get_send_midi_clock()) { + send_position_event (position, 0); + } _last_tick = position; } -void MidiClockTicker::transport_looped() +void +MidiClockTicker::transport_looped() { Location* loop_location = _session->locations()->auto_loop_location(); assert(loop_location); @@ -143,7 +154,8 @@ void MidiClockTicker::transport_looped() } } -void MidiClockTicker::tick (const framepos_t& transport_frame) +void +MidiClockTicker::tick (const framepos_t& transport_frame) { if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f || _midi_port == 0) { return; @@ -155,9 +167,11 @@ void MidiClockTicker::tick (const framepos_t& transport_frame) MIDI::JackMIDIPort* mp = dynamic_cast<MIDI::JackMIDIPort*> (_midi_port); + /* DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Transport: %1, last tick time: %2, next tick time: %3, offset: %4, cycle length: %5\n", transport_frame, _last_tick, next_tick, next_tick_offset, mp ? mp->nframes_this_cycle() : 0)); + */ if (!mp || (next_tick_offset >= mp->nframes_this_cycle())) { break; @@ -171,7 +185,8 @@ void MidiClockTicker::tick (const framepos_t& transport_frame) } } -double MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position) +double +MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position) { const Tempo& current_tempo = _session->tempo_map().tempo_at (transport_position); double frames_per_beat = current_tempo.frames_per_beat (_session->nominal_frame_rate()); @@ -182,47 +197,88 @@ double MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position) return frames_per_quarter_note / double (_ppqn); } -void MidiClockTicker::send_midi_clock_event (pframes_t offset) +void +MidiClockTicker::send_midi_clock_event (pframes_t offset) { if (!_midi_port) { return; } - DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Tick with offset %1\n", offset)); + // DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Tick with offset %1\n", offset)); static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CLOCK }; _midi_port->write (_midi_clock_tick, 1, offset); } -void MidiClockTicker::send_start_event (pframes_t offset) +void +MidiClockTicker::send_start_event (pframes_t offset) { if (!_midi_port) { return; } + DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Start %1\n", _last_tick)); + static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_START }; _midi_port->write (_midi_clock_tick, 1, offset); } -void MidiClockTicker::send_continue_event (pframes_t offset) +void +MidiClockTicker::send_continue_event (pframes_t offset) { if (!_midi_port) { return; } + DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Continue %1\n", _last_tick)); + static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CONTINUE }; _midi_port->write (_midi_clock_tick, 1, offset); } -void MidiClockTicker::send_stop_event (pframes_t offset) +void +MidiClockTicker::send_stop_event (pframes_t offset) { if (!_midi_port) { return; } + DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Stop %1\n", _last_tick)); + static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_STOP }; _midi_port->write (_midi_clock_tick, 1, offset); } +void +MidiClockTicker::send_position_event (framepos_t transport_position, pframes_t offset) +{ + if (_midi_port == 0 || _session == 0 || _session->engine().freewheeling()) { + return; + } + + const TempoMap& tempo = _session->tempo_map(); + Timecode::BBT_Time time; + _session->bbt_time (transport_position, time); + const double beats_per_bar = tempo.meter_at(transport_position).divisions_per_bar(); + /* Midi Beats in terms of Song Position Pointer is equivalent to total + sixteenth notes at 'time' */ + const uint32_t midi_beats = 4 * (((time.bars - 1) * beats_per_bar) + time.beats - 1); + + /* can only use 14bits worth */ + if (midi_beats > 0x3fff) { + return; + } + + /* split midi beats into a 14bit value */ + MIDI::byte msg[3] = { + MIDI_CMD_COMMON_SONG_POS, + midi_beats & 0x007f, + midi_beats & 0x3f80 + }; + + DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Song Position: %1\n", midi_beats)); + + _midi_port->midimsg (msg, sizeof (msg), offset); +} diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index c6a348ddfb..7d90709b6f 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -398,6 +398,9 @@ Track::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, case MonitoringInput: be_silent = false; break; + default: + be_silent = false; + break; } } @@ -436,7 +439,8 @@ Track::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, } if (no_meter) { - _meter->reset(); + BufferSet& bufs (_session.get_silent_buffers (n_process_buffers())); + _meter->run (bufs, 0, 0, nframes, true); _input->process_input (boost::shared_ptr<Processor>(), start_frame, end_frame, nframes); } else { _input->process_input (_meter, start_frame, end_frame, nframes); @@ -447,7 +451,7 @@ Track::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, } else { - BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers()); + BufferSet& bufs = _session.get_route_buffers (n_process_buffers()); fill_buffers_with_input (bufs, _input, nframes); @@ -492,7 +496,7 @@ Track::silent_roll (pframes_t nframes, framepos_t /*start_frame*/, framepos_t /* framecnt_t playback_distance; - BufferSet& bufs (_session.get_silent_buffers (n_process_buffers())); + BufferSet& bufs (_session.get_route_buffers (n_process_buffers(), true)); int const dret = _diskstream->process (bufs, _session.transport_frame(), nframes, playback_distance, false); need_butler = _diskstream->commit (playback_distance); diff --git a/libs/ardour/vumeterdsp.cc b/libs/ardour/vumeterdsp.cc new file mode 100644 index 0000000000..67d48f6c54 --- /dev/null +++ b/libs/ardour/vumeterdsp.cc @@ -0,0 +1,89 @@ +/* + Copyright (C) 2012 Fons Adriaensen <fons@linuxaudio.org> + Adopted for Ardour 2013 by Robin Gareus <robin@gareus.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <math.h> +#include "ardour/vumeterdsp.h" + + +float Vumeterdsp::_w; +float Vumeterdsp::_g; + + +Vumeterdsp::Vumeterdsp (void) : + _z1 (0), + _z2 (0), + _m (0), + _res (true) +{ +} + + +Vumeterdsp::~Vumeterdsp (void) +{ +} + + +void Vumeterdsp::process (float *p, int n) +{ + float z1, z2, m, t1, t2; + + z1 = _z1; + z2 = _z2; + m = _res ? 0: _m; + _res = false; + + n /= 4; + while (n--) + { + t2 = z2 / 2; + t1 = fabsf (*p++) - t2; + z1 += _w * (t1 - z1); + t1 = fabsf (*p++) - t2; + z1 += _w * (t1 - z1); + t1 = fabsf (*p++) - t2; + z1 += _w * (t1 - z1); + t1 = fabsf (*p++) - t2; + z1 += _w * (t1 - z1); + z2 += 4 * _w * (z1 - z2); + if (z2 > m) m = z2; + } + + _z1 = z1; + _z2 = z2 + 1e-10f; + _m = m; +} + + +float Vumeterdsp::read (void) +{ + _res = true; + return _g * _m; +} + +void Vumeterdsp::reset () +{ + _z1 = _z2 = _m = .0f; + _res = true; +} + +void Vumeterdsp::init (float fsamp) +{ + _w = 11.1f / fsamp; + _g = 1.5f * 1.571f; +} diff --git a/libs/ardour/wscript b/libs/ardour/wscript index 5e8b27d4ea..87dce06a2a 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -92,6 +92,8 @@ libardour_sources = [ 'globals.cc', 'graph.cc', 'graphnode.cc', + 'iec1ppmdsp.cc', + 'iec2ppmdsp.cc', 'import.cc', 'instrument_info.cc', 'internal_return.cc', @@ -209,6 +211,7 @@ libardour_sources = [ 'user_bundle.cc', 'utils.cc', 'version.cc', + 'vumeterdsp.cc', 'worker.cc' ] diff --git a/libs/gtkmm2ext/fastmeter.cc b/libs/gtkmm2ext/fastmeter.cc index 6ea1a6dd4b..d826def7ff 100644 --- a/libs/gtkmm2ext/fastmeter.cc +++ b/libs/gtkmm2ext/fastmeter.cc @@ -44,6 +44,9 @@ bool FastMeter::no_rgba_overlay = false; FastMeter::Pattern10Map FastMeter::vm_pattern_cache; FastMeter::PatternBgMap FastMeter::vb_pattern_cache; +FastMeter::Pattern10Map FastMeter::hm_pattern_cache; +FastMeter::PatternBgMap FastMeter::hb_pattern_cache; + FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o, int len, int clr0, int clr1, int clr2, int clr3, int clr4, int clr5, int clr6, int clr7, @@ -51,19 +54,25 @@ FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o, int len, int bgc0, int bgc1, int bgh0, int bgh1, float stp0, float stp1, - float stp2, float stp3 + float stp2, float stp3, + int styleflags ) + : pixheight(0) + , pixwidth(0) + , _styleflags(styleflags) + , orientation(o) + , hold_cnt(hold) + , hold_state(0) + , bright_hold(false) + , current_level(0) + , current_peak(0) + , highlight(false) { - orientation = o; - hold_cnt = hold; - hold_state = 0; - bright_hold = false; - current_peak = 0; - current_level = 0; last_peak_rect.width = 0; last_peak_rect.height = 0; + last_peak_rect.x = 0; + last_peak_rect.y = 0; - highlight = false; no_rgba_overlay = ! Glib::getenv("NO_METER_SHADE").empty(); _clr[0] = clr0; @@ -96,10 +105,18 @@ FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o, int len, if (!len) { len = 250; } - fgpattern = request_vertical_meter(dimen, len, _clr, _stp, true); - bgpattern = request_vertical_background (dimen, len, _bgc, false); - pixheight = len; - pixwidth = dimen; + if (orientation == Vertical) { + pixheight = len; + pixwidth = dimen; + fgpattern = request_vertical_meter(pixwidth + 2, pixheight + 2, _clr, _stp, _styleflags); + bgpattern = request_vertical_background (pixwidth + 2, pixheight + 2, _bgc, false); + + } else { + pixheight = dimen; + pixwidth = len; + fgpattern = request_horizontal_meter(pixwidth + 2, pixheight + 2, _clr, _stp, _styleflags); + bgpattern = request_horizontal_background (pixwidth + 2, pixheight + 2, _bgc, false); + } pixrect.width = pixwidth; pixrect.height = pixheight; @@ -107,7 +124,7 @@ FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o, int len, request_width = pixrect.width + 2; request_height= pixrect.height + 2; - queue_draw (); + clear (); } FastMeter::~FastMeter () @@ -116,11 +133,12 @@ FastMeter::~FastMeter () Cairo::RefPtr<Cairo::Pattern> FastMeter::generate_meter_pattern ( - int width, int height, int *clr, float *stp, bool shade) + int width, int height, int *clr, float *stp, int styleflags, bool horiz) { guint8 r,g,b,a; double knee; - double soft = 1.5 / (double) height; + const double soft = 3.0 / (double) height; + const double offs = -1.0 / (double) height; cairo_pattern_t* pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, height); @@ -133,54 +151,55 @@ FastMeter::generate_meter_pattern ( cairo_pattern_add_color_stop_rgb (pat, 0.0, r/255.0, g/255.0, b/255.0); - knee = ((float)height * stp[3] / 115.0f); // -0dB + knee = offs + stp[3] / 115.0f; // -0dB UINT_TO_RGBA (clr[8], &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height) - soft, + cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee, r/255.0, g/255.0, b/255.0); UINT_TO_RGBA (clr[7], &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height) + soft, + cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft, r/255.0, g/255.0, b/255.0); - knee = ((float)height * stp[2]/ 115.0f); // -3dB || -2dB + knee = offs + stp[2]/ 115.0f; // -3dB || -2dB UINT_TO_RGBA (clr[6], &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height) - soft, + cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee, r/255.0, g/255.0, b/255.0); UINT_TO_RGBA (clr[5], &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height) + soft, + cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft, r/255.0, g/255.0, b/255.0); - knee = ((float)height * stp[1] / 115.0f); // -9dB + knee = offs + stp[1] / 115.0f; // -9dB UINT_TO_RGBA (clr[4], &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height) - soft, + cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee, r/255.0, g/255.0, b/255.0); UINT_TO_RGBA (clr[3], &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height) + soft, + cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft, r/255.0, g/255.0, b/255.0); - knee = ((float)height * stp[0] / 115.0f); // -18dB + knee = offs + stp[0] / 115.0f; // -18dB UINT_TO_RGBA (clr[2], &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height) - soft, + cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee, r/255.0, g/255.0, b/255.0); UINT_TO_RGBA (clr[1], &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgb (pat, 1.0 - (knee/(double)height) + soft, + cairo_pattern_add_color_stop_rgb (pat, 1.0 - knee + soft, r/255.0, g/255.0, b/255.0); UINT_TO_RGBA (clr[0], &r, &g, &b, &a); // bottom cairo_pattern_add_color_stop_rgb (pat, 1.0, r/255.0, g/255.0, b/255.0); - if (shade && !no_rgba_overlay) { + if ((styleflags & 1) && !no_rgba_overlay) { cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, width, 0.0); - cairo_pattern_add_color_stop_rgba (shade_pattern, 0, 1.0, 1.0, 1.0, 0.2); - cairo_pattern_add_color_stop_rgba (shade_pattern, 1, 0.0, 0.0, 0.0, 0.3); + cairo_pattern_add_color_stop_rgba (shade_pattern, 0, 0.0, 0.0, 0.0, 0.15); + cairo_pattern_add_color_stop_rgba (shade_pattern, 0.4, 1.0, 1.0, 1.0, 0.05); + cairo_pattern_add_color_stop_rgba (shade_pattern, 1, 0.0, 0.0, 0.0, 0.25); cairo_surface_t* surface; cairo_t* tc = 0; @@ -189,19 +208,49 @@ FastMeter::generate_meter_pattern ( cairo_set_source (tc, pat); cairo_rectangle (tc, 0, 0, width, height); cairo_fill (tc); + cairo_pattern_destroy (pat); + cairo_set_source (tc, shade_pattern); cairo_rectangle (tc, 0, 0, width, height); cairo_fill (tc); - - cairo_pattern_destroy (pat); cairo_pattern_destroy (shade_pattern); - pat = cairo_pattern_create_for_surface (surface); + if (styleflags & 2) { // LED stripes + cairo_save (tc); + cairo_set_line_width(tc, 1.0); + cairo_set_source_rgba(tc, .0, .0, .0, 0.4); + //cairo_set_operator (tc, CAIRO_OPERATOR_SOURCE); + for (float y=0.5; y < height; y+= 2.0) { + cairo_move_to(tc, 0, y); + cairo_line_to(tc, width, y); + cairo_stroke (tc); + } + cairo_restore (tc); + } + pat = cairo_pattern_create_for_surface (surface); cairo_destroy (tc); cairo_surface_destroy (surface); } + if (horiz) { + cairo_surface_t* surface; + cairo_t* tc = 0; + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, height, width); + tc = cairo_create (surface); + + cairo_matrix_t m; + cairo_matrix_init_rotate (&m, -M_PI/2.0); + cairo_matrix_translate (&m, -height, 0); + cairo_pattern_set_matrix (pat, &m); + cairo_set_source (tc, pat); + cairo_rectangle (tc, 0, 0, height, width); + cairo_fill (tc); + cairo_pattern_destroy (pat); + pat = cairo_pattern_create_for_surface (surface); + cairo_destroy (tc); + cairo_surface_destroy (surface); + } Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false)); return p; @@ -210,7 +259,7 @@ FastMeter::generate_meter_pattern ( Cairo::RefPtr<Cairo::Pattern> FastMeter::generate_meter_background ( - int width, int height, int *clr, bool shade) + int width, int height, int *clr, bool shade, bool horiz) { guint8 r0,g0,b0,r1,g1,b1,a; @@ -251,6 +300,25 @@ FastMeter::generate_meter_background ( cairo_surface_destroy (surface); } + if (horiz) { + cairo_surface_t* surface; + cairo_t* tc = 0; + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, height, width); + tc = cairo_create (surface); + + cairo_matrix_t m; + cairo_matrix_init_rotate (&m, -M_PI/2.0); + cairo_matrix_translate (&m, -height, 0); + cairo_pattern_set_matrix (pat, &m); + cairo_set_source (tc, pat); + cairo_rectangle (tc, 0, 0, height, width); + cairo_fill (tc); + cairo_pattern_destroy (pat); + pat = cairo_pattern_create_for_surface (surface); + cairo_destroy (tc); + cairo_surface_destroy (surface); + } + Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false)); return p; @@ -258,18 +326,16 @@ FastMeter::generate_meter_background ( Cairo::RefPtr<Cairo::Pattern> FastMeter::request_vertical_meter( - int width, int height, int *clr, float *stp, bool shade) + int width, int height, int *clr, float *stp, int styleflags) { - if (height < min_pattern_metric_size) - height = min_pattern_metric_size; - if (height > max_pattern_metric_size) - height = max_pattern_metric_size; + height = max(height, min_pattern_metric_size); + height = min(height, max_pattern_metric_size); const Pattern10MapKey key (width, height, stp[0], stp[1], stp[2], stp[3], clr[0], clr[1], clr[2], clr[3], clr[4], clr[5], clr[6], clr[7], - clr[8], clr[9]); + clr[8], clr[9], styleflags); Pattern10Map::iterator i; if ((i = vm_pattern_cache.find (key)) != vm_pattern_cache.end()) { @@ -278,7 +344,7 @@ FastMeter::request_vertical_meter( // TODO flush pattern cache if it gets too large Cairo::RefPtr<Cairo::Pattern> p = generate_meter_pattern ( - width, height, clr, stp, shade); + width, height, clr, stp, styleflags, false); vm_pattern_cache[key] = p; return p; @@ -288,12 +354,11 @@ Cairo::RefPtr<Cairo::Pattern> FastMeter::request_vertical_background( int width, int height, int *bgc, bool shade) { - if (height < min_pattern_metric_size) - height = min_pattern_metric_size; - if (height > max_pattern_metric_size) - height = max_pattern_metric_size; + height = max(height, min_pattern_metric_size); + height = min(height, max_pattern_metric_size); + height += 2; - const PatternBgMapKey key (width, height, bgc[0], bgc[1]); + const PatternBgMapKey key (width, height, bgc[0], bgc[1], shade); PatternBgMap::iterator i; if ((i = vb_pattern_cache.find (key)) != vb_pattern_cache.end()) { return i->second; @@ -301,12 +366,62 @@ FastMeter::request_vertical_background( // TODO flush pattern cache if it gets too large Cairo::RefPtr<Cairo::Pattern> p = generate_meter_background ( - width, height, bgc, shade); + width, height, bgc, shade, false); vb_pattern_cache[key] = p; return p; } +Cairo::RefPtr<Cairo::Pattern> +FastMeter::request_horizontal_meter( + int width, int height, int *clr, float *stp, int styleflags) +{ + width = max(width, min_pattern_metric_size); + width = min(width, max_pattern_metric_size); + + const Pattern10MapKey key (width, height, + stp[0], stp[1], stp[2], stp[3], + clr[0], clr[1], clr[2], clr[3], + clr[4], clr[5], clr[6], clr[7], + clr[8], clr[9], styleflags); + + Pattern10Map::iterator i; + if ((i = hm_pattern_cache.find (key)) != hm_pattern_cache.end()) { + return i->second; + } + // TODO flush pattern cache if it gets too large + + Cairo::RefPtr<Cairo::Pattern> p = generate_meter_pattern ( + height, width, clr, stp, styleflags, true); + + hm_pattern_cache[key] = p; + return p; +} + +Cairo::RefPtr<Cairo::Pattern> +FastMeter::request_horizontal_background( + int width, int height, int *bgc, bool shade) +{ + width = max(width, min_pattern_metric_size); + width = min(width, max_pattern_metric_size); + width += 2; + + const PatternBgMapKey key (width, height, bgc[0], bgc[1], shade); + PatternBgMap::iterator i; + if ((i = hb_pattern_cache.find (key)) != hb_pattern_cache.end()) { + return i->second; + } + // TODO flush pattern cache if it gets too large + + Cairo::RefPtr<Cairo::Pattern> p = generate_meter_background ( + height, width, bgc, shade, true); + + hb_pattern_cache[key] = p; + + return p; +} + + void FastMeter::set_hold_count (long val) @@ -325,6 +440,16 @@ FastMeter::set_hold_count (long val) void FastMeter::on_size_request (GtkRequisition* req) { + if (orientation == Vertical) { + vertical_size_request (req); + } else { + horizontal_size_request (req); + } +} + +void +FastMeter::vertical_size_request (GtkRequisition* req) +{ req->height = request_height; req->height = max(req->height, min_pattern_metric_size); req->height = min(req->height, max_pattern_metric_size); @@ -334,8 +459,30 @@ FastMeter::on_size_request (GtkRequisition* req) } void +FastMeter::horizontal_size_request (GtkRequisition* req) +{ + req->width = request_width; + req->width = max(req->width, min_pattern_metric_size); + req->width = min(req->width, max_pattern_metric_size); + req->width += 2; + + req->height = request_height; +} + +void FastMeter::on_size_allocate (Gtk::Allocation &alloc) { + if (orientation == Vertical) { + vertical_size_allocate (alloc); + } else { + horizontal_size_allocate (alloc); + } + queue_draw (); +} + +void +FastMeter::vertical_size_allocate (Gtk::Allocation &alloc) +{ if (alloc.get_width() != request_width) { alloc.set_width (request_width); } @@ -349,7 +496,7 @@ FastMeter::on_size_allocate (Gtk::Allocation &alloc) } if (pixheight != h) { - fgpattern = request_vertical_meter (request_width, h, _clr, _stp, true); + fgpattern = request_vertical_meter (request_width, h, _clr, _stp, _styleflags); bgpattern = request_vertical_background (request_width, h, highlight ? _bgh : _bgc, highlight); pixheight = h - 2; pixwidth = request_width - 2; @@ -358,10 +505,39 @@ FastMeter::on_size_allocate (Gtk::Allocation &alloc) DrawingArea::on_size_allocate (alloc); } +void +FastMeter::horizontal_size_allocate (Gtk::Allocation &alloc) +{ + if (alloc.get_height() != request_height) { + alloc.set_height (request_height); + } + + int w = alloc.get_width(); + w = max (w, min_pattern_metric_size + 2); + w = min (w, max_pattern_metric_size + 2); + + if (w != alloc.get_width()) { + alloc.set_width (w); + } + + if (pixwidth != w) { + fgpattern = request_horizontal_meter (w, request_height, _clr, _stp, _styleflags); + bgpattern = request_horizontal_background (w, request_height, highlight ? _bgh : _bgc, highlight); + pixwidth = w - 2; + pixheight = request_height - 2; + } + + DrawingArea::on_size_allocate (alloc); +} + bool FastMeter::on_expose_event (GdkEventExpose* ev) { - return vertical_expose (ev); + if (orientation == Vertical) { + return vertical_expose (ev); + } else { + return horizontal_expose (ev); + } } bool @@ -378,7 +554,7 @@ FastMeter::vertical_expose (GdkEventExpose* ev) cairo_clip (cr); cairo_set_source_rgb (cr, 0, 0, 0); // black - rounded_rectangle (cr, 0, 0, pixrect.width + 2, pixheight + 2, 2); + rounded_rectangle (cr, 0, 0, pixwidth + 2, pixheight + 2, 2); cairo_stroke (cr); top_of_meter = (gint) floor (pixheight * current_level); @@ -413,14 +589,87 @@ FastMeter::vertical_expose (GdkEventExpose* ev) last_peak_rect.x = 1; last_peak_rect.width = pixwidth; last_peak_rect.y = max(1, 1 + pixheight - (gint) floor (pixheight * current_peak)); - if (bright_hold) { - last_peak_rect.height = max(0, min(4, pixheight - last_peak_rect.y -1 )); + if (bright_hold || (_styleflags & 2)) { + last_peak_rect.height = max(0, min(3, pixheight - last_peak_rect.y - 1 )); } else { - last_peak_rect.height = max(0, min(2, pixheight - last_peak_rect.y -1 )); + last_peak_rect.height = max(0, min(2, pixheight - last_peak_rect.y - 1 )); } cairo_set_source (cr, fgpattern->cobj()); - cairo_rectangle (cr, 1, last_peak_rect.y, pixwidth, last_peak_rect.height); + cairo_rectangle (cr, last_peak_rect.x, last_peak_rect.y, last_peak_rect.width, last_peak_rect.height); + + if (bright_hold && !no_rgba_overlay) { + cairo_fill_preserve (cr); + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.3); + } + cairo_fill (cr); + + } else { + last_peak_rect.width = 0; + last_peak_rect.height = 0; + } + + cairo_destroy (cr); + + return TRUE; +} + +bool +FastMeter::horizontal_expose (GdkEventExpose* ev) +{ + Glib::RefPtr<Gdk::Window> win = get_window (); + gint right_of_meter; + GdkRectangle intersection; + GdkRectangle background; + + cairo_t* cr = gdk_cairo_create (get_window ()->gobj()); + + cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height); + cairo_clip (cr); + + cairo_set_source_rgb (cr, 0, 0, 0); // black + rounded_rectangle (cr, 0, 0, pixwidth + 2, pixheight + 2, 2); + cairo_stroke (cr); + + right_of_meter = (gint) floor (pixwidth * current_level); + + /* reset the height & origin of the rect that needs to show the pixbuf + */ + + pixrect.width = right_of_meter; + + background.x = 1 + right_of_meter; + background.y = 1; + background.width = pixwidth - right_of_meter; + background.height = pixheight; + + if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) { + cairo_set_source (cr, bgpattern->cobj()); + cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height); + cairo_fill (cr); + } + + if (gdk_rectangle_intersect (&pixrect, &ev->area, &intersection)) { + cairo_set_source (cr, fgpattern->cobj()); + cairo_rectangle (cr, intersection.x, intersection.y, intersection.width, intersection.height); + cairo_fill (cr); + } + + // draw peak bar + + if (hold_state) { + last_peak_rect.y = 1; + last_peak_rect.height = pixheight; + const int xpos = floor (pixwidth * current_peak); + if (bright_hold || (_styleflags & 2)) { + last_peak_rect.width = min(3, xpos ); + } else { + last_peak_rect.width = min(2, xpos ); + } + last_peak_rect.x = 1 + max(0, xpos - last_peak_rect.width); + + cairo_set_source (cr, fgpattern->cobj()); + cairo_rectangle (cr, last_peak_rect.x, last_peak_rect.y, last_peak_rect.width, last_peak_rect.height); if (bright_hold && !no_rgba_overlay) { cairo_fill_preserve (cr); @@ -444,6 +693,8 @@ FastMeter::set (float lvl, float peak) float old_level = current_level; float old_peak = current_peak; + if (pixwidth <= 0 || pixheight <=0) return; + if (peak == -1) { if (lvl >= current_peak) { current_peak = lvl; @@ -475,7 +726,11 @@ FastMeter::set (float lvl, float peak) return; } - queue_vertical_redraw (win, old_level); + if (orientation == Vertical) { + queue_vertical_redraw (win, old_level); + } else { + queue_horizontal_redraw (win, old_level); + } } void @@ -538,8 +793,8 @@ FastMeter::queue_vertical_redraw (const Glib::RefPtr<Gdk::Window>& win, float ol } rect.x = 1; rect.y = max(1, 1 + pixheight - (gint) floor (pixheight * current_peak)); - if (bright_hold) { - rect.height = max(0, min(4, pixheight - last_peak_rect.y -1 )); + if (bright_hold || (_styleflags & 2)) { + rect.height = max(0, min(3, pixheight - last_peak_rect.y -1 )); } else { rect.height = max(0, min(2, pixheight - last_peak_rect.y -1 )); } @@ -557,13 +812,88 @@ FastMeter::queue_vertical_redraw (const Glib::RefPtr<Gdk::Window>& win, float ol } void +FastMeter::queue_horizontal_redraw (const Glib::RefPtr<Gdk::Window>& win, float old_level) +{ + GdkRectangle rect; + + gint new_right = (gint) floor (pixwidth * current_level); + + rect.height = pixheight; + rect.y = 1; + + if (current_level > old_level) { + rect.x = 1 + pixrect.width; + /* colored/pixbuf got larger, just draw the new section */ + rect.width = new_right - pixrect.width; + } else { + /* it got smaller, compute the difference */ + rect.x = 1 + new_right; + /* rect.height is the old.x (smaller) minus the new.x (larger) */ + rect.width = pixrect.width - new_right; + } + + GdkRegion* region = 0; + bool queue = false; + + if (rect.height != 0) { + + /* ok, first region to draw ... */ + + region = gdk_region_rectangle (&rect); + queue = true; + } + + /* redraw the last place where the last peak hold bar was; + the next expose will draw the new one whether its part of + expose region or not. + */ + + if (last_peak_rect.width * last_peak_rect.height != 0) { + if (!queue) { + region = gdk_region_new (); + queue = true; + } + gdk_region_union_with_rect (region, &last_peak_rect); + } + + if (hold_state && current_peak > 0) { + if (!queue) { + region = gdk_region_new (); + queue = true; + } + rect.y = 1; + rect.height = pixheight; + const int xpos = floor (pixwidth * current_peak); + if (bright_hold || (_styleflags & 2)) { + rect.width = min(3, xpos); + } else { + rect.width = min(2, xpos); + } + rect.x = 1 + max(0, xpos - rect.width); + gdk_region_union_with_rect (region, &rect); + } + + if (queue) { + gdk_window_invalidate_region (win->gobj(), region, true); + } + if (region) { + gdk_region_destroy(region); + region = 0; + } +} + +void FastMeter::set_highlight (bool onoff) { if (highlight == onoff) { return; } highlight = onoff; - bgpattern = request_vertical_background (request_width, pixheight, highlight ? _bgh : _bgc, highlight); + if (orientation == Vertical) { + bgpattern = request_vertical_background (pixwidth + 2, pixheight + 2, highlight ? _bgh : _bgc, highlight); + } else { + bgpattern = request_horizontal_background (pixwidth + 2, pixheight + 2, highlight ? _bgh : _bgc, highlight); + } queue_draw (); } diff --git a/libs/gtkmm2ext/gtkmm2ext/fastmeter.h b/libs/gtkmm2ext/gtkmm2ext/fastmeter.h index 15c962deb4..8070748963 100644 --- a/libs/gtkmm2ext/gtkmm2ext/fastmeter.h +++ b/libs/gtkmm2ext/gtkmm2ext/fastmeter.h @@ -47,7 +47,8 @@ class FastMeter : public Gtk::DrawingArea { float stp0 = 55.0, // log_meter(-18); float stp1 = 77.5, // log_meter(-9); float stp2 = 92.5, // log_meter(-3); // 95.0, // log_meter(-2); - float stp3 = 100.0 + float stp3 = 100.0, + int styleflags = 3 ); virtual ~FastMeter (); @@ -67,7 +68,6 @@ protected: bool on_expose_event (GdkEventExpose*); void on_size_request (GtkRequisition*); void on_size_allocate (Gtk::Allocation&); - private: Cairo::RefPtr<Cairo::Pattern> fgpattern; @@ -79,6 +79,7 @@ private: int _clr[10]; int _bgc[2]; int _bgh[2]; + int _styleflags; Orientation orientation; GdkRectangle pixrect; @@ -94,19 +95,30 @@ private: bool highlight; bool vertical_expose (GdkEventExpose*); + void vertical_size_request (GtkRequisition*); + void vertical_size_allocate (Gtk::Allocation&); void queue_vertical_redraw (const Glib::RefPtr<Gdk::Window>&, float); + bool horizontal_expose (GdkEventExpose*); + void horizontal_size_request (GtkRequisition*); + void horizontal_size_allocate (Gtk::Allocation&); + void queue_horizontal_redraw (const Glib::RefPtr<Gdk::Window>&, float); + static bool no_rgba_overlay; static Cairo::RefPtr<Cairo::Pattern> generate_meter_pattern ( - int w, int h, int *clr, float *stp, bool shade); + int, int, int *, float *, int, bool); static Cairo::RefPtr<Cairo::Pattern> request_vertical_meter ( - int w, int h, int *clr, float *stp, bool shade); + int, int, int *, float *, int); + static Cairo::RefPtr<Cairo::Pattern> request_horizontal_meter ( + int, int, int *, float *, int); static Cairo::RefPtr<Cairo::Pattern> generate_meter_background ( - int w, int h, int *bgc, bool shade); + int, int, int *, bool, bool); static Cairo::RefPtr<Cairo::Pattern> request_vertical_background ( - int w, int h, int *bgc, bool shade); + int, int, int *, bool); + static Cairo::RefPtr<Cairo::Pattern> request_horizontal_background ( + int, int, int *, bool); struct Pattern10MapKey { Pattern10MapKey ( @@ -114,38 +126,45 @@ private: float stp0, float stp1, float stp2, float stp3, int c0, int c1, int c2, int c3, int c4, int c5, int c6, int c7, - int c8, int c9 + int c8, int c9, int st ) : dim(w, h) , stp(stp0, stp1, stp2, stp3) , cols(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) + , style(st) {} inline bool operator<(const Pattern10MapKey& rhs) const { return (dim < rhs.dim) || (dim == rhs.dim && stp < rhs.stp) - || (dim == rhs.dim && stp == rhs.stp && cols < rhs.cols); + || (dim == rhs.dim && stp == rhs.stp && cols < rhs.cols) + || (dim == rhs.dim && stp == rhs.stp && cols == rhs.cols && style < rhs.style); } boost::tuple<int, int> dim; boost::tuple<float, float, float, float> stp; boost::tuple<int, int, int, int, int, int, int, int, int, int> cols; + int style; }; typedef std::map<Pattern10MapKey, Cairo::RefPtr<Cairo::Pattern> > Pattern10Map; struct PatternBgMapKey { - PatternBgMapKey (int w, int h, int c0, int c1) + PatternBgMapKey (int w, int h, int c0, int c1, bool shade) : dim(w, h) , cols(c0, c1) + , sh(shade) {} inline bool operator<(const PatternBgMapKey& rhs) const { - return (dim < rhs.dim) || (dim == rhs.dim && cols < rhs.cols); + return (dim < rhs.dim) || (dim == rhs.dim && cols < rhs.cols) || (dim == rhs.dim && cols == rhs.cols && (sh && !rhs.sh)); } boost::tuple<int, int> dim; boost::tuple<int, int> cols; + bool sh; }; typedef std::map<PatternBgMapKey, Cairo::RefPtr<Cairo::Pattern> > PatternBgMap; static Pattern10Map vm_pattern_cache; static PatternBgMap vb_pattern_cache; + static Pattern10Map hm_pattern_cache; + static PatternBgMap hb_pattern_cache; static int min_pattern_metric_size; // min dimension for axis that displays the meter level static int max_pattern_metric_size; // max dimension for axis that displays the meter level }; diff --git a/libs/gtkmm2ext/gtkmm2ext/keyboard.h b/libs/gtkmm2ext/gtkmm2ext/keyboard.h index 84988e1525..2c6b026a42 100644 --- a/libs/gtkmm2ext/gtkmm2ext/keyboard.h +++ b/libs/gtkmm2ext/gtkmm2ext/keyboard.h @@ -164,7 +164,7 @@ class Keyboard : public sigc::trackable, PBD::Stateful } }; - sigc::signal0<void> ShiftReleased; + sigc::signal0<void> ZoomVerticalModifierReleased; protected: static Keyboard* _the_keyboard; diff --git a/libs/gtkmm2ext/keyboard.cc b/libs/gtkmm2ext/keyboard.cc index f694471d9a..5087f61a23 100644 --- a/libs/gtkmm2ext/keyboard.cc +++ b/libs/gtkmm2ext/keyboard.cc @@ -248,12 +248,15 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) keyval = event->keyval; } - if (keyval == GDK_Shift_L) { + if (event->state & ScrollZoomVerticalModifier) { /* There is a special and rather hacky situation in Editor which makes - it useful to know when a shift key has been released, so emit a signal - here (see Editor::_stepping_axis_view) + it useful to know when the modifier key for vertical zoom has been + released, so emit a signal here (see Editor::_stepping_axis_view). + Note that the state bit for the modifier key is set for the key-up + event when the modifier is released, but not the key-down when it + is pressed, so we get here on key-up, which is what we want. */ - ShiftReleased (); /* EMIT SIGNAL */ + ZoomVerticalModifierReleased (); /* EMIT SIGNAL */ } if (event->type == GDK_KEY_PRESS) { diff --git a/libs/pbd/pbd/ringbuffer.h b/libs/pbd/pbd/ringbuffer.h index a1a6151542..bb5485a8f3 100644 --- a/libs/pbd/pbd/ringbuffer.h +++ b/libs/pbd/pbd/ringbuffer.h @@ -233,6 +233,7 @@ RingBuffer<T>::get_read_vector (typename RingBuffer<T>::rw_vector *vec) vec->buf[0] = &buf[r]; vec->len[0] = free_cnt; + vec->buf[1] = 0; vec->len[1] = 0; } } diff --git a/libs/pbd/pbd/stl_delete.h b/libs/pbd/pbd/stl_delete.h index ac2161560c..bca0ea9e21 100644 --- a/libs/pbd/pbd/stl_delete.h +++ b/libs/pbd/pbd/stl_delete.h @@ -21,17 +21,10 @@ #define __libmisc_stl_delete_h__ -#if __clang__ && __APPLE__ && __cplusplus >= 201103L -#include <vector> -#ifndef _CPP_VECTOR -#define _CPP_VECTOR -#endif -#endif - /* To actually use any of these deletion functions, you need to first include the revelant container type header. */ -#if defined(_CPP_VECTOR) || defined(_GLIBCXX_VECTOR) || defined(__SGI_STL_VECTOR) +#if defined(_CPP_VECTOR) || defined(_GLIBCXX_VECTOR) || defined(__SGI_STL_VECTOR) || defined(_LIBCPP_VECTOR) template<class T> void vector_delete (std::vector<T *> *vec) { typename std::vector<T *>::iterator i; @@ -41,7 +34,7 @@ template<class T> void vector_delete (std::vector<T *> *vec) } vec->clear (); } -#endif // _CPP_VECTOR || _GLIBCXX_VECTOR || __SGI_STL_VECTOR +#endif // _CPP_VECTOR || _GLIBCXX_VECTOR || __SGI_STL_VECTOR || _LIBCPP_VECTOR #if defined(_CPP_MAP) || defined(_GLIBCXX_MAP) || defined(__SGI_STL_MAP) template<class K, class T> void map_delete (std::map<K, T *> *m) diff --git a/libs/surfaces/osc/osc.h b/libs/surfaces/osc/osc.h index 5c3422799b..84dd0d9c86 100644 --- a/libs/surfaces/osc/osc.h +++ b/libs/surfaces/osc/osc.h @@ -188,7 +188,7 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest> static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \ return static_cast<OSC*>(user_data)->cb_ ## name (path, types, argv, argc, data); \ } \ - int cb_ ## name (const char *, const char *, lo_arg **argv, int argc, void *data) { \ + int cb_ ## name (const char *, const char *, lo_arg **argv, int argc, void *) { \ if (argc > 1) { \ name (argv[0]->arg1type, argv[1]->arg2type,argv[2]->arg3type); \ } \ @@ -199,7 +199,7 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest> static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \ return static_cast<OSC*>(user_data)->cb_ ## name (path, types, argv, argc, data); \ } \ - int cb_ ## name (const char *, const char *, lo_arg **argv, int argc, void *data) { \ + int cb_ ## name (const char *, const char *, lo_arg **argv, int argc, void *) { \ if (argc > 1) { \ name (argv[0]->arg1type, argv[1]->arg2type,argv[2]->arg3type,argv[3]->arg4type); \ } \ |