- cleanup Ui.Track: event_list -> all_events? - #(poke Mispeled, field) fieldp field results in compiler bus error - program to launch logview and seq together - ^T on the cmdline prints stuff!? - signal deriver doesn't record track in stack - try record punning CURRENT - factor scroll redrawing into a single class - scroll to right, tracks don't receive clicks - happened automatically adding a pitch track: assertion: w() == body->w()'> 7 TrackTile::update_sizes() + 1208 (util.h:44) 8 TrackTile::insert_track(int, TrackView*, int) + 1082 (TrackTile.cc:167) 9 BlockView::insert_track_view(int, TrackView*, int) + 155 (Block.cc:489) 10 BlockView::insert_track(int, Tracklike const&, int) + 85 (Block.cc:376) 11 insert_track + 205 (c_interface.cc:187) solution: text entry is collapsed by track add, remove, or resize - subderive blocks in rejangn are giving "omitting note with 0 duration" - clicking jumps to points that arrows won't jump to - auto scroll is doing the wrong thing on a click - also auto scroll annoying, scroll down then when it passes threshold suddenly jump. curser in middle, move down, view suddenly jumps to bottom - playback should have multiple lines when a block is derived multiple times have a set of playback selnums? - stop play when a neg dur note is playing in white space never turns off - neg dur before sub derive also sounds forever, I think it has to do with not passing the next note * all notes off lang cmd * move inst lang cmds to Cmd.Lang.LInst - rederive lang cmd - insts with breath are not easy to use if I make sure breah control goes thru then I shouldn't need anything special - local inst db, in Ui.State, so I can e.g. set pb range for fm/* inst - some way to turn off all midi thru / input - midi input doesn't advance on note off - midi thru doesn't pick up default inst empty scale defaults in Derive, but not in Cmd - cmd to resize window to fit tracks * default inst and pitch for blocks with none - scroll box should be red when the derivation is not up to date, back to green when it is, that way you can see if derivation failed * test should only run one test if it's an exact match * insert time on a control event copies it - implement continuous controller warp - make Track.UnsortedEvents and Track.SortedEvents, type or newtype? * sample rendering has little white lines * sample rendering is still assuming linear interpolation between samples - empty tempo track should default to 1 * tempo shouldn't be linear interpolated by default - insert and delete time should use the selection if non-point * update Cmd.CmdTest * with negative events I want control text to go on top, but how is the control event supposed to know? track flag to override text side? - can I use negative 0? I'm worried that it's brittle... haskell: isNegativeZero, c: signbit(..) - join for control tracks could be useful, just delete following evt * move map_track etc. from Cmd.Edit to a new module * LPitch should use map_track - rename project -> namespace * cmd support for negative durs: select range, edit modify overlapping evt, etc. - hspp screws up \\ string continuations - methods no longer hardcoded, e.g. Map MethodId MethodInterpolator - document / enforce rules for CallId, Control, etc? - stack: bid/tid/* should highlight the entire track * crashing bug adding new track to skeleton * just editing a note shouldn't change its dur! - test relative pitch slide! - more symbolic calls, e.g. -/_\\/ and -// - should tab in raw edit mode go to method? how to go back then? - select track, st3 style select block, track - symbolic score, as in doc/custom_symbols - cut + paste didn't work with a point paste - skel_display status can be two chars: Sm is solo+mute track management: - resize a bunch of tracks at once - collapse tracks down to minimum width? - editing for "pattern list" block - double click call to jump to its block? MILESTONES 0.1 + scales and keyswitches + efficient thru - dense / efficient control signals - lazy signals - memoize deriver output, to avoid unnecessary rederivation - midi record / integrator - save undo history - linux and windows ports future - display / edit derivations inline - print scores - mouse oriented signal editing - freeze tracks / audio memoization: doc/freeze_track - vst host - sync with audio editor: jack or rewire - non-midi instruments far future - render audio - include audio inline - make sure pitch terminology is consistent: KeyNumber = scale independent note, Note = note in scale, Pitch = freq easily mapped to and from nn, same as NoteNumber, NoteNumber = Midi.Key + decimal ---- - optimization: if a msg aborts or doesn't run any cmds, don't bother to run diff. except that hardly ever happens if I do shortcut thru - per-project short aliases for inst names so you can fit them in tracks easily display signal: cmd makes a change to a controller track diff (and cmd) generate TrackEvents update sync processes TrackEvents and TrackAllEvents and merges it with samples so where does sync get the samples? I can pass it [(TrackId, Samples)] that comes from (Track, Signal), which comes from a partial derivation most derivers should be able to get that from the Skeleton **** - switch to darcs hashed repo format darcs optimize --upgrade darcs optimize --pristine note input / thru: - keyswitch support in midi thru - profile midi->midi thru and implement a fast path if necessary bugs: * apparently -0 isn't saved? * comment event should be ignored... or use just ;? in any case I should be able to make it 0 dur * warning is missing a space: "performance: no pitch signalpos: (TrackP..." - Perform.Midi.Perform: control lead time is not enough, make each note have a "pre-decay" to check for presetting controls, and remove sort post proc - clipboard is not handling the skeleton properly - deriving signal causes event derive to fail too? - undo should not move windows! some bug is making undo randomly jump to (0, 0), windows are also going to weird places on load - can share pitches doesn't consider a whole step transposition unshareable - is kbd entry letting keys like 1 fall through? * Edit.cmd_delete_time is still a little funky, an event with only 2 time steps is deleted, >2 is shortened. - keymap collisions are logged twice - Create.rename_project loses the merged tracks - bring block windows to the front after a load - tracks with different tempos play correctly, but playback follows tempo - unparsed notes are played instead of dropped, it's because the pitch is dropped but not the note - bizarre hint importing requirements in Cmd.LanguageEnviron + track down ghc rts crashes, assertion failure add -DS flag crash is when evacuating pinned memory, is it a foreign ptr? - run under valgrind - why doesn't valgrind reveal bad memory access from haskell, e.g. poke... from http://www.haskell.org/gtk2hs/ A note of caution: Using Gtk2Hs together with the -threaded ghc is currently not supported. The reason is that GHC's garbage collector might free Xlib or Win32 objects using an OS thread different to the one that is used to execute all other Gtk+ functions. * fltk: moving a track title while it's expanded doesn't work - hint refuses to compile when Cmd.NoteEntry emits a warning cleanup: - split Derive.State into dynamically scoped, constant, and logging parts - State.structure only used by Clip_test - Makefile: ghc --make doesn't understand the hsc -> hs link, which leads to manual inclusion of $(UI_HS) in the deps - remove Util.Log -> Perform.Warning import by translating IDs into strings? On the other hand, it's not unreasonable for logs to use other data types - having collapsed state in c++ is kind of error-prone, should I go back to trying to put it in haskell? - hspp doesn't catch calls to Derive.throw and Derive.warn within Derive error prone things: - setting some state like project directly through State won't update global status. Maybe I could fix this and also avoid the scattered syncs by doing a special state diff after cmds sync: state_project, state_project_scale - creating a block through State.create_block instead of Cmd.create_block won't get the current track box color - since tracklang lets me apply derivers to tracks and skel makes the structure explicit, do I still need the schema? at least for Cmds, I do need a way to look up Cmds based on track focus. Before doing anything rash, think about ways to derive e.g. 工尺譜. performance: speed and memory profiling: - respond to incoming notes - diff and modify UI - derive a large score * pause before starting background derive to avoid thrashing during edits? - only derive first few seconds? Or derive up to selection + a few seconds? implement caching first to log incrementally, emit log msg every n sec of derivation - use a lazy storeable vector for [Score.Event] and [Midi.Message] to save memory? random little hangs are annoying. figure out what's going on. GC? - timer can summarize one responder loop cycle? - get diff results is really slow from yi bug: * GHC triggers a major GC everytime Yi becomes active whenever user resumes typing * Major GC takes increasingly long time as number of object grows (as expected) So, we have to iron out all memory leaks. - send style id to c++ instead of all the style elements - strictify some basic datatypes with ! and {-# UNPACK #-}: Ui.Event, Midi.Message, Perform.Midi.Instrument.Instrument - collapsing a track shouldn't trigger a rederive caching: - in c++, cache marks and events from callback - cache track cmds for each track, update when the track title or skeleton changes - deriver caching, see doc/derive_cache - derive multiple blocks with strategies, par, parMap. Can I spark all subderivations? fltk: - draw arrows in SkeletonDisplay.cc properly - figure out how to have a minimal title bar in os x (win.border(0) removes it altogether) I can set something like kUtilityWindowClass in Fl_mac.cxx:Fl_X::make, but it doesn't get any kbd input - can I get the windows into an os x windows menu? draw bugs: - when scrolling upwards, ruler mark text is not drawn completely - doesn't redraw after switching monitors UI Msgs Track / dividers can have separate color for upper part, for collapsable tracks event track - "currently edited" event shouldn't be hidden by previous ones - I think I still need a better story for collapsed events. Maybe keep a local cache of TrackPos -> IsHidden, this is just a record of where text was drawn. It seems to do this right I'd have to redraw the events each time the selection moved, start from the selection and work outwards. This way the "selected" event is visible. Of course I only have to redraw out to the last event that had to change. And I think I can still optimize scrolling, I just have to keep the local pos->hidden cache, which gets cleared on a track update. Ruler MoveTile - only capture drag on a plain drag with no modifiers libfltk: + try cocoa fltk patch - wait for clipping and modifier event patches to go in + window position not restored on load - had to patch fltk, test Fl_cocoa.mm, make str for Fl_mac.cxx - str 2309 + fltk 1.3 Fl_Display_Text has alignment bugs, and too slow - sent mail to list logging: - trying to derive relative blocks generates a lot of log spam, can I avoid that somehow? - commands like Selection or MIDI thru generate too much log spam, maybe filter logs for those? - compile_to_signals spams too much when there is an error logview: - haskell and c++ use the same machine readable format - LogView should use Util.Fltk - tabs are not lining up properly - option to wrap lines or not? - hide or display various attrs: date, file, function, ... - collapse duplicate lines control scale markers on pitch signals - haskell will have to send [(String, Val)]. Either cache it or avoid cache problems by always passing it but keep as a a ForeignPtr in haskell. - fltk implementation - more render options, e.g. solid with color gradient dense sampled signals - efficient storage, preferably as a Signal so no conversion is necessary - display dense signals: omit text and trigger lines when zoomed out Ui: - some kind of special highlight to indicate the active block - rethrow c++ exceptions as FltkError Track - events pass style as a uchar ID for consistency and memory savings - benchmark large TrackEvents more compact implemnetation than Data.Map? profile first! - priorities: memory efficiency, persistent, merge speed (insert many) shallow tree of dense chunks? can I take advantage of non-overlap? [(pos0, data), (pos1, end), ...] data Event = Event String StyleId | End | ControlVal Double - I think memory efficiency is more important than modification speed - modify IntMap for Word64s, add toDescList - send patch to libraries@haskell.org - visual indication when both solo and mute is on - adjacent collpsed tracks are merged skeleton: - parse skeleton in LanguageCmds test: - tests count number of tests in addition to checks within each test - it should be possible to build only certain tests into RunTests - use generics or Foldable or something to write a generic StructEqual integrator / midi record: - implement REPL repl - haskeline sucks for long lines, add multiple line editing? really I'd prefer plan9 style esc then edit - could add syntax mangling, but probably better to add it to the mangler so it works for everyone Cmd: ? a module with easy access to all GlobalKeymap cmds for cmdline access - cmd to give a view focus and bring it to the front - Cmd_test vi style keymap: - movement: hjkl, HJKL to move timestep+1 or skip to next inst track, bf to move timestep at block section rank, BF to move to top and bottom of block - esc and i for edit mode - number prefixed cmds? not for now * selection scrolling should scroll so the next 2 timesteps are visible Keymap Cmd.Edit - alternate finale-like note entry: hold down step key to set step and turn on edit mode, but only while the key is down - trackerlike note entry: entered events are all as long as the block (merge will clip them to the next event) - map selection through function - transpose selection - controller edit mode accepts two numbers and moves on, no spaces - a legato command that always goes to the next note would still be useful - swap tracks keeping skeleton up to date - double / halve events under selection - stretch events in selection to another length (need two selections?) Cmd.Selection Cmd.TimeStep - snap to event begin/end Cmd.NoteTrack - record velocity if there is a velocity track - chord input, if there are multiple note tracks for this inst Cmd.Language - lang cmd stuff to load string serialized tracks for event cut and paste - an aux data input for the lang socket might be useful, to paste in data without having to quote it Cmd.LanguageCmd - some way to more easily type IDs, either the mangler adds a let for pbid, pvid, etc., or the mangler turns into Cmd.Play - warn about unallocated instruments (Convert.verify) * make sure the whole stack is lazy - play loops smarter background derivation - wait a second before deriving - don't derive while a key or mouse button is down - start playing from top of displayed area - start playing from TimeStep before insert point Undo - figure out how to checkpoint just state diffs - add undo history to on-disk format Cmd.MakeRuler - functions to modify zoom levels and other mark attributes - functions to splice or delete time or a Meter into a ruler Cmd.Freeze - details in doc/freeze_track Cmd.Save - save with a magic number so I can load songs, inst configs, etc. - gzip save files Derive: - derivers for seleh patterns - do a code version and a block version - block version requires block arguments and variable substitution TrackLang tracklang * note track can pipe through derivers: '>fm8/bass | d0 arg0 arg1 | d1' * echo deriver, '>fm8/bass | echo 2', signals: echo_feedback, echo_time - Derive.Call.map_asc_events, I need Seq.merge_asc_lists for this. - make sure signal derivation doesn't do calls * implement num -> signal coercion * implement mandatory signal args * implement _ dummy arg - implement call by arg name e.g. "delay time=%xyz" - implement control calls - implement block level calls in block title - other attributes in block title, e.g. "alias=?squiggle? | xyz"? - support pitch signals, e.g. "tune-to %*some-sig" but that requires named pitch signals - Currently calls are [Score.Event] -> [Score.Event]. Clearly they should be able to work on DeriveT as well so they can work in score time and take advantage of behavioural abstraction. Then 'a | b' is really 'b . a'. tracklang2: - data NoteDeriver = (start, dur, EventDeriver) - note track emits [NoteDeriver], merges to NoteDeriver - skeleton compile now has to merge NoteDeriver and toplevel 'derive' finally runs it. - change calls from [Score.Event] to [NoteDeriver] - parser support for '=' - val typed signals - val signals in derive state - two pass note track parsing - modify calls to extract args from environ - implement calls below - I need a way to give default args to each call. Normally signals do this and they would give me a way to change the default args in time, but I would need typed signals, and still might want a way to set the name of a signal for an arg. So for the moment I can use a separate mechanism, but it should be dynamically scoped via Derive.State. So why do I need ';' at all then? It signals the event is not derived into notes, but maybe that's obvious enough from the syntax. I think I could make '>inst' shorthand for 'inst = >inst' and '+attr' shorthand for 'attrs + attr'. But what if I want to scope the setting to a note? '' -> a null call derives a note 'x = y' -> set val for rest of track 'x = y |' -> set val within the derivation of a note '+attr' -> shorthand for 'attrs += attr |' '+attr1 +attr2' -> shorthand for 'attrs += attr1 | attrs += attr2 |' '>inst | block' -> set inst and call 'block' '|' -> derive two notes (or error if this isn't useful) '| x = y' -> error, x = y is ignored This brings up the possibility of being able to set the "null" deriver for a track. Normally it's the one that emits [Event ...], but could there be a use for replacing it with something else? Implement "damping" notes that way? Now the track title really is just composed with the track: >inst | blah I still have to signal a note track though, and a leading '>' still seams reasonable. But now I can write '> | sets_inst_based_on_env'. A problem with the 'set val' statements is that I have to evaluate them to be able to evaluate notes past it. This makes finding the next event tricky. A signal wouldn't have this problem but that's only because the signal is evaluated in a separate track. That seems notationally inconvenient, though I suppose automatic track collapse and creation could improve this. Hmm, the presence of random seed means I have to evaluate in a line... except if I make random a function of seed + trackpos. "Associative" derivation seems like a useful property in general. What if I have a deriver that wants to know if there's a note at the next major downbeat? Also this lets me derive only a portion of a block. So I could do two passes on a note track: one pass extracts the '=' and turns them into signals, next pass does processing. I can even put them in their own track if I want, I just add a note track and don't put in notes... or maybe I need a '=' title or something because as note generators, note tracks need to go at the bottom. - Implement tick as a call: Need to get next and prev Ui.Event, get pitch from pitch sig to_local (between (to_gloal prev_pos) (to_gloal next_pos) d_absolute_at = d_at . to_local at-abs time deriver = let *WARP* = if (warp-function *WARP*) then Warp (sref-inverse (warp-function *WARP*)) time) stretch func else Warp time (warp-stretch *WARP*) NIL in deriver - Implement suppress as call: This is more tricky, how can a call modify neighbors? Especially preceding ones. This seems to mean I still need postproc calls: DeriveT -> DeriveT. Internally it evaluates the deriver, processes the Score.Events and wraps it in another deriver (the seq equivalent of cue). After that most behaviours are ineffective, but them's the breaks I guess. It seems nicer if I could pass something to the block to cause it to skip the downbeat, but how can I do this in a non-ad-hoc way? No, I think I can just use a normal call: "sub | drop". - Implement tuplet: 't *n1 *n2 *n3 |' runs deriver three times with three different pitches. - 't' expects a deriver, while 'some-block' and '' don't. Some derivers can go both ways: 'seed = 42' sets 'seed' in the current env, while 'seed = 42 | sub' sets it in the 'sub' call. How do I express this difference? Calls need types for "needs arg", "no arg", and "optional arg". Then after type checking I pass (Maybe Deriver). - Also, when looking for the next note on, I should skip notes which are just 'statements' that produce no notes. That way I can set a var without screwing up negative duration dur calculation. - Implement clip-call: Undo the call stretchig, this should be efficient because of stretch combining: d_stretch (recip (dur/block_dur)) $ d_clip dur $ deriver "unstretch | sub" A non-block call (including notes) will have a block_dur == dur. I can also imagine a version without the clip. 'unstretch' is a crummy name though. 'restore'? 'abs-dur'? - Implement seleh derivation. The tricky thing here is I want n notes, not a call with n args. But I don't necessarily want to derive to Score.Event and postprocess, I want to transform Ui.Event. What it really wants to work with is [Deriver]. So maybe I can split the track parsing process into: TrackId -> [(start, dur, Parsed)] -> [(start, dur, Deriver)] -> [Deriver] -> Deriver Seleh can pair derivers: seq [stretch 0.5 (seq d1 d2), stretch 0.5 (seq d1 d2)] (d1 @> d2) ~ 0.5 @> (d1 @> d2) ~ 0.5 Of course, I may also want to get destinations based on where they are in the beat, so I'd need the (start, dur, Deriver) format. Without logical-stop I don't know how long a Deriver is, so I need the triples. So how to insert a deriver, or replace the note-placing step? Maybe I can make Derive = (start, dur, EventDeriver). This is like logical-stop except that it's under control of the caller, the deriver itself has no control over its stop time. Sequence is nice in that it guarantees an increasing time, but these would be combined with merge and have to have their own external sorted guarantee, just like [Score.Event]. So track emits [Deriver], then track calls take [Deriver] -> [Deriver], the final track operation is a merge. I might even be able to use this to get negative durations right. The [Deriver] merge can pass next note on... but it wants next event on, so it still has to query the next deriver. PitchTrack pitch - implement PitchTrack.cmd_raw edit, so I can enter fractional notes - Multiple pitch tracks, so derivers (e.g. tuned just scale) can take pitch track args. The way this could work is that the state_pitch becomes 'Map SignalName PitchSignal' and the "" signal is taken by the note deriver during convert. Track syntax: "*scale" -> ("", ScaleId scale) "*scale, psig -> ("psig", ScaleId scale) NoteTrack note negative duration - figuring out note duration is still not correct, I pass the position of the next event, but not the next Score.Event. ControlTrack control - configurable interpolators instead of a hardcoded ADT - sine - constant slope, exp slope (i.e. slope until next control event) scales - implement pengumbang pengisep - enharmonics for Twelve - just intonation - looks like fun: http://en.wikipedia.org/wiki/Bohlen-Pierce_scale - Control track management? It should be possible to have a note or a bunch of note tracks with a bunch of control tracks and control the clutter. Ideas: collapse has limited usefulness when there are too many, even with color coding. I could do this with logview: selecting a note track logs a list of its control tracks and whether they are hidden or not. Clicking on one in logview will emit a cmd that will hide or show that track. Or I could use a UI for adding new controls too: click a track, then a cmd 'add_control "vel"', this will unhide and focus the control if it exists, or create a new one and link it with the skeleton if it doesn't. ^T is intended to create new note tracks, and they're only linked to tempo initially. This implies a slightly more generic and acme-ish system for logview: anything enclosed in {}s can be clicked and will be sent verbatim, even if it's in the catch line: -- title (tracknum): inst_name, allocation, [control tracks] Inst (track 1): fm8/inst1, fm8:0,1,2, [vel {hide 2}, pedal {show 3}] - suspend automatic derivation while there's a note down? use Cmd.Mod instead of the note_id map since it should be more reliable. - block derivation memoization / caching - set instrument within note track, controller within control track - separate instrument track, as a kind of controller track - instrument aliases to make a shorthand for setting instrument, and also setting keyswitch on current instrument - display derived blocks - 3 way merge for derived blocks Perform: Instrument - some kind of organized way to manage instruments and instrument config - some basic midi instrument defs for generic midi (dev, patch) Signal - lazy implementation - continuous tempo warping for signals tempo: "2" -> "1", "2", cont: "2" -> "i, 1", should emit a bent line Midi: - Convert certain attrs to controls for cc 'keyswitches'. Instrument DB: - search lang supports quotes - search lang supports - to exclude a term - original file goes in a tag, not the text - bug: discarded insts still in index - ability to edit tags, esp. add "favorite rating" - now that PatchTemplate is gone, maybe I can use a simpler storage format - standardized tags - put file in a tag so I can search on it I can also use it to create a *.txt file with custom info - explicitly allow merged patches, so I can get params from syx but send program change Midi: bandwidth - keep stats - display widget misc ideas: - should be a documented extensible way to add new track types without modifying core ADTs - chord input... think about some kind of compact representation - if derivation needs event IDs, maybe I can use the value-supply package - safecopy package does version controlled serialization - think about yi's approach to keybindings as a parser and keybinding state - also investigate yi's approach to configuration research: - loading fonts in fltk, and drawing new fonts - subscribe to haskell-art - download sequencers and see how they ship midi reliably - learn about hs gtk for reference future: - check out jack some more. I don't necessarily support it in the beginning but should have an idea at least. Looks like I could use it for midi i/o, but what's the advantage over e.g. portmidi? Maybe the ability to send midi to e.g. local apps in standalone mode? Or would be be better to support vst? - sync via jack with e.g. ardour, rosegarden - vst interface - liblash would let me save plugin / jack configuration