fix merge conflict from master

This commit is contained in:
Paul Davis 2013-07-31 20:11:15 -04:00
commit 6a436fd826
87 changed files with 4623 additions and 1814 deletions

View file

@ -989,3 +989,25 @@ style "default_toggle_button"
bg[ACTIVE] = @@COLPREFIX@_contrasting_indicator
fg[ACTIVE] = @@COLPREFIX@_darkest
}
style "meter_strip_dpm" = "default"
{
}
style "meter_strip_ppm" = "default"
{
bg[NORMAL] = { 0.1, 0.1, 0.1 }
fg[NORMAL] = { 1.0, 1.0, 1.0 }
}
style "meter_strip_vu" = "default"
{
bg[NORMAL] = { .84, .77, .58 }
fg[NORMAL] = { 0.0, 0.0, 0.0 }
}
style "meter_strip_sep" = "default"
{
bg[NORMAL] = { 0.0, 0.0, 0.0 }
}

View file

@ -221,7 +221,8 @@
<Option name="solo safe: led active" value="ff0000ff"/>
<Option name="solo safe: text" value="c7c7d8ff"/>
<Option name="solo safe: text active" value="c8c8d9ff"/>
<Option name="meterbridge peaklabel" value="cc4422ff"/>
<Option name="meterbridge peaklabel" value="ff1111ff"/>
<Option name="meter color BBC" value="ffa500ff"/>
<Option name="meterbridge peakindicator: fill start" value="444444ff"/>
<Option name="meterbridge peakindicator: fill end" value="333333ff"/>
<Option name="meterbridge peakindicator on: fill start" value="ff0000ff"/>

View file

@ -290,6 +290,11 @@ widget "*PluginLoadButton" style:highest "small_button"
widget "*PluginLoadButton*" style:highest "small_button"
widget "*PluginEditorButton" style:highest "default_toggle_button"
widget "*meterstripPPM" style:highest "meter_strip_ppm"
widget "*meterstripDPM" style:highest "meter_strip_dpm"
widget "*meterstripVU" style:highest "meter_strip_vu"
widget "*BlackSeparator" style:highest "meter_strip_sep"
widget "*MetricDialogFrame" style:highest "base_frame"
widget "*MetricEntry" style:highest "medium_bold_entry"
widget "*MetricButton" style:highest "default_button"

View file

@ -185,6 +185,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
, solo_alert_button (_("solo"))
, feedback_alert_button (_("feedback"))
, editor_meter(0)
, speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
, theme_manager (X_("theme-manager"), _("Theme Manager"))
, key_editor (X_("key-editor"), _("Key Bindings"))
@ -1037,6 +1039,9 @@ ARDOUR_UI::every_point_zero_something_seconds ()
// august 2007: actual update frequency: 25Hz (40ms), not 100Hz
SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
if (editor_meter) {
editor_meter->update_meters();
}
return TRUE;
}
@ -1492,7 +1497,14 @@ ARDOUR_UI::open_session ()
open_session_selector->set_current_folder(Config->get_default_session_parent_dir());
}
open_session_selector->add_shortcut_folder (Config->get_default_session_parent_dir());
string default_session_folder = Config->get_default_session_parent_dir();
try {
/* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
open_session_selector->add_shortcut_folder (default_session_folder);
}
catch (Glib::Error & e) {
std::cerr << "open_session_selector->add_shortcut_folder (" << default_session_folder << ") threw Glib::Error " << e.what() << std::endl;
}
FileFilter session_filter;
session_filter.add_pattern ("*.ardour");
@ -4119,3 +4131,29 @@ ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_pat
msg.run ();
}
void
ARDOUR_UI::reset_peak_display ()
{
if (!_session || !_session->master_out() || !editor_meter) return;
editor_meter->clear_meters();
}
void
ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
{
if (!_session || !_session->master_out()) return;
if (group == _session->master_out()->route_group()) {
reset_peak_display ();
}
}
void
ARDOUR_UI::reset_route_peak_display (Route* route)
{
if (!_session || !_session->master_out()) return;
if (_session->master_out().get() == route) {
reset_peak_display ();
}
}

View file

@ -104,6 +104,7 @@ class SpeakerDialog;
class ThemeManager;
class TimeInfoBox;
class MidiTracer;
class LevelMeterHBox;
class GlobalPortMatrixWindow;
class GUIObjectState;
@ -281,6 +282,10 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void get_process_buffers ();
void drop_process_buffers ();
void reset_peak_display ();
void reset_route_peak_display (ARDOUR::Route*);
void reset_group_peak_display (ARDOUR::RouteGroup*);
const std::string& announce_string() const { return _announce_string; }
protected:
@ -444,6 +449,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
ArdourButton feedback_alert_button;
Gtk::VBox alert_box;
Gtk::VBox meter_box;
LevelMeterHBox * editor_meter;
void solo_blink (bool);
void sync_blink (bool);

View file

@ -417,6 +417,7 @@ ARDOUR_UI::setup_transport ()
transport_tearoff_hbox.pack_start (_editor_transport_box, false, false);
}
transport_tearoff_hbox.pack_start (alert_box, false, false);
transport_tearoff_hbox.pack_start (meter_box, false, false);
if (Profile->get_sae()) {
Image* img = manage (new Image ((::get_icon (X_("sae")))));

View file

@ -43,6 +43,7 @@
#include "keyeditor.h"
#include "location_ui.h"
#include "main_clock.h"
#include "meter_patterns.h"
#include "midi_tracer.h"
#include "mixer_ui.h"
#include "public_editor.h"
@ -190,6 +191,26 @@ ARDOUR_UI::set_session (Session *s)
point_zero_something_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_something_seconds), 40);
update_format ();
if (editor_meter) {
meter_box.remove(*editor_meter);
delete editor_meter;
editor_meter = 0;
}
if (_session && _session->master_out()) {
editor_meter = new LevelMeterHBox(_session);
editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
editor_meter->clear_meters();
editor_meter->set_type (_session->master_out()->meter_type());
editor_meter->setup_meters (30, 12, 6);
meter_box.pack_start(*editor_meter);
ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display));
ArdourMeter::ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_route_peak_display));
ArdourMeter::ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_group_peak_display));
}
}
int
@ -229,6 +250,12 @@ ARDOUR_UI::unload_session (bool hide_stuff)
point_one_second_connection.disconnect ();
point_zero_something_second_connection.disconnect();
if (editor_meter) {
meter_box.remove(*editor_meter);
delete editor_meter;
editor_meter = 0;
}
ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
rec_button.set_sensitive (false);

View file

@ -2013,7 +2013,7 @@ framepos_t
AudioClock::frame_duration_from_bbt_string (framepos_t pos, const string& str) const
{
if (_session == 0) {
error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
error << "AudioClock::frame_duration_from_bbt_string() called with BBT mode but without session!" << endmsg;
return 0;
}

View file

@ -65,6 +65,7 @@ CANVAS_VARIABLE(canvasvar_MeasureLineBar, "measure line bar")
CANVAS_VARIABLE(canvasvar_MeasureLineBeat, "measure line beat")
CANVAS_VARIABLE(canvasvar_MeterBar, "meter bar")
CANVAS_VARIABLE(canvasvar_MeterBridgePeakLabel, "meterbridge peaklabel")
CANVAS_VARIABLE(canvasvar_MeterColorBBC, "meter color BBC")
CANVAS_VARIABLE(canvasvar_MeterColor0, "meter fill: 0")
CANVAS_VARIABLE(canvasvar_MeterColor1, "meter fill: 1")
CANVAS_VARIABLE(canvasvar_MeterColor2, "meter fill: 2")

View file

@ -697,7 +697,7 @@ Editor::Editor ()
signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
Gtkmm2ext::Keyboard::the_keyboard().ShiftReleased.connect (sigc::mem_fun (*this, &Editor::shift_key_released));
Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
/* allow external control surfaces/protocols to do various things */
@ -5499,7 +5499,7 @@ Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* ev
}
void
Editor::shift_key_released ()
Editor::zoom_vertical_modifier_released()
{
_stepping_axis_view = 0;
}

View file

