using QuikDawEditor.MiscClasses; using QuikDawEditor.EDITING.PianoRollModel; using QuikDawEditor.EditingClasses; using QuikDawEditor.Undo; using System; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using static QuikDawEditor.EDITING.MiscMethods; using static QuikDawEditor.EDITING.StaticProperties; using System.Collections.Generic; namespace QuikDawEditor { public partial class PianoRoll : UserControl, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public string RelRes() { ReleaseResources(); return "Resources released"; } public PianoRoll() { this.InitializeComponent(); } private void PRoll_Loaded(object sender, RoutedEventArgs e) { SnapToCB.SelectedIndex = 5; //set initial to snap 16th notes } private void ThisPianoRoll_VerticalScrollChange(double setVertical) { UDScrollViewer.ScrollToVerticalOffset(setVertical); } public double SnapToMilliseconds { get { return NoteSnapTo == 0 ? -1 : 4 / NoteSnapTo * MillisecondsPerBeat; } } public double SnapToMillisecondsTriplet { get { return 2 / (3 / thisPianoRoll.tripletRes) * MillisecondsPerBeat; } } public double NoteSnapTo = 4; private void SnapToCB_SelectionChanged(object sender, SelectionChangedEventArgs e) { string switchExpr = this.SnapToCB.SelectedValue.ToString(); switch (switchExpr) { case "---": NoteSnapTo = 0; break; case "Whole note": NoteSnapTo = 1; break; case "1/2 note": NoteSnapTo = 2; break; case "1/4 note": NoteSnapTo = 4; break; case "1/8 note": NoteSnapTo = 8; break; case "1/16 note": NoteSnapTo = 16; break; } } private void FixMidiOverlaps() { //// Check heads, tails and completely containing another note //foreach (DisplayableMidiNoteOnEvent snote in SelectedNotes) //{ // for (int evno = DisplayableMidiNotes.Count - 1; evno >= 0; evno += -1) // { // CheckNote = DisplayableMidiNotes[evno]; // if (CheckNote.NoteNum == snote.NoteNum & !(CheckNote == snote)) // { // // Note contains another note // if (CheckNote.AbsTime >= snote.AbsTime & CheckNote.AbsTime + CheckNote.NoteLen < snote.AbsTime + snote.NoteLen) // { // MidiEvents.Remove(CheckNote.NEvent); // this.NoteCanvas.Children.Remove(CheckNote.MyPath); // DisplayableMidiNotes.Remove(CheckNote); // } // else // { // // Note overlaps tail of another // if (CheckNote.AbsTime <= snote.AbsTime & CheckNote.AbsTime + CheckNote.NoteLen > snote.AbsTime) // { // CheckNote.NoteLen = (int)(snote.AbsTime - CheckNote.AbsTime); // UpdatePath(ref CheckNote); // } // // Note overlaps head of another // if (snote.AbsTime <= CheckNote.AbsTime & snote.AbsTime + snote.NoteLen > CheckNote.AbsTime) // { // CheckNote.AbsTime = snote.AbsTime + snote.NoteLen; // CheckNote.NoteLen -= (int)snote.AbsTime + snote.NoteLen - (int)CheckNote.AbsTime; // UpdatePath(ref CheckNote); // } // } // } // } //} } private Cursor DefCursor = Cursors.Arrow; private void UDScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { UDPianoScrollViewer.ScrollToVerticalOffset(UDScrollViewer.VerticalOffset); ScaleScrollViewer.ScrollToHorizontalOffset(UDScrollViewer.HorizontalOffset); MidiEventsSV.ScrollToHorizontalOffset(UDScrollViewer.HorizontalOffset); if (thisPianoRoll != null) thisPianoRoll.VerticalScrollValue = UDScrollViewer.VerticalOffset; } private void UDPianoScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { e.Handled = true; UDScrollViewer.ScrollToVerticalOffset(UDScrollViewer.VerticalOffset + Math.Sign(e.Delta) * -25); } double currentSnapToMs { get { return thisPianoRoll.TripletOn ? SnapToMillisecondsTriplet : SnapToMilliseconds; } } private void PianoKeyPlayOff(int noteval) { PianoKey playingPianoKey = thisPianoRoll.PianoKeys.Where(pk => pk.NoteNo == noteval).FirstOrDefault(); if (playingPianoKey != null) { playingPianoKey.IsPlaying = false; } } private void PianoKeyPlayOn(int noteval) { PianoKey toPlayPianoKey = thisPianoRoll.PianoKeys.Where(pk => pk.NoteNo == noteval).FirstOrDefault(); if (toPlayPianoKey != null) { toPlayPianoKey.IsPlaying = true; } } private Clip myClip {get{return thisPianoRoll?.myClip; } } private PianoRollModel thisPianoRoll { get { return (PianoRollModel)this.DataContext; } } private void HideBut_Click(object sender, RoutedEventArgs e) { if (projPlayer.IsPianoRollPlaying) return; thisPianoRoll.IsVisible = false; editingProject.NeedsSaving = true; } private void ToggleTripletBut_Click(object sender, RoutedEventArgs e) { thisPianoRoll.TripletOn = !thisPianoRoll.TripletOn; } private void QuantizeMI_Click(object sender, RoutedEventArgs e) { Quantize_Execute(); } double lastChangeValue = 0; private void MidiNoteTransposeKnob_ValueChanged(object sender, double Value) { int valchange = (int)(Value - lastChangeValue); foreach (QDMidiNote mnote in thisPianoRoll.MidiNotes) mnote.Note += valchange; RelativeTransposeValue += valchange; lastChangeValue = Value; } int RelativeTransposeValue; private void MidiNoteTransKnob_PreviewMouseDown(object sender, MouseButtonEventArgs e) { RelativeTransposeValue = 0; } private void MidiNoteTransKnob_PreviewMouseUp(object sender, MouseButtonEventArgs e) { lastChangeValue = 0; ((MidiNoteTransposeKnob)sender).Value = 0; undoActions.Add(new MidiTransposeUndo(myClip.UndoClipID, RelativeTransposeValue)); myClip.UpdateMidiImageSource(); } private void PianoRoll_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { thisPianoRoll.VerticalScrollChange -= ThisPianoRoll_VerticalScrollChange; thisPianoRoll.VerticalScrollChange += ThisPianoRoll_VerticalScrollChange; thisPianoRoll.ScrollToNoteChange -= ThisPianoRoll_ScrollToNoteChange; thisPianoRoll.ScrollToNoteChange += ThisPianoRoll_ScrollToNoteChange; } private void ThisPianoRoll_ScrollToNoteChange(double scrollToNote) { int centeringNote = (int)(scrollToNote + UDScrollViewer.ActualHeight / PianoRollNoteHeight); thisPianoRoll.VerticalScrollValue = NotesIC.ActualHeight * (127D - centeringNote) / 127D; } private void PianoRoll_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { if (myClip != null) thisPianoRoll.DrawMeasureLines(); if (this.IsVisible) this.Focus(); } private void ShowMidiEventsMI_SubmenuOpened(object sender, RoutedEventArgs e) { MidiEventsLB.Items.Clear(); foreach (QDMidiEvent qme in myClip.ClipMidiEvents) MidiEventsLB.Items.Add(qme.GetType().ToString() + " ::: " + qme.ClipRelTimeMs.ToString() + (qme is QDMidiNote ? " note: " + ((QDMidiNote)qme).Note.ToString() : "") + " val=" + qme.MainValue.ToString()); } private void MidiEventViewCB_DropDownClosed(object sender, EventArgs e) { undoActions.Add(new MidiEventsSourceSelectUndo(thisPianoRoll.PreviousMidiEventIndex, thisPianoRoll)); thisPianoRoll.PreviousMidiEventIndex = thisPianoRoll.SelectedMidiEventIndex; } private void MidiEventViewCB_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (MidiEventViewCB.SelectedIndex == -1) return; if (thisPianoRoll.SelectedMidiEventIndex == -1) return; TextBlock tblock = (TextBlock)MidiEventViewCB.SelectedItem; switch (tblock.Text) { case "Velocities": MidiEventsIC.ItemsSource = thisPianoRoll.MidiNotes; break; case "Sustain": MidiEventsIC.ItemsSource = myClip.ClipSustainEvents; break; case "Pitch bend": MidiEventsIC.ItemsSource = myClip.ClipPitchChangeEvents; break; case "Modulation": MidiEventsIC.ItemsSource = myClip.ClipModulationEvents; break; } } private void Triplet4thRB_Checked(object sender, RoutedEventArgs e) { if (thisPianoRoll == null) return; thisPianoRoll.tripletRes = 1; thisPianoRoll.DrawTripletLines(); TripletSelectCM.IsOpen = false; } private void Triplet8thRB_Checked(object sender, RoutedEventArgs e) { thisPianoRoll.tripletRes = 0.5; thisPianoRoll.DrawTripletLines(); TripletSelectCM.IsOpen = false; } private void Triplet16thRB_Checked(object sender, RoutedEventArgs e) { thisPianoRoll.tripletRes = 0.25; thisPianoRoll.DrawTripletLines(); TripletSelectCM.IsOpen = false; } private void PianoRoll_PreviewMouseUp(object sender, MouseButtonEventArgs e) { if (EventsGridSplitter.IsFocused) return; if (MidiEventViewCB.IsDropDownOpen) return; if (SnapToCB.IsDropDownOpen) return; if (ToggleTripletBut.IsFocused) return; if (PianoRollPlayBut.IsFocused) return; if (HideBut.IsFocused) return; this.Focus(); } private void NotesIC_MouseLeave(object sender, MouseEventArgs e) { Cursor = Cursors.Arrow; } private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e) { // MessageBox.Show("mouse down"); } private void PlayMidiClipBut_Click(object sender, RoutedEventArgs e) { thisPianoRoll.myTrack = myClip.myTrack; thisPianoRoll.clipPlaying = !thisPianoRoll.clipPlaying; thisPianoRoll.myTrack.StopMidiNotes(); switch (thisPianoRoll.clipPlaying) { case true: foreach (Track t in editingProject.GetAllTracksInProject) t.IsPianoRollMuted = true; thisPianoRoll.myTrack.IsPianoRollMuted = false; thisPianoRoll.keepProjectPlaying = projPlayer.IsProjectPlaying; thisPianoRoll.keepPlayPos = projPlayer.CurrentPlayingPosMS; projPlayer.IsProjectPlaying = true; projPlayer.CurrentPlayingPosMS = myClip.ClipLeftMs + thisPianoRoll.CurrentMidiPlayingPosMS; projPlayer.PlayControlsDPDisabled = true; break; case false: thisPianoRoll.StopPlay(); projPlayer.IsProjectPlaying = false; projPlayer.PlayControlsDPDisabled = false; break; } } } }