Merge branch 'master' into windows
[ardour.git] / gtk2_ardour / canvas_patch_change.cc
index b4da0d5b460a6fbd57a7c251297a8684b5644dd0..7ab0eefd8c59a107122719c2b126651b7ef0e416 100644 (file)
 
 #include <iostream>
 
-#include <glibmm/regex.h>
+#include <boost/algorithm/string.hpp>
+
+#include "pbd/stacktrace.h"
 
 #include "gtkmm2ext/keyboard.h"
-#include "ardour/midi_patch_manager.h"
+#include "ardour/instrument_info.h"
+#include "midi++/midnam_patch.h"
 
 #include "ardour_ui.h"
 #include "midi_region_view.h"
@@ -38,29 +41,32 @@ using namespace std;
 /** @param x x position in pixels.
  */
 CanvasPatchChange::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)
+       MidiRegionView&                   region,
+       Group&                            parent,
+       const string&                     text,
+       double                            height,
+       double                            x,
+       double                            y,
+       ARDOUR::InstrumentInfo&           info,
+       ARDOUR::MidiModel::PatchChangePtr patch,
+       bool                              active_channel)
        : CanvasFlag(
-                       region,
-                       parent,
-                       height,
-                       ARDOUR_UI::config()->canvasvar_MidiPatchChangeOutline.get(),
-                       ARDOUR_UI::config()->canvasvar_MidiPatchChangeFill.get(),
-                       x,
-                       y)
-       , _model_name(model_name)
-       , _custom_device_mode(custom_device_mode)
+               region,
+               parent,
+               height,
+               (active_channel
+                ? ARDOUR_UI::config()->canvasvar_MidiPatchChangeOutline.get()
+                : ARDOUR_UI::config()->canvasvar_MidiPatchChangeInactiveChannelOutline.get()),
+               (active_channel
+                ? ARDOUR_UI::config()->canvasvar_MidiPatchChangeFill.get()
+                : ARDOUR_UI::config()->canvasvar_MidiPatchChangeInactiveChannelFill.get()),
+               x,
+               y)
+       , _info (info)
        , _patch (patch)
        , _popup_initialized(false)
 {
-       set_text(text);
+       set_text (text);
 }
 
 CanvasPatchChange::~CanvasPatchChange()
@@ -70,9 +76,7 @@ CanvasPatchChange::~CanvasPatchChange()
 void
 CanvasPatchChange::initialize_popup_menus()
 {
-       boost::shared_ptr<ChannelNameSet> channel_name_set =
-               MidiPatchManager::instance()
-               .find_channel_name_set(_model_name, _custom_device_mode, _patch->channel());
+       boost::shared_ptr<ChannelNameSet> channel_name_set = _info.get_patches (_patch->channel());
 
        if (!channel_name_set) {
                return;
@@ -80,73 +84,99 @@ CanvasPatchChange::initialize_popup_menus()
 
        const ChannelNameSet::PatchBanks& patch_banks = channel_name_set->patch_banks();
 
-       // fill popup menu:
-       Gtk::Menu::MenuList& patch_bank_menus = _popup.items();
-
-       for (ChannelNameSet::PatchBanks::const_iterator bank = patch_banks.begin();
-            bank != patch_banks.end();
-            ++bank) {
-               Glib::RefPtr<Glib::Regex> underscores = Glib::Regex::create("_");
-               std::string replacement(" ");
-
-               Gtk::Menu& patch_bank_menu = *manage(new Gtk::Menu());
-
-               const PatchBank::PatchNameList& patches = (*bank)->patch_name_list();
-               Gtk::Menu::MenuList& patch_menus = patch_bank_menu.items();
+       if (patch_banks.size() > 1) {
+               // fill popup menu:
+               Gtk::Menu::MenuList& patch_bank_menus = _popup.items();
+               
+               for (ChannelNameSet::PatchBanks::const_iterator bank = patch_banks.begin();
+                    bank != patch_banks.end();
+                    ++bank) {
+                       Gtk::Menu& patch_bank_menu = *manage(new Gtk::Menu());
+                       
+                       const PatchNameList& patches = (*bank)->patch_name_list();
+                       Gtk::Menu::MenuList& patch_menus = patch_bank_menu.items();
+                       
+                       for (PatchNameList::const_iterator patch = patches.begin();
+                            patch != patches.end();
+                            ++patch) {
+                               std::string name = (*patch)->name();
+                               boost::replace_all (name, "_", " ");
+                               
+                               patch_menus.push_back(
+                                       Gtk::Menu_Helpers::MenuElem(
+                                               name,
+                                               sigc::bind(sigc::mem_fun(*this, &CanvasPatchChange::on_patch_menu_selected),
+                                                          (*patch)->patch_primary_key())) );
+                       }
+                       
+                       std::string name = (*bank)->name();
+                       boost::replace_all (name, "_", " ");
+                       
+                       patch_bank_menus.push_back(
+                               Gtk::Menu_Helpers::MenuElem(
+                                       name,
+                                       patch_bank_menu) );
+               }
+       } else {
+               /* only one patch bank, so make it the initial menu */
 
-               for (PatchBank::PatchNameList::const_iterator patch = patches.begin();
+               const PatchNameList& patches = patch_banks.front()->patch_name_list();
+               Gtk::Menu::MenuList& patch_menus = _popup.items();
+               
+               for (PatchNameList::const_iterator patch = patches.begin();
                     patch != patches.end();
                     ++patch) {
-                       std::string name = underscores->replace((*patch)->name().c_str(), -1, 0, replacement);
-
-                       patch_menus.push_back(
-                               Gtk::Menu_Helpers::MenuElem(
+                       std::string name = (*patch)->name();
+                       boost::replace_all (name, "_", " ");
+                       
+                       patch_menus.push_back (
+                               Gtk::Menu_Helpers::MenuElem (
                                        name,
-                                       sigc::bind(
-                                               sigc::mem_fun(*this, &CanvasPatchChange::on_patch_menu_selected),
-                                               (*patch)->patch_primary_key())) );
+                                       sigc::bind (sigc::mem_fun(*this, &CanvasPatchChange::on_patch_menu_selected),
+                                                   (*patch)->patch_primary_key())));
                }
-
-
-               std::string name = underscores->replace((*bank)->name().c_str(), -1, 0, replacement);
-
-               patch_bank_menus.push_back(
-                       Gtk::Menu_Helpers::MenuElem(
-                               name,
-                               patch_bank_menu) );
        }
 }
-
+       
 void
 CanvasPatchChange::on_patch_menu_selected(const PatchPrimaryKey& key)
 {
        _region.change_patch_change (*this, key);
 }
 
+static bool
+in_edit_mode(Editor* editor)
+{
+       return (editor->internal_editing() &&
+               (editor->current_mouse_mode() == Editing::MouseObject ||
+                editor->current_mouse_mode() == Editing::MouseDraw));
+}
+
 bool
 CanvasPatchChange::on_event (GdkEvent* ev)
 {
+       /* XXX: icky dcast */
+       Editor* e = dynamic_cast<Editor*> (&_region.get_time_axis_view().editor());
+       
+       if (!in_edit_mode(e)) {
+               return false;
+       }
+
        switch (ev->type) {
        case GDK_BUTTON_PRESS:
-       {
-               /* XXX: icky dcast */
-               Editor* e = dynamic_cast<Editor*> (&_region.get_time_axis_view().editor());
-               if (e->current_mouse_mode() == Editing::MouseObject && e->internal_editing()) {
-
-                       if (Gtkmm2ext::Keyboard::is_delete_event (&ev->button)) {
-
-                               _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 PatchChangeDrag (e, this, &_region), ev);
-                               return true;
-                       }
+               if (Gtkmm2ext::Keyboard::is_delete_event (&ev->button)) {
+                       
+                       _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 PatchChangeDrag (e, this, &_region), ev);
+                       return true;
                }
 
                if (ev->button.button == 3) {
@@ -160,14 +190,13 @@ CanvasPatchChange::on_event (GdkEvent* ev)
                        return true;
                }
                break;
-       }
 
        case GDK_KEY_PRESS:
                switch (ev->key.keyval) {
                case GDK_Up:
                case GDK_KP_Up:
                case GDK_uparrow:
-                       if (Keyboard::modifier_state_contains (ev->scroll.state, Keyboard::PrimaryModifier)) {
+                       if (Keyboard::modifier_state_contains (ev->key.state, Keyboard::PrimaryModifier)) {
                                _region.previous_bank (*this);
                        } else {
                                _region.previous_patch (*this);
@@ -176,12 +205,16 @@ CanvasPatchChange::on_event (GdkEvent* ev)
                case GDK_Down:
                case GDK_KP_Down:
                case GDK_downarrow:
-                       if (Keyboard::modifier_state_contains (ev->scroll.state, Keyboard::PrimaryModifier)) {
+                       if (Keyboard::modifier_state_contains (ev->key.state, Keyboard::PrimaryModifier)) {
                                _region.next_bank (*this);
                        } else {
                                _region.next_patch (*this);
                        }
                        break;
+               case GDK_Delete:
+               case GDK_BackSpace:
+                       _region.delete_patch_change (this);
+                       break;
                default:
                        break;
                }
@@ -194,27 +227,24 @@ CanvasPatchChange::on_event (GdkEvent* ev)
                        } else {
                                _region.previous_patch (*this);
                        }
-                       return true;
                } else if (ev->scroll.direction == GDK_SCROLL_DOWN) {
-                       if (Keyboard::modifier_state_contains (ev->scroll.state, Keyboard::PrimaryModifier)) {
-                               _region.next_bank (*this);
-                       } else {
-                               _region.next_patch (*this);
-                       }
-                       return true;
+                               if (Keyboard::modifier_state_contains (ev->scroll.state, Keyboard::PrimaryModifier)) {
+                                       _region.next_bank (*this);
+                               } else {
+                                       _region.next_patch (*this);
+                               }
                }
-               break;
+               return true;
 
        case GDK_ENTER_NOTIFY:
                _region.patch_entered (this);
+               return true;
                break;
 
        case GDK_LEAVE_NOTIFY:
                _region.patch_left (this);
-               break;
-
-       case GDK_BUTTON_RELEASE:
                return true;
+               break;
 
        default:
                break;