@ -1249,13 +1249,17 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
bool idle_drop_paths (std::vector<std::string> paths, framepos_t frame, double ypos, bool copy);
void drop_paths_part_two (const std::vector<std::string>& paths, framepos_t frame, double ypos, bool copy);
int import_sndfiles (std::vector<std::string> paths, Editing::ImportMode mode, ARDOUR::SrcQuality, framepos_t& pos,
int import_sndfiles (std::vector<std::string> paths, Editing::ImportDisposition, Editing::ImportMode mode,
ARDOUR::SrcQuality, framepos_t& pos,
int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::Track>&, bool);
int embed_sndfiles (std::vector<std::string> paths, bool multiple_files, bool& check_sample_rate, Editing::ImportMode mode,
int embed_sndfiles (std::vector<std::string> paths, bool multiple_files, bool& check_sample_rate,
Editing::ImportDisposition disposition, Editing::ImportMode mode,
framepos_t& pos, int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::Track>&);
int add_sources (std::vector<std::string> paths, ARDOUR::SourceList& sources, framepos_t& pos, Editing::ImportMode,
int add_sources (std::vector<std::string> paths, ARDOUR::SourceList& sources, framepos_t& pos,
Editing::ImportDisposition, Editing::ImportMode,
int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::Track>&, bool add_channel_suffix);
int finish_bringing_in_material (boost::shared_ptr<ARDOUR::Region> region, uint32_t, uint32_t, framepos_t& pos, Editing::ImportMode mode,
boost::shared_ptr<ARDOUR::Track>& existing_track);
@ -2078,15 +2082,16 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
bool _control_point_toggled_on_press;
/** This is used by TimeAxisView to keep a track of the TimeAxisView that is currently being
stepped in height using Shift-Scrollwheel. When a scroll event occurs, we do the step on
this _stepping_axis_view if it is non-0 (and we set up this _stepping_axis_view with the
TimeAxisView underneath the mouse if it is 0). Then Editor resets _stepping_axis_view when
the shift key is released. In this (hacky) way, pushing shift and moving the scroll wheel
will operate on the same track until shift is released (rather than skipping about to whatever
happens to be underneath the mouse at the time).
stepped in height using ScrollZoomVerticalModifier+Scrollwheel. When a scroll event
occurs, we do the step on this _stepping_axis_view if it is non-0 (and we set up this
_stepping_axis_view with the TimeAxisView underneath the mouse if it is 0). Then Editor
resets _stepping_axis_view when the modifier key is released. In this (hacky) way,
pushing the modifier key and moving the scroll wheel will operate on the same track
until the key is released (rather than skipping about to whatever happens to be
underneath the mouse at the time).
*/
TimeAxisView* _stepping_axis_view;
void shift_key_released ();
void zoom_vertical_modifier_released();
friend class Drag;
friend class RegionDrag;

View file

@ -264,7 +264,7 @@ Editor::get_nth_selected_midi_track (int nth) const
}
void
Editor::do_import (vector<string> paths, ImportDisposition chns, ImportMode mode, SrcQuality quality, framepos_t& pos)
Editor::do_import (vector<string> paths, ImportDisposition disposition, ImportMode mode, SrcQuality quality, framepos_t& pos)
{
boost::shared_ptr<Track> track;
vector<string> to_import;
@ -280,7 +280,7 @@ Editor::do_import (vector<string> paths, ImportDisposition chns, ImportMode mode
bool ok = true;
if (chns == Editing::ImportMergeFiles) {
if (disposition == Editing::ImportMergeFiles) {
/* create 1 region from all paths, add to 1 track,
ignore "track"
@ -299,7 +299,7 @@ Editor::do_import (vector<string> paths, ImportDisposition chns, ImportMode mode
ok = false;
} else {
ipw.show ();
ok = (import_sndfiles (paths, mode, quality, pos, 1, 1, track, false) == 0);
ok = (import_sndfiles (paths, disposition, mode, quality, pos, 1, 1, track, false) == 0);
}
} else {
@ -334,7 +334,7 @@ Editor::do_import (vector<string> paths, ImportDisposition chns, ImportMode mode
ipw.show ();
switch (chns) {
switch (disposition) {
case Editing::ImportDistinctFiles:
to_import.clear ();
@ -344,7 +344,7 @@ Editor::do_import (vector<string> paths, ImportDisposition chns, ImportMode mode
track = get_nth_selected_audio_track (nth++);
}
ok = (import_sndfiles (to_import, mode, quality, pos, 1, -1, track, replace) == 0);
ok = (import_sndfiles (to_import, disposition, mode, quality, pos, 1, -1, track, replace) == 0);
break;
case Editing::ImportDistinctChannels:
@ -352,7 +352,7 @@ Editor::do_import (vector<string> paths, ImportDisposition chns, ImportMode mode
to_import.clear ();
to_import.push_back (*a);
ok = (import_sndfiles (to_import, mode, quality, pos, -1, -1, track, replace) == 0);
ok = (import_sndfiles (to_import, disposition, mode, quality, pos, -1, -1, track, replace) == 0);
break;
case Editing::ImportSerializeFiles:
@ -360,7 +360,7 @@ Editor::do_import (vector<string> paths, ImportDisposition chns, ImportMode mode
to_import.clear ();
to_import.push_back (*a);
ok = (import_sndfiles (to_import, mode, quality, pos, 1, 1, track, replace) == 0);
ok = (import_sndfiles (to_import, disposition, mode, quality, pos, 1, 1, track, replace) == 0);
break;
case Editing::ImportMergeFiles:
@ -378,7 +378,7 @@ Editor::do_import (vector<string> paths, ImportDisposition chns, ImportMode mode
}
void
Editor::do_embed (vector<string> paths, ImportDisposition chns, ImportMode mode, framepos_t& pos)
Editor::do_embed (vector<string> paths, ImportDisposition import_as, ImportMode mode, framepos_t& pos)
{
boost::shared_ptr<Track> track;
bool check_sample_rate = true;
@ -388,7 +388,7 @@ Editor::do_embed (vector<string> paths, ImportDisposition chns, ImportMode mode,
int nth = 0;
bool use_timestamp = (pos == -1);
switch (chns) {
switch (import_as) {
case Editing::ImportDistinctFiles:
for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
@ -404,7 +404,7 @@ Editor::do_embed (vector<string> paths, ImportDisposition chns, ImportMode mode,
track = get_nth_selected_audio_track (nth++);
}
if (embed_sndfiles (to_embed, multi, check_sample_rate, mode, pos, 1, -1, track) < -1) {
if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, 1, -1, track) < -1) {
goto out;
}
}
@ -421,14 +421,14 @@ Editor::do_embed (vector<string> paths, ImportDisposition chns, ImportMode mode,
to_embed.clear ();
to_embed.push_back (*a);
if (embed_sndfiles (to_embed, multi, check_sample_rate, mode, pos, -1, -1, track) < -1) {
if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, -1, -1, track) < -1) {
goto out;
}
}
break;
case Editing::ImportMergeFiles:
if (embed_sndfiles (paths, multi, check_sample_rate, mode, pos, 1, 1, track) < -1) {
if (embed_sndfiles (paths, multi, check_sample_rate, import_as, mode, pos, 1, 1, track) < -1) {
goto out;
}
break;
@ -444,7 +444,7 @@ Editor::do_embed (vector<string> paths, ImportDisposition chns, ImportMode mode,
to_embed.clear ();
to_embed.push_back (*a);
if (embed_sndfiles (to_embed, multi, check_sample_rate, mode, pos, 1, 1, track) < -1) {
if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, 1, 1, track) < -1) {
goto out;
}
}
@ -460,7 +460,7 @@ Editor::do_embed (vector<string> paths, ImportDisposition chns, ImportMode mode,
}
int
Editor::import_sndfiles (vector<string> paths, ImportMode mode, SrcQuality quality, framepos_t& pos,
Editor::import_sndfiles (vector<string> paths, ImportDisposition disposition, ImportMode mode, SrcQuality quality, framepos_t& pos,
int target_regions, int target_tracks, boost::shared_ptr<Track>& track, bool replace)
{
import_status.paths = paths;
@ -501,6 +501,7 @@ Editor::import_sndfiles (vector<string> paths, ImportMode mode, SrcQuality quali
import_status.paths,
import_status.sources,
import_status.pos,
disposition,
import_status.mode,
import_status.target_regions,
import_status.target_tracks,
@ -518,7 +519,8 @@ Editor::import_sndfiles (vector<string> paths, ImportMode mode, SrcQuality quali
int
Editor::embed_sndfiles (vector<string> paths, bool multifile,
bool& check_sample_rate, ImportMode mode, framepos_t& pos, int target_regions, int target_tracks,
bool& check_sample_rate, ImportDisposition disposition, ImportMode mode,
framepos_t& pos, int target_regions, int target_tracks,
boost::shared_ptr<Track>& track)
{
boost::shared_ptr<AudioFileSource> source;
@ -603,6 +605,7 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile,
set_canvas_cursor (_cursors->wait);
for (int n = 0; n < finfo.channels; ++n) {
try {
/* check if we have this thing embedded already */
@ -638,7 +641,8 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile,
goto out;
}
ret = add_sources (paths, sources, pos, mode, target_regions, target_tracks, track, true);
ret = add_sources (paths, sources, pos, disposition, mode, target_regions, target_tracks, track, true);
out:
set_canvas_cursor (current_canvas_cursor);
@ -646,7 +650,7 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile,
}
int
Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos, ImportMode mode,
Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos, ImportDisposition disposition, ImportMode mode,
int target_regions, int target_tracks, boost::shared_ptr<Track>& track, bool /*add_channel_suffix*/)
{
vector<boost::shared_ptr<Region> > regions;
@ -707,10 +711,43 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (*x);
if (fs) {
region_name = region_name_from_path (fs->path(), false, false, sources.size(), n);
} else{
region_name = (*x)->name();
if (sources.size() > 1 && disposition == ImportDistinctChannels) {
/* generate a per-channel region name so that things work as
* intended
*/
string path;
if (fs) {
region_name = basename_nosuffix (fs->path());
} else {
region_name = (*x)->name();
}
switch (sources.size()) {
/* zero and one channel handled
by previous if() condition
*/
case 2:
if (n == 0) {
region_name += "-L";
} else {
region_name += "-R";
}
break;
default:
region_name += (char) '-';
region_name += (char) ('1' + n);
break;
}
} else {
if (fs) {
region_name = region_name_from_path (fs->path(), false, false, sources.size(), n);
} else{
region_name = (*x)->name();
}
}
PropertyList plist;

View file

@ -2373,6 +2373,7 @@ CursorDrag::fake_locate (framepos_t t)
framepos_t const f = _editor->playhead_cursor->current_frame;
s->send_mmc_locate (f);
s->send_full_time_code (f);
s->send_song_position_pointer (f);
}
show_verbose_cursor_time (t);

View file

@ -6950,7 +6950,7 @@ Editor::uncombine_regions ()
void
Editor::toggle_midi_input_active (bool flip_others)
{
bool onoff;
bool onoff = false;
boost::shared_ptr<RouteList> rl (new RouteList);
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {

View file

@ -111,7 +111,7 @@ Editor::embed_audio_from_video (std::string path, framepos_t n)
ipw.show ();
boost::shared_ptr<ARDOUR::Track> track;
bool ok = (import_sndfiles (paths, Editing::ImportAsTrack, ARDOUR::SrcBest, n, 1, 1, track, false) == 0);
bool ok = (import_sndfiles (paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, ARDOUR::SrcBest, n, 1, 1, track, false) == 0);
if (ok && track) {
boost::shared_ptr<ARDOUR::Playlist> pl = track->playlist();
pl->find_next_region(n, ARDOUR::End, 0)->set_video_locked(true);

View file

@ -167,8 +167,12 @@ EngineControl::EngineControl ()
strings.clear ();
strings.push_back (_("None"));
#ifdef __APPLE__
strings.push_back (_("coremidi"));
#else
strings.push_back (_("seq"));
strings.push_back (_("raw"));
#endif
set_popdown_strings (midi_driver_combo, strings);
midi_driver_combo.set_active_text (strings.front ());
@ -439,6 +443,12 @@ EngineControl::build_command_line (vector<string>& cmd)
cmd.push_back ("-T"); // temporary */
/* setup coremidi before the driver, otherwise jack won't start */
if (midi_driver_combo.get_active_text() == _("coremidi")) {
cmd.push_back ("-X coremidi");
}
/* next the driver */
cmd.push_back ("-d");

View file

@ -87,7 +87,7 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
, fps_checkbox (_("Override FPS (Default is to retain FPS from the input video file):"))
, meta_checkbox (_("Include Session Metadata"))
#if 1 /* tentative debug mode */
, debug_checkbox (_("Enable Debug Mode: Print ffmpeg Command & Output to stdout."))
, debug_checkbox (_("Debug Mode: Print ffmpeg command and output to stdout."))
#endif
{
set_session (s);

View file

@ -84,7 +84,7 @@ GainMeterBase::GainMeterBase (Session* s, bool horizontal, int fader_length, int
gain_slider = manage (new VSliderController (&gain_adjustment, fader_length, fader_girth, false));
}
level_meter = new LevelMeter(_session);
level_meter = new LevelMeterHBox(_session);
level_meter->ButtonPress.connect_same_thread (_level_meter_connection, boost::bind (&GainMeterBase::level_meter_button_press, this, _1));
meter_metric_area.signal_button_press_event().connect (sigc::mem_fun (*this, &GainMeterBase::level_meter_button_press));
@ -526,9 +526,12 @@ GainMeterBase::gain_changed ()
void
GainMeterBase::set_meter_strip_name (const char * name)
{
char tmp[256];
meter_metric_area.set_name (name);
meter_ticks1_area.set_name (name);
meter_ticks2_area.set_name (name);
sprintf(tmp, "Mark%sLeft", name);
meter_ticks1_area.set_name (tmp);
sprintf(tmp, "Mark%sRight", name);
meter_ticks2_area.set_name (tmp);
}
void
@ -950,6 +953,8 @@ GainMeter::GainMeter (Session* s, int fader_length)
meter_hbox.pack_start (meter_metric_area, false, false);
}
GainMeter::~GainMeter () { }
void
GainMeter::set_controls (boost::shared_ptr<Route> r,
boost::shared_ptr<PeakMeter> meter,
@ -977,6 +982,10 @@ GainMeter::set_controls (boost::shared_ptr<Route> r,
}
if (_route) {
_route->active_changed.connect (model_connections, invalidator (*this), boost::bind (&GainMeter::route_active_changed, this), gui_context ());
}
/*
if we have a non-hidden route (ie. we're not the click or the auditioner),
pack some route-dependent stuff.
@ -1013,19 +1022,31 @@ GainMeter::get_gm_width ()
gint
GainMeter::meter_metrics_expose (GdkEventExpose *ev)
{
return meter_expose_metrics(ev, _types, &meter_metric_area);
if (!_route) {
if (_types.empty()) { _types.push_back(DataType::AUDIO); }
return meter_expose_metrics(ev, MeterPeak, _types, &meter_metric_area);
}
return meter_expose_metrics(ev, _route->meter_type(), _types, &meter_metric_area);
}
gint
GainMeter::meter_ticks1_expose (GdkEventExpose *ev)
{
return meter_expose_ticks(ev, _types, &meter_ticks1_area);
if (!_route) {
if (_types.empty()) { _types.push_back(DataType::AUDIO); }
return meter_expose_ticks(ev, MeterPeak, _types, &meter_ticks1_area);
}
return meter_expose_ticks(ev, _route->meter_type(), _types, &meter_ticks1_area);
}
gint
GainMeter::meter_ticks2_expose (GdkEventExpose *ev)
{
return meter_expose_ticks(ev, _types, &meter_ticks2_area);
if (!_route) {
if (_types.empty()) { _types.push_back(DataType::AUDIO); }
return meter_expose_ticks(ev, MeterPeak, _types, &meter_ticks2_area);
}
return meter_expose_ticks(ev, _route->meter_type(), _types, &meter_ticks2_area);
}
boost::shared_ptr<PBD::Controllable>
@ -1067,19 +1088,22 @@ GainMeter::meter_configuration_changed (ChanCount c)
set_meter_strip_name ("AudioBusMetricsInactive");
}
}
else if (
(type == (1 << DataType::MIDI))
|| (_route && boost::dynamic_pointer_cast<MidiTrack>(_route))
) {
if (!_route || _route->active()) {
set_meter_strip_name ("MidiTrackMetrics");
} else {
set_meter_strip_name ("MidiTrackMetricsInactive");
}
}
else if (type == (1 << DataType::AUDIO)) {
if (!_route || _route->active()) {
set_meter_strip_name ("AudioTrackMetrics");
} else {
set_meter_strip_name ("AudioTrackMetricsInactive");
}
}
else if (type == (1 << DataType::MIDI)) {
if (!_route || _route->active()) {
set_meter_strip_name ("MidiTrackMetrics");
} else {
set_meter_strip_name ("MidiTrackMetricsInactive");
}
} else {
if (!_route || _route->active()) {
set_meter_strip_name ("AudioMidiTrackMetrics");
@ -1087,11 +1111,22 @@ GainMeter::meter_configuration_changed (ChanCount c)
set_meter_strip_name ("AudioMidiTrackMetricsInactive");
}
}
setup_meters();
meter_clear_pattern_cache(4);
}
void
GainMeter::route_active_changed ()
{
if (_meter) {
meter_configuration_changed (_meter->input_streams ());
}
}
void
GainMeter::meter_type_changed (MeterType t)
{
_route->set_meter_type(t);
RedrawMetrics();
}

View file

@ -89,7 +89,7 @@ class GainMeterBase : virtual public sigc::trackable, ARDOUR::SessionHandlePtr
boost::shared_ptr<PBD::Controllable> get_controllable();
LevelMeter& get_level_meter() const { return *level_meter; }
LevelMeterHBox& get_level_meter() const { return *level_meter; }
Gtkmm2ext::SliderController& get_gain_slider() const { return *gain_slider; }
/** Emitted in the GUI thread when a button is pressed over the level meter;
@ -117,7 +117,7 @@ class GainMeterBase : virtual public sigc::trackable, ARDOUR::SessionHandlePtr
Gtk::DrawingArea meter_metric_area;
Gtk::DrawingArea meter_ticks1_area;
Gtk::DrawingArea meter_ticks2_area;
LevelMeter *level_meter;
LevelMeterHBox *level_meter;
sigc::connection gain_watching;
@ -201,7 +201,7 @@ class GainMeter : public GainMeterBase, public Gtk::VBox
{
public:
GainMeter (ARDOUR::Session*, int);
~GainMeter () {}
virtual ~GainMeter ();
virtual void set_controls (boost::shared_ptr<ARDOUR::Route> route,
boost::shared_ptr<ARDOUR::PeakMeter> meter,
@ -210,6 +210,7 @@ class GainMeter : public GainMeterBase, public Gtk::VBox
int get_gm_width ();
void setup_meters (int len=0);
void set_type (ARDOUR::MeterType);
void route_active_changed ();
protected:
void hide_all_meters ();

View file

@ -22,7 +22,6 @@
#include "ardour/meter.h"
#include <gtkmm2ext/utils.h>
#include <gtkmm2ext/fastmeter.h>
#include <gtkmm2ext/barcontroller.h>
#include "midi++/manager.h"
#include "pbd/fastlog.h"
@ -44,27 +43,29 @@ using namespace Gtkmm2ext;
using namespace Gtk;
using namespace std;
LevelMeter::LevelMeter (Session* s)
: _meter (0)
LevelMeterBase::LevelMeterBase (Session* s, PBD::EventLoop::InvalidationRecord* ir, FastMeter::Orientation o)
: parent_invalidator(ir)
, _meter (0)
, _meter_orientation(o)
, regular_meter_width (6)
, meter_length (0)
, thin_meter_width(2)
{
set_session (s);
set_spacing (1);
Config->ParameterChanged.connect (_parameter_connection, invalidator (*this), boost::bind (&LevelMeter::parameter_changed, this, _1), gui_context());
UI::instance()->theme_changed.connect (sigc::mem_fun(*this, &LevelMeter::on_theme_changed));
ColorsChanged.connect (sigc::mem_fun (*this, &LevelMeter::color_handler));
Config->ParameterChanged.connect (_parameter_connection, parent_invalidator, boost::bind (&LevelMeterBase::parameter_changed, this, _1), gui_context());
UI::instance()->theme_changed.connect (sigc::mem_fun(*this, &LevelMeterBase::on_theme_changed));
ColorsChanged.connect (sigc::mem_fun (*this, &LevelMeterBase::color_handler));
max_peak = minus_infinity();
meter_type = MeterPeak;
}
void
LevelMeter::on_theme_changed()
LevelMeterBase::on_theme_changed()
{
style_changed = true;
}
LevelMeter::~LevelMeter ()
LevelMeterBase::~LevelMeterBase ()
{
for (vector<MeterInfo>::iterator i = meters.begin(); i != meters.end(); i++) {
delete (*i).meter;
@ -72,7 +73,7 @@ LevelMeter::~LevelMeter ()
}
void
LevelMeter::set_meter (PeakMeter* meter)
LevelMeterBase::set_meter (PeakMeter* meter)
{
_configuration_connection.disconnect();
_meter_type_connection.disconnect();
@ -80,13 +81,48 @@ LevelMeter::set_meter (PeakMeter* meter)
_meter = meter;
if (_meter) {
_meter->ConfigurationChanged.connect (_configuration_connection, invalidator (*this), boost::bind (&LevelMeter::configuration_changed, this, _1, _2), gui_context());
_meter->TypeChanged.connect (_meter_type_connection, invalidator (*this), boost::bind (&LevelMeter::meter_type_changed, this, _1), gui_context());
_meter->ConfigurationChanged.connect (_configuration_connection, parent_invalidator, boost::bind (&LevelMeterBase::configuration_changed, this, _1, _2), gui_context());
_meter->TypeChanged.connect (_meter_type_connection, parent_invalidator, boost::bind (&LevelMeterBase::meter_type_changed, this, _1), gui_context());
}
}
static float meter_lineup_cfg(MeterLineUp lul, float offset) {
switch (lul) {
case MeteringLineUp24:
return offset + 6.0;
case MeteringLineUp20:
return offset + 2.0;
case MeteringLineUp18:
return offset;
case MeteringLineUp15:
return offset - 3.0;
default:
break;
}
return offset;
}
static float meter_lineup(float offset) {
return meter_lineup_cfg(Config->get_meter_line_up_level(), offset);
}
static float vu_standard() {
// note - default meter config is +2dB (france)
switch (Config->get_meter_vu_standard()) {
default:
case MeteringVUfrench: // 0VU = -2dBu
return 0;
case MeteringVUamerican: // 0VU = 0dBu
return -2;
case MeteringVUstandard: // 0VU = +4dBu
return -6;
case MeteringVUeight: // 0VU = +8dBu
return -10;
}
}
float
LevelMeter::update_meters ()
LevelMeterBase::update_meters ()
{
vector<MeterInfo>::iterator i;
uint32_t n;
@ -114,7 +150,19 @@ LevelMeter::update_meters ()
const float peak = _meter->meter_level (n, meter_type);
if (meter_type == MeterPeak) {
(*i).meter->set (log_meter (peak));
} else {
} else if (meter_type == MeterIEC1NOR) {
(*i).meter->set (meter_deflect_nordic (peak + meter_lineup(0)));
} else if (meter_type == MeterIEC1DIN) {
(*i).meter->set (meter_deflect_din (peak + meter_lineup_cfg(Config->get_meter_line_up_din(), 3.0)));
} else if (meter_type == MeterIEC2BBC || meter_type == MeterIEC2EBU) {
(*i).meter->set (meter_deflect_ppm (peak + meter_lineup(0)));
} else if (meter_type == MeterVU) {
(*i).meter->set (meter_deflect_vu (peak + vu_standard() + meter_lineup(0)));
} else if (meter_type == MeterK14) {
(*i).meter->set (meter_deflect_k (peak, 14), meter_deflect_k(_meter->meter_level(n, MeterPeak), 14));
} else if (meter_type == MeterK20) {
(*i).meter->set (meter_deflect_k (peak, 20), meter_deflect_k(_meter->meter_level(n, MeterPeak), 20));
} else { // RMS
(*i).meter->set (log_meter (peak), log_meter(_meter->meter_level(n, MeterPeak)));
}
}
@ -124,9 +172,9 @@ LevelMeter::update_meters ()
}
void
LevelMeter::parameter_changed (string p)
LevelMeterBase::parameter_changed (string p)
{
ENSURE_GUI_THREAD (*this, &LevelMeter::parameter_changed, p)
ENSURE_GUI_THREAD (*this, &LevelMeterBase::parameter_changed, p)
if (p == "meter-hold") {
vector<MeterInfo>::iterator i;
@ -140,6 +188,10 @@ LevelMeter::parameter_changed (string p)
color_changed = true;
setup_meters (meter_length, regular_meter_width, thin_meter_width);
}
else if (p == "meter-style-led") {
color_changed = true;
setup_meters (meter_length, regular_meter_width, thin_meter_width);
}
else if (p == "meter-peak") {
vector<MeterInfo>::iterator i;
uint32_t n;
@ -151,32 +203,34 @@ LevelMeter::parameter_changed (string p)
}
void
LevelMeter::configuration_changed (ChanCount /*in*/, ChanCount /*out*/)
LevelMeterBase::configuration_changed (ChanCount /*in*/, ChanCount /*out*/)
{
color_changed = true;
setup_meters (meter_length, regular_meter_width, thin_meter_width);
}
void
LevelMeter::meter_type_changed (MeterType t)
LevelMeterBase::meter_type_changed (MeterType t)
{
meter_type = t;
color_changed = true;
setup_meters (meter_length, regular_meter_width, thin_meter_width);
MeterTypeChanged(t);
}
void
LevelMeter::hide_all_meters ()
LevelMeterBase::hide_all_meters ()
{
for (vector<MeterInfo>::iterator i = meters.begin(); i != meters.end(); ++i) {
if ((*i).packed) {
remove (*((*i).meter));
mtr_remove (*((*i).meter));
(*i).packed = false;
}
}
}
void
LevelMeter::setup_meters (int len, int initial_width, int thin_width)
LevelMeterBase::setup_meters (int len, int initial_width, int thin_width)
{
hide_all_meters ();
@ -206,11 +260,17 @@ LevelMeter::setup_meters (int len, int initial_width, int thin_width)
meters.push_back (MeterInfo());
}
//cerr << "LevelMeter::setup_meters() called color_changed = " << color_changed << " colors: " << endl;//DEBUG
//cerr << "LevelMeterBase::setup_meters() called color_changed = " << color_changed << " colors: " << endl;//DEBUG
for (int32_t n = nmeters-1; nmeters && n >= 0 ; --n) {
uint32_t c[10];
uint32_t b[4];
float stp[4];
int styleflags = Config->get_meter_style_led() ? 3 : 1;
b[0] = ARDOUR_UI::config()->canvasvar_MeterBackgroundBot.get();
b[1] = ARDOUR_UI::config()->canvasvar_MeterBackgroundTop.get();
b[2] = 0x991122ff; // red highlight gradient Bot
b[3] = 0x551111ff; // red highlight gradient Top
if (n < nmidi) {
c[0] = ARDOUR_UI::config()->canvasvar_MidiMeterColor0.get();
c[1] = ARDOUR_UI::config()->canvasvar_MidiMeterColor1.get();
@ -227,33 +287,6 @@ LevelMeter::setup_meters (int len, int initial_width, int thin_width)
stp[2] = 115.0 * 100.0 / 128.0;
stp[3] = 115.0 * 112.0 / 128.0;
} else {
switch (Config->get_meter_line_up_level()) {
case MeteringLineUp24:
stp[0] = 42.0;
stp[1] = 77.5;
stp[2] = 92.5;
stp[3] = 100.0;
break;
case MeteringLineUp20:
stp[0] = 50.0;
stp[1] = 77.5;
stp[2] = 92.5;
stp[3] = 100.0;
break;
default:
case MeteringLineUp18:
stp[0] = 55.0;
stp[1] = 77.5;
stp[2] = 92.5;
stp[3] = 100.0;
break;
case MeteringLineUp15:
stp[0] = 62.5;
stp[1] = 77.5;
stp[2] = 92.5;
stp[3] = 100.0;
break;
}
c[0] = ARDOUR_UI::config()->canvasvar_MeterColor0.get();
c[1] = ARDOUR_UI::config()->canvasvar_MeterColor1.get();
c[2] = ARDOUR_UI::config()->canvasvar_MeterColor2.get();
@ -264,57 +297,145 @@ LevelMeter::setup_meters (int len, int initial_width, int thin_width)
c[7] = ARDOUR_UI::config()->canvasvar_MeterColor7.get();
c[8] = ARDOUR_UI::config()->canvasvar_MeterColor8.get();
c[9] = ARDOUR_UI::config()->canvasvar_MeterColor9.get();
switch (meter_type) {
case MeterK20:
stp[0] = 115.0 * meter_deflect_k(-40, 20); //-20
stp[1] = 115.0 * meter_deflect_k(-20, 20); // 0
stp[2] = 115.0 * meter_deflect_k(-18, 20); // +2
stp[3] = 115.0 * meter_deflect_k(-16, 20); // +4
c[0] = c[1] = 0x008800ff;
c[2] = c[3] = 0x00ff00ff;
c[4] = c[5] = 0xffff00ff;
c[6] = c[7] = 0xffff00ff;
c[8] = c[9] = 0xff0000ff;
break;
case MeterK14:
stp[0] = 115.0 * meter_deflect_k(-34, 14); //-20
stp[1] = 115.0 * meter_deflect_k(-14, 14); // 0
stp[2] = 115.0 * meter_deflect_k(-12, 14); // +2
stp[3] = 115.0 * meter_deflect_k(-10, 14); // +4
c[0] = c[1] = 0x008800ff;
c[2] = c[3] = 0x00ff00ff;
c[4] = c[5] = 0xffff00ff;
c[6] = c[7] = 0xffff00ff;
c[8] = c[9] = 0xff0000ff;
break;
case MeterIEC2BBC:
c[0] = c[1] = c[2] = c[3] = c[4] = c[5] = c[6] = c[7] = c[8] = c[9] =
ARDOUR_UI::config()->color_by_name ("meter color BBC");
stp[0] = stp[1] = stp[2] = stp[3] = 115.0;
break;
case MeterIEC2EBU:
stp[0] = 115.0 * meter_deflect_ppm(-24); // ignored
stp[1] = 115.0 * meter_deflect_ppm(-18);
stp[2] = 115.0 * meter_deflect_ppm( -9);
stp[3] = 115.0 * meter_deflect_ppm( 0); // ignored
c[3] = c[2] = c[1];
c[6] = c[7] = c[8] = c[9];
break;
case MeterIEC1NOR:
stp[0] = 115.0 * meter_deflect_nordic(-30); // ignored
stp[1] = 115.0 * meter_deflect_nordic(-18);
stp[2] = 115.0 * meter_deflect_nordic(-12);
stp[3] = 115.0 * meter_deflect_nordic( -9); // ignored
//c[2] = c[3] = c[1]; // dark-green
c[0] = c[1] = c[2]; // bright-green
c[6] = c[7] = c[8] = c[9];
break;
case MeterIEC1DIN:
stp[0] = 115.0 * meter_deflect_din(-29); // ignored
stp[1] = 115.0 * meter_deflect_din(-18);
stp[2] = 115.0 * meter_deflect_din(-15); // ignored
stp[3] = 115.0 * meter_deflect_din( -9);
c[0] = c[1] = c[2] = c[3] = 0x00aa00ff;
c[4] = c[6];
c[5] = c[7];
break;
case MeterVU:
stp[0] = 115.0 * meter_deflect_vu(-26); // -6
stp[1] = 115.0 * meter_deflect_vu(-23); // -3
stp[2] = 115.0 * meter_deflect_vu(-20); // 0
stp[3] = 115.0 * meter_deflect_vu(-18); // +2
c[0] = c[1] = c[2] = c[3] = c[4] = c[5] = 0x00aa00ff;
c[6] = c[7] = c[8] = c[9] = 0xff8800ff;
break;
default: // PEAK, RMS
stp[1] = 77.5; // 115 * log_meter(-10)
stp[2] = 92.5; // 115 * log_meter(-3)
stp[3] = 100.0; // 115 * log_meter(0)
switch (Config->get_meter_line_up_level()) {
case MeteringLineUp24:
stp[0] = 42.0;
break;
case MeteringLineUp20:
stp[0] = 50.0;
break;
default:
case MeteringLineUp18:
stp[0] = 55.0;
break;
case MeteringLineUp15:
stp[0] = 62.5;
break;
}
}
}
if (meters[n].width != width || meters[n].length != len || color_changed) {
if (meters[n].width != width || meters[n].length != len || color_changed || meter_type != visible_meter_type) {
bool hl = meters[n].meter ? meters[n].meter->get_highlight() : false;
meters[n].packed = false;
delete meters[n].meter;
meters[n].meter = new FastMeter ((uint32_t) floor (Config->get_meter_hold()), width, FastMeter::Vertical, len,
meters[n].meter = new FastMeter ((uint32_t) floor (Config->get_meter_hold()), width, _meter_orientation, len,
c[0], c[1], c[2], c[3], c[4],
c[5], c[6], c[7], c[8], c[9],
ARDOUR_UI::config()->canvasvar_MeterBackgroundBot.get(),
ARDOUR_UI::config()->canvasvar_MeterBackgroundTop.get(),
0x991122ff, 0x551111ff,
stp[0], stp[1], stp[2], stp[3]
b[0], b[1], b[2], b[3],
stp[0], stp[1], stp[2], stp[3],
styleflags
);
meters[n].meter->set_highlight(hl);
meters[n].width = width;
meters[n].length = len;
meters[n].meter->add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
meters[n].meter->signal_button_press_event().connect (sigc::mem_fun (*this, &LevelMeter::meter_button_press));
meters[n].meter->signal_button_release_event().connect (sigc::mem_fun (*this, &LevelMeter::meter_button_release));
meters[n].meter->signal_button_press_event().connect (sigc::mem_fun (*this, &LevelMeterBase::meter_button_press));
meters[n].meter->signal_button_release_event().connect (sigc::mem_fun (*this, &LevelMeterBase::meter_button_release));
}
pack_end (*meters[n].meter, false, false);
//pack_end (*meters[n].meter, false, false);
mtr_pack (*meters[n].meter);
meters[n].meter->show_all ();
meters[n].packed = true;
}
show();
//show();
color_changed = false;
visible_meter_type = meter_type;
}
void
LevelMeter::set_type(MeterType t)
LevelMeterBase::set_type(MeterType t)
{
meter_type = t;
_meter->set_type(t);
}
bool
LevelMeter::meter_button_press (GdkEventButton* ev)
LevelMeterBase::meter_button_press (GdkEventButton* ev)
{
return ButtonPress (ev); /* EMIT SIGNAL */
}
bool
LevelMeter::meter_button_release (GdkEventButton* ev)
LevelMeterBase::meter_button_release (GdkEventButton* ev)
{
if (ev->button == 1) {
clear_meters (false);
}
ButtonRelease(ev);
return true;
}
void LevelMeter::clear_meters (bool reset_highlight)
void LevelMeterBase::clear_meters (bool reset_highlight)
{
for (vector<MeterInfo>::iterator i = meters.begin(); i < meters.end(); i++) {
(*i).meter->clear();
@ -325,14 +446,53 @@ void LevelMeter::clear_meters (bool reset_highlight)
max_peak = minus_infinity();
}
void LevelMeter::hide_meters ()
void LevelMeterBase::hide_meters ()
{
hide_all_meters();
}
void
LevelMeter::color_handler ()
LevelMeterBase::color_handler ()
{
color_changed = true;
setup_meters (meter_length, regular_meter_width, thin_meter_width);
}
LevelMeterHBox::LevelMeterHBox(Session* s)
: LevelMeterBase(s, invalidator(*this))
{
set_spacing(1);
show();
}
LevelMeterHBox::~LevelMeterHBox() {}
void
LevelMeterHBox::mtr_pack(Gtk::Widget &w) {
pack_end (w, false, false);
}
void
LevelMeterHBox::mtr_remove(Gtk::Widget &w) {
remove (w);
}
LevelMeterVBox::LevelMeterVBox(Session* s)
: LevelMeterBase(s, invalidator(*this), FastMeter::Horizontal)
{
set_spacing(1);
show();
}
LevelMeterVBox::~LevelMeterVBox() {}
void
LevelMeterVBox::mtr_pack(Gtk::Widget &w) {
pack_end (w, false, false);
}
void
LevelMeterVBox::mtr_remove(Gtk::Widget &w) {
remove (w);
}

View file

@ -37,6 +37,7 @@
#include <gtkmm2ext/click_box.h>
#include <gtkmm2ext/focus_entry.h>
#include <gtkmm2ext/slider_controller.h>
#include <gtkmm2ext/fastmeter.h>
#include "enums.h"
@ -44,18 +45,16 @@ namespace ARDOUR {
class Session;
class PeakMeter;
}
namespace Gtkmm2ext {
class FastMeter;
}
namespace Gtk {
class Menu;
}
class LevelMeter : public Gtk::HBox, public ARDOUR::SessionHandlePtr
class LevelMeterBase : public ARDOUR::SessionHandlePtr
{
public:
LevelMeter (ARDOUR::Session*);
~LevelMeter ();
LevelMeterBase (ARDOUR::Session*, PBD::EventLoop::InvalidationRecord* ir,
Gtkmm2ext::FastMeter::Orientation o = Gtkmm2ext::FastMeter::Vertical);
virtual ~LevelMeterBase ();
virtual void set_meter (ARDOUR::PeakMeter* meter);
@ -72,10 +71,17 @@ class LevelMeter : public Gtk::HBox, public ARDOUR::SessionHandlePtr
/** Emitted in the GUI thread when a button is pressed over the meter */
PBD::Signal1<bool, GdkEventButton *> ButtonPress;
PBD::Signal1<bool, GdkEventButton *> ButtonRelease;
PBD::Signal1<void, ARDOUR::MeterType> MeterTypeChanged;
protected:
virtual void mtr_pack(Gtk::Widget &w) = 0;
virtual void mtr_remove(Gtk::Widget &w) = 0;
private:
PBD::EventLoop::InvalidationRecord* parent_invalidator;
ARDOUR::PeakMeter* _meter;
Gtkmm2ext::FastMeter::Orientation _meter_orientation;
Width _width;
@ -101,6 +107,7 @@ class LevelMeter : public Gtk::HBox, public ARDOUR::SessionHandlePtr
std::vector<MeterInfo> meters;
float max_peak;
ARDOUR::MeterType meter_type;
ARDOUR::MeterType visible_meter_type;
PBD::ScopedConnection _configuration_connection;
PBD::ScopedConnection _meter_type_connection;
@ -120,5 +127,27 @@ class LevelMeter : public Gtk::HBox, public ARDOUR::SessionHandlePtr
void color_handler ();
};
class LevelMeterHBox : public LevelMeterBase, public Gtk::HBox
{
public:
LevelMeterHBox (ARDOUR::Session*);
~LevelMeterHBox();
protected:
void mtr_pack(Gtk::Widget &w);
void mtr_remove(Gtk::Widget &w);
};
class LevelMeterVBox : public LevelMeterBase, public Gtk::VBox
{
public:
LevelMeterVBox (ARDOUR::Session*);
~LevelMeterVBox();
protected:
void mtr_pack(Gtk::Widget &w);
void mtr_remove(Gtk::Widget &w);
};
#endif /* __ardour_gtk_track_meter_h__ */

View file

@ -34,7 +34,17 @@ alt_log_meter (float power)
}
#endif
inline float
/* prototypes - avoid compiler warning */
static inline float log_meter (float db);
static inline float meter_deflect_ppm (float);
static inline float meter_deflect_din (float);
static inline float meter_deflect_nordic (float);
static inline float meter_deflect_vu (float);
static inline float meter_deflect_k (float, float);
static inline float
log_meter (float db)
{
gfloat def = 0.0f; /* Meter deflection %age */
@ -65,4 +75,71 @@ log_meter (float db)
return def/115.0f;
}
static inline float
meter_deflect_ppm (float db)
{
if (db < -30) {
// 2.258 == ((-30 + 32.0)/ 28.0) / 10^(-30 / 20);
return (dB_to_coefficient(db) * 2.258769757f);
} else {
const float rv = (db + 32.0f) / 28.0f;
if (rv < 1.0) {
return rv;
} else {
return 1.0;
}
}
}
static inline float
meter_deflect_din (float db)
{
float rv = dB_to_coefficient(db);
rv = sqrtf (sqrtf (2.3676f * rv)) - 0.1803f;
if (rv >= 1.0) {
return 1.0;
} else {
return (rv > 0 ? rv : 0.0);
}
}
static inline float
meter_deflect_nordic (float db)
{
if (db < -60) {
return 0.0;
} else {
const float rv = (db + 60.0f) / 54.0f;
if (rv < 1.0) {
return rv;
} else {
return 1.0;
}
}
}
static inline float
meter_deflect_vu (float db)
{
const float rv = 6.77165f * dB_to_coefficient(db);
if (rv > 1.0) return 1.0;
return rv;
}
static inline float
meter_deflect_k (float db, float krange)
{
db+=krange;
if (db < -40.0f) {
return (dB_to_coefficient(db) * 500.0f / (krange + 45.0f));
} else {
const float rv = (db + 45.0f) / (krange + 45.0f);
if (rv < 1.0) {
return rv;
} else {
return 1.0;
}
}
}
#endif /* __ardour_gtk_log_meter_h__ */

File diff suppressed because it is too large Load diff

View file

@ -37,8 +37,8 @@ extern sigc::signal<void> RedrawMetrics;
extern sigc::signal<void, int, ARDOUR::RouteGroup*, ARDOUR::MeterType> SetMeterTypeMulti;
gint meter_expose_ticks (GdkEventExpose *ev, std::vector<ARDOUR::DataType> types, Gtk::DrawingArea *mta);
gint meter_expose_metrics (GdkEventExpose *ev, std::vector<ARDOUR::DataType> types, Gtk::DrawingArea *mma);
gint meter_expose_ticks (GdkEventExpose *ev, ARDOUR::MeterType type, std::vector<ARDOUR::DataType> types, Gtk::DrawingArea *mta);
gint meter_expose_metrics (GdkEventExpose *ev, ARDOUR::MeterType type, std::vector<ARDOUR::DataType> types, Gtk::DrawingArea *mma);
void meter_clear_pattern_cache(int which=7);

View file

@ -56,18 +56,24 @@ using namespace ArdourMeter;
PBD::Signal1<void,MeterStrip*> MeterStrip::CatchDeletion;
PBD::Signal0<void> MeterStrip::MetricChanged;
PBD::Signal0<void> MeterStrip::ConfigurationChanged;
MeterStrip::MeterStrip (int metricmode)
MeterStrip::MeterStrip (int metricmode, MeterType mt)
: AxisView(0)
, RouteUI(0)
{
level_meter = 0;
_strip_type = 0;
set_spacing(2);
_tick_bar = 0;
_metricmode = -1;
metric_type = MeterPeak;
mtr_vbox.set_spacing(2);
nfo_vbox.set_spacing(2);
peakbx.set_size_request(-1, 14);
namebx.set_size_request(18, 52);
spacer.set_size_request(-1,0);
set_metric_mode(metricmode);
set_metric_mode(metricmode, mt);
meter_metric_area.set_size_request(25, 10);
meter_metric_area.signal_expose_event().connect (
@ -76,15 +82,30 @@ MeterStrip::MeterStrip (int metricmode)
meterbox.pack_start(meter_metric_area, true, false);
pack_start (peakbx, false, false);
pack_start (meterbox, true, true);
pack_start (btnbox, false, false);
pack_start (namebx, false, false);
mtr_vbox.pack_start (peakbx, false, false);
mtr_vbox.pack_start (meterbox, true, true);
mtr_vbox.pack_start (spacer, false, false);
mtr_container.add(mtr_vbox);
mtr_hsep.set_size_request(-1,1);
mtr_hsep.set_name("BlackSeparator");
nfo_vbox.pack_start (mtr_hsep, false, false);
nfo_vbox.pack_start (btnbox, false, false);
nfo_vbox.pack_start (namebx, false, false);
pack_start (mtr_container, true, true);
pack_start (nfo_vbox, false, false);
peakbx.show();
btnbox.show();
meter_metric_area.show();
meterbox.show();
spacer.show();
mtr_vbox.show();
mtr_container.show();
mtr_hsep.show();
nfo_vbox.show();
UI::instance()->theme_changed.connect (sigc::mem_fun(*this, &MeterStrip::on_theme_changed));
ColorsChanged.connect (sigc::mem_fun (*this, &MeterStrip::on_theme_changed));
@ -97,11 +118,15 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr<ARDOUR::Route> rt)
, _route(rt)
, peak_display()
{
set_spacing(2);
mtr_vbox.set_spacing(2);
nfo_vbox.set_spacing(2);
RouteUI::set_route (rt);
SessionHandlePtr::set_session (sess);
_has_midi = false;
_tick_bar = 0;
_metricmode = -1;
metric_type = MeterPeak;
int meter_width = 6;
if (_route->shared_peak_meter()->input_streams().n_total() == 1) {
@ -109,12 +134,12 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr<ARDOUR::Route> rt)
}
// level meter + ticks
level_meter = new LevelMeter(sess);
level_meter = new LevelMeterHBox(sess);
level_meter->set_meter (_route->shared_peak_meter().get());
level_meter->clear_meters();
level_meter->setup_meters (220, meter_width, 6);
level_meter->set_type (_route->meter_type());
level_meter->ButtonPress.connect_same_thread (level_meter_connection, boost::bind (&MeterStrip::level_meter_button_press, this, _1));
level_meter->setup_meters (220, meter_width, 6);
level_meter->ButtonRelease.connect_same_thread (level_meter_connection, boost::bind (&MeterStrip::level_meter_button_release, this, _1));
level_meter->MeterTypeChanged.connect_same_thread (level_meter_connection, boost::bind (&MeterStrip::meter_type_changed, this, _1));
meter_align.set(0.5, 0.5, 0.0, 1.0);
@ -147,6 +172,7 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr<ARDOUR::Route> rt)
name_label.set_size_request(18, 50);
name_label.set_alignment(-1.0, .5);
ARDOUR_UI::instance()->set_tip (name_label, _route->name());
ARDOUR_UI::instance()->set_tip (*level_meter, _route->name());
namebx.set_size_request(18, 52);
namebx.pack_start(name_label, true, false, 3);
@ -170,24 +196,42 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr<ARDOUR::Route> rt)
mutebox.set_size_request(16, 16);
solobox.set_size_request(16, 16);
recbox.set_size_request(16, 16);
spacer.set_size_request(-1,0);
update_button_box();
update_name_box();
update_background (_route->meter_type());
mtr_vbox.pack_start (peakbx, false, false);
mtr_vbox.pack_start (meterbox, true, true);
mtr_vbox.pack_start (spacer, false, false);
mtr_container.add(mtr_vbox);
mtr_hsep.set_size_request(-1,1);
mtr_hsep.set_name("BlackSeparator");
nfo_vbox.pack_start (mtr_hsep, false, false);
nfo_vbox.pack_start (btnbox, false, false);
nfo_vbox.pack_start (namebx, false, false);
pack_start (mtr_container, true, true);
pack_start (nfo_vbox, false, false);
pack_start (peakbx, false, false);
pack_start (meterbox, true, true);
pack_start (btnbox, false, false);
pack_start (namebx, false, false);
name_label.show();
peak_display.show();
peakbx.show();
meter_ticks1_area.show();
meter_ticks2_area.show();
meterbox.show();
spacer.show();
level_meter->show();
meter_align.show();
peak_align.show();
btnbox.show();
mtr_vbox.show();
mtr_container.show();
mtr_hsep.show();
nfo_vbox.show();
_route->shared_peak_meter()->ConfigurationChanged.connect (
route_connections, invalidator (*this), boost::bind (&MeterStrip::meter_configuration_changed, this, _1), gui_context()
@ -210,6 +254,7 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr<ARDOUR::Route> rt)
_route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&MeterStrip::strip_property_changed, this, _1), gui_context());
peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &MeterStrip::peak_button_release), false);
name_label.signal_button_release_event().connect (sigc::mem_fun(*this, &MeterStrip::name_label_button_release), false);
UI::instance()->theme_changed.connect (sigc::mem_fun(*this, &MeterStrip::on_theme_changed));
ColorsChanged.connect (sigc::mem_fun (*this, &MeterStrip::on_theme_changed));
@ -303,6 +348,9 @@ MeterStrip::strip_property_changed (const PropertyChange& what_changed)
ENSURE_GUI_THREAD (*this, &MeterStrip::strip_name_changed, what_changed)
name_label.set_text(_route->name());
ARDOUR_UI::instance()->set_tip (name_label, _route->name());
if (level_meter) {
ARDOUR_UI::instance()->set_tip (*level_meter, _route->name());
}
}
void
@ -347,13 +395,13 @@ MeterStrip::meter_configuration_changed (ChanCount c)
if (boost::dynamic_pointer_cast<AudioTrack>(_route) == 0
&& boost::dynamic_pointer_cast<MidiTrack>(_route) == 0
) {
meter_ticks1_area.set_name ("AudioBusMetricsLeft");
meter_ticks2_area.set_name ("AudioBusMetricsRight");
meter_ticks1_area.set_name ("MyAudioBusMetricsLeft");
meter_ticks2_area.set_name ("MyAudioBusMetricsRight");
_has_midi = false;
}
else if (type == (1 << DataType::AUDIO)) {
meter_ticks1_area.set_name ("AudioTrackMetricsLeft");
meter_ticks2_area.set_name ("AudioTrackMetricsRight");
meter_ticks1_area.set_name ("MyAudioTrackMetricsLeft");
meter_ticks2_area.set_name ("MyAudioTrackMetricsRight");
_has_midi = false;
}
else if (type == (1 << DataType::MIDI)) {
@ -365,9 +413,40 @@ MeterStrip::meter_configuration_changed (ChanCount c)
meter_ticks2_area.set_name ("AudioMidiTrackMetricsRight");
_has_midi = true;
}
set_tick_bar(_tick_bar);
if (old_has_midi != _has_midi) MetricChanged();
on_theme_changed();
if (old_has_midi != _has_midi) MetricChanged();
else ConfigurationChanged();
}
void
MeterStrip::set_tick_bar (int m)
{
std::string n;
_tick_bar = m;
if (_tick_bar & 1) {
n = meter_ticks1_area.get_name();
if (n.substr(0,3) != "Bar") {
meter_ticks1_area.set_name("Bar" + n);
}
} else {
n = meter_ticks1_area.get_name();
if (n.substr(0,3) == "Bar") {
meter_ticks1_area.set_name(n.substr(3,-1));
}
}
if (_tick_bar & 2) {
n = meter_ticks2_area.get_name();
if (n.substr(0,3) != "Bar") {
meter_ticks2_area.set_name("Bar" + n);
}
} else {
n = meter_ticks2_area.get_name();
if (n.substr(0,3) == "Bar") {
meter_ticks2_area.set_name(n.substr(3,-1));
}
}
}
void
@ -380,9 +459,31 @@ void
MeterStrip::on_size_allocate (Gtk::Allocation& a)
{
const int wh = a.get_height();
int nh = ceilf(wh * .11f);
if (nh < 52) nh = 52;
if (nh > 148) nh = 148;
int nh;
int mh = 0;
if (_session) {
mh = _session->config.get_meterbridge_label_height();
}
switch (mh) {
default:
case 0:
nh = ceilf(wh * .12f);
if (nh < 52) nh = 52;
if (nh > 148) nh = 148;
break;
case 1:
nh = 52;
break;
case 2:
nh = 88;
break;
case 3:
nh = 106;
break;
case 4:
nh = 148;
break;
}
namebx.set_size_request(18, nh);
if (_route) {
name_label.set_size_request(18, nh-2);
@ -394,12 +495,22 @@ MeterStrip::on_size_allocate (Gtk::Allocation& a)
gint
MeterStrip::meter_metrics_expose (GdkEventExpose *ev)
{
return meter_expose_metrics(ev, _types, &meter_metric_area);
if (_route) {
return meter_expose_metrics(ev, _route->meter_type(), _types, &meter_metric_area);
} else {
return meter_expose_metrics(ev, metric_type, _types, &meter_metric_area);
}
}
void
MeterStrip::set_metric_mode (int metricmode)
MeterStrip::set_metric_mode (int metricmode, ARDOUR::MeterType mt)
{
if (metric_type == mt && _metricmode == metricmode) {
return;
}
metric_type = mt;
_metricmode = metricmode;
_types.clear ();
switch(metricmode) {
case 0:
@ -420,25 +531,50 @@ MeterStrip::set_metric_mode (int metricmode)
_types.push_back (DataType::AUDIO);
break;
}
update_background (mt);
meter_metric_area.queue_draw ();
}
void
MeterStrip::set_pos (int pos)
MeterStrip::update_background(MeterType type)
{
switch(type) {
case MeterIEC1DIN:
case MeterIEC1NOR:
case MeterIEC2BBC:
case MeterIEC2EBU:
case MeterK14:
case MeterK20:
mtr_container.set_name ("meterstripPPM");
break;
case MeterVU:
mtr_container.set_name ("meterstripVU");
break;
default:
mtr_container.set_name ("meterstripDPM");
}
}
MeterType
MeterStrip::meter_type()
{
assert((!_route && _strip_type == 0) || (_route && _strip_type != 0));
if (!_route) return metric_type;
return _route->meter_type();
}
gint
MeterStrip::meter_ticks1_expose (GdkEventExpose *ev)
{
return meter_expose_ticks(ev, _types, &meter_ticks1_area);
assert(_route);
return meter_expose_ticks(ev, _route->meter_type(), _types, &meter_ticks1_area);
}
gint
MeterStrip::meter_ticks2_expose (GdkEventExpose *ev)
{
return meter_expose_ticks(ev, _types, &meter_ticks2_area);
assert(_route);
return meter_expose_ticks(ev, _route->meter_type(), _types, &meter_ticks2_area);
}
void
@ -546,11 +682,13 @@ MeterStrip::parameter_changed (std::string const & p)
else if (p == "show-name-on-meterbridge") {
update_name_box();
}
else if (p == "meterbridge-label-height") {
queue_resize();
}
}
bool
MeterStrip::level_meter_button_press (GdkEventButton* ev)
MeterStrip::level_meter_button_release (GdkEventButton* ev)
{
if (ev->button == 3) {
popup_level_meter_menu (ev);
@ -571,8 +709,15 @@ MeterStrip::popup_level_meter_menu (GdkEventButton* ev)
RadioMenuItem::Group group;
_suspend_menu_callbacks = true;
add_level_meter_item (items, group, ArdourMeter::meter_type_string(MeterPeak), MeterPeak);
add_level_meter_item (items, group, ArdourMeter::meter_type_string(MeterKrms), MeterKrms);
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak), MeterPeak);
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterKrms), MeterKrms);
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1DIN), MeterIEC1DIN);
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1NOR), MeterIEC1NOR);
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2BBC), MeterIEC2BBC);
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK20), MeterK20);
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK14), MeterK14);
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterVU), MeterVU);
MeterType cmt = _route->meter_type();
const std::string cmn = ArdourMeter::meter_type_string(cmt);
@ -589,8 +734,53 @@ MeterStrip::popup_level_meter_menu (GdkEventButton* ev)
_suspend_menu_callbacks = false;
}
bool
MeterStrip::name_label_button_release (GdkEventButton* ev)
{
if (!_session) return true;
if (!_session->config.get_show_name_on_meterbridge()) return true;
if (ev->button == 3) {
popup_name_label_menu (ev);
return true;
}
return false;
}
void
MeterStrip::add_level_meter_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, MeterType type)
MeterStrip::popup_name_label_menu (GdkEventButton* ev)
{
using namespace Gtk::Menu_Helpers;
Gtk::Menu* m = manage (new Menu);
MenuList& items = m->items ();
RadioMenuItem::Group group;
_suspend_menu_callbacks = true;
add_label_height_item (items, group, _("Variable height"), 0);
add_label_height_item (items, group, _("Short"), 1);
add_label_height_item (items, group, _("Tall"), 2);
add_label_height_item (items, group, _("Grande"), 3);
add_label_height_item (items, group, _("Venti"), 4);
m->popup (ev->button, ev->time);
_suspend_menu_callbacks = false;
}
void
MeterStrip::add_label_height_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, uint32_t h)
{
using namespace Menu_Helpers;
items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (*this, &MeterStrip::set_label_height), h)));
RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
i->set_active (_session && _session->config.get_meterbridge_label_height() == h);
}
void
MeterStrip::add_level_meter_type_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, MeterType type)
{
using namespace Menu_Helpers;
@ -603,13 +793,26 @@ void
MeterStrip::set_meter_type (MeterType type)
{
if (_suspend_menu_callbacks) return;
if (_route->meter_type() == type) return;
level_meter->set_type (type);
}
void
MeterStrip::set_label_height (uint32_t h)
{
if (_suspend_menu_callbacks) return;
_session->config.set_meterbridge_label_height(h);
}
void
MeterStrip::meter_type_changed (MeterType type)
{
_route->set_meter_type(type);
if (_route->meter_type() != type) {
_route->set_meter_type(type);
}
update_background (type);
MetricChanged();
}
void

View file

@ -47,7 +47,7 @@ class MeterStrip : public Gtk::VBox, public RouteUI
{
public:
MeterStrip (ARDOUR::Session*, boost::shared_ptr<ARDOUR::Route>);
MeterStrip (int);
MeterStrip (int, ARDOUR::MeterType);
~MeterStrip ();
void set_session (ARDOUR::Session* s);
@ -56,6 +56,7 @@ class MeterStrip : public Gtk::VBox, public RouteUI
static PBD::Signal1<void,MeterStrip*> CatchDeletion;
static PBD::Signal0<void> MetricChanged;
static PBD::Signal0<void> ConfigurationChanged;
void reset_peak_display ();
void reset_route_peak_display (ARDOUR::Route*);
@ -63,9 +64,13 @@ class MeterStrip : public Gtk::VBox, public RouteUI
void set_meter_type_multi (int, ARDOUR::RouteGroup*, ARDOUR::MeterType);
void set_metric_mode (int);
void set_pos(int);
void set_metric_mode (int, ARDOUR::MeterType);
int get_metric_mode() { return _metricmode; }
void set_tick_bar (int);
int get_tick_bar() { return _tick_bar; }
bool has_midi() { return _has_midi; }
bool is_metric_display() { return _strip_type == 0; }
ARDOUR::MeterType meter_type();
protected:
boost::shared_ptr<ARDOUR::Route> _route;
@ -88,7 +93,12 @@ class MeterStrip : public Gtk::VBox, public RouteUI
void set_button_names ();
private:
Gtk::VBox mtr_vbox;
Gtk::VBox nfo_vbox;
Gtk::EventBox mtr_container;
Gtk::HSeparator mtr_hsep;
Gtk::HBox meterbox;
Gtk::HBox spacer;
Gtk::HBox namebx;
ArdourButton name_label;
Gtk::DrawingArea meter_metric_area;
@ -106,19 +116,21 @@ class MeterStrip : public Gtk::VBox, public RouteUI
ArdourButton peak_display;
std::vector<ARDOUR::DataType> _types;
ARDOUR::MeterType metric_type;
float max_peak;
bool _has_midi;
int _tick_bar;
int _strip_type;
int _metricmode;
LevelMeter *level_meter;
LevelMeterHBox *level_meter;
PBD::ScopedConnection _config_connection;
void strip_property_changed (const PBD::PropertyChange&);
void meter_configuration_changed (ARDOUR::ChanCount);
void meter_type_changed (ARDOUR::MeterType);
static int max_pattern_metric_size; // == FastMeter::max_pattern_metric_size
void update_background (ARDOUR::MeterType);
bool peak_button_release (GdkEventButton*);
@ -128,10 +140,16 @@ class MeterStrip : public Gtk::VBox, public RouteUI
void update_name_box ();
bool _suspend_menu_callbacks;
bool level_meter_button_press (GdkEventButton* ev);
bool level_meter_button_release (GdkEventButton* ev);
void popup_level_meter_menu (GdkEventButton* ev);
void add_level_meter_item (Gtk::Menu_Helpers::MenuList& items, Gtk::RadioMenuItem::Group& group, std::string const & name, ARDOUR::MeterType mode);
void add_level_meter_type_item (Gtk::Menu_Helpers::MenuList&, Gtk::RadioMenuItem::Group&, std::string const &, ARDOUR::MeterType);
bool name_label_button_release (GdkEventButton* ev);
void popup_name_label_menu (GdkEventButton* ev);
void add_label_height_item (Gtk::Menu_Helpers::MenuList&, Gtk::RadioMenuItem::Group&, std::string const &, uint32_t);
void set_meter_type (ARDOUR::MeterType mode);
void set_label_height (uint32_t);
};
#endif /* __ardour_mixer_strip__ */

View file

@ -101,8 +101,8 @@ Meterbridge::Meterbridge ()
, VisibilityTracker (*((Gtk::Window*) this))
, _visible (false)
, _show_busses (false)
, metrics_left (1)
, metrics_right (2)
, metrics_left (1, MeterPeak)
, metrics_right (2, MeterPeak)
, cur_max_width (-1)
{
set_name ("Meter Bridge");
@ -140,7 +140,8 @@ Meterbridge::Meterbridge ()
signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
Route::SyncOrderKeys.connect (*this, invalidator (*this), boost::bind (&Meterbridge::sync_order_keys, this, _1), gui_context());
MeterStrip::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Meterbridge::remove_strip, this, _1), gui_context());
MeterStrip::MetricChanged.connect_same_thread (*this, boost::bind(&Meterbridge::update_metrics, this));
MeterStrip::MetricChanged.connect (*this, invalidator (*this), boost::bind(&Meterbridge::resync_order, this), gui_context());
MeterStrip::ConfigurationChanged.connect (*this, invalidator (*this), boost::bind(&Meterbridge::queue_resize, this), gui_context());
/* work around ScrolledWindowViewport alignment mess Part one */
Gtk::HBox * yspc = manage (new Gtk::HBox());
@ -192,6 +193,10 @@ Meterbridge::Meterbridge ()
Meterbridge::~Meterbridge ()
{
while (_metrics.size() > 0) {
delete (_metrics.back());
_metrics.pop_back();
}
}
void
@ -332,9 +337,31 @@ Meterbridge::on_size_request (Gtk::Requisition* r)
Gtk::Window::on_size_request(r);
Gdk::Geometry geom;
geom.max_width = meterarea.get_width() + metrics_left.get_width() + metrics_right.get_width();
Gtk::Requisition mr = meterarea.size_request();
geom.max_width = mr.width + metrics_left.get_width() + metrics_right.get_width();
geom.max_height = max_height;
#ifndef GTKOSX
/* on OSX this leads to a constant live-loop: show/hide scrollbar
* on Linux, the window is resized IFF the scrollbar was not visible
*/
const Gtk::Scrollbar * hsc = scroller.get_hscrollbar();
Glib::RefPtr<Gdk::Screen> screen = get_screen ();
Gdk::Rectangle monitor_rect;
screen->get_monitor_geometry (0, monitor_rect);
const int scr_w = monitor_rect.get_width() - 44;
if (cur_max_width < geom.max_width
&& cur_max_width < scr_w
&& !(scroller.get_hscrollbar_visible() && hsc)) {
int h = r->height;
*r = Gtk::Requisition();
r->width = geom.max_width;
r->height = h;
}
#endif
if (cur_max_width != geom.max_width) {
cur_max_width = geom.max_width;
geom.height_inc = 16;
@ -349,6 +376,10 @@ Meterbridge::on_size_allocate (Gtk::Allocation& a)
const Gtk::Scrollbar * hsc = scroller.get_hscrollbar();
if (scroller.get_hscrollbar_visible() && hsc) {
if (!scroll_connection.connected()) {
scroll_connection = scroller.get_hscrollbar()->get_adjustment()->signal_value_changed().connect(sigc::mem_fun (*this, &Meterbridge::on_scroll));
scroller.get_hscrollbar()->get_adjustment()->signal_changed().connect(sigc::mem_fun (*this, &Meterbridge::on_scroll));
}
gint scrollbar_spacing;
gtk_widget_style_get (GTK_WIDGET (scroller.gobj()),
"scrollbar-spacing", &scrollbar_spacing, NULL);
@ -362,6 +393,41 @@ Meterbridge::on_size_allocate (Gtk::Allocation& a)
Gtk::Window::on_size_allocate(a);
}
void
Meterbridge::on_scroll()
{
if (!scroller.get_hscrollbar()) return;
Adjustment* adj = scroller.get_hscrollbar()->get_adjustment();
int leftend = adj->get_value();
int rightend = scroller.get_width() + leftend;
int mm_left = _mm_left;
int mm_right = _mm_right;
ARDOUR::MeterType mt_left = _mt_left;
ARDOUR::MeterType mt_right = _mt_right;
for (unsigned int i = 0; i < _metrics.size(); ++i) {
int sx, dx, dy;
int mm = _metrics[i]->get_metric_mode();
sx = (mm & 2) ? _metrics[i]->get_width() : 0;
_metrics[i]->translate_coordinates(meterarea, sx, 0, dx, dy);
if (dx < leftend && !(mm&2)) {
mm_left = mm;
mt_left = _metrics[i]->meter_type();
}
if (dx > rightend && (mm&2)) {
mm_right = mm;
mt_right = _metrics[i]->meter_type();
break;
}
}
metrics_left.set_metric_mode(mm_left, mt_left);
metrics_right.set_metric_mode(mm_right, mt_right);
}
void
Meterbridge::set_session (Session* s)
{
@ -550,7 +616,6 @@ Meterbridge::add_strips (RouteList& routes)
}
resync_order();
update_metrics();
}
void
@ -567,28 +632,10 @@ Meterbridge::remove_strip (MeterStrip* strip)
break;
}
}
update_metrics();
}
void
Meterbridge::update_metrics ()
{
bool have_midi = false;
for (list<MeterBridgeStrip>::iterator i = strips.begin(); i != strips.end(); ++i) {
if ( (*i).s->has_midi() && (*i).visible) {
have_midi = true;
break;
}
}
if (have_midi) {
metrics_right.set_metric_mode(2);
} else {
metrics_right.set_metric_mode(3);
}
}
void
Meterbridge::sync_order_keys (RouteSortOrderKey src)
Meterbridge::sync_order_keys (RouteSortOrderKey)
{
Glib::Threads::Mutex::Lock lm (_resync_mutex);
@ -597,6 +644,12 @@ Meterbridge::sync_order_keys (RouteSortOrderKey src)
int pos = 0;
int vis = 0;
MeterStrip * last = 0;
unsigned int metrics = 0;
MeterType lmt = MeterPeak;
bool have_midi = false;
metrics_left.set_metric_mode(1, lmt);
for (list<MeterBridgeStrip>::iterator i = strips.begin(); i != strips.end(); ++i) {
@ -642,9 +695,80 @@ Meterbridge::sync_order_keys (RouteSortOrderKey src)
(*i).visible = true;
vis++;
}
(*i).s->set_pos(vis);
(*i).s->set_tick_bar(0);
MeterType nmt = (*i).s->meter_type();
if (nmt == MeterKrms) nmt = MeterPeak; // identical metrics
if (pos == 0) {
(*i).s->set_tick_bar(1);
}
if ((*i).visible && nmt != lmt && pos == 0) {
lmt = nmt;
metrics_left.set_metric_mode(1, lmt);
} else if ((*i).visible && nmt != lmt) {
if (last) {
last->set_tick_bar(last->get_tick_bar() | 2);
}
(*i).s->set_tick_bar((*i).s->get_tick_bar() | 1);
if (_metrics.size() <= metrics) {
_metrics.push_back(new MeterStrip(have_midi ? 2 : 3, lmt));
meterarea.pack_start (*_metrics[metrics], false, false);
_metrics[metrics]->set_session(_session);
_metrics[metrics]->show();
} else {
_metrics[metrics]->set_metric_mode(have_midi ? 2 : 3, lmt);
}
meterarea.reorder_child(*_metrics[metrics], pos++);
metrics++;
lmt = nmt;
if (_metrics.size() <= metrics) {
_metrics.push_back(new MeterStrip(1, lmt));
meterarea.pack_start (*_metrics[metrics], false, false);
_metrics[metrics]->set_session(_session);
_metrics[metrics]->show();
} else {
_metrics[metrics]->set_metric_mode(1, lmt);
}
meterarea.reorder_child(*_metrics[metrics], pos++);
metrics++;
have_midi = false;
}
if ((*i).visible && (*i).s->has_midi()) {
have_midi = true;
}
meterarea.reorder_child(*((*i).s), pos++);
if ((*i).visible) {
last = (*i).s;
}
}
if (last) {
last->set_tick_bar(last->get_tick_bar() | 2);
}
metrics_right.set_metric_mode(have_midi ? 2 : 3, lmt);
while (_metrics.size() > metrics) {
meterarea.remove(*_metrics.back());
delete (_metrics.back());
_metrics.pop_back();
}
_mm_left = metrics_left.get_metric_mode();
_mt_left = metrics_left.meter_type();
_mm_right = metrics_right.get_metric_mode();
_mt_right = metrics_right.meter_type();
on_scroll();
queue_resize();
}
void
@ -659,21 +783,17 @@ Meterbridge::parameter_changed (std::string const & p)
if (p == "show-busses-on-meterbridge") {
_show_busses = _session->config.get_show_busses_on_meterbridge();
resync_order();
update_metrics();
}
else if (p == "show-master-on-meterbridge") {
_show_master = _session->config.get_show_master_on_meterbridge();
resync_order();
update_metrics();
}
else if (p == "show-midi-on-meterbridge") {
_show_midi = _session->config.get_show_midi_on_meterbridge();
resync_order();
update_metrics();
}
else if (p == "meter-line-up-level") {
meter_clear_pattern_cache();
update_metrics();
}
else if (p == "show-rec-on-meterbridge") {
scroller.queue_resize();
@ -687,6 +807,9 @@ Meterbridge::parameter_changed (std::string const & p)
else if (p == "show-name-on-meterbridge") {
scroller.queue_resize();
}
else if (p == "meterbridge-label-height") {
scroller.queue_resize();
}
}
void

