* first prototype of program changes UI show up correctly (see http://www.flickr.com/photos/24012642@N02/2451596190/)

git-svn-id: svn://localhost/ardour2/branches/3.0@3293 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Hans Baier 2008-04-29 07:28:24 +00:00
parent f41f334be6
commit 6d319e2132
14 changed files with 180 additions and 40 deletions

View file

@ -131,6 +131,7 @@ automation_streamview.cc
automation_time_axis.cc
axis_view.cc
bundle_manager.cc
canvas-program-change.cc
canvas-midi-event.cc
canvas-note.cc
canvas-simpleline.c

View file

@ -27,7 +27,7 @@
namespace Gnome {
namespace Canvas {
class CanvasHit : public Diamond, public CanvasMidiEvent {
class CanvasHit : public Diamond, public CanvasNoteEvent {
public:
CanvasHit(
MidiRegionView& region,
@ -47,7 +47,7 @@ public:
void set_outline_color(uint32_t c) { property_outline_color_rgba() = c; }
void set_fill_color(uint32_t c) { property_fill_color_rgba() = c; }
bool on_event(GdkEvent* ev) { return CanvasMidiEvent::on_event(ev); }
bool on_event(GdkEvent* ev) { return CanvasNoteEvent::on_event(ev); }
};
} // namespace Gnome

View file

@ -31,7 +31,7 @@ namespace Gnome {
namespace Canvas {
CanvasMidiEvent::CanvasMidiEvent(MidiRegionView& region, Item* item,
CanvasNoteEvent::CanvasMidiEvent(MidiRegionView& region, Item* item,
const boost::shared_ptr<ARDOUR::Note> note)
: _region(region)
, _item(item)
@ -44,21 +44,21 @@ CanvasMidiEvent::CanvasMidiEvent(MidiRegionView& region, Item* item,
_text = new Text(*(item->property_parent()));
}
CanvasMidiEvent::~CanvasMidiEvent()
CanvasNoteEvent::~CanvasNoteEvent()
{
if(_text) delete _text;
if(_channel_selector_widget) delete _channel_selector_widget;
}
void
CanvasMidiEvent::move_event(double dx, double dy)
CanvasNoteEvent::move_event(double dx, double dy)
{
_item->move(dx, dy);
_text->move(dx, dy);
}
void
CanvasMidiEvent::show_velocity(void)
CanvasNoteEvent::show_velocity(void)
{
_text->property_x() = (x1() + x2()) /2;
_text->property_y() = (y1() + y2()) /2;
@ -73,13 +73,13 @@ CanvasMidiEvent::show_velocity(void)
}
void
CanvasMidiEvent::hide_velocity(void)
CanvasNoteEvent::hide_velocity(void)
{
_text->hide();
}
void
CanvasMidiEvent::on_channel_selection_change(uint16_t selection)
CanvasNoteEvent::on_channel_selection_change(uint16_t selection)
{
// make note change its color if its channel is not marked active
if( (selection & (1 << _note->channel())) == 0 ) {
@ -95,7 +95,7 @@ CanvasMidiEvent::on_channel_selection_change(uint16_t selection)
}
void
CanvasMidiEvent::on_channel_change(uint8_t channel)
CanvasNoteEvent::on_channel_change(uint8_t channel)
{
_region.note_selected(this, true);
hide_channel_selector();
@ -103,14 +103,14 @@ CanvasMidiEvent::on_channel_change(uint8_t channel)
}
void
CanvasMidiEvent::show_channel_selector(void)
CanvasNoteEvent::show_channel_selector(void)
{
if(_channel_selector_widget == 0) {
cerr << "Note has channel: " << int(_note->channel()) << endl;
SingleMidiChannelSelector* _channel_selector = new SingleMidiChannelSelector(_note->channel());
_channel_selector->show_all();
_channel_selector->channel_selected.connect(
sigc::mem_fun(this, &CanvasMidiEvent::on_channel_change));
sigc::mem_fun(this, &CanvasNoteEvent::on_channel_change));
_channel_selector_widget =
new Widget(*(_item->property_parent()),
@ -129,7 +129,7 @@ CanvasMidiEvent::show_channel_selector(void)
}
void
CanvasMidiEvent::hide_channel_selector(void)
CanvasNoteEvent::hide_channel_selector(void)
{
if(_channel_selector_widget) {
_channel_selector_widget->hide();
@ -139,7 +139,7 @@ CanvasMidiEvent::hide_channel_selector(void)
}
void
CanvasMidiEvent::selected(bool yn)
CanvasNoteEvent::selected(bool yn)
{
if (!_note) {
return;
@ -159,7 +159,7 @@ CanvasMidiEvent::selected(bool yn)
bool
CanvasMidiEvent::on_event(GdkEvent* ev)
CanvasNoteEvent::on_event(GdkEvent* ev)
{
MidiStreamView *streamview = _region.midi_stream_view();
static uint8_t drag_delta_note = 0;

View file

@ -44,14 +44,14 @@ namespace Canvas {
*
* A newer, better canvas should remove the need for all the ugly here.
*/
class CanvasMidiEvent : public sigc::trackable {
class CanvasNoteEvent : public sigc::trackable {
public:
CanvasMidiEvent(
MidiRegionView& region,
Item* item,
const boost::shared_ptr<ARDOUR::Note> note = boost::shared_ptr<ARDOUR::Note>());
virtual ~CanvasMidiEvent();
virtual ~CanvasNoteEvent();
bool on_event(GdkEvent* ev);

View file

@ -80,11 +80,11 @@ CanvasNote::on_event(GdkEvent* ev)
return true;
default:
return CanvasMidiEvent::on_event(ev);
return CanvasNoteEvent::on_event(ev);
}
default:
return CanvasMidiEvent::on_event(ev);
return CanvasNoteEvent::on_event(ev);
}
}

View file

@ -29,7 +29,7 @@
namespace Gnome {
namespace Canvas {
class CanvasNote : public SimpleRect, public CanvasMidiEvent {
class CanvasNote : public SimpleRect, public CanvasNoteEvent {
public:
CanvasNote(
MidiRegionView& region,

View file

@ -0,0 +1,58 @@
#include "canvas-program-change.h"
#include <iostream>
using namespace ArdourCanvas;
using namespace std;
CanvasProgramChange::CanvasProgramChange(
MidiRegionView& region,
Group& parent,
boost::shared_ptr<MIDI::Event> event,
double height,
double x,
double y)
: Group(parent, x, y),
_region(region),
_event(event),
_text(0),
_line(0),
_rect(0),
_widget(0)
{
_text = new Text(*this);
ostringstream pgm(ios::ate);
pgm << int(event->pgm_number());
_text->property_text() = pgm.str();
_text->property_justification() = Gtk::JUSTIFY_CENTER;
_text->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiProgramChangeOutline.get();
double flagwidth = _text->property_text_width() + 10.0;
double flagheight = _text->property_text_height() + 3.0;
_text->property_x() = flagwidth / 2.0;
_text->property_y() = flagheight / 2.0;
_text->show();
_line = new SimpleLine(*this, 0.0, 0.0, 0.0, height);
_line->property_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiProgramChangeOutline.get();
_rect = new SimpleRect(*this, 0.0, 0.0, flagwidth, flagheight);
_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiProgramChangeOutline.get();
_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiProgramChangeFill.get();
_text->lower_to_bottom();
_text->raise(2);
assert(_widget == 0);
assert(_text != 0);
assert(_line != 0);
assert(_rect != 0);
}
CanvasProgramChange::~CanvasProgramChange()
{
if(_line)
delete _line;
if(_rect)
delete _rect;
if(_text)
delete _text;
if(_widget)
delete _widget;
}

View file

@ -0,0 +1,43 @@
#ifndef CANVASPROGRAMCHANGE_H_
#define CANVASPROGRAMCHANGE_H_
#include <libgnomecanvasmm/group.h>
#include "simplerect.h"
#include "simpleline.h"
#include "midi_region_view.h"
#include <libgnomecanvasmm/text.h>
#include <libgnomecanvasmm/widget.h>
#include <ardour/midi_model.h>
namespace Gnome
{
namespace Canvas
{
class CanvasProgramChange : public Group
{
public:
CanvasProgramChange(
MidiRegionView& region,
Group& parent,
boost::shared_ptr<MIDI::Event> event,
double height,
double x = 0.0,
double y = 0.0
);
virtual ~CanvasProgramChange();
private:
MidiRegionView& _region;
boost::shared_ptr<MIDI::Event> _event;
Text* _text;
SimpleLine* _line;
SimpleRect* _rect;
Widget* _widget;
};
} // namespace Canvas
} // namespace Gnome
#endif /*CANVASPROGRAMCHANGE_H_*/

View file

@ -65,6 +65,8 @@ CANVAS_VARIABLE(canvasvar_MidiNoteOutlineMid, "midi note outline mid")
CANVAS_VARIABLE(canvasvar_MidiNoteOutlineMin, "midi note outline min")
CANVAS_VARIABLE(canvasvar_MidiNoteOutlineInactiveChannel, "midi note outline inactive channel")
CANVAS_VARIABLE(canvasvar_MidiNoteSelectedOutline, "midi note selected outline")
CANVAS_VARIABLE(canvasvar_MidiProgramChangeFill, "midi program change fill")
CANVAS_VARIABLE(canvasvar_MidiProgramChangeOutline, "midi program change outline")
CANVAS_VARIABLE(canvasvar_MidiSelectRectFill, "midi select rect fill")
CANVAS_VARIABLE(canvasvar_MidiSelectRectOutline, "midi select rect outline")
CANVAS_VARIABLE(canvasvar_MidiTrackBase, "midi track base")

View file

@ -174,7 +174,7 @@ MidiGhostRegion::~MidiGhostRegion()
//clear_events();
}
MidiGhostRegion::Event::Event(ArdourCanvas::CanvasMidiEvent* e)
MidiGhostRegion::Event::Event(ArdourCanvas::CanvasNoteEvent* e)
: event(e)
{
}

View file

@ -28,7 +28,7 @@
namespace Gnome {
namespace Canvas {
class CanvasMidiEvent;
class CanvasNoteEvent;
class CanvasNote;
class CanvasHit;
class Diamond;
@ -76,11 +76,11 @@ class MidiGhostRegion : public GhostRegion {
public:
class Event : public sigc::trackable {
public:
Event(ArdourCanvas::CanvasMidiEvent*);
Event(ArdourCanvas::CanvasNoteEvent*);
virtual ~Event() {}
virtual void x_changed() = 0;
ArdourCanvas::CanvasMidiEvent* event;
ArdourCanvas::CanvasNoteEvent* event;
};
class Note : public Event {

View file

@ -41,6 +41,7 @@
#include "simpleline.h"
#include "canvas-hit.h"
#include "canvas-note.h"
#include "canvas-program-change.h"
#include "public_editor.h"
#include "ghostregion.h"
#include "midi_time_axis.h"
@ -474,6 +475,16 @@ MidiRegionView::redisplay_model()
add_note(_model->note_at(i));
}
MidiModel::PgmChanges& pgm_changes = _model->pgm_changes();
/*
for (MidiModel::PgmChanges::const_iterator i = pgm_changes.begin();
i != pgm_changes.end();
++i) {
add_pgm_change()
}
*/
for_each(pgm_changes.begin(), pgm_changes.end(), sigc::mem_fun(this, &MidiRegionView::add_pgm_change));
end_write();
/*for (Automatable::Controls::const_iterator i = _model->controls().begin();
@ -792,6 +803,27 @@ MidiRegionView::add_note(const boost::shared_ptr<Note> note)
}
}
void
MidiRegionView::add_pgm_change(boost::shared_ptr<MIDI::Event> event)
{
assert(event->time() >= 0);
// dont display notes beyond the region bounds
if(
event->time() - _region->start() >= _region->length() ||
event->time() < _region->start()
) {
return;
}
ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group();
const double x = trackview.editor.frame_to_pixel((nframes_t)event->time() - _region->start());
double height = midi_stream_view()->contents_height();
new CanvasProgramChange(*this, *group, event, height, x, 1.0);
//TODO : keep track of pgm changes
}
void
MidiRegionView::delete_selection()
{

View file

@ -37,6 +37,7 @@
#include "canvas.h"
#include "canvas-note.h"
#include "canvas-midi-event.h"
#include "canvas-program-change.h"
namespace ARDOUR {
class MidiRegion;
@ -80,6 +81,8 @@ class MidiRegionView : public RegionView
void add_note(const boost::shared_ptr<ARDOUR::Note> note);
void resolve_note(uint8_t note_num, double end_time);
void add_pgm_change(boost::shared_ptr<MIDI::Event> event);
void begin_write();
void end_write();
@ -101,7 +104,7 @@ class MidiRegionView : public RegionView
_delta_command->add(note);
}
void command_remove_note(ArdourCanvas::CanvasMidiEvent* ev) {
void command_remove_note(ArdourCanvas::CanvasNoteEvent* ev) {
if (_delta_command && ev->note()) {
_selection.erase(ev);
_delta_command->remove(ev->note());
@ -123,15 +126,15 @@ class MidiRegionView : public RegionView
midi_view()->midi_track()->diskstream()->playlist_modified();
}
void note_entered(ArdourCanvas::CanvasMidiEvent* ev);
void unique_select(ArdourCanvas::CanvasMidiEvent* ev);
void note_selected(ArdourCanvas::CanvasMidiEvent* ev, bool add);
void note_deselected(ArdourCanvas::CanvasMidiEvent* ev, bool add);
void note_entered(ArdourCanvas::CanvasNoteEvent* ev);
void unique_select(ArdourCanvas::CanvasNoteEvent* ev);
void note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add);
void note_deselected(ArdourCanvas::CanvasNoteEvent* ev, bool add);
void delete_selection();
size_t selection_size() { return _selection.size(); }
void move_selection(double dx, double dy);
void note_dropped(ArdourCanvas::CanvasMidiEvent* ev, double dt, uint8_t dnote);
void note_dropped(ArdourCanvas::CanvasNoteEvent* ev, double dt, uint8_t dnote);
/**
* This function is needed to subtract the region start in pixels
@ -243,14 +246,14 @@ class MidiRegionView : public RegionView
uint16_t last_channel_selection;
void midi_channel_selection_changed(uint16_t selection);
void clear_selection_except(ArdourCanvas::CanvasMidiEvent* ev);
void clear_selection_except(ArdourCanvas::CanvasNoteEvent* ev);
void clear_selection() { clear_selection_except(NULL); }
void update_drag_selection(double last_x, double x, double last_y, double y);
double _default_note_length;
boost::shared_ptr<ARDOUR::MidiModel> _model;
std::vector<ArdourCanvas::CanvasMidiEvent*> _events;
std::vector<ArdourCanvas::CanvasNoteEvent*> _events;
ArdourCanvas::CanvasNote** _active_notes;
ArdourCanvas::Group* _note_group;
ARDOUR::MidiModel::DeltaCommand* _delta_command;
@ -259,7 +262,7 @@ class MidiRegionView : public RegionView
int _pressed_button;
/// currently selected CanvasMidiEvents
typedef std::set<ArdourCanvas::CanvasMidiEvent*> Selection;
typedef std::set<ArdourCanvas::CanvasNoteEvent*> Selection;
Selection _selection;
/**

View file

@ -87,6 +87,7 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
}
}
/* TODO: Disabled for stablility reasons
MidiControlIterator earliest_control(boost::shared_ptr<AutomationList>(), DBL_MAX, 0.0);
_control_iters.reserve(model.controls().size());
@ -98,8 +99,8 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
double x, y;
bool ret = i->second->list()->rt_safe_earliest_event_unlocked(t, DBL_MAX, x, y);
if (!ret) {
/*cerr << "MIDI Iterator: CC " << i->first.id() << " (size " << i->second->list()->size()
<< ") has no events past " << t << endl;*/
//cerr << "MIDI Iterator: CC " << i->first.id() << " (size " << i->second->list()->size()
// << ") has no events past " << t << endl;
continue;
}
@ -118,6 +119,8 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
--_control_iter;
}
}
*/
if (_note_iter != model.notes().end()) {
_event = MIDI::Event((*_note_iter)->on_event(), false);
@ -126,10 +129,12 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
++_note_iter;
}
/** TODO: Disabled for stability reasons
if (earliest_control.automation_list && earliest_control.x < _event.time())
model.control_to_midi_event(_event, earliest_control);
else
_control_iter = _control_iters.end();
*/
_pgm_change_iter = model.pgm_changes().end();
// find first program change which begins after t
@ -556,12 +561,13 @@ MidiModel::append_cc_unlocked(uint8_t chan, double time, uint8_t number, uint8_t
assert(chan < 16);
assert(_writing);
/** TODO: disabled for now until debugged....
_edited = true;
Parameter param(MidiCCAutomation, number, chan);
boost::shared_ptr<AutomationControl> control = Automatable::control(param, true);
control->list()->fast_simple_add(time, (double)value);
*/
}
void
@ -577,11 +583,6 @@ MidiModel::append_pgm_change_unlocked(uint8_t chan, double time, uint8_t number)
event_ptr->set_channel(chan);
event_ptr->set_pgm_number(number);
_pgm_changes.push_back(event_ptr);
cerr << "MidiModel::append_pgm_change_unlocked: appended pgm change" << endl;
for(PgmChanges::iterator i = _pgm_changes.begin(); i != _pgm_changes.end(); ++i) {
cerr << "_pgm_changes contents: channel " << int((*i)->channel()) << dec << " time: " << int((*i)->time()) << hex << " program number: " << int(int((*i)->pgm_number())) <<endl;
}
//<< int(_pgm_changes.) << " time: " << time << " program number: " << int(number) <<endl;
}
void