From 0c96144e4adf13b66f20517f2f57e3a458c52923 Mon Sep 17 00:00:00 2001 From: mescalinum Date: Sun, 27 Sep 2009 18:25:24 +0000 Subject: - new feature: in-patch metadata - add in-patch saving of column widths svn path=/trunk/externals/ffext/; revision=12473 --- composer/Editor.cpp | 3 +- composer/Makefile | 7 ++- composer/PdClasses.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++++---- composer/PdClasses.hpp | 3 +- composer/Song.hpp | 4 +- composer/Track.hpp | 10 ++-- composer/editor.tk | 46 +++++++++++++++++- 7 files changed, 177 insertions(+), 19 deletions(-) diff --git a/composer/Editor.cpp b/composer/Editor.cpp index 6a89181..a5db283 100644 --- a/composer/Editor.cpp +++ b/composer/Editor.cpp @@ -72,11 +72,10 @@ void Editor::dispatch(t_track_proxy *x, int argc, t_atom* argv) string s = ""; for(int i = 0; i < argc; i++) { - s += " {"; + s += " "; char buf[MAXPDSTRING]; atom_string(&argv[i], buf, MAXPDSTRING); s += buf; - s += "}"; } sys_vgui("pd::composer::dispatch %s%s\n", x->editor_recv->s_name, diff --git a/composer/Makefile b/composer/Makefile index 7074c49..c2d5e73 100644 --- a/composer/Makefile +++ b/composer/Makefile @@ -28,7 +28,9 @@ endif LIBNAME = composer INCLUDES = -I../../pd/src -I/usr/include #-I/usr/include/tcl$(TCL_VERSION) -CFLAGS += -funroll-loops -fno-operator-names -fno-omit-frame-pointer -falign-functions=16 -Wall -fPIC +CFLAGS += -funroll-loops -fno-operator-names -fno-omit-frame-pointer -falign-functions=16 +CFLAGS += -Wall -Wno-unused +CFLAGS += -fPIC CFLAGS += -DPDSUF=\"$(PDSUF)\" LDSHARED = $(CXX) $(PDBUNDLEFLAGS) @@ -45,9 +47,10 @@ clean:: .SUFFIXES: .cpp .o -SRCS = Song.cpp Pattern.cpp Track.cpp Editor.o PdClasses.cpp +SRCS = HasMeta.cpp Song.cpp Pattern.cpp Track.cpp Editor.o PdClasses.cpp OBJS = ${SRCS:.cpp=.o} AUTOGENERATED_SOURCES = methods.hpp methods_pd.hpp methods_ed.hpp classsetup.cpp callwrappers_pd.cpp callwrappers_ed.cpp +HasMeta.o: HasMeta.cpp HasMeta.hpp Song.o: Song.cpp Song.hpp Pattern.o: Pattern.cpp Pattern.hpp Track.o: Track.cpp Track.hpp diff --git a/composer/PdClasses.cpp b/composer/PdClasses.cpp index 7ea37a0..1729fa1 100644 --- a/composer/PdClasses.cpp +++ b/composer/PdClasses.cpp @@ -89,7 +89,8 @@ void track_proxy_save(t_gobj *z, t_binbuf *b) gensym("track"), gensym(s->getName().c_str()), gensym(t->getName().c_str())); - for(map::iterator i = t->patternsBegin(); i != t->patternsEnd(); i++) + // save paterns + for(Track::pattern_iterator i = t->pattern_begin(); i != t->pattern_end(); i++) { Pattern *pattern = i->second; binbuf_addv(b, "ss", gensym(TRACK_SELECTOR), gensym("data")); @@ -119,6 +120,14 @@ void track_proxy_save(t_gobj *z, t_binbuf *b) binbuf_addv(b, ";"); } + // save metadata + for(Track::meta_iterator i = t->meta_begin(); i != t->meta_end(); i++) + { + binbuf_addv(b, "ssssss;", gensym(TRACK_SELECTOR), + gensym("meta"), gensym("track"), gensym("set"), + gensym(i->first.c_str()), gensym(i->second.c_str())); + } + binbuf_addv(b, "sss;", gensym(TRACK_SELECTOR), gensym("data"), gensym("end")); } @@ -181,21 +190,119 @@ void track_proxy_send_result(t_track_proxy *x, int outlet, int editor) } } -int track_proxy_editor(t_track_proxy *x, t_floatarg arg) +int track_proxy_meta(t_track_proxy *x, t_symbol *sel, int argc, t_atom *argv) +{ + result_argc = 0; + t_symbol *action = 0, *target = 0, *key = 0; + int w = -1; + + if(argc < 3 || !IS_A_SYMBOL(argv,0) || !IS_A_SYMBOL(argv,1) || !IS_A_SYMBOL(argv,2)) + { + pd_error(x, "meta: bad arguments"); + goto usage; + } + target = argv[0].a_w.w_symbol; + action = argv[1].a_w.w_symbol; + key = argv[2].a_w.w_symbol; + + if(action == gensym("get")) w = 0; + if(action == gensym("set")) w = 1; + if(w < 0) goto badargs; + + if(target == gensym("song")) + { + pd_error(x, "meta: %s target not implemented yet", target->s_name); + return -1; + } + else if(target == gensym("track")) + { + string arg = ""; + string atomStr = ""; + for(int i = 3; i < argc; i++) + { + if(arg.length()) arg += " "; + char buf[MAXPDSTRING]; + atom_string(&argv[i], buf, MAXPDSTRING); + atomStr = buf; + if(atomStr.find(" ", 0) != string::npos) + arg += "{" + atomStr + "}"; + else + arg += atomStr; + } + + if(w) + { + if(argc < 4) goto badargs; + x->track->setMeta(key->s_name, arg); + } + else + { + if(argc < 3) goto badargs; + string value = ""; + if(argc == 3 && !x->track->hasMeta(key->s_name)) + { + pd_error(x, "meta: key '%s' does not exist into %s", key->s_name, target->s_name); + return -5; + } + if(x->track->hasMeta(key->s_name)) + value = x->track->getMeta(key->s_name); + else + value = arg; + cerr << "meta.track.get << '" << value << "'" << endl; + SETSYMBOL(&result_argv[0], gensym("meta")); + SETSYMBOL(&result_argv[1], target); + SETSYMBOL(&result_argv[2], key); + SETSYMBOL(&result_argv[3], gensym(value.c_str())); + result_argc = 4; + } + return 0; + } + +badargs: + pd_error(x, "meta: bad arguments"); +usage: + post("usage: meta song|track set "); + post(" meta song|track get "); + return 1; +} + +int track_proxy_editor(t_track_proxy *x, t_symbol *sel, int argc, t_atom *argv) { - t_int a = (t_int) arg; - if(a < 0) + result_argc = 0; + t_symbol *arg1 = 0, *arg2 = 0, *arg3 = 0; + if(argc < 1 || !IS_A_SYMBOL(argv,0)) + { + pd_error(x, "editor: missing subcommand"); + goto usage; + } + + arg1 = argv[0].a_w.w_symbol; + if(arg1 == gensym("show")) + { + Editor::openWindow(x); + } + else if(arg1 == gensym("hide")) + { + Editor::closeWindow(x); + } + else if(arg1 == gensym("toggle")) { if(!x->editor_open) Editor::openWindow(x); else Editor::closeWindow(x); } else { - if(a > 0) Editor::openWindow(x); - else Editor::closeWindow(x); + pd_error(x, "editor: unknown subcommand: %s", arg1->s_name); + goto usage; } - result_argc = 0; return 0; + +usage: + post("track: editor: available subcommands:"); + post(" editor show"); + post(" editor hide"); + post(" editor toggle"); + return 1; } int track_proxy_getpatterns(t_track_proxy *x) @@ -203,7 +310,7 @@ int track_proxy_getpatterns(t_track_proxy *x) SETSYMBOL(&result_argv[0], gensym("patternnames")); result_argc = 1; Track *t = x->track; - for(map::iterator i = t->patternsBegin(); i != t->patternsEnd(); i++) + for(Track::pattern_iterator i = t->pattern_begin(); i != t->pattern_end(); i++) { if(result_argc >= MAX_RESULT_SIZE) { diff --git a/composer/PdClasses.hpp b/composer/PdClasses.hpp index 122325f..15e401c 100644 --- a/composer/PdClasses.hpp +++ b/composer/PdClasses.hpp @@ -30,7 +30,8 @@ void track_proxy_properties(t_gobj *z, t_glist *owner); void track_proxy_send_result(t_track_proxy *x, int outlet, int editor); /*#begin methods*/ -int track_proxy_editor(t_track_proxy *x, t_floatarg arg); +int track_proxy_meta(t_track_proxy *x, t_symbol *sel, int argc, t_atom *argv); +int track_proxy_editor(t_track_proxy *x, t_symbol *sel, int argc, t_atom *argv); int track_proxy_getpatterns(t_track_proxy *x); int track_proxy_getpatternsize(t_track_proxy *x, t_symbol *pat); int track_proxy_setrow(t_track_proxy *x, t_symbol *sel, int argc, t_atom *argv); diff --git a/composer/Song.hpp b/composer/Song.hpp index ead7285..7784ad5 100644 --- a/composer/Song.hpp +++ b/composer/Song.hpp @@ -1,6 +1,8 @@ #ifndef COMPOSER_SONG_H_INCLUDED #define COMPOSER_SONG_H_INCLUDED +#include "HasMeta.hpp" + #include #include @@ -11,7 +13,7 @@ using std::map; using std::string; -class Song +class Song : public HasMeta { private: static map byname; diff --git a/composer/Track.hpp b/composer/Track.hpp index 35113e0..9301214 100644 --- a/composer/Track.hpp +++ b/composer/Track.hpp @@ -1,6 +1,8 @@ #ifndef COMPOSER_TRACK_H_INCLUDED #define COMPOSER_TRACK_H_INCLUDED +#include "HasMeta.hpp" + #include #include @@ -12,7 +14,7 @@ using std::map; class Song; class Pattern; -class Track +class Track : public HasMeta { public: static Track *byName(string songName, string trackName); @@ -30,10 +32,12 @@ public: void copyPattern(const string &src, const string &dst); void removePattern(const string &p); inline unsigned int getPatternCount() {return patterns.size();} - inline map::iterator patternsBegin() {return patterns.begin();} - inline map::iterator patternsEnd() {return patterns.end();} inline Song *getSong() {return song;} inline const string &getName() {return name;} + + typedef map::const_iterator pattern_iterator; + inline pattern_iterator pattern_begin() const {return patterns.begin();} + inline pattern_iterator pattern_end() const {return patterns.end();} }; #endif // COMPOSER_TRACK_H_INCLUDED diff --git a/composer/editor.tk b/composer/editor.tk index 95c5731..4f816f0 100644 --- a/composer/editor.tk +++ b/composer/editor.tk @@ -257,6 +257,18 @@ namespace eval pd::composer { return $n } + proc checkColumnSizes {id} { + variable w + variable columnsizes + set newsz {} + # tktable width returns a list of pairs (!) + foreach pair [$w($id).t width] {lappend newsz {*}$pair} + if {$columnsizes($id) != $newsz} { + set columnsizes($id) $newsz + sendGui [editCommand meta track set colw {*}$newsz] + } + } + proc createMainWindow {id} { debugPrint [info level 0] variable currentpattern; @@ -266,6 +278,7 @@ namespace eval pd::composer { variable patterns variable startup variable showpattern + variable columnsizes variable [getDataVar $id] catch {destroy $w($id)} @@ -322,6 +335,16 @@ namespace eval pd::composer { -rowtagcommand "[namespace current]::rowTag $id" #grid $w($id).t -row 10 -column 0 -sticky news + if {![llength [info procs ::tk::table::ChangeWidth_]]} { + rename ::tk::table::ChangeWidth ::tk::table::ChangeWidth_ + proc ::tk::table::ChangeWidth {w i a} " + ::pd::composer::checkColumnSizes $id + uplevel ::tk::table::ChangeWidth_ \$w \$i \$a + " + } + + set columnsizes($id) {} + debugPrint "scrollbars" grid [ttk::scrollbar $w($id).vscroll -orient vertical -command "$w($id).t yview"] -row 10 -column 1 -sticky ns grid [ttk::scrollbar $w($id).hscroll -orient horizontal -command "$w($id).t xview"] -row 15 -column 0 -sticky ew @@ -345,7 +368,7 @@ namespace eval pd::composer { debugPrint "wm" wm minsize $w($id) 300 150 - wm protocol $w($id) WM_DELETE_WINDOW [list [namespace current]::sendGui [editCommand editor 0]] + wm protocol $w($id) WM_DELETE_WINDOW [list [namespace current]::sendGui [editCommand editor hide]] debugPrint "menu" menu $w($id).m -tearoff 0 @@ -369,12 +392,12 @@ namespace eval pd::composer { debugPrint "more-bind-events" bind $w($id).t "$w($id).t activate @%x,%y; tk_popup $w($id).m %X %Y" bind $w($id).t "switchColumnType $id" + bind $w($id).t "[namespace current]::checkColumnSizes $id" set startup($id) 1 set showpattern($id) 0 debugPrint "request-patterns" sendGui [editCommand getpatterns] - #sendGui [editCommand gettracks] return $w($id) } @@ -583,10 +606,15 @@ namespace eval pd::composer { set new_size [list $pat_rows $pat_cols] debugPrint "got patternsize: '$pat_name' (size = $pat_rows x $pat_cols)" if {![dict exists $size($id) $pat_name] || [dict get $size($id) $pat_name] != $new_size || $showpattern($id)} { + # TODO: uhm, does this really need to be inside the if??? dict set size($id) $pat_name $new_size + + # request rows for {set i 0} {$i < $pat_rows} {incr i} { sendGui [editCommand getrow $pat_name $i] } + # ...and column width + sendGui [editCommand meta track get colw none] } } patternrow { @@ -624,6 +652,20 @@ namespace eval pd::composer { debugPrint "dataVar = [getDataVar $id $pat_name]" setCellValueUI $id $pat_name $row_num $col_num $cell } + meta { + switch -exact [lindex $args 1] { + track { + switch -exact [lindex $args 2] { + colw { + set a [lrange $args 3 end] + puts stderr "meta.track.colw a='$a'" + if {$a == {none}} return + $w($id).t width {*}$a + } + } + } + } + } } } } -- cgit v1.2.1