View file

@ -78,7 +78,6 @@ class Meterbridge :
void add_strips (ARDOUR::RouteList&);
void remove_strip (MeterStrip *);
void update_metrics ();
void session_going_away ();
void sync_order_keys (ARDOUR::RouteSortOrderKey src);
@ -116,6 +115,7 @@ class Meterbridge :
MeterStrip metrics_left;
MeterStrip metrics_right;
std::vector<MeterStrip *> _metrics;
Gtk::VBox metrics_vpacker_left;
Gtk::VBox metrics_vpacker_right;
@ -147,6 +147,12 @@ class Meterbridge :
void parameter_changed (std::string const & p);
void on_theme_changed ();
void on_scroll ();
sigc::connection scroll_connection;
int _mm_left, _mm_right;
ARDOUR::MeterType _mt_left, _mt_right;
};
#endif

View file

@ -2134,7 +2134,14 @@ MixerStrip::popup_level_meter_menu (GdkEventButton* ev)
items.push_back (SeparatorElem());
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterPeak), MeterPeak);
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterKrms), MeterKrms);
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterKrms), MeterKrms);
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterIEC1DIN), MeterIEC1DIN);
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterIEC1NOR), MeterIEC1NOR);
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterIEC2BBC), MeterIEC2BBC);
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK20), MeterK20);
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK14), MeterK14);
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterVU), MeterVU);
int _strip_type;
if (_route->is_master()) {

View file

@ -1926,7 +1926,7 @@ void
Mixer_UI::toggle_midi_input_active (bool flip_others)
{
boost::shared_ptr<RouteList> rl (new RouteList);
bool onoff;
bool onoff = false;
set_route_targets_for_operation ();

File diff suppressed because it is too large Load diff

View file

@ -213,6 +213,7 @@ void
ProcessorEntry::set_enum_width (Width w)
{
_width = w;
_button.set_text (name (_width));
}
void
@ -658,7 +659,8 @@ PluginInsertProcessorEntry::SplittingIcon::on_expose_event (GdkEventExpose* ev)
cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
cairo_clip (cr);
cairo_set_line_width (cr, 1);
cairo_set_line_width (cr, 1.5);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
Gtk::Allocation a = get_allocation();
double const width = a.get_width();
@ -673,12 +675,19 @@ PluginInsertProcessorEntry::SplittingIcon::on_expose_event (GdkEventExpose* ev)
Gdk::Color const fg = get_style()->get_fg (STATE_NORMAL);
cairo_set_source_rgb (cr, fg.get_red_p (), fg.get_green_p (), fg.get_blue_p ());
cairo_move_to (cr, width * 0.3, height);
cairo_line_to (cr, width * 0.3, height * 0.5);
cairo_line_to (cr, width * 0.7, height * 0.5);
cairo_line_to (cr, width * 0.7, height);
cairo_move_to (cr, width * 0.5, height * 0.5);
cairo_line_to (cr, width * 0.5, 0);
const float si_l = rint(width * 0.3) + .5;
const float si_c = rint(width * 0.5) + .5;
const float si_r = rint(width * 0.7) + .5;
const float si_m = rint(height * 0.5) + .5;
cairo_move_to (cr, si_l, height);
cairo_line_to (cr, si_l, si_m);
cairo_line_to (cr, si_r, si_m);
cairo_line_to (cr, si_r, height);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
cairo_move_to (cr, si_c, si_m);
cairo_line_to (cr, si_c, 0);
cairo_stroke (cr);
return true;

View file

@ -831,7 +831,7 @@ public:
t->attach (*l, 0, 1, 1, 2, FILL);
t->attach (_video_server_url_entry, 1, 2, 1, 2, FILL);
Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
_("Base URL of the video-server including http prefix. This is usually 'http://hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when the video-server is runing locally"));
_("Base URL of the video-server including http prefix. This is usually 'http://hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when the video-server is running locally"));
l = manage (new Label (_("Video Folder:")));
l->set_alignment (0, 0.5);
@ -1928,20 +1928,50 @@ RCOptionEditor::RCOptionEditor ()
ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
"meter-line-up-level",
_("Meter line-up level"),
_("Meter line-up level; 0dBu"),
sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_level),
sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_level)
);
mlu->add (MeteringLineUp24, _("-24dB"));
mlu->add (MeteringLineUp20, _("-20dB (SMPTE)"));
mlu->add (MeteringLineUp18, _("-18dB (EBU)"));
mlu->add (MeteringLineUp15, _("-15dB"));
mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
Gtkmm2ext::UI::instance()->set_tip (mlu->tip_widget(), _("Configure meter-ticks and color-knee point."));
Gtkmm2ext::UI::instance()->set_tip (mlu->tip_widget(), _("Configure meter-marks and color-knee point for dBFS scale DPM, set reference level for IEC1/Nordic, IEC2 PPM and VU meter."));
add_option (S_("Preferences|GUI"), mlu);
ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
"meter-line-up-din",
_("IEC1/DIN Meter line-up level; 0dBu"),
sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_din),
sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_din)
);
mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
add_option (S_("Preferences|GUI"), mld);
ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
"meter-vu-standard",
_("VU Meter standard"),
sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_vu_standard),
sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_vu_standard)
);
mvu->add (MeteringVUfrench, _("0VU = -2dBu (France)"));
mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
mvu->add (MeteringVUeight, _("0VU = +8dBu"));
add_option (S_("Preferences|GUI"), mvu);
Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
HSliderOption *mpks = new HSliderOption("meter-peak",
_("Peak threshold [dBFS]"),
@ -1955,6 +1985,15 @@ RCOptionEditor::RCOptionEditor ()
_("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
add_option (S_("Preferences|GUI"), mpks);
add_option (S_("Preferences|GUI"),
new BoolOption (
"meter-style-led",
_("LED meter style"),
sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_style_led),
sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_style_led)
));
}
void

