steps toward rulers for the MIDI cue editor
This commit is contained in:
parent
e3205bded0
commit
f6b069d251
@ -168,6 +168,12 @@ CueEditor::reset_zoom (samplecnt_t n)
|
||||
ZoomChanged(); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
samplecnt_t
|
||||
CueEditor::get_current_zoom () const
|
||||
{
|
||||
return samples_per_pixel;
|
||||
}
|
||||
|
||||
void
|
||||
CueEditor::reposition_and_zoom (samplepos_t, double)
|
||||
{
|
||||
|
@ -50,6 +50,9 @@ MidiCueEditor::MidiCueEditor()
|
||||
, horizontal_adjustment (0.0, 0.0, 1e16)
|
||||
, view (nullptr)
|
||||
, mouse_mode (Editing::MouseDraw)
|
||||
, bbt_metric (*this)
|
||||
, timebar_height (15.)
|
||||
, n_timebars (1)
|
||||
{
|
||||
build_canvas ();
|
||||
|
||||
@ -117,7 +120,23 @@ MidiCueEditor::build_canvas ()
|
||||
rubberband_rect->set_fill_color (UIConfiguration::instance().color_mod ("rubber band rect", "selection rect"));
|
||||
CANVAS_DEBUG_NAME (rubberband_rect, X_("cue rubberband rect"));
|
||||
|
||||
bg = new CueMidiBackground (hv_scroll_group);
|
||||
|
||||
Pango::FontDescription font (UIConfiguration::instance().get_SmallerFont());
|
||||
Pango::FontDescription larger_font (UIConfiguration::instance().get_SmallBoldFont());
|
||||
bbt_ruler = new ArdourCanvas::Ruler (time_line_group, &bbt_metric, ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height));
|
||||
bbt_ruler->set_font_description (font);
|
||||
bbt_ruler->set_second_font_description (larger_font);
|
||||
Gtkmm2ext::Color base = UIConfiguration::instance().color ("ruler base");
|
||||
Gtkmm2ext::Color text = UIConfiguration::instance().color ("ruler text");
|
||||
bbt_ruler->set_fill_color (base);
|
||||
bbt_ruler->set_outline_color (text);
|
||||
CANVAS_DEBUG_NAME (bbt_ruler, "bbt ruler");
|
||||
|
||||
data_group = new ArdourCanvas::Container (hv_scroll_group);
|
||||
data_group->move (ArdourCanvas::Duple (0., timebar_height * n_timebars));
|
||||
CANVAS_DEBUG_NAME (data_group, "cue data group");
|
||||
|
||||
bg = new CueMidiBackground (data_group);
|
||||
_canvas_viewport->signal_size_allocate().connect (sigc::mem_fun(*this, &MidiCueEditor::canvas_allocate));
|
||||
|
||||
_canvas->set_name ("MidiCueCanvas");
|
||||
@ -139,7 +158,6 @@ MidiCueEditor::canvas_enter_leave (GdkEventCrossing* ev)
|
||||
_canvas_viewport->canvas()->grab_focus ();
|
||||
ActionManager::set_sensitive (_midi_actions, true);
|
||||
EditingContext::push_editing_context (this);
|
||||
std::cerr << "GRAB FOCUS\n";
|
||||
}
|
||||
break;
|
||||
case GDK_LEAVE_NOTIFY:
|
||||
@ -147,7 +165,6 @@ MidiCueEditor::canvas_enter_leave (GdkEventCrossing* ev)
|
||||
ActionManager::set_sensitive (_midi_actions, false);
|
||||
ARDOUR_UI::instance()->reset_focus (_canvas_viewport);
|
||||
EditingContext::pop_editing_context ();
|
||||
std::cerr << "DROP FOCUS\n";
|
||||
}
|
||||
default:
|
||||
break;
|
||||
@ -159,8 +176,9 @@ void
|
||||
MidiCueEditor::canvas_allocate (Gtk::Allocation alloc)
|
||||
{
|
||||
bg->set_size (alloc.get_width(), alloc.get_height());
|
||||
|
||||
if (view) {
|
||||
view->set_size (alloc.get_width(), alloc.get_height());
|
||||
view->set_size (alloc.get_width(), alloc.get_height() - (timebar_height * n_timebars));
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,6 +229,8 @@ MidiCueEditor::reset_zoom (samplecnt_t spp)
|
||||
if (view) {
|
||||
view->set_samples_per_pixel (spp);
|
||||
}
|
||||
|
||||
bbt_ruler->set_range (0, current_page_samples());
|
||||
}
|
||||
|
||||
samplecnt_t
|
||||
@ -268,7 +288,7 @@ MidiCueEditor::set_region (std::shared_ptr<ARDOUR::MidiTrack> t, std::shared_ptr
|
||||
return;
|
||||
}
|
||||
|
||||
view = new MidiCueView (t, *hv_scroll_group, *this, *bg, 0xff0000ff);
|
||||
view = new MidiCueView (t, *data_group, *this, *bg, 0xff0000ff);
|
||||
view->set_region (r);
|
||||
|
||||
bg->set_view (view);
|
||||
@ -460,3 +480,349 @@ MidiCueEditor::region_selection()
|
||||
RegionSelection rs;
|
||||
return rs;
|
||||
}
|
||||
|
||||
static void
|
||||
edit_last_mark_label (std::vector<ArdourCanvas::Ruler::Mark>& marks, const std::string& newlabel)
|
||||
{
|
||||
ArdourCanvas::Ruler::Mark copy = marks.back();
|
||||
copy.label = newlabel;
|
||||
marks.pop_back ();
|
||||
marks.push_back (copy);
|
||||
}
|
||||
|
||||
void
|
||||
MidiCueEditor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, samplepos_t leftmost, samplepos_t rightmost, gint /*maxchars*/)
|
||||
{
|
||||
if (_session == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<Temporal::TempoMap> tmap;
|
||||
|
||||
if (view) {
|
||||
/* XXX MAKE MAP FROM REGION->SOURCE */
|
||||
tmap.reset (new Temporal::TempoMap (Temporal::Tempo (120, 4), Temporal::Meter (4, 4)));
|
||||
} else {
|
||||
tmap.reset (new Temporal::TempoMap (Temporal::Tempo (120, 4), Temporal::Meter (4, 4)));
|
||||
}
|
||||
|
||||
EditingContext::TempoMapScope tms (*this, tmap);
|
||||
Temporal::TempoMapPoints::const_iterator i;
|
||||
|
||||
char buf[64];
|
||||
Temporal::BBT_Time next_beat;
|
||||
double bbt_position_of_helper;
|
||||
bool helper_active = false;
|
||||
ArdourCanvas::Ruler::Mark mark;
|
||||
const samplecnt_t sr (_session->sample_rate());
|
||||
|
||||
Temporal::TempoMapPoints grid;
|
||||
grid.reserve (4096);
|
||||
|
||||
|
||||
/* prevent negative values of leftmost from creeping into tempomap
|
||||
*/
|
||||
|
||||
const Beats left = tmap->quarters_at_sample (leftmost).round_down_to_beat();
|
||||
const Beats lower_beat = (left < Beats() ? Beats() : left);
|
||||
|
||||
using std::max;
|
||||
|
||||
switch (bbt_ruler_scale) {
|
||||
|
||||
case bbt_show_quarters:
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 0, 1);
|
||||
break;
|
||||
case bbt_show_eighths:
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 0, 2);
|
||||
break;
|
||||
case bbt_show_sixteenths:
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 0, 4);
|
||||
break;
|
||||
case bbt_show_thirtyseconds:
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 0, 8);
|
||||
break;
|
||||
case bbt_show_sixtyfourths:
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 0, 16);
|
||||
break;
|
||||
case bbt_show_onetwentyeighths:
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 0, 32);
|
||||
break;
|
||||
|
||||
case bbt_show_1:
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 1);
|
||||
break;
|
||||
|
||||
case bbt_show_4:
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 4);
|
||||
break;
|
||||
|
||||
case bbt_show_16:
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 16);
|
||||
break;
|
||||
|
||||
case bbt_show_64:
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 64);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* bbt_show_many */
|
||||
tmap->get_grid (grid, max (tmap->superclock_at (lower_beat), (superclock_t) 0), samples_to_superclock (rightmost, sr), 128);
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0 // DEBUG GRID
|
||||
for (auto const& g : grid) {
|
||||
std::cout << "Grid " << g.time() << " Beats: " << g.beats() << " BBT: " << g.bbt() << " sample: " << g.sample(_session->nominal_sample_rate ()) << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (distance (grid.begin(), grid.end()) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* we can accent certain lines depending on the user's Grid choice */
|
||||
/* for example, even in a 4/4 meter we can draw a grid with triplet-feel */
|
||||
/* and in this case you will want the accents on '3s' not '2s' */
|
||||
uint32_t bbt_divisor = 2;
|
||||
|
||||
using namespace Editing;
|
||||
|
||||
switch (_grid_type) {
|
||||
case GridTypeBeatDiv3:
|
||||
bbt_divisor = 3;
|
||||
break;
|
||||
case GridTypeBeatDiv5:
|
||||
bbt_divisor = 5;
|
||||
break;
|
||||
case GridTypeBeatDiv6:
|
||||
bbt_divisor = 3;
|
||||
break;
|
||||
case GridTypeBeatDiv7:
|
||||
bbt_divisor = 7;
|
||||
break;
|
||||
case GridTypeBeatDiv10:
|
||||
bbt_divisor = 5;
|
||||
break;
|
||||
case GridTypeBeatDiv12:
|
||||
bbt_divisor = 3;
|
||||
break;
|
||||
case GridTypeBeatDiv14:
|
||||
bbt_divisor = 7;
|
||||
break;
|
||||
case GridTypeBeatDiv16:
|
||||
break;
|
||||
case GridTypeBeatDiv20:
|
||||
bbt_divisor = 5;
|
||||
break;
|
||||
case GridTypeBeatDiv24:
|
||||
bbt_divisor = 6;
|
||||
break;
|
||||
case GridTypeBeatDiv28:
|
||||
bbt_divisor = 7;
|
||||
break;
|
||||
case GridTypeBeatDiv32:
|
||||
break;
|
||||
default:
|
||||
bbt_divisor = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t bbt_beat_subdivision = 1;
|
||||
switch (bbt_ruler_scale) {
|
||||
case bbt_show_quarters:
|
||||
bbt_beat_subdivision = 1;
|
||||
break;
|
||||
case bbt_show_eighths:
|
||||
bbt_beat_subdivision = 1;
|
||||
break;
|
||||
case bbt_show_sixteenths:
|
||||
bbt_beat_subdivision = 2;
|
||||
break;
|
||||
case bbt_show_thirtyseconds:
|
||||
bbt_beat_subdivision = 4;
|
||||
break;
|
||||
case bbt_show_sixtyfourths:
|
||||
bbt_beat_subdivision = 8;
|
||||
break;
|
||||
case bbt_show_onetwentyeighths:
|
||||
bbt_beat_subdivision = 16;
|
||||
break;
|
||||
default:
|
||||
bbt_beat_subdivision = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
bbt_beat_subdivision *= bbt_divisor;
|
||||
|
||||
switch (bbt_ruler_scale) {
|
||||
|
||||
case bbt_show_many:
|
||||
snprintf (buf, sizeof(buf), "cannot handle %" PRIu32 " bars", bbt_bars);
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
mark.label = buf;
|
||||
mark.position = leftmost;
|
||||
marks.push_back (mark);
|
||||
break;
|
||||
|
||||
case bbt_show_64:
|
||||
for (i = grid.begin(); i != grid.end(); i++) {
|
||||
BBT_Time bbt ((*i).bbt());
|
||||
if (bbt.is_bar()) {
|
||||
if (bbt.bars % 64 == 1) {
|
||||
if (bbt.bars % 256 == 1) {
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, bbt.bars);
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
} else {
|
||||
buf[0] = '\0';
|
||||
if (bbt.bars % 256 == 129) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
}
|
||||
}
|
||||
mark.label = buf;
|
||||
mark.position = (*i).sample (sr);
|
||||
marks.push_back (mark);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case bbt_show_16:
|
||||
for (i = grid.begin(); i != grid.end(); i++) {
|
||||
BBT_Time bbt ((*i).bbt());
|
||||
if (bbt.is_bar()) {
|
||||
if (bbt.bars % 16 == 1) {
|
||||
if (bbt.bars % 64 == 1) {
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, bbt.bars);
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
} else {
|
||||
buf[0] = '\0';
|
||||
if (bbt.bars % 64 == 33) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
}
|
||||
}
|
||||
mark.label = buf;
|
||||
mark.position = (*i).sample(sr);
|
||||
marks.push_back (mark);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case bbt_show_4:
|
||||
for (i = grid.begin(); i != grid.end(); ++i) {
|
||||
BBT_Time bbt ((*i).bbt());
|
||||
if (bbt.is_bar()) {
|
||||
if (bbt.bars % 4 == 1) {
|
||||
if (bbt.bars % 16 == 1) {
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, bbt.bars);
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
} else {
|
||||
buf[0] = '\0';
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
}
|
||||
mark.label = buf;
|
||||
mark.position = (*i).sample (sr);
|
||||
marks.push_back (mark);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case bbt_show_1:
|
||||
for (i = grid.begin(); i != grid.end(); ++i) {
|
||||
BBT_Time bbt ((*i).bbt());
|
||||
if (bbt.is_bar()) {
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, bbt.bars);
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
mark.label = buf;
|
||||
mark.position = (*i).sample (sr);
|
||||
marks.push_back (mark);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case bbt_show_quarters:
|
||||
|
||||
mark.label = "";
|
||||
mark.position = leftmost;
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
marks.push_back (mark);
|
||||
|
||||
for (i = grid.begin(); i != grid.end(); ++i) {
|
||||
|
||||
BBT_Time bbt ((*i).bbt());
|
||||
|
||||
if ((*i).sample (sr) < leftmost && (bbt_bar_helper_on)) {
|
||||
snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, bbt.bars, bbt.beats);
|
||||
edit_last_mark_label (marks, buf);
|
||||
} else {
|
||||
|
||||
if (bbt.is_bar()) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, bbt.bars);
|
||||
} else if ((bbt.beats % 2) == 1) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
buf[0] = '\0';
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
buf[0] = '\0';
|
||||
}
|
||||
mark.label = buf;
|
||||
mark.position = (*i).sample (sr);
|
||||
marks.push_back (mark);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case bbt_show_eighths:
|
||||
case bbt_show_sixteenths:
|
||||
case bbt_show_thirtyseconds:
|
||||
case bbt_show_sixtyfourths:
|
||||
case bbt_show_onetwentyeighths:
|
||||
|
||||
bbt_position_of_helper = leftmost + (3 * get_current_zoom ());
|
||||
|
||||
mark.label = "";
|
||||
mark.position = leftmost;
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
marks.push_back (mark);
|
||||
|
||||
for (i = grid.begin(); i != grid.end(); ++i) {
|
||||
|
||||
BBT_Time bbt ((*i).bbt());
|
||||
|
||||
if ((*i).sample (sr) < leftmost && (bbt_bar_helper_on)) {
|
||||
snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, bbt.bars, bbt.beats);
|
||||
edit_last_mark_label (marks, buf);
|
||||
helper_active = true;
|
||||
} else {
|
||||
|
||||
if (bbt.is_bar()) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, bbt.bars);
|
||||
} else if (bbt.ticks == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, bbt.beats);
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
buf[0] = '\0';
|
||||
}
|
||||
|
||||
if (((*i).sample(sr) < bbt_position_of_helper) && helper_active) {
|
||||
buf[0] = '\0';
|
||||
}
|
||||
mark.label = buf;
|
||||
mark.position = (*i).sample (sr);
|
||||
marks.push_back (mark);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
#include <gtkmm/adjustment.h>
|
||||
|
||||
#include "canvas/ruler.h"
|
||||
|
||||
#include "cue_editor.h"
|
||||
|
||||
namespace Gtk {
|
||||
@ -102,8 +104,6 @@ class MidiCueEditor : public CueEditor
|
||||
ArdourCanvas::GtkCanvasViewport* _canvas_viewport;
|
||||
ArdourCanvas::GtkCanvas* _canvas;
|
||||
|
||||
ArdourCanvas::Container* tempo_group;
|
||||
|
||||
/* The group containing all other groups that are scrolled vertically
|
||||
and horizontally.
|
||||
*/
|
||||
@ -117,11 +117,11 @@ class MidiCueEditor : public CueEditor
|
||||
*/
|
||||
ArdourCanvas::ScrollGroup* cursor_scroll_group;
|
||||
|
||||
/* The group containing all trackviews. */
|
||||
ArdourCanvas::Container* no_scroll_group;
|
||||
|
||||
ArdourCanvas::Container* global_rect_group;
|
||||
ArdourCanvas::Container* no_scroll_group;
|
||||
ArdourCanvas::Container* data_group;
|
||||
ArdourCanvas::Container* time_line_group;
|
||||
ArdourCanvas::Ruler* bbt_ruler;
|
||||
|
||||
ArdourCanvas::Rectangle* transport_loop_range_rect;
|
||||
|
||||
@ -136,6 +136,25 @@ class MidiCueEditor : public CueEditor
|
||||
RegionSelection region_selection();
|
||||
|
||||
bool canvas_enter_leave (GdkEventCrossing* ev);
|
||||
|
||||
void metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>&, samplepos_t, samplepos_t, gint);
|
||||
|
||||
class BBTMetric : public ArdourCanvas::Ruler::Metric
|
||||
{
|
||||
public:
|
||||
BBTMetric (MidiCueEditor& ec) : context (&ec) {}
|
||||
|
||||
void get_marks (std::vector<ArdourCanvas::Ruler::Mark>& marks, int64_t lower, int64_t upper, int maxchars) const {
|
||||
context->metric_get_bbt (marks, lower, upper, maxchars);
|
||||
}
|
||||
|
||||
private:
|
||||
MidiCueEditor* context;
|
||||
};
|
||||
|
||||
BBTMetric bbt_metric;
|
||||
double timebar_height;
|
||||
size_t n_timebars;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user