diff --git a/gtk2_ardour/trigger_clip_picker.cc b/gtk2_ardour/trigger_clip_picker.cc index b08b624100..abd9428b96 100644 --- a/gtk2_ardour/trigger_clip_picker.cc +++ b/gtk2_ardour/trigger_clip_picker.cc @@ -16,18 +16,173 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include +#include + +#include + +#include "pbd/basename.h" +#include "pbd/file_utils.h" +#include "pbd/search_path.h" + +#include "ardour/audiofilesource.h" +#include "ardour/directory_names.h" +#include "ardour/filesystem_paths.h" +#include "ardour/smf_source.h" + +#include "gtkmm2ext/menu_elems.h" #include "gtkmm2ext/utils.h" #include "trigger_clip_picker.h" +#include "pbd/i18n.h" + +using namespace Gtk; +using namespace ARDOUR; + TriggerClipPicker::TriggerClipPicker () - : _fc (Gtk::FILE_CHOOSER_ACTION_OPEN) + : _fcd (_("Select Sample Folder"), FILE_CHOOSER_ACTION_SELECT_FOLDER) { - Gtkmm2ext::add_volume_shortcuts (_fc); - pack_start (_fc); - _fc.show (); + _scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC); + _scroller.add (_view); + + Gtkmm2ext::add_volume_shortcuts (_fcd); + _fcd.add_button (Stock::CANCEL, RESPONSE_CANCEL); + _fcd.add_button (Stock::OK, RESPONSE_ACCEPT); + + PBD::Searchpath spath (ardour_data_search_path ()); + spath.add_subdirectory_to_paths(media_dir_name); + for (auto const& f : spath) { + maybe_add_dir (f); + } + + maybe_add_dir (Glib::build_filename (user_config_directory(), media_dir_name)); + + for (auto const& f : _fcd.list_shortcut_folders ()) { + maybe_add_dir (f); + } + assert (_dir.items ().size () > 0); + + _dir.AddMenuElem (Menu_Helpers::SeparatorElem ()); + _dir.AddMenuElem (Menu_Helpers::MenuElem (_("Other..."), sigc::mem_fun (*this, &TriggerClipPicker::open_dir))); + + pack_start (_dir, false, false); + pack_start (_scroller); + + _model = TreeStore::create (_columns); + _view.set_model (_model); + _view.append_column (_("File Name"), _columns.name); + _view.set_headers_visible (true); + _view.set_reorderable (false); + _view.get_selection ()->set_mode (SELECTION_MULTIPLE); + + /* DnD */ + std::vector dnd; + dnd.push_back (TargetEntry ("text/uri-list")); + _view.enable_model_drag_source (dnd, Gdk::MODIFIER_MASK, Gdk::ACTION_COPY); + + _view.get_selection ()->signal_changed ().connect (sigc::mem_fun (*this, &TriggerClipPicker::row_selected)); + _view.signal_row_activated ().connect (sigc::mem_fun (*this, &TriggerClipPicker::row_activated)); + _view.signal_drag_data_get ().connect (sigc::mem_fun (*this, &TriggerClipPicker::drag_data_get)); + + _scroller.show (); + _view.show (); + _dir.show (); + + _dir.items ().front ().activate (); } TriggerClipPicker::~TriggerClipPicker () { } + +void +TriggerClipPicker::maybe_add_dir (std::string const& dir) +{ + if (Glib::file_test (dir, Glib::FILE_TEST_IS_DIR | Glib::FILE_TEST_EXISTS)) { + _dir.AddMenuElem (Gtkmm2ext::MenuElemNoMnemonic (Glib::path_get_basename (dir), sigc::bind (sigc::mem_fun (*this, &TriggerClipPicker::list_dir), dir))); + } +} + +void +TriggerClipPicker::row_selected () +{ + if (_view.get_selection ()->count_selected_rows () < 1) { + return; + } + + TreeView::Selection::ListHandle_Path rows = _view.get_selection ()->get_selected_rows (); + for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin (); i != rows.end (); ++i) { + TreeIter iter; + if ((iter = _model->get_iter (*i))) { + } + } +} + +void +TriggerClipPicker::row_activated (TreeModel::Path const&, TreeViewColumn*) +{ + // TODO audition +} + +void +TriggerClipPicker::drag_data_get (Glib::RefPtr const&, SelectionData& data, guint, guint time) +{ + if (data.get_target () != "text/uri-list") { + return; + } + std::vector uris; + TreeView::Selection::ListHandle_Path rows = _view.get_selection ()->get_selected_rows (); + for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin (); i != rows.end (); ++i) { + TreeIter iter; + if ((iter = _model->get_iter (*i))) { + uris.push_back (Glib::filename_to_uri ((*iter)[_columns.path])); + } + } + data.set_uris (uris); +} + +static bool +audio_midi_suffix (const std::string& str, void* /*arg*/) +{ + if (AudioFileSource::safe_audio_file_extension (str)) { + return true; + } + if (SMFSource::safe_midi_file_extension (str)) { + return true; + } + return false; +} + +void +TriggerClipPicker::open_dir () +{ + Gtk::Window* tlw = dynamic_cast (get_toplevel ()); + if (tlw) { + _fcd.set_transient_for (*tlw); + } + int result = _fcd.run(); + _fcd.hide (); + switch (result) { + case RESPONSE_ACCEPT: + list_dir (_fcd.get_filename ()); + break; + default: + break; + } +} + +void +TriggerClipPicker::list_dir (std::string const& dir) +{ + std::vector fl; + PBD::find_files_matching_filter (fl, dir, audio_midi_suffix, 0, false, true, false); + _dir.set_active (Glib::path_get_basename (dir)); + + _model->clear (); + for (auto& f : fl) { + TreeModel::Row row = *(_model->append ()); + row[_columns.name] = Glib::path_get_basename (f); + row[_columns.path] = f; + } +} diff --git a/gtk2_ardour/trigger_clip_picker.h b/gtk2_ardour/trigger_clip_picker.h index 85c1eca9ad..fb68b54fe5 100644 --- a/gtk2_ardour/trigger_clip_picker.h +++ b/gtk2_ardour/trigger_clip_picker.h @@ -19,8 +19,16 @@ #ifndef __gtk_ardour_trigger_clip_picker_h__ #define __gtk_ardour_trigger_clip_picker_h__ +#include + #include -#include +#include +#include +#include +#include +#include + +#include "widgets/ardour_dropdown.h" class TriggerClipPicker : public Gtk::VBox { @@ -29,7 +37,30 @@ public: ~TriggerClipPicker (); private: - Gtk::FileChooserWidget _fc; + void list_dir (std::string const&); + void open_dir (); + void row_selected (); + void row_activated (Gtk::TreeModel::Path const&, Gtk::TreeViewColumn*); + void drag_data_get (Glib::RefPtr const&, Gtk::SelectionData&, guint, guint); + void maybe_add_dir (std::string const&); + + ArdourWidgets::ArdourDropdown _dir; + Gtk::FileChooserDialog _fcd; + + struct Columns : public Gtk::TreeModel::ColumnRecord { + Columns () + { + add (name); + add (path); + } + Gtk::TreeModelColumn name; + Gtk::TreeModelColumn path; + }; + + Columns _columns; + Glib::RefPtr _model; + Gtk::TreeView _view; + Gtk::ScrolledWindow _scroller; }; #endif