View file

@ -32,6 +32,7 @@
#include "ardour/return.h"
#include "ardour/route.h"
#include "ardour/send.h"
#include "ardour/internal_send.h"
#include "ardour_ui.h"
#include "gui_thread.h"
@ -510,7 +511,12 @@ RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> proc)
boost::shared_ptr<PluginInsert> plugin_insert;
boost::shared_ptr<PortInsert> port_insert;
if ((send = boost::dynamic_pointer_cast<Send> (proc)) != 0) {
if ((boost::dynamic_pointer_cast<InternalSend> (proc)) != 0) {
cleanup_view();
_processor.reset ((Processor*) 0);
update_title();
return;
} else if ((send = boost::dynamic_pointer_cast<Send> (proc)) != 0) {
SendUI *send_ui = new SendUI (this, send, _session);

View file

@ -61,11 +61,16 @@ using namespace ARDOUR;
using namespace PBD;
uint32_t RouteUI::_max_invert_buttons = 3;
sigc::signal<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
boost::weak_ptr<Route> RouteUI::_showing_sends_to;
RouteUI::RouteUI (ARDOUR::Session* sess)
: AxisView(sess)
, mute_menu(0)
, solo_menu(0)
, sends_menu(0)
, record_menu(0)
, _invert_menu(0)
{
if (sess) init ();
}
@ -166,7 +171,7 @@ RouteUI::init ()
monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
BusSendDisplayChanged.connect (sigc::mem_fun (*this, &RouteUI::bus_send_display_changed));
BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
}
void

View file

@ -225,7 +225,7 @@ class RouteUI : public virtual AxisView
* by a click on the `Sends' button. The parameter is the route that the sends are
* to, or 0 if no route is now in this mode.
*/
static sigc::signal<void, boost::shared_ptr<ARDOUR::Route> > BusSendDisplayChanged;
static PBD::Signal1<void, boost::shared_ptr<ARDOUR::Route> > BusSendDisplayChanged;
protected:
PBD::ScopedConnectionList route_connections;

View file

@ -344,7 +344,8 @@ SoundFileBox::audition ()
try {
afs = boost::dynamic_pointer_cast<AudioFileSource> (
SourceFactory::createExternal (DataType::AUDIO, *_session,
path, n, Source::Flag (0), false));
path, n,
Source::Flag (0), false));
srclist.push_back(afs);

View file

@ -805,7 +805,15 @@ ArdourStartup::setup_new_session_page ()
string::size_type last_dir_sep = session_parent_dir.rfind(G_DIR_SEPARATOR);
session_parent_dir = session_parent_dir.substr(0, last_dir_sep);
new_folder_chooser.set_current_folder (session_parent_dir);
new_folder_chooser.add_shortcut_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
string default_session_folder = poor_mans_glob (Config->get_default_session_parent_dir());
try {
/* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
new_folder_chooser.add_shortcut_folder (default_session_folder);
}
catch (Glib::Error & e) {
std::cerr << "new_folder_chooser.add_shortcut_folder (" << default_session_folder << ") threw Glib::Error " << e.what() << std::endl;
}
} else {
new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
}

View file

@ -724,10 +724,8 @@ SystemExec::start (int stderr_mode)
signal(SIGPIPE, SIG_DFL);
#endif
#ifndef __WIN32__
int good_fds[1] = { 0 };
int good_fds[1] = { -1 };
close_allv(good_fds);
#endif
::execve(argp[0], argp, envp);
/* if we reach here something went wrong.. */

View file

@ -71,18 +71,19 @@ TranscodeFfmpeg::TranscodeFfmpeg (std::string f)
}
if (ffmpeg_exe.empty() || ffprobe_exe.empty()) {
warning << _(
warning << string_compose(
_(
"No ffprobe or ffmpeg executables could be found on this system.\n"
"Video import and export is not possible until you install those tools.\n"
"Ardour requires ffmpeg and ffprobe from ffmpeg.org - version 1.1 or newer.\n"
"%1 requires ffmpeg and ffprobe from ffmpeg.org - version 1.1 or newer.\n"
"\n"
"The tools are included with the Ardour releases from ardour.org "
"The tools are included with the %1 releases from ardour.org "
"and also available with the video-server at http://x42.github.com/harvid/\n"
"\n"
"Important: the files need to be installed in $PATH and named ffmpeg_harvid and ffprobe_harvid.\n"
"If you already have a suitable ffmpeg installation on your system, we recommend creating "
"symbolic links from ffmpeg to ffmpeg_harvid and from ffprobe to ffprobe_harvid.\n"
) << endmsg;
), PROGRAM_NAME) << endmsg;
return;
}
ffexecok = true;
@ -395,7 +396,7 @@ TranscodeFfmpeg::encode (std::string outfile, std::string inf_a, std::string inf
}
bool
TranscodeFfmpeg::extract_audio (std::string outfile, ARDOUR::framecnt_t samplerate, unsigned int stream)
TranscodeFfmpeg::extract_audio (std::string outfile, ARDOUR::framecnt_t /*samplerate*/, unsigned int stream)
{
if (!probeok) return false;
if (stream >= m_audio.size()) return false;

View file

@ -68,7 +68,7 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
, bitrate_adjustment (2000, 500, 10000, 10, 100, 0)
, bitrate_spinner (bitrate_adjustment)
#if 1 /* tentative debug mode */
, debug_checkbox (_("Debug Mode: Print ffmpeg Command and Output to stdout."))
, debug_checkbox (_("Debug Mode: Print ffmpeg command and output to stdout."))
#endif
{
set_session (s);

View file

@ -301,6 +301,53 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s
}
}
bool
rgba_p_from_style (string style, float *r, float *g, float *b, string attr, int state)
{
static Gtk::Window* window = 0;
assert (r && g && b);
if (window == 0) {
window = new Window (WINDOW_TOPLEVEL);
}
Gtk::EventBox foo;
window->add (foo);
foo.set_name (style);
foo.ensure_style ();
GtkRcStyle* rc = foo.get_style()->gobj()->rc_style;
if (!rc) {
warning << string_compose (_("missing RGBA style for \"%1\""), style) << endl;
return false;
}
if (attr == "fg") {
*r = rc->fg[state].red / 65535.0;
*g = rc->fg[state].green / 65535.0;
*b = rc->fg[state].blue / 65535.0;
} else if (attr == "bg") {
*r = rc->bg[state].red / 65535.0;
*g = rc->bg[state].green / 65535.0;
*b = rc->bg[state].blue / 65535.0;
} else if (attr == "base") {
*r = rc->base[state].red / 65535.0;
*g = rc->base[state].green / 65535.0;
*b = rc->base[state].blue / 65535.0;
} else if (attr == "text") {
*r = rc->text[state].red / 65535.0;
*g = rc->text[state].green / 65535.0;
*b = rc->text[state].blue / 65535.0;
} else {
return false;
}
window->remove ();
return true;
}
bool
canvas_item_visible (ArdourCanvas::Item* item)
{
@ -348,7 +395,7 @@ emulate_key_event (Gtk::Widget* w, unsigned int keyval)
ev.state = 0;
ev.keyval = keyval;
ev.length = 0;
ev.string = (gchar*) "";
ev.string = "";
ev.hardware_keycode = keymapkey[0].keycode;
ev.group = keymapkey[0].group;
g_free(keymapkey);

View file

@ -56,6 +56,8 @@ Pango::FontDescription get_font_for_style (std::string widgetname);
uint32_t rgba_from_style (std::string, uint32_t, uint32_t, uint32_t, uint32_t, std::string = "fg", int = Gtk::STATE_NORMAL, bool = true);
bool rgba_p_from_style (std::string, float*, float*, float*, std::string = "fg", int = Gtk::STATE_NORMAL);
void decorate (Gtk::Window& w, Gdk::WMDecoration d);
bool canvas_item_visible (ArdourCanvas::Item* item);

View file

@ -95,8 +95,10 @@ VideoServerDialog::VideoServerDialog (Session* s)
}
else {
PBD::warning <<
_("The external video server 'harvid' can not be found. The tool is included with the Ardour releases from ardour.org, "
"alternatively you can download it from http://x42.github.com/harvid/ or acquire it from your distribution.") << endmsg;
string_compose(
_("The external video server 'harvid' can not be found. The tool is included with the %1 releases from ardour.org, "
"alternatively you can download it from http://x42.github.com/harvid/ or acquire it from your distribution."), PROGRAM_NAME)
<< endmsg;
}
@ -137,7 +139,9 @@ VideoServerDialog::VideoServerDialog (Session* s)
t->attach (*l, 0, 1, 2, 3, FILL);
t->attach (cachesize_spinner, 1, 2, 2, 3);
l = manage (new Label (_("Ardour relies on an external Video Server for the videotimeline.\nThe server configured in Edit -> Prefereces -> Video is not reachable.\nDo you want ardour to launch 'harvid' on this machine?"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
l = manage (new Label (string_compose(
_("%1 relies on an external Video Server for the videotimeline.\nThe server configured in Edit -> Prefereces -> Video is not reachable.\nDo you want ardour to launch 'harvid' on this machine?"), PROGRAM_NAME)
, Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
l->set_max_width_chars(80);
l->set_line_wrap();
vbox->pack_start (*l, true, true, 4);

View file

@ -502,14 +502,18 @@ VideoTimeLine::video_file_info (std::string filename, bool local)
_session->config.set_timecode_format(timecode_60);
break;
default:
warning << _("Failed to set session-framerate: ") << video_file_fps << _(" does not have a corresponding option setting in Ardour.") << endmsg; /* TODO: gettext arg */
warning << string_compose (
_("Failed to set session-framerate: '%1' does not have a corresponding option setting in %2."),
video_file_fps, PROGRAM_NAME ) << endmsg;
break;
}
_session->config.set_video_pullup(0); /* TODO only set if set_timecode_format() was successful ?!*/
}
if (floor(video_file_fps*100) != floor(_session->timecode_frames_per_second()*100)) {
warning << _("Video file's framerate is not equal to Ardour session timecode's framerate: ")
<< video_file_fps << _(" vs ") << _session->timecode_frames_per_second() << endmsg;
warning << string_compose(
_("Video file's framerate is not equal to %1 session timecode's framerate: '%2' vs '%3'"),
PROGRAM_NAME, video_file_fps, _session->timecode_frames_per_second())
<< endmsg;
}
flush_local_cache ();
@ -580,8 +584,8 @@ VideoTimeLine::check_server_docroot ()
|| lines.at(0).empty()
|| lines.at(0).at(0) != video_get_docroot(Config)) {
warning << string_compose(
_("Video-server docroot mismatch. Ardour: '%1', video-server: '%2'. This usually means that the video server was not started by ardour and uses a different document-root."),
video_get_docroot(Config), lines.at(0).at(0))
_("Video-server docroot mismatch. %1: '%2', video-server: '%3'. This usually means that the video server was not started by ardour and uses a different document-root."),
PROGRAM_NAME, video_get_docroot(Config), lines.at(0).at(0))
<< endmsg;
ok = false; // TODO allow to override
}
@ -814,8 +818,8 @@ VideoTimeLine::terminated_video_monitor () {
vmonitor->save_session();
delete vmonitor;
}
GuiUpdate("set-xjadeo-active-off");
vmonitor=0;
GuiUpdate("set-xjadeo-active-off");
if (reopen_vmonitor) {
reopen_vmonitor=false;
open_video_monitor();

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
};

View file

@ -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 ();

View file

@ -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 */

View file

@ -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); }

View file

@ -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)

View file

@ -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;

View file

@ -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);
};
}

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

100
libs/ardour/iec1ppmdsp.cc Normal file
View file

@ -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: */

100
libs/ardour/iec2ppmdsp.cc Normal file
View file

@ -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: */

View file

@ -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: */

View file

@ -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;

View file

@ -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]);

View file

@ -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 ((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(_kmeter)) {
return accurate_coefficient_to_dB (_kmeter[n - n_midi]->read());
}
return minus_infinity();
}
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 (CHECKSIZE(_iec2meter)) {
return accurate_coefficient_to_dB (_iec2meter[n - n_midi]->read());
}
}
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);
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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)"

View file

@ -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;
}

View file

@ -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);

View file

@ -4174,11 +4174,18 @@ 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)
{

View file

@ -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 ()
{

View file

@ -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;

View file

@ -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);
}

View file

@ -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);

89
libs/ardour/vumeterdsp.cc Normal file
View file

@ -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;
}

View file

@ -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'
]

View file

@ -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)
@ -324,6 +439,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);
@ -333,8 +458,30 @@ FastMeter::on_size_request (GtkRequisition* req)
req->width = request_width;
}
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 ));
}
@ -556,6 +811,77 @@ 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)
{
@ -563,7 +889,11 @@ FastMeter::set_highlight (bool 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 ();
}

View file

@ -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
};

View file

@ -164,7 +164,7 @@ class Keyboard : public sigc::trackable, PBD::Stateful
}
};
sigc::signal0<void> ShiftReleased;
sigc::signal0<void> ZoomVerticalModifierReleased;
protected:
static Keyboard* _the_keyboard;

View file

@ -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) {

View file

@ -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;
}
}

View file

@ -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)

View file

@ -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); \
} \

View file

@ -135,3 +135,17 @@
fun:ladspa_descriptor
fun:*
}
{
<glib utf8>
Memcheck:Addr8
fun:wcslen
fun:wcscoll_l
fun:*
}
{
<glib utf8>
Memcheck:Addr8
fun:wcslen
fun:wcsxfrm_l
fun:*
}