summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/canvas-program-change.h61
-rw-r--r--gtk2_ardour/canvas_patch_change.cc (renamed from gtk2_ardour/canvas-program-change.cc)81
-rw-r--r--gtk2_ardour/canvas_patch_change.h74
-rw-r--r--gtk2_ardour/patch_change_dialog.cc106
-rw-r--r--gtk2_ardour/patch_change_dialog.h (renamed from gtk2_ardour/program_change_dialog.h)22
-rw-r--r--gtk2_ardour/program_change_dialog.cc52
-rw-r--r--libs/evoral/evoral/PatchChange.hpp166
7 files changed, 419 insertions, 143 deletions
diff --git a/gtk2_ardour/canvas-program-change.h b/gtk2_ardour/canvas-program-change.h
deleted file mode 100644
index 51a7d427e4..0000000000
--- a/gtk2_ardour/canvas-program-change.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef CANVASPROGRAMCHANGE_H_
-#define CANVASPROGRAMCHANGE_H_
-
-#include "canvas-flag.h"
-
-class MidiRegionView;
-
-namespace MIDI {
- namespace Name {
- struct PatchPrimaryKey;
- }
-}
-
-namespace Gnome {
-namespace Canvas {
-
-class CanvasProgramChange : public CanvasFlag
-{
-public:
- CanvasProgramChange(
- MidiRegionView& region,
- Group& parent,
- const string& text,
- double height,
- double x,
- double y,
- string& model_name,
- string& custom_device_mode,
- double _event_time,
- uint8_t channel,
- uint8_t program
- );
-
- virtual ~CanvasProgramChange();
-
- virtual bool on_event(GdkEvent* ev);
-
- string model_name () const { return _model_name; }
- string custom_device_mode () const { return _custom_device_mode; }
- double event_time () const { return _event_time; }
- uint8_t program () const { return _program; }
- uint8_t channel () const { return _channel; }
-
- void initialize_popup_menus();
-
- void on_patch_menu_selected(const MIDI::Name::PatchPrimaryKey& key);
-
-private:
- string _model_name;
- string _custom_device_mode;
- double _event_time;
- uint8_t _channel;
- uint8_t _program;
- Gtk::Menu _popup;
- bool _popup_initialized;
-};
-
-} // namespace Canvas
-} // namespace Gnome
-
-#endif /*CANVASPROGRAMCHANGE_H_*/
diff --git a/gtk2_ardour/canvas-program-change.cc b/gtk2_ardour/canvas_patch_change.cc
index 4e178819f2..320f0c0d00 100644
--- a/gtk2_ardour/canvas-program-change.cc
+++ b/gtk2_ardour/canvas_patch_change.cc
@@ -1,3 +1,22 @@
+/*
+ Copyright (C) 2000-2010 Paul Davis
+
+ 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 <iostream>
#include <glibmm/regex.h>
@@ -6,7 +25,7 @@
#include "ardour/midi_patch_manager.h"
#include "ardour_ui.h"
#include "midi_region_view.h"
-#include "canvas-program-change.h"
+#include "canvas_patch_change.h"
#include "editor.h"
#include "editor_drag.h"
@@ -15,9 +34,8 @@ using namespace MIDI::Name;
using namespace std;
/** @param x x position in pixels.
- * @param event_time PC time in beats, with respect to the start of the source.
*/
-CanvasProgramChange::CanvasProgramChange(
+CanvasPatchChange::CanvasPatchChange(
MidiRegionView& region,
Group& parent,
const string& text,
@@ -26,37 +44,33 @@ CanvasProgramChange::CanvasProgramChange(
double y,
string& model_name,
string& custom_device_mode,
- double event_time,
- uint8_t channel,
- uint8_t program)
+ ARDOUR::MidiModel::PatchChangePtr patch)
: CanvasFlag(
region,
parent,
height,
- ARDOUR_UI::config()->canvasvar_MidiProgramChangeOutline.get(),
- ARDOUR_UI::config()->canvasvar_MidiProgramChangeFill.get(),
+ ARDOUR_UI::config()->canvasvar_MidiPatchChangeOutline.get(),
+ ARDOUR_UI::config()->canvasvar_MidiPatchChangeFill.get(),
x,
y)
- , _model_name(model_name)
- , _custom_device_mode(custom_device_mode)
- , _event_time(event_time)
- , _channel(channel)
- , _program(program)
- , _popup_initialized(false)
+ , _model_name(model_name)
+ , _custom_device_mode(custom_device_mode)
+ , _patch (patch)
+ , _popup_initialized(false)
{
set_text(text);
}
-CanvasProgramChange::~CanvasProgramChange()
+CanvasPatchChange::~CanvasPatchChange()
{
}
void
-CanvasProgramChange::initialize_popup_menus()
+CanvasPatchChange::initialize_popup_menus()
{
boost::shared_ptr<ChannelNameSet> channel_name_set =
MidiPatchManager::instance()
- .find_channel_name_set(_model_name, _custom_device_mode, _channel);
+ .find_channel_name_set(_model_name, _custom_device_mode, _patch->channel());
if (!channel_name_set) {
return;
@@ -87,7 +101,7 @@ CanvasProgramChange::initialize_popup_menus()
Gtk::Menu_Helpers::MenuElem(
name,
sigc::bind(
- sigc::mem_fun(*this, &CanvasProgramChange::on_patch_menu_selected),
+ sigc::mem_fun(*this, &CanvasPatchChange::on_patch_menu_selected),
(*patch)->patch_primary_key())) );
}
@@ -102,14 +116,14 @@ CanvasProgramChange::initialize_popup_menus()
}
void
-CanvasProgramChange::on_patch_menu_selected(const PatchPrimaryKey& key)
+CanvasPatchChange::on_patch_menu_selected(const PatchPrimaryKey& key)
{
cerr << " got patch program number " << key.program_number << endl;
- _region.program_selected(*this, key);
+ _region.change_patch_change (*this, key);
}
bool
-CanvasProgramChange::on_event (GdkEvent* ev)
+CanvasPatchChange::on_event (GdkEvent* ev)
{
switch (ev->type) {
case GDK_BUTTON_PRESS:
@@ -120,11 +134,16 @@ CanvasProgramChange::on_event (GdkEvent* ev)
if (Gtkmm2ext::Keyboard::is_delete_event (&ev->button)) {
- _region.delete_program_change (this);
+ _region.delete_patch_change (this);
+ return true;
+
+ } else if (Gtkmm2ext::Keyboard::is_edit_event (&ev->button)) {
+
+ _region.edit_patch_change (this);
return true;
} else if (ev->button.button == 1) {
- e->drags()->set (new ProgramChangeDrag (e, this, &_region), ev);
+ e->drags()->set (new PatchChangeDrag (e, this, &_region), ev);
return true;
}
}
@@ -145,12 +164,12 @@ CanvasProgramChange::on_event (GdkEvent* ev)
case GDK_Up:
case GDK_KP_Up:
case GDK_uparrow:
- _region.previous_program(*this);
+ _region.previous_patch (*this);
break;
case GDK_Down:
case GDK_KP_Down:
case GDK_downarrow:
- _region.next_program(*this);
+ _region.next_patch (*this);
break;
default:
break;
@@ -159,14 +178,22 @@ CanvasProgramChange::on_event (GdkEvent* ev)
case GDK_SCROLL:
if (ev->scroll.direction == GDK_SCROLL_UP) {
- _region.previous_program(*this);
+ _region.previous_patch (*this);
return true;
} else if (ev->scroll.direction == GDK_SCROLL_DOWN) {
- _region.next_program(*this);
+ _region.next_patch (*this);
return true;
}
break;
+ case GDK_ENTER_NOTIFY:
+ _region.patch_entered (this);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ _region.patch_left (this);
+ break;
+
default:
break;
}
diff --git a/gtk2_ardour/canvas_patch_change.h b/gtk2_ardour/canvas_patch_change.h
new file mode 100644
index 0000000000..79eb80dfae
--- /dev/null
+++ b/gtk2_ardour/canvas_patch_change.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 2000-2010 Paul Davis
+
+ 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 CANVAS_PATCH_CHANGE_H_
+#define CANVAS_PATCH_CHANGE_H_
+
+#include "canvas-flag.h"
+
+class MidiRegionView;
+
+namespace MIDI {
+ namespace Name {
+ struct PatchPrimaryKey;
+ }
+}
+
+namespace Gnome {
+namespace Canvas {
+
+class CanvasPatchChange : public CanvasFlag
+{
+public:
+ CanvasPatchChange(
+ MidiRegionView& region,
+ Group& parent,
+ const string& text,
+ double height,
+ double x,
+ double y,
+ string& model_name,
+ string& custom_device_mode,
+ ARDOUR::MidiModel::PatchChangePtr patch
+ );
+
+ virtual ~CanvasPatchChange();
+
+ virtual bool on_event(GdkEvent* ev);
+
+ string model_name () const { return _model_name; }
+ string custom_device_mode () const { return _custom_device_mode; }
+ ARDOUR::MidiModel::PatchChangePtr patch () const { return _patch; }
+
+ void initialize_popup_menus();
+
+ void on_patch_menu_selected(const MIDI::Name::PatchPrimaryKey& key);
+
+private:
+ string _model_name;
+ string _custom_device_mode;
+ ARDOUR::MidiModel::PatchChangePtr _patch;
+ Gtk::Menu _popup;
+ bool _popup_initialized;
+};
+
+} // namespace Canvas
+} // namespace Gnome
+
+#endif /*CANVASPROGRAMCHANGE_H_*/
diff --git a/gtk2_ardour/patch_change_dialog.cc b/gtk2_ardour/patch_change_dialog.cc
new file mode 100644
index 0000000000..e4efdc2532
--- /dev/null
+++ b/gtk2_ardour/patch_change_dialog.cc
@@ -0,0 +1,106 @@
+/*
+ Copyright (C) 2010 Paul Davis
+ Author: Carl Hetherington <cth@carlh.net>
+
+ 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 <gtkmm/stock.h>
+#include <gtkmm/table.h>
+#include "ardour/beats_frames_converter.h"
+#include "patch_change_dialog.h"
+
+using namespace Gtk;
+
+/** @param tc If non-0, a time converter for this patch change. If 0, time and channel controls will be desensitized */
+PatchChangeDialog::PatchChangeDialog (
+ const ARDOUR::BeatsFramesConverter* tc,
+ ARDOUR::Session* session,
+ Evoral::PatchChange<Evoral::MusicalTime> const & patch,
+ const Gtk::BuiltinStockID& ok
+ )
+ : ArdourDialog (_("Patch Change"), true)
+ , _time_converter (tc)
+ , _time (X_("patchchangetime"), true, X_("PatchChangeTimeClock"), true, false)
+ , _channel (*manage (new Adjustment (1, 1, 16, 1, 4)))
+ , _program (*manage (new Adjustment (1, 1, 128, 1, 16)))
+ , _bank (*manage (new Adjustment (1, 1, 16384, 1, 64)))
+{
+ Table* t = manage (new Table (4, 2));
+ t->set_spacings (6);
+ int r = 0;
+
+ if (_time_converter) {
+
+ Label* l = manage (new Label (_("Time")));
+ l->set_alignment (0, 0.5);
+ t->attach (*l, 0, 1, r, r + 1);
+ t->attach (_time, 1, 2, r, r + 1);
+ ++r;
+
+ _time.set_session (session);
+ _time.set_mode (AudioClock::BBT);
+ _time.set (_time_converter->to (patch.time ()), true);
+
+ l = manage (new Label (_("Channel")));
+ l->set_alignment (0, 0.5);
+ t->attach (*l, 0, 1, r, r + 1);
+ t->attach (_channel, 1, 2, r, r + 1);
+ ++r;
+
+ _channel.set_value (patch.channel() + 1);
+ }
+
+ Label* l = manage (new Label (_("Program")));
+ l->set_alignment (0, 0.5);
+ t->attach (*l, 0, 1, r, r + 1);
+ t->attach (_program, 1, 2, r, r + 1);
+ ++r;
+
+ _program.set_value (patch.program () + 1);
+
+ l = manage (new Label (_("Bank")));
+ l->set_alignment (0, 0.5);
+ t->attach (*l, 0, 1, r, r + 1);
+ t->attach (_bank, 1, 2, r, r + 1);
+ ++r;
+
+ _bank.set_value (patch.bank() + 1);
+
+ get_vbox()->add (*t);
+
+ add_button (Stock::CANCEL, RESPONSE_CANCEL);
+ add_button (ok, RESPONSE_ACCEPT);
+ set_default_response (RESPONSE_ACCEPT);
+
+ show_all ();
+}
+
+Evoral::PatchChange<Evoral::MusicalTime>
+PatchChangeDialog::patch () const
+{
+ Evoral::MusicalTime t = 0;
+ if (_time_converter) {
+ t = _time_converter->from (_time.current_time ());
+ }
+
+ return Evoral::PatchChange<Evoral::MusicalTime> (
+ t,
+ _channel.get_value_as_int() - 1,
+ _program.get_value_as_int() - 1,
+ _bank.get_value_as_int() - 1
+ );
+}
diff --git a/gtk2_ardour/program_change_dialog.h b/gtk2_ardour/patch_change_dialog.h
index 9da36ad6ed..02eb311d48 100644
--- a/gtk2_ardour/program_change_dialog.h
+++ b/gtk2_ardour/patch_change_dialog.h
@@ -19,15 +19,31 @@
*/
#include <gtkmm/spinbutton.h>
+#include "evoral/PatchChange.hpp"
#include "ardour_dialog.h"
+#include "audio_clock.h"
-class ProgramChangeDialog : public ArdourDialog
+namespace ARDOUR {
+ class BeatsFramesConverter;
+ class Session;
+}
+
+class PatchChangeDialog : public ArdourDialog
{
public:
- ProgramChangeDialog ();
+ PatchChangeDialog (
+ const ARDOUR::BeatsFramesConverter *,
+ ARDOUR::Session *,
+ Evoral::PatchChange<Evoral::MusicalTime> const &,
+ const Gtk::BuiltinStockID &
+ );
- uint8_t program () const;
+ Evoral::PatchChange<Evoral::MusicalTime> patch () const;
private:
+ const ARDOUR::BeatsFramesConverter* _time_converter;
+ AudioClock _time;
+ Gtk::SpinButton _channel;
Gtk::SpinButton _program;
+ Gtk::SpinButton _bank;
};
diff --git a/gtk2_ardour/program_change_dialog.cc b/gtk2_ardour/program_change_dialog.cc
deleted file mode 100644
index f333447f4a..0000000000
--- a/gtk2_ardour/program_change_dialog.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- Copyright (C) 2010 Paul Davis
- Author: Carl Hetherington <cth@carlh.net>
-
- 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 <gtkmm/stock.h>
-#include <gtkmm/table.h>
-#include "program_change_dialog.h"
-
-using namespace Gtk;
-
-ProgramChangeDialog::ProgramChangeDialog ()
- : ArdourDialog (_("Add Program Change"), true)
- , _program (*manage (new Adjustment (1, 1, 128, 1, 16)))
-{
- Table* t = manage (new Table (1, 2));
-
- Label* l = manage (new Label (_("Program")));
- l->set_alignment (0, 0.5);
- t->attach (*l, 0, 1, 1, 2);
- t->attach (_program, 1, 2, 1, 2);
-
- get_vbox()->add (*t);
-
- add_button (Stock::CANCEL, RESPONSE_CANCEL);
- add_button (Stock::ADD, RESPONSE_ACCEPT);
- set_default_response (RESPONSE_ACCEPT);
-
- show_all ();
-}
-
-/** @return Program change number, counted from 0 */
-uint8_t
-ProgramChangeDialog::program () const
-{
- return _program.get_value_as_int () - 1;
-}
diff --git a/libs/evoral/evoral/PatchChange.hpp b/libs/evoral/evoral/PatchChange.hpp
new file mode 100644
index 0000000000..576a1d2e98
--- /dev/null
+++ b/libs/evoral/evoral/PatchChange.hpp
@@ -0,0 +1,166 @@
+/*
+ Copyright (C) 2010 Paul Davis
+ Author: Carl Hetherington <cth@carlh.net>
+
+ 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 EVORAL_PATCH_CHANGE_HPP
+#define EVORAL_PATCH_CHANGE_HPP
+
+#include "evoral/Event.hpp"
+#include "evoral/MIDIEvent.hpp"
+
+namespace Evoral {
+
+/** Event representing a `patch change', composed of a LSB and MSB
+ * bank select and then a program change.
+ */
+template<typename Time>
+class PatchChange
+{
+public:
+ /** @param t Time.
+ * @param c Channel.
+ * @param p Program change number (counted from 0).
+ * @param b Bank number (counted from 0, 14-bit).
+ */
+ PatchChange (Time t, uint8_t c, uint8_t p, int b)
+ : _bank_change_msb (0, t, 3, 0, true)
+ , _bank_change_lsb (0, t, 3, 0, true)
+ , _program_change (0, t, 2, 0, true)
+ {
+ _bank_change_msb.buffer()[0] = MIDI_CMD_CONTROL | c;
+ _bank_change_msb.buffer()[1] = MIDI_CTL_MSB_BANK;
+ _bank_change_msb.buffer()[2] = (b >> 7) & 0x7f;
+
+ _bank_change_lsb.buffer()[0] = MIDI_CMD_CONTROL | c;
+ _bank_change_lsb.buffer()[1] = MIDI_CTL_LSB_BANK;
+ _bank_change_lsb.buffer()[2] = b & 0x7f;
+
+ _program_change.buffer()[0] = MIDI_CMD_PGM_CHANGE | c;
+ _program_change.buffer()[1] = p;
+ }
+
+ PatchChange (const PatchChange & other)
+ : _bank_change_msb (other._bank_change_msb, true)
+ , _bank_change_lsb (other._bank_change_lsb, true)
+ , _program_change (other._program_change, true)
+ {
+ set_id (other.id ());
+ }
+
+ event_id_t id () const {
+ return _program_change.id ();
+ }
+
+ void set_id (event_id_t id) {
+ _bank_change_msb.set_id (id);
+ _bank_change_lsb.set_id (id);
+ _program_change.set_id (id);
+ }
+
+ Time time () const {
+ return _program_change.time ();
+ }
+
+ void set_time (Time t) {
+ _bank_change_msb.set_time (t);
+ _bank_change_lsb.set_time (t);
+ _program_change.set_time (t);
+ }
+
+ void set_channel (uint8_t c) {
+ _bank_change_msb.buffer()[0] &= 0xf0;
+ _bank_change_msb.buffer()[0] |= c;
+ _bank_change_lsb.buffer()[0] &= 0xf0;
+ _bank_change_lsb.buffer()[0] |= c;
+ _program_change.buffer()[0] &= 0xf0;
+ _program_change.buffer()[0] |= c;
+ }
+
+ uint8_t program () const {
+ return _program_change.buffer()[1];
+ }
+
+ void set_program (uint8_t p) {
+ _program_change.buffer()[1] = p;
+ }
+
+ int bank () const {
+ return (bank_msb() << 7) | bank_lsb();
+ }
+
+ void set_bank (int b) {
+ _bank_change_msb.buffer()[2] = (b >> 7) & 0x7f;
+ _bank_change_lsb.buffer()[2] = b & 0x7f;
+ }
+
+ uint8_t bank_msb () const {
+ return _bank_change_msb.buffer()[2];
+ }
+
+ uint8_t bank_lsb () const {
+ return _bank_change_lsb.buffer()[2];
+ }
+
+ uint8_t channel () const { return _program_change.buffer()[0] & 0xf; }
+
+ inline bool operator< (const PatchChange<Time>& o) const {
+ if (time() != o.time()) {
+ return time() < o.time();
+ }
+
+ if (bank != o.bank()) {
+ return bank() < o.bank();
+ }
+
+ return (program() < o.program());
+ }
+
+ inline bool operator== (const PatchChange<Time>& o) const {
+ return (time() == o.time() && program() == o.program() && bank() == o.bank());
+ }
+
+ /** The PatchChange is made up of messages() MIDI messages; this method returns them by index.
+ * @param i index of message to return.
+ */
+ MIDIEvent<Time> const & message (int i) const {
+ switch (i) {
+ case 0:
+ return _bank_change_msb;
+ case 1:
+ return _bank_change_lsb;
+ case 2:
+ return _program_change;
+ default:
+ assert (false);
+ }
+ }
+
+ /** @return Number of MIDI messages that make up this change */
+ int messages () const {
+ return 3;
+ }
+
+private:
+ MIDIEvent<Time> _bank_change_msb;
+ MIDIEvent<Time> _bank_change_lsb;
+ MIDIEvent<Time> _program_change;
+};
+
+}
+
+#endif