Sunday, August 1, 2010

Was tying note offs to ons in run recording to save space, but this loses the ordering info which is more important. It could be possible to recover the order using the score, but it is hard, and if playback is affected by noteoffs in future this would break.

Adding full info for noteoff serialisation. Solves hassles with bad links between note ons and offs (though this was a good checksum mechanism). Makes code more simple too.

The session can contain the user to score settings (saved when the first run begins) and each run saves settings diff at the beginning. Run also saves a time diff (in seconds will do).

It really should be a session that links a user to a score, with settings linked to a session. Too much work to change now though. Current design manages the 'current' (latest) settings better anyway without needing another table.

Wednesday, March 3, 2010

There seem to be quite a few annoying cases where different objects have the same method (ie UIElement and Animatable both define "BeginAnimation").

Buttons now fade when mouse stops and instantly appear if it moves again. Buttons fade quickly if score starts playing. Buttons don't appear if playing (though I might need to review this). Time to hook up buttons (and get a sammich).

I worked on making a CommandBinding class that takes a source Command (as usual) but points to a target Command (such as a RelayCommand in the VM) rather than methods on the view. Since CommandBinding does not inherit from DependencyObject I had to use a child DependencyObject class to hold a bindable ICommand property. When the source command fires CanExecute, the new CommandBinding class handles it. On the first fire, it uses the event Source as a dataContext (the control that has the CommandBinding in its CommandBindings) and binds the new child DO object's Command property to the target Command. It then passes CanExecute/Execute calls straight through to that command.

Past bed time :/

Tuesday, March 2, 2010

Bar UI mechanics pretty much done. Still need to:
- Hook up buttons
- Position UI within parent bounds (done for x axis, see next point for y axis)
- Handle cases where lines are very small
- Make UI fade out when playing starts or mouse stops for a while

todo
- Fix race condition around PlayAndRemoveNoteOffs (called from Pause command on UI thread and HandleTick on timer thread). Check for other race conditions.
- Try/catch in HandleTick (especially for when app is closed down when playing) and other events/properties.
- Find/fix note ons not turning off.
- Find or make themes for numericUpDown control (or find another control).
- Fix bug in numericUpDown max value going too far.
- Algorithm for determining left/right hand, and UI to change it.

Fixed problems in generic numericupdown theme; it'll do for now.

Saturday, February 27, 2010

Added canvas to LinePanel to contain UI overlays, but it needs to have inverse scale transform to scale back to normal size; feels wrong.

Will try making LinePanel contain nothing but scoreLine drawing and wrap it in a parent panel. This will move some complexity out of scorePanel too.

Friday, February 26, 2010

Next job is to finish bar overlays.
- Do overlays live in LinePanel, ScorePanel or a new child of ScorePanel?
- Overlays must go away when mouse movement stops for a while or piano things happen.

The problem with overlays on the LinePanel is they could be better positioned by the ScorePanel (since it knows where other things live relative to the linePanel). Also, they are affected by the LinePanel's scaleTransform.

I'll put them in ScorePanel. All mouseover overlays should go away when the mouse leaves the panel.

Translating mouseMove point to linePanels. Transforms have a 'Point Transform(Point fromPoint)' method and an Inverse property (returning another Transform) which come in very handy.

Thursday, February 25, 2010

When arranging visuals, you need to specify a location and size.

Getting the size of a visual (that has already been measured, arranged and rendered) is easy; myVisual.RenderSize. Getting the location isn't quite as obvious; you have to use the TransformToAncestor(Visual) or VisualTreeHelper.GetOffset(myVisual) (which an extension method would help). Either way it doesn't quite seem right.

I've decided that visuals will be arranged to (0, 0) and a TranslateTransform will be applied to position them. Getting the location is no harder than before, and animating the position of the visuals is done through the transform. Managing the transforms will be a little tricky since all transforms applied to a visual (translates, scales etc) must be inside a TransformGroup transform. Objects that manipulate this group can't step on each others' toes.

I don't seem to have much luck with the LayoutTransform property, only RenderTransform. Maybe there's a bug somewhere...

I just found out that "A TranslateTransform in a LayoutTransform has no effect". There's your problem. I could apply a scaleTransform in layout and translate in render.

Nope, that failed (weird behaviour). LayoutTransform seems to be more trouble than its worth. Putting scale and translate into a groupTransform in RenderTransform works, so I'll throw some properties to get/set them in child panel.

To change the value of a dependencyProperty that has been animated (such as TranslateTransform.XProperty), you have to clear the animation by "animating" the property again with a null animation. Calling ClearValue() or SetCurrentValue() don't work.

Sunday, February 21, 2010

I'm now officially self employed. Hopefully there won't be a need to change that any time soon.

Some changes I'd like to make to the exisiting score parser:
- Make sure that it can roll back or run forward to any step in the process via the UI
- Store template XAML
- Store numbers
- Compare elements against other elements within the score (group paths so they're more like glyphs, perhaps even replace redundant instances). This might make handling characters easier.

Friday, January 29, 2010

Now keeping notes for todos and notes to help me work through problems. I'll keep notes for record keeping if/when I can be bothered.

todo Found an issue with bottom beam of 3rd/4th notes, last bar, 5th last line of rev etude (has stroke but no fill).

Working on controls that appear over the score with mouseover (currently bar for bar start/end).

Bar popup has the target bar and start/end toggle. Its DataContext is the ScoreEditVM (which has access to the UserToScore). UserToScore has current start/end bars.

There's only ever one bar popup in focus at the time. Could bind popup bar to ScoreEditVM CurrentBar and make IsStart/IsEnd, but that's getting messy.

Could create UserToScore DP in barpopup, bind it and call methods on UTS, but that subverts try/catches etc. I think the messiness above is required, but perhaps not in ScoreEditVM.

Process is:
Mouse moves over panel,
translate mouse coords to ScoreLine coords
find bar from coords (method in ScoreLine)
if (can/should show bar ui [ie not playing]), show it <---
on click, call set start bar with current bar [react to property change]

if (can/should show bar ui [ie not playing]), show it (mouseMovement when playing is ok, timer to hide ui)

IsPlaying comes from ScoreEditVM.
bool ScoreEditVM.ShowOverlayUI



on mouse leave etc similar.

Tuesday, January 19, 2010

Getting bored with daily notes now.

Over the past few days I've mainly worked on processing user midi events and that seems to be working. Little things like changing who plays what during a run are broken.

Got most of a midi diagnostics form running.

Removed last dependencies on ini file and now using config file for all app settings.

Did more work on midi diagnostics.
todo Scan input and output devices until one connects during initialisation (and swallow exceptions), save settings to db, add midi channel spinner.
Create save/ok/cancel dialog button control.
Trigger property changes when actions complete.
try/catches around input/output

Saturday, January 16, 2010

Fixed problems in last post yesterday, and have spent until now debugging last issues with saving/loading (dots on notes were being thrown away, tied notes across lines failed etc). Op72 #1 first page and Rev etude seem to save and load completely now.

todo There might be a timing issue in the top stave of bar 52 in the Rev etude, and a note pitch issue in the 81st bar.

todo Some accidentals on grace notes aren't being picked up in bars 23 and 24 in the Op72 #1.

I guess it's time to add buttons for tutor/user plays. There's still no concept of left hand/right hand yet, but I'll make it default to top/bottom staves for now.

todo maybe Make PropertyChanged in try/catch + logged etc?


Working through old code for processing user input.

Wednesday, January 13, 2010

Fixing holes in score after loading. I need to set line and (maybe) bar and stave on elements and things should be fairly complete. Score currently plays but note pitches are wrong due to clefs not having staves etc.

Tuesday, January 12, 2010

It turns out that obfuscated fonts cannot be deobfuscated without their original file name (which is a guid with a .odttf extension). I'll have to either package fonts with their filenames intact or as unobfuscated .ttf files. I think I'll go for option a.

Fucked about for ages, having trouble with weird behaviour (I think to do with WPF font cache or something). Too hot to keep proper notes (10:30pm, 32.5 degrees and no air con).

Working on UI and VM to open scores from DB. Need to make a generic modal dialog window that accepts a viewcontrol as content.

A viewModel object can now fire an event and pass another viewModel object (ie the vm for selecting a score from the database). The first vm's view may catch the event and create a new window. The window's content is set to the vm and its style is a global modal dialog window xaml style. The xaml for the window content is a datatemplate for the vm's type.

todo maybe: Actions need a default error message. A message like a null reference exception isn't very handy without a prefix for what failed.
todo maybe: Handle technical errors better such as with a message about an internal error and some reporting mechanism.

Fkn 11:25pm, 32.2 degrees.

Sunday, January 10, 2010

Scores seem to be saving and loading correctly, though there is some issue displaying glyphs to do with fonts.

The midi output device can only be used by one thing at a time, so I'll need to handle it better.

Friday, January 8, 2010

Using propertyChanged events means one event gets fired in the sender and a switch statement in the listener. I guess it's hard to make anything more optimal. A separate event for each property would get out of hand.

Using bindings within model/vm classes would be more simple than subscribing and unsubscribing to objects as they come and go.

Maybe something similar would work to push UI requests up to the UI layer. Another alternative is a static class to which objects can push requests and UI things can listen.
Linking objects to parents/siblings etc as they are instantiated and deserialised helps. It two objects are related, I link the later objects to earlier objects (in terms of the serialisation/des process). If objects have Next and Prev properties, I make the Prev property set the other object's Next property too.

I might have a problem with notes that have multiple stems depending on the order of the stems.

I just found 'MusicXML'. A WPF app that can open and display scores from this format sounds good for v2.

Finally have all data and fonts packed up in binary stream and compressed. Most of the deserialisation code is written, will start testing it tomorrow.