Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to set note range in MIDI editor to one note. #553

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 45 additions & 17 deletions gtk2_ardour/midi_streamview.cc
Original file line number Diff line number Diff line change
Expand Up @@ -270,18 +270,8 @@ MidiStreamView::redisplay_track ()

list<RegionView*>::iterator i;

// Load models if necessary, and find note range of all our contents
_range_dirty = false;
_data_note_min = 127;
_data_note_max = 0;
_trackview.track()->playlist()->foreach_region(
sigc::mem_fun (*this, &StreamView::update_contents_metrics));

// No notes, use default range
if (!_range_dirty) {
_data_note_min = 60;
_data_note_max = 71;
}
// Load models if necessary, and find note range of all our contents;
read_data_note_range_from_regions();

// Flag region views as invalid and disable drawing
for (i = region_views.begin(); i != region_views.end(); ++i) {
Expand All @@ -301,6 +291,23 @@ MidiStreamView::redisplay_track ()
}


void
MidiStreamView::read_data_note_range_from_regions()
{
// Load models if necessary, and find note range of all our contents
_range_dirty = false;
_data_note_min = 127;
_data_note_max = 0;
_trackview.track()->playlist()->foreach_region(
sigc::mem_fun (*this, &StreamView::update_contents_metrics));

// No notes, use default range
if (!_range_dirty) {
_data_note_min = 60;
_data_note_max = 71;
}
}

void
MidiStreamView::update_contents_height ()
{
Expand Down Expand Up @@ -376,12 +383,33 @@ MidiStreamView::draw_note_lines()
void
MidiStreamView::set_note_range(VisibleNoteRange r)
{
if (r == FullRange) {
switch (r) {
case FullRange:
_lowest_note = 0;
_highest_note = 127;
} else {
break;
case OneNoteRange:
_lowest_note = _data_note_min;
_highest_note = _data_note_min;
break;
default:
/* range was one note so need read note data range again
* (if there was other notes range will be expanded)
*/
if (_lowest_note == _highest_note)
read_data_note_range_from_regions();
/* the range read may still contain only one note,
* if so, we have to enlarge it manually
*/
if (_data_note_min == _data_note_max) {
if (_data_note_max < 117)
_data_note_max += 11;
else
_data_note_min -= 11;
}
_lowest_note = _data_note_min;
_highest_note = _data_note_max;
break;
}

apply_note_range(_lowest_note, _highest_note, true);
Expand All @@ -394,11 +422,11 @@ MidiStreamView::apply_note_range(uint8_t lowest, uint8_t highest, bool to_region
_lowest_note = lowest;

int const max_note_height = 20; // This should probably be based on text size...
int const range = _highest_note - _lowest_note;
int const range = _highest_note == _lowest_note ? 1 : _highest_note - _lowest_note;
int const pixels_per_note = floor (child_height () / range);

/* do not grow note height beyond 10 pixels */
if (pixels_per_note > max_note_height) {
/* do not grow note height beyond 10 pixels (except when we want one note) */
if (pixels_per_note > max_note_height && range > 1) {

int const available_note_range = floor (child_height() / max_note_height);
int additional_notes = available_note_range - range;
Expand Down
4 changes: 3 additions & 1 deletion gtk2_ardour/midi_streamview.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class MidiStreamView : public StreamView

enum VisibleNoteRange {
FullRange,
ContentsRange
ContentsRange,
OneNoteRange
};

Gtk::Adjustment note_range_adjustment;
Expand Down Expand Up @@ -133,6 +134,7 @@ class MidiStreamView : public StreamView
void draw_note_lines();
bool update_data_note_range(uint8_t min, uint8_t max);
void update_contents_metrics(boost::shared_ptr<ARDOUR::Region> r);
void read_data_note_range_from_regions();

void color_handler ();

Expand Down
5 changes: 5 additions & 0 deletions gtk2_ardour/midi_time_axis.cc
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,11 @@ MidiTimeAxisView::append_extra_display_menu_items ()
sigc::bind (sigc::mem_fun(*this, &MidiTimeAxisView::set_note_range),
MidiStreamView::ContentsRange, true)));

range_items.push_back (
MenuElem (_("One Note"),
sigc::bind (sigc::mem_fun(*this, &MidiTimeAxisView::set_note_range),
MidiStreamView::OneNoteRange, true)));

items.push_back (MenuElem (_("Note Range"), *range_menu));
items.push_back (MenuElem (_("Note Mode"), *build_note_mode_menu()));
items.push_back (MenuElem (_("Channel Selector..."),
Expand Down
55 changes: 46 additions & 9 deletions gtk2_ardour/piano_roll_header.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <iostream>
#include "evoral/midi_events.h"
#include "ardour/midi_track.h"
#include "ardour/parameter_descriptor.h"

#include "gtkmm2ext/keyboard.h"

Expand All @@ -34,6 +35,7 @@

using namespace std;
using namespace Gtkmm2ext;
using namespace ARDOUR;

PianoRollHeader::Color PianoRollHeader::white = PianoRollHeader::Color(0.77f, 0.78f, 0.76f);
PianoRollHeader::Color PianoRollHeader::white_highlight = PianoRollHeader::Color(1.00f, 0.40f, 0.40f);
Expand Down Expand Up @@ -302,6 +304,7 @@ PianoRollHeader::on_expose_event (GdkEventExpose* ev)
int oct_rel;
int y1 = max(rect.y, 0);
int y2 = min(rect.y + rect.height, (int) floor(_view.contents_height() - 1.0f));
bool is_white_key;

//Cairo::TextExtents te;
lowest = max(_view.lowest_note(), _view.y_to_note(y2));
Expand All @@ -313,7 +316,6 @@ PianoRollHeader::on_expose_event (GdkEventExpose* ev)

cr->select_font_face ("Georgia", Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_BOLD);
font_size = min((double) 10.0f, _note_height - 4.0f);
cr->set_font_size(font_size);

/* fill the entire rect with the color for non-highlighted white notes.
* then we won't have to draw the background for those notes,
Expand Down Expand Up @@ -348,6 +350,8 @@ PianoRollHeader::on_expose_event (GdkEventExpose* ev)
case 8:
case 10:
/* black note */
is_white_key = false;

if (i == _highlighted_note) {
bg.set(black_highlight);
} else {
Expand Down Expand Up @@ -378,6 +382,8 @@ PianoRollHeader::on_expose_event (GdkEventExpose* ev)

default:
/* white note */
is_white_key = true;

if (i == _highlighted_note) {
bg.set(white_highlight);
} else {
Expand Down Expand Up @@ -443,25 +449,56 @@ PianoRollHeader::on_expose_event (GdkEventExpose* ev)

}

/* render the name of which C this is */
if (oct_rel == 0) {
std::stringstream s;
/* if only one note visible render note name vertical (because A#3 don't fit on key) */
if (lowest == highest) {
string const note_name = ParameterDescriptor::midi_note_name(i);
double y = floor(_view.note_to_y(i)) - 0.5f;
double note_height = floor(_view.note_to_y(i - 1)) - y;

int cn = i / 12 - 1;
s << "C" << cn;
cr->set_font_size(font_size);

Cairo::TextExtents te;
cr->get_text_extents(note_name, te);

double r, g, b;

//cr->get_text_extents(s.str(), te);
cr->set_source_rgb(0.30f, 0.30f, 0.30f);
if (is_white_key)
note_name_color(white, r, g, b);
else
note_name_color(black, r, g, b);

cr->set_source_rgb(r, g, b);
cr->move_to(2.0f + font_size , y + note_height - 1.0f - (note_height - te.width) / 2.0f);
cr->rotate(M_PI / -2.0); // -90 degrees
cr->show_text(note_name);
}
else if (oct_rel == 0) {
/* render the name of which C this is */
double y = floor(_view.note_to_y(i)) - 0.5f;
double note_height = floor(_view.note_to_y(i - 1)) - y;

double r, g, b;
note_name_color(white, r, g, b);

cr->set_source_rgb(r, g, b);
cr->move_to(2.0f, y + note_height - 1.0f - (note_height - font_size) / 2.0f);
cr->show_text(s.str());
cr->show_text(ParameterDescriptor::midi_note_name(i));
}
}

return true;
}

void
PianoRollHeader::note_name_color(const PianoRollHeader::Color& key_color, double& r, double& g, double& b)
{
Gtkmm2ext::Color text_color = Gtkmm2ext::rgba_to_color(key_color.r, key_color.g, key_color.b, 1.0f);
text_color = Gtkmm2ext::contrasting_text_color(text_color);

double a;
Gtkmm2ext::color_to_rgba(text_color, r, g, b, a);
}

bool
PianoRollHeader::on_motion_notify_event (GdkEventMotion* ev)
{
Expand Down
2 changes: 2 additions & 0 deletions gtk2_ardour/piano_roll_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class PianoRollHeader : public Gtk::DrawingArea {
static Color black_shade_light;
static Color black_shade_dark;

static void note_name_color(const Color& key_color, double& r, double& g, double& b);

PianoRollHeader(const PianoRollHeader&);

enum ItemType {
Expand Down