implement a looooooot of stuff

This commit is contained in:
Nikolaus Gullotta 2019-03-29 13:58:54 -05:00 committed by Nikolaus Gullotta
parent d4c99d6d38
commit 4805a600c7
No known key found for this signature in database
GPG key ID: 565F60578092AA31
5 changed files with 406 additions and 19 deletions

View file

@ -232,13 +232,14 @@ void EditorRouteGroups::recall() {
}
void EditorRouteGroups::write() {
camera->write();
// camera->write();
}
void EditorRouteGroups::load() {
string path = Glib::build_filename(user_config_directory(-1), "snapshot.xml");
camera->load(path);
MixerSnapshotDialog* m = new MixerSnapshotDialog();
m->set_session(_session);
m->run();
}

View file

@ -1,25 +1,60 @@
#include <iostream>
#include "ardour/filesystem_paths.h"
#include "ardour/session_state_utils.h"
#include "ardour/session_directory.h"
#include <glib.h>
#include <glibmm.h>
#include <glibmm/datetime.h>
#include <gtkmm/table.h>
#include "widgets/tooltips.h"
#include "widgets/choice.h"
#include "widgets/prompter.h"
#include "mixer_snapshot_dialog.h"
#include "pbd/basename.h"
#include "pbd/file_utils.h"
#include "pbd/gstdio_compat.h"
#include "pbd/i18n.h"
using namespace Gtk;
using namespace PBD;
using namespace std;
using namespace ARDOUR;
using namespace ArdourWidgets;
struct ColumnInfo {
int index;
int sort_idx;
AlignmentEnum al;
const char* label;
const char* tooltip;
};
MixerSnapshotDialog::MixerSnapshotDialog()
: ArdourDialog(_("this is a dialog"), true, false)
{
set_name("msdialog");
Table* table = new Table(3, 3);
table->set_size_request(-1, 600);
table->attach (scroller, 0, 3, 0, 5);
get_vbox()->pack_start (*table);
global_model = Gtk::ListStore::create(_columns);
local_model = Gtk::ListStore::create(_columns);
bootstrap_display_and_model(global_display, global_model, true);
bootstrap_display_and_model(local_display, local_model, false);
// global_display.set_focus_on_click();
// local_display.set_focus_on_click();
// global_display.signal_cursor_changed().connect(sigc::mem_fun(*this, &MixerSnapshotDialog::callback));
// local_display.signal_cursor_changed().connect(sigc::mem_fun(*this, &MixerSnapshotDialog::callback));
// global_display.get_selection()->signal_changed().connect(sigc::bind(sigc::mem_fun(*this, &MixerSnapshotDialog::selection_changed), true), false);
// local_display.get_selection()->signal_changed().connect(sigc::bind(sigc::mem_fun(*this, &MixerSnapshotDialog::selection_changed), false), false);
global_display.signal_button_press_event().connect(sigc::bind(sigc::mem_fun(*this, &MixerSnapshotDialog::button_press), true), false);
local_display.signal_button_press_event().connect(sigc::bind(sigc::mem_fun(*this, &MixerSnapshotDialog::button_press), false), false);
}
MixerSnapshotDialog::~MixerSnapshotDialog()
@ -27,6 +62,266 @@ MixerSnapshotDialog::~MixerSnapshotDialog()
}
void MixerSnapshotDialog::set_session(Session* s)
{
if(s)
ArdourDialog::set_session(s);
refill();
}
bool MixerSnapshotDialog::button_press(GdkEventButton* ev, bool global)
{
if (ev->type == GDK_2BUTTON_PRESS) {
TreeModel::iterator iter;
if(global) {
iter = global_display.get_selection()->get_selected();
} else {
iter = local_display.get_selection()->get_selected();
}
global_display.get_selection()->unselect_all();
local_display.get_selection()->unselect_all();
if(iter) {
MixerSnapshot* s = (*iter)[_columns.snapshot];
s->recall();
return true;
}
}
return false;
}
bool MixerSnapshotDialog::bootstrap_display_and_model(Gtkmm2ext::DnDTreeView<string>& display, Glib::RefPtr<ListStore> model, bool global)
{
if(!model) {
return false;
}
display.set_model(model);
display.append_column(_("Fav"), _columns.favorite);
display.append_column(_("Name"), _columns.name);
display.append_column(_("# Tracks"), _columns.n_tracks);
display.append_column(_("# VCAs"), _columns.n_vcas);
display.append_column(_("# Groups"), _columns.n_groups);
display.append_column(_("Special Tracks"), _columns.has_specials);
display.append_column(_("Date"), _columns.date);
display.append_column(_("Version"), _columns.version);
//newest snaps should be at the top
model->set_sort_column(6, SORT_DESCENDING);
display.set_headers_visible(true);
display.set_headers_clickable(true);
display.set_reorderable(false);
display.set_rules_hint(true);
display.add_object_drag(_columns.name.index(), "");
display.set_drag_column(_columns.name.index());
CellRendererToggle* fav_cell = dynamic_cast<CellRendererToggle*>(display.get_column_cell_renderer(0));
fav_cell->property_activatable() = true;
fav_cell->property_radio() = true;
fav_cell->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &MixerSnapshotDialog::fav_cell_action), global));
HBox* add_remove = manage(new HBox);
Button* btn_add = manage(new Button("New"));
Button* btn_del = manage(new Button("Delete"));
Button* btn_load = manage(new Button("New From Session"));
add_remove->pack_start(*btn_add, true, true);
add_remove->pack_start(*btn_del, true, true);
add_remove->pack_start(*btn_load, true, true);
VBox* vbox = manage(new VBox);
vbox->set_homogeneous();
vbox->pack_start(*add_remove);
vbox->set_size_request(800, -1);
if(global) {
btn_add->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &MixerSnapshotDialog::new_snapshot), true));
global_scroller.set_border_width(10);
global_scroller.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC);
global_scroller.add(global_display);
Table* table = manage(new Table(3, 3));
table->set_size_request(-1, 400);
table->attach(global_scroller, 0, 3, 0, 5 );
table->attach(*vbox, 2, 3, 6, 8, FILL|EXPAND, FILL, 5, 5);
get_vbox()->pack_start(*table);
} else {
btn_add->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &MixerSnapshotDialog::new_snapshot), false));
local_scroller.set_border_width(10);
local_scroller.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC);
local_scroller.add(local_display);
Table* table = manage(new Table(3, 3));
table->set_size_request(-1, 400);
table->attach(local_scroller, 0, 3, 0, 5 );
table->attach(*vbox, 2, 3, 6, 8, FILL|EXPAND, FILL, 5, 5);
get_vbox()->pack_start(*table);
}
ColumnInfo ci[] = {
{ 0, 0, ALIGN_CENTER, _("Favorite"), _("") },
{ 1, 1, ALIGN_LEFT, _("Name"), _("") },
{ 2, 2, ALIGN_CENTER, _("# Tracks"), _("") },
{ 3, 3, ALIGN_CENTER, _("# VCAs"), _("") },
{ 4, 4, ALIGN_CENTER, _("# Groups"), _("") },
{ 5, 5, ALIGN_CENTER, _("Special Tracks"), _("") },
{ 6, 8, ALIGN_LEFT, _("Date"), _("") },
{ 7, 7, ALIGN_LEFT, _("Version"), _("") },
{ -1,-1, ALIGN_CENTER, 0, 0 }
};
for (int i = 0; ci[i].index >= 0; ++i) {
ColumnInfo info = ci[i];
TreeViewColumn* col = display.get_column(info.index);
Label* label = manage(new Label (info.label));
label->set_alignment(info.al);
set_tooltip(*label, info.tooltip);
col->set_widget(*label);
label->show();
col->set_sort_column(info.sort_idx);
col->set_expand(false);
col->set_alignment(info.al);
//...and this sets the alignment for the data cells
CellRendererText* rend = dynamic_cast<CellRendererText*>(display.get_column_cell_renderer(info.index));
if (rend) {
rend->property_xalign() = (info.al == ALIGN_RIGHT ? 1.0 : (info.al == ALIGN_LEFT ? 0.0 : 0.5));
}
}
return true;
}
void MixerSnapshotDialog::new_snapshot(bool global)
{
MixerSnapshot* snap = new MixerSnapshot(_session);
ArdourWidgets::Prompter prompter(true);
string new_name;
prompter.set_name("New Mixer Snapshot Prompter");
prompter.set_title(_("Mixer Snapshot Name:"));
prompter.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
prompter.set_prompt(_("Set Mixer Snapshot Name"));
prompter.set_initial_text(snap->label);
if (prompter.run() == RESPONSE_ACCEPT) {
prompter.get_result(new_name);
if (new_name.length() > 0) {
snap->label = new_name;
snap->snap();
snap->write(global);
refill();
}
}
}
void MixerSnapshotDialog::refill()
{
global_model->clear();
string global_directory = Glib::build_filename(user_config_directory(-1), "mixer_snapshots/");
vector<string> files;
find_files_matching_pattern(files, global_directory, "*.xml");
for(vector<string>::iterator i = files.begin(); i != files.end(); i++) {
string path = *(i);
string name = basename_nosuffix(*(i));
MixerSnapshot* snap = new MixerSnapshot(_session, path);
snap->label = name;
TreeModel::Row row = *(global_model->append());
if (name.length() > 48) {
name = name.substr (0, 48);
name.append("...");
}
row[_columns.name] = name;
row[_columns.favorite] = snap->favorite;
row[_columns.version] = snap->get_last_modified_with();
row[_columns.n_tracks] = snap->get_routes().size();
row[_columns.n_vcas] = snap->get_vcas().size();
row[_columns.n_groups] = snap->get_groups().size();;
row[_columns.has_specials] = true;
GStatBuf gsb;
g_stat(path.c_str(), &gsb);
Glib::DateTime gdt(Glib::DateTime::create_now_local(gsb.st_mtime));
row[_columns.timestamp] = gsb.st_mtime;
row[_columns.date] = gdt.format ("%F %H:%M");;
row[_columns.full_path] = path;
row[_columns.snapshot] = snap;
}
local_model->clear();
files.clear();
string local_directory = Glib::build_filename(_session->session_directory().root_path(), "mixer_snapshots/");
find_files_matching_pattern(files, local_directory, "*.xml");
for(vector<string>::iterator i = files.begin(); i != files.end(); i++) {
string path = *(i);
string name = basename_nosuffix(*(i));
MixerSnapshot* snap = new MixerSnapshot(_session, path);
snap->label = name;
TreeModel::Row row = *(local_model->append());
if (name.length() > 48) {
name = name.substr (0, 48);
name.append("...");
}
row[_columns.name] = name;
row[_columns.favorite] = snap->favorite;
row[_columns.version] = snap->get_last_modified_with();
row[_columns.n_tracks] = snap->get_routes().size();
row[_columns.n_vcas] = snap->get_vcas().size();
row[_columns.n_groups] = snap->get_groups().size();;
row[_columns.has_specials] = true;
GStatBuf gsb;
g_stat(path.c_str(), &gsb);
Glib::DateTime gdt(Glib::DateTime::create_now_local(gsb.st_mtime));
row[_columns.timestamp] = gsb.st_mtime;
row[_columns.date] = gdt.format ("%F %H:%M");;
row[_columns.full_path] = path;
row[_columns.snapshot] = snap;
}
}
void MixerSnapshotDialog::fav_cell_action(const string& path, bool global)
{
TreeModel::iterator iter;
if(global)
iter = global_model->get_iter(path);
else
iter = local_model->get_iter(path);
if(iter) {
MixerSnapshot* snap = (*iter)[_columns.snapshot];
snap->favorite = !snap->favorite;
(*iter)[_columns.favorite] = snap->favorite;
snap->write(global);
}
}
int MixerSnapshotDialog::run() {
show_all();
return 0;

View file

@ -45,12 +45,54 @@ class MixerSnapshotDialog : public ArdourDialog
MixerSnapshotDialog();
~MixerSnapshotDialog();
void set_session(ARDOUR::Session*);
int run();
private:
Gtkmm2ext::DnDTreeView<std::string> snap_display;
Gtk::ScrolledWindow scroller;
bool button_press(GdkEventButton*, bool);
void new_snapshot(bool);
bool bootstrap_display_and_model(Gtkmm2ext::DnDTreeView<std::string>&, Glib::RefPtr<Gtk::ListStore>, bool);
void fav_cell_action(const std::string&, bool);
void refill();
struct MixerSnapshotColumns : public Gtk::TreeModel::ColumnRecord {
MixerSnapshotColumns () {
add (favorite);
add (name);
add (n_tracks);
add (n_vcas);
add (n_groups);
add (has_specials);
add (date);
add (version);
add (timestamp);
add (full_path);
add (snapshot);
}
Gtk::TreeModelColumn<bool> favorite;
Gtk::TreeModelColumn<std::string> name;
Gtk::TreeModelColumn<std::string> version;
Gtk::TreeModelColumn<int> n_tracks;
Gtk::TreeModelColumn<int> n_vcas;
Gtk::TreeModelColumn<int> n_groups;
Gtk::TreeModelColumn<bool> has_specials;
Gtk::TreeModelColumn<std::string> date;
Gtk::TreeModelColumn<int64_t> timestamp;
Gtk::TreeModelColumn<std::string> full_path;
Gtk::TreeModelColumn<MixerSnapshot*> snapshot;
};
MixerSnapshotColumns _columns;
Gtkmm2ext::DnDTreeView<std::string> global_display;
Gtkmm2ext::DnDTreeView<std::string> local_display;
Gtk::ScrolledWindow global_scroller;
Gtk::ScrolledWindow local_scroller;
Glib::RefPtr<Gtk::ListStore> global_model;
Glib::RefPtr<Gtk::ListStore> local_model;
};
#endif

View file

@ -42,7 +42,7 @@ class MixerSnapshot
void snap(boost::shared_ptr<ARDOUR::Route>);
void recall();
void clear();
void write();
void write(bool);
void load(std::string);
struct State {
@ -62,10 +62,13 @@ class MixerSnapshot
std::vector<State> get_routes() {return route_states;};
std::vector<State> get_groups() {return group_states;};
std::vector<State> get_vcas() {return vca_states;};
std::string get_last_modified_with() {return last_modified_with;};
int id;
std::string label;
std::time_t timestamp;
bool favorite;
bool has_specials;
private:
ARDOUR::Session* _session;
@ -74,7 +77,7 @@ class MixerSnapshot
void load_from_session(std::string);
void load_from_session(XMLNode&);
std::string last_modified_with;
std::vector<State> route_states;
std::vector<State> group_states;
std::vector<State> vca_states;

View file

@ -6,6 +6,8 @@
#include "ardour/filename_extensions.h"
#include "ardour/filesystem_paths.h"
#include "ardour/session_state_utils.h"
#include "ardour/revision.h"
#include "ardour/session_directory.h"
#include "pbd/i18n.h"
#include "pbd/xml++.h"
@ -22,6 +24,8 @@ MixerSnapshot::MixerSnapshot(Session* s)
: id(0)
, label("snapshot")
, timestamp(time(0))
, favorite(false)
, last_modified_with("")
{
if(s)
_session = s;
@ -31,11 +35,21 @@ MixerSnapshot::MixerSnapshot(Session* s, string file_path)
: id(0)
, label("snapshot")
, timestamp(time(0))
, favorite(false)
, last_modified_with("")
{
if(s)
_session = s;
load_from_session(file_path);
if(Glib::file_test(file_path.c_str(), Glib::FILE_TEST_IS_DIR))
load_from_session(file_path);
string suffix = "." + PBD::get_suffix(file_path);
if(suffix == statefile_suffix)
load_from_session(file_path);
if(suffix == ".xml")
load(file_path);
}
MixerSnapshot::~MixerSnapshot()
@ -192,6 +206,9 @@ void MixerSnapshot::reassign_masters(boost::shared_ptr<Slavable> slv, XMLNode no
void MixerSnapshot::recall()
{
if(!_session)
return;
_session->begin_reversible_command(_("mixer-snapshot recall"));
//vcas
@ -245,11 +262,21 @@ void MixerSnapshot::recall()
_session->commit_reversible_command();
}
void MixerSnapshot::write()
{
void MixerSnapshot::write(bool global)
{
if(empty())
return;
XMLNode* node = new XMLNode("MixerSnapshot");
XMLNode* child;
child = node->add_child ("ProgramVersion");
string modified_with = string_compose("%1 %2", PROGRAM_NAME, revision);
child->set_property("modified-with", modified_with);
child = node->add_child ("Favorite");
child->set_property("favorite", favorite);
child = node->add_child("Routes");
for(vector<State>::iterator i = route_states.begin(); i != route_states.end(); i++) {
child->add_child_copy((*i).node);
@ -265,10 +292,15 @@ void MixerSnapshot::write()
child->add_child_copy((*i).node);
}
string snap = Glib::build_filename(user_config_directory(-1), label + ".xml");
string path = "";
if(global)
path = Glib::build_filename(user_config_directory(-1), "mixer_snapshots/", label + ".xml");
else
path = Glib::build_filename(_session->session_directory().root_path(), "mixer_snapshots/", label + ".xml");
XMLTree tree;
tree.set_root(node);
tree.write(snap.c_str());
tree.write(path.c_str());
}
void MixerSnapshot::load(string path)
@ -286,9 +318,23 @@ void MixerSnapshot::load(string path)
return;
}
XMLNode* route_node = find_named_node(*root, "Routes");
XMLNode* group_node = find_named_node(*root, "Groups");
XMLNode* vca_node = find_named_node(*root, "VCAS");
XMLNode* version_node = find_named_node(*root, "ProgramVersion");
XMLNode* fav_node = find_named_node(*root, "Favorite");
XMLNode* route_node = find_named_node(*root, "Routes");
XMLNode* group_node = find_named_node(*root, "Groups");
XMLNode* vca_node = find_named_node(*root, "VCAS");
if(version_node) {
string version;
version_node->get_property(X_("modified-with"), version);
last_modified_with = version;
}
if(fav_node) {
string fav;
fav_node->get_property(X_("favorite"), fav);
favorite = atoi(fav.c_str());
}
if(route_node) {
XMLNodeList nlist = route_node->children();