Rough-in the Mixer Snapshot List

TODO:
  * Create a Route Template Manager in libardour, to populate the lists
  * Implement right-click operations to rename and remove items in list
  * Add a button to create new snapshot, or Import a snapshot from other session
  * Probably:  turn the mixer-list into a set of tabs, like the editor list
This commit is contained in:
Ben Loftis 2019-07-25 18:26:13 -05:00 committed by Nikolaus Gullotta
parent 4ac66cd534
commit 5142e0cc3d
No known key found for this signature in database
GPG key ID: 565F60578092AA31
12 changed files with 303 additions and 7 deletions

View file

@ -13,6 +13,7 @@
<menuitem action='SnapshotStay'/>
<menuitem action='SnapshotSwitch'/>
#endif
<menuitem action='MixerSnapshot'/>
<menuitem action='SaveTemplate'/>
<menuitem action='Archive'/>
<separator/>

View file

@ -101,6 +101,7 @@
#include "ardour/audioengine.h"
#include "ardour/audiofilesource.h"
#include "ardour/automation_watch.h"
#include "ardour/directory_names.h"
#include "ardour/disk_reader.h"
#include "ardour/disk_writer.h"
#include "ardour/filename_extensions.h"

View file

@ -307,7 +307,7 @@ public:
void start_duplicate_routes ();
void save_as_template_dialog_response (int response, SaveTemplateDialog* d);
void save_route_template ();
void save_route_template (bool local); //local route templates are "mixer snapshots"
void apply_route_template ();
void new_from_route_template ();

View file

@ -189,8 +189,14 @@ ARDOUR_UI::install_actions ()
ActionManager::write_sensitive_actions.push_back (act);
ActionManager::route_selection_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("MixerSnapshot"), _("Mixer Snapshot..."),
sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_route_template), true));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act);
ActionManager::route_selection_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("save-route-template"), _("Save Selected Tracks as Template..."),
sigc::mem_fun(*this, &ARDOUR_UI::save_route_template));
sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_route_template), false));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act);
ActionManager::route_selection_sensitive_actions.push_back (act);

View file

@ -519,7 +519,7 @@ void MixerSnapshotDialog::refill_display(bool global)
for(vector<string>::iterator i = files.begin(); i != files.end(); i++) {
string path = *(i);
MixerSnapshot* snap = new MixerSnapshot(_session, path);
MixerSnapshot* snap = new MixerSnapshot(_session, path); //ToDo: pretty sure this is leaked
new_row(model, snap, path);
}
}

View file

@ -0,0 +1,198 @@
/*
Copyright (C) 2000-2019 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 <glib.h>
#include "pbd/file_utils.h"
#include "pbd/gstdio_compat.h"
#include <glibmm.h>
#include <glibmm/datetime.h>
#include <gtkmm/liststore.h>
#include "ardour/directory_names.h"
#include "ardour/filename_extensions.h"
#include "ardour/filesystem_paths.h"
#include "ardour/session.h"
#include "ardour/session_state_utils.h"
#include "ardour/session_directory.h"
#include "widgets/choice.h"
#include "widgets/prompter.h"
#include "ardour_ui.h"
#include "utils.h"
#include "pbd/i18n.h"
#include "mixer_snapshots.h"
using namespace std;
using namespace PBD;
using namespace Gtk;
using namespace ARDOUR;
using namespace ARDOUR_UI_UTILS;
MixerSnapshotList::MixerSnapshotList ()
{
_snapshot_model = ListStore::create (_columns);
_snapshot_display.set_model (_snapshot_model);
_snapshot_display.append_column (_("Mixer Snapshots (double-click to load)"), _columns.name);
// _snapshot_display.append_column (_("Modified Date"), _columns.timestamp);
_snapshot_display.set_size_request (75, -1);
_snapshot_display.set_headers_visible (true);
_snapshot_display.set_reorderable (false);
_scroller.add (_snapshot_display);
_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
_snapshot_display.get_selection()->signal_changed().connect (sigc::mem_fun(*this, &MixerSnapshotList::selection_changed));
_snapshot_display.signal_button_press_event().connect (sigc::mem_fun (*this, &MixerSnapshotList::button_press), false);
}
void
MixerSnapshotList::set_session (Session* s)
{
SessionHandlePtr::set_session (s);
redisplay ();
}
/* A new snapshot has been selected. */
void
MixerSnapshotList::selection_changed ()
{
if (_snapshot_display.get_selection()->count_selected_rows() == 0) {
return;
}
TreeModel::iterator i = _snapshot_display.get_selection()->get_selected();
//std::string snap_path = (*i)[_columns.snap];
_snapshot_display.set_sensitive (false);
// ARDOUR_UI::instance()->load_session (_session->path(), string (snap_name));
_snapshot_display.set_sensitive (true);
}
bool
MixerSnapshotList::button_press (GdkEventButton* ev)
{
if (ev->button == 3) {
return true;
}
return false;
}
/** Pop up the snapshot display context menu.
* @param button Button used to open the menu.
* @param time Menu open time.
* @param snapshot_name Name of the snapshot that the menu click was over.
*/
void
MixerSnapshotList::popup_context_menu (int button, int32_t time, std::string snapshot_name)
{
using namespace Menu_Helpers;
MenuList& items (_menu.items());
items.clear ();
const bool modification_allowed = (_session->snap_name() != snapshot_name && _session->name() != snapshot_name);
/* add_item_with_sensitivity (items, MenuElem (_("Remove"), sigc::bind (sigc::mem_fun (*this, &MixerSnapshotList::remove), snapshot_name)), modification_allowed);
add_item_with_sensitivity (items, MenuElem (_("Rename..."), sigc::bind (sigc::mem_fun (*this, &MixerSnapshotList::rename), snapshot_name)), modification_allowed);
*/
_menu.popup (button, time);
}
void
MixerSnapshotList::rename (std::string old_name)
{
ArdourWidgets::Prompter prompter(true);
string new_name;
prompter.set_name ("Prompter");
prompter.set_title (_("Rename Snapshot"));
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
prompter.set_prompt (_("New name of snapshot"));
prompter.set_initial_text (old_name);
if (prompter.run() == RESPONSE_ACCEPT) {
prompter.get_result (new_name);
if (new_name.length()) {
// _session->rename_state (old_name, new_name);
redisplay ();
}
}
}
void
MixerSnapshotList::remove (std::string name)
{
vector<string> choices;
std::string prompt = string_compose (_("Do you really want to remove snapshot \"%1\" ?\n(which cannot be undone)"), name);
choices.push_back (_("No, do nothing."));
choices.push_back (_("Yes, remove it."));
ArdourWidgets::Choice prompter (_("Remove snapshot"), prompt, choices);
if (prompter.run () == 1) {
// _session->remove_state (name);
redisplay ();
}
}
void
MixerSnapshotList::redisplay ()
{
if (_session == 0) {
return;
}
std::string local_snap_path = Glib::build_filename(_session->session_directory().root_path(), route_templates_dir_name);
_snapshot_model->clear();
std::string suffix_pattern ("*");
suffix_pattern = suffix_pattern + template_suffix; // "*.template"
vector<string> files;
find_files_matching_pattern(files, local_snap_path, suffix_pattern); //assume they are all templates in here?
if(files.empty()) {
return;
}
for(vector<string>::iterator i = files.begin(); i != files.end(); i++) {
string path = *(i);
MixerSnapshot* snap = new MixerSnapshot(_session, path); //ToDo: this is leaked; probably need a "template manager" in libardour
TreeModel::Row row = *(_snapshot_model->append());
row[_columns.name] = snap->get_label();
row[_columns.snapshot] = snap;
}
}

View file

@ -0,0 +1,70 @@
/*
Copyright (C) 2000-2019 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 __gtk_ardour_mixer_snapshots_h__
#define __gtk_ardour_mixer_snapshots_h__
#include <gtkmm/widget.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/treemodel.h>
#include <gtkmm/treeview.h>
#include "ardour/mixer_snapshot.h"
class MixerSnapshotList : public ARDOUR::SessionHandlePtr
{
public:
MixerSnapshotList ();
void set_session (ARDOUR::Session *);
Gtk::Widget& widget () {
return _scroller;
}
void redisplay ();
private:
Gtk::ScrolledWindow _scroller;
struct Columns : public Gtk::TreeModel::ColumnRecord {
Columns () {
add (name);
add (timestamp);
add (snapshot);
}
Gtk::TreeModelColumn<std::string> name;
Gtk::TreeModelColumn<std::int64_t> timestamp;
Gtk::TreeModelColumn<ARDOUR::MixerSnapshot*> snapshot; //ToDo: these are leaked
};
Columns _columns;
Glib::RefPtr<Gtk::ListStore> _snapshot_model;
Gtk::TreeView _snapshot_display;
Gtk::Menu _menu;
bool button_press (GdkEventButton *);
void selection_changed ();
void popup_context_menu (int, int32_t, std::string);
void remove (std::string);
void rename (std::string);
};
#endif // __gtk_ardour_mixer_snapshots_h__

View file

@ -68,6 +68,7 @@
#include "foldback_strip.h"
#include "keyboard.h"
#include "mixer_ui.h"
#include "mixer_snapshots.h"
#include "mixer_strip.h"
#include "monitor_section.h"
#include "plugin_selector.h"
@ -273,7 +274,12 @@ Mixer_UI::Mixer_UI ()
rhs_pane2.add (rhs_pane1);
rhs_pane2.add (group_display_frame);
list_vpacker.pack_start (rhs_pane2, true, true);
_mix_snaps = new MixerSnapshotList();
rhs_pane3.add (rhs_pane2);
rhs_pane3.add (_mix_snaps->widget());
list_vpacker.pack_start (rhs_pane3, true, true);
vca_label_bar.set_size_request (-1, 16 + 1); /* must match height in GroupTabs::set_size_request() + 1 border px*/
vca_vpacker.pack_start (vca_label_bar, false, false);
@ -325,6 +331,7 @@ Mixer_UI::Mixer_UI ()
rhs_pane1.set_drag_cursor (*PublicEditor::instance().cursors()->expand_up_down);
rhs_pane2.set_drag_cursor (*PublicEditor::instance().cursors()->expand_up_down);
rhs_pane3.set_drag_cursor (*PublicEditor::instance().cursors()->expand_up_down);
list_hpane.set_drag_cursor (*PublicEditor::instance().cursors()->expand_left_right);
inner_pane.set_drag_cursor (*PublicEditor::instance().cursors()->expand_left_right);
@ -349,6 +356,7 @@ Mixer_UI::Mixer_UI ()
favorite_plugins_frame.show();
rhs_pane1.show();
rhs_pane2.show();
rhs_pane3.show();
strip_packer.show();
inner_pane.show();
vca_scroller.show();
@ -1097,6 +1105,8 @@ Mixer_UI::set_session (Session* sess)
_group_tabs->set_session (sess);
_mix_snaps->set_session (sess);
if (!_session) {
_selection.clear ();
return;

View file

@ -70,6 +70,7 @@ class AxisView;
class FoldbackStrip;
class MixerStrip;
class PluginSelector;
class MixerSnapshotList;
class MixerGroupTabs;
class MonitorSection;
class VCAMasterStrip;
@ -187,6 +188,7 @@ private:
Gtk::ComboBoxText favorite_plugins_tag_combo;
ArdourWidgets::VPane rhs_pane1;
ArdourWidgets::VPane rhs_pane2;
ArdourWidgets::VPane rhs_pane3;
ArdourWidgets::HPane inner_pane;
Gtk::VBox strip_group_box;
Gtk::HBox strip_packer;
@ -203,6 +205,8 @@ private:
MixerGroupTabs* _group_tabs;
MixerSnapshotList* _mix_snaps;
bool on_scroll_event (GdkEventScroll*);
bool on_vca_scroll_event (GdkEventScroll*);

View file

@ -31,9 +31,12 @@
using namespace Gtk;
using namespace ARDOUR;
SaveTemplateDialog::SaveTemplateDialog (const std::string& name, const std::string& desc)
SaveTemplateDialog::SaveTemplateDialog (const std::string& name, const std::string& desc, bool local)
: ArdourDialog (_("Save as template"))
{
printf("saving %s\n", local ? "LOCAL" : "PREFS");
_local = local;
_name_entry.get_buffer()->set_text (name);
_description_editor.get_buffer()->set_text (desc);
_description_editor.set_wrap_mode (Gtk::WRAP_WORD);

View file

@ -30,12 +30,14 @@
class SaveTemplateDialog : public ArdourDialog
{
public:
SaveTemplateDialog (const std::string& name, const std::string& description = "");
SaveTemplateDialog (const std::string& name, const std::string& description = "", bool local = false);
std::string get_template_name () const;
std::string get_description () const;
bool is_local() { return _local; }
private:
bool _local;
Gtk::Entry _name_entry;
Gtk::TextView _description_editor;
};

View file

@ -166,6 +166,7 @@ gtk2_ardour_sources = [
'mixer_snapshot_dialog.cc',
'mixer_snapshot_substitution_dialog.cc',
'mixer_group_tabs.cc',
'mixer_snapshots.cc',
'mixer_strip.cc',
'mixer_ui.cc',
'meterbridge.cc',