ardour
patch_change.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000-2010 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #include <iostream>
21 
22 #include <boost/algorithm/string.hpp>
23 
24 #include <glibmm/regex.h>
25 
26 #include "gtkmm2ext/keyboard.h"
27 #include "gtkmm2ext/utils.h"
28 
29 #include "midi++/midnam_patch.h"
30 
31 #include "canvas/debug.h"
32 
33 #include "ardour_ui.h"
34 #include "editor.h"
35 #include "editor_drag.h"
36 #include "midi_region_view.h"
37 #include "patch_change.h"
38 
39 using namespace MIDI::Name;
40 using namespace std;
42 
46  ArdourCanvas::Container* parent,
47  const string& text,
48  double height,
49  double x,
50  double y,
53  : _region (region)
54  , _info (info)
55  , _patch (patch)
56  , _popup_initialized(false)
57 {
58  _flag = new ArdourCanvas::Flag (
59  parent,
60  height,
61  ARDOUR_UI::config()->color ("midi patch change outline"),
62  ARDOUR_UI::config()->color_mod ("midi patch change fill", "midi patch change fill"),
63  ArdourCanvas::Duple (x, y),
64  true);
65 
66  CANVAS_DEBUG_NAME (_flag, text);
67 
68  _flag->Event.connect (sigc::mem_fun (*this, &PatchChange::event_handler));
69  _flag->set_font_description (ARDOUR_UI::config()->get_SmallFont());
70  _flag->set_text(text);
71 }
72 
74 {
75  delete _flag;
76 }
77 
78 void
80 {
81  using namespace MIDI::Name;
82 
83  boost::shared_ptr<ChannelNameSet> channel_name_set = _info.get_patches (_patch->channel());
84 
85  if (!channel_name_set) {
86  return;
87  }
88 
89  const ChannelNameSet::PatchBanks& patch_banks = channel_name_set->patch_banks();
90 
91  if (patch_banks.size() > 1) {
92 
93  // fill popup menu:
94  Gtk::Menu::MenuList& patch_bank_menus = _popup.items();
95 
96  for (ChannelNameSet::PatchBanks::const_iterator bank = patch_banks.begin();
97  bank != patch_banks.end();
98  ++bank) {
99  Glib::RefPtr<Glib::Regex> underscores = Glib::Regex::create("_");
100  std::string replacement(" ");
101 
102  Gtk::Menu& patch_bank_menu = *manage(new Gtk::Menu());
103 
104  const PatchNameList& patches = (*bank)->patch_name_list();
105  Gtk::Menu::MenuList& patch_menus = patch_bank_menu.items();
106 
107  for (PatchNameList::const_iterator patch = patches.begin();
108  patch != patches.end();
109  ++patch) {
110  std::string name = underscores->replace((*patch)->name().c_str(), -1, 0, replacement);
111 
112  patch_menus.push_back(
113  Gtk::Menu_Helpers::MenuElem(
114  name,
115  sigc::bind(
116  sigc::mem_fun(*this, &PatchChange::on_patch_menu_selected),
117  (*patch)->patch_primary_key())) );
118  }
119 
120 
121  std::string name = underscores->replace((*bank)->name().c_str(), -1, 0, replacement);
122 
123  patch_bank_menus.push_back(
124  Gtk::Menu_Helpers::MenuElem(
125  name,
126  patch_bank_menu) );
127  }
128 
129  } else {
130  /* only one patch bank, so make it the initial menu */
131 
132  const PatchNameList& patches = patch_banks.front()->patch_name_list();
133  Gtk::Menu::MenuList& patch_menus = _popup.items();
134 
135  for (PatchNameList::const_iterator patch = patches.begin();
136  patch != patches.end();
137  ++patch) {
138  std::string name = (*patch)->name();
139  boost::replace_all (name, "_", " ");
140 
141  patch_menus.push_back (
142  Gtk::Menu_Helpers::MenuElem (
143  name,
144  sigc::bind (sigc::mem_fun(*this, &PatchChange::on_patch_menu_selected),
145  (*patch)->patch_primary_key())));
146  }
147  }
148 }
149 
150 void
151 PatchChange::on_patch_menu_selected(const PatchPrimaryKey& key)
152 {
153  _region.change_patch_change (*this, key);
154 }
155 
156 bool
158 {
159  /* XXX: icky dcast */
160  Editor* e = dynamic_cast<Editor*> (&_region.get_time_axis_view().editor());
161 
162  if (!e->internal_editing()) {
163  return false;
164  }
165 
166  switch (ev->type) {
167  case GDK_BUTTON_PRESS:
168  if (e->current_mouse_mode() == Editing::MouseContent) {
169 
170  if (Gtkmm2ext::Keyboard::is_delete_event (&ev->button)) {
171 
173  return true;
174 
175  } else if (Gtkmm2ext::Keyboard::is_edit_event (&ev->button)) {
176 
177  _region.edit_patch_change (this);
178  return true;
179 
180  } else if (ev->button.button == 1) {
181  e->drags()->set (new PatchChangeDrag (e, this, &_region), ev);
182  return true;
183  }
184  }
185 
186  if (ev->button.button == 3) {
187  if (!_popup_initialized) {
189  _popup_initialized = true;
190  }
191  _popup.popup(ev->button.button, ev->button.time);
192  return true;
193  }
194  break;
195 
196  case GDK_KEY_PRESS:
197  switch (ev->key.keyval) {
198  case GDK_Up:
199  case GDK_KP_Up:
200  case GDK_uparrow:
202  *this, Keyboard::modifier_state_contains(ev->key.state, Keyboard::TertiaryModifier), 1);
203  return true;
204  case GDK_Down:
205  case GDK_KP_Down:
206  case GDK_downarrow:
208  *this, Keyboard::modifier_state_contains(ev->key.state, Keyboard::TertiaryModifier), -1);
209  return true;
210  default:
211  break;
212  }
213  break;
214 
215  case GDK_KEY_RELEASE:
216  switch (ev->key.keyval) {
217  case GDK_BackSpace:
218  case GDK_Delete:
220  default:
221  break;
222  }
223  break;
224 
225  case GDK_SCROLL:
226  if (ev->scroll.direction == GDK_SCROLL_UP) {
228  *this, Keyboard::modifier_state_contains(ev->scroll.state, Keyboard::TertiaryModifier), 1);
229  return true;
230  } else if (ev->scroll.direction == GDK_SCROLL_DOWN) {
232  *this, Keyboard::modifier_state_contains(ev->scroll.state, Keyboard::TertiaryModifier), -1);
233  return true;
234  }
235  break;
236 
237  case GDK_ENTER_NOTIFY:
238  _region.patch_entered (this);
239  break;
240 
241  case GDK_LEAVE_NOTIFY:
242  _region.patch_left (this);
243  break;
244 
245  default:
246  break;
247  }
248 
249  return false;
250 }
251 
252 void
253 PatchChange::move (ArdourCanvas::Duple d)
254 {
255  _flag->move (d);
256 }
257 
258 void
259 PatchChange::set_height (ArdourCanvas::Distance height)
260 {
261  _flag->set_height (height);
262 }
263 
264 void
266 {
267  _flag->hide ();
268 }
269 
270 void
272 {
273  _flag->show ();
274 }
void patch_left(PatchChange *)
void delete_patch_change(PatchChange *)
TimeAxisView & get_time_axis_view() const
PublicEditor & editor() const
boost::shared_ptr< MIDI::Name::ChannelNameSet > get_patches(uint8_t channel)
ARDOUR::InstrumentInfo & _info
Definition: patch_change.h:65
Definition: Beats.hpp:239
LIBPBD_API int replace_all(std::string &str, const std::string &target, const std::string &replacement)
Definition: strreplace.cc:24
void on_patch_menu_selected(const MIDI::Name::PatchPrimaryKey &key)
ArdourCanvas::Flag * _flag
Definition: patch_change.h:69
void change_patch_change(PatchChange &old_patch, const MIDI::Name::PatchPrimaryKey &new_patch)
void move(ArdourCanvas::Duple)
LIBGTKMM2EXT_API uint64_t Keyboard
Definition: debug.cc:23
MidiRegionView & _region
Definition: patch_change.h:64
Editing::MouseMode current_mouse_mode() const
Definition: editor.h:179
bool internal_editing() const
void set(Drag *, GdkEvent *, Gdk::Cursor *c=MouseCursors::invalid_cursor())
Definition: editor_drag.cc:124
ARDOUR::MidiModel::PatchChangePtr patch() const
Definition: patch_change.h:57
void step_patch(PatchChange &patch, bool bank, int delta)
PatchChange(MidiRegionView &region, ArdourCanvas::Container *parent, const std::string &text, double height, double x, double y, ARDOUR::InstrumentInfo &info, ARDOUR::MidiModel::PatchChangePtr patch)
void set_height(ArdourCanvas::Distance)
void patch_entered(PatchChange *)
LIBPBD_API Transmitter info
DragManager * drags() const
Definition: editor.h:461
static bool is_delete_event(GdkEventButton *)
Definition: keyboard.cc:498
const char * name
static bool is_edit_event(GdkEventButton *)
Definition: keyboard.cc:470
Definition: editor.h:134
std::list< boost::shared_ptr< Patch > > PatchNameList
static UIConfiguration * config()
Definition: ardour_ui.h:188
bool _popup_initialized
Definition: patch_change.h:68
ARDOUR::MidiModel::PatchChangePtr _patch
Definition: patch_change.h:66
Gtk::Menu _popup
Definition: patch_change.h:67
void initialize_popup_menus()
Definition: patch_change.cc:79
void edit_patch_change(PatchChange *)
bool event_handler(GdkEvent *)
LIBARDOUR_API PBD::PropertyDescriptor< bool > color
Definition: route_group.cc:50