using static QuikDawEditor.EDITING.MidiMethods; namespace QuikDawEditor; public partial class ProjectPlayer { public void ChangePlayPos(double playposms) { //StopAllNotes(); bufferedSampleProvider.ClearBuffer(); //CAN CAUSE STATIC ON CHANGE PLAYPOS but re-synchronizes UI/audio //bufferedSampleProvider.ClearBufferTapered(); //CAN CAUSE STATIC ON CHANGE PLAYPOS but re-synchronizes UI/audio ////Does it help to clear the vst buffers as well? //foreach (Track t in editingProject.GetAllTracksInProject) // t.FlushVsts(); CurrentPlayingPosMS = playposms; mmsp.ResetAllClips(CurrentPlayingPosMS); StopAllNotes(); } internal void UpdatePlayPosLine() { NotifyPropertyChanged(nameof(CurrentPlayPosPixels)); NotifyPropertyChanged(nameof(PlayTimeCodeString)); } string lastPlayTimeCodeString = ""; string newPlayTimeCodeString = ""; int updateUICounter = 0; internal double RecordStartPosMS; private double _CurrentPlayingPosMS = 0; public double CurrentPlayingPosMS { get { return _CurrentPlayingPosMS; } set { _CurrentPlayingPosMS = value; if (!IsProjectRecording) //If recording, don't stop at end { if (_CurrentPlayingPosMS > editingProject.projectEndPointMs) { _CurrentPlayingPosMS += ProcessingRateMs; IsProjectPlaying = false; } } if (IsProjectLooped) { if (_CurrentPlayingPosMS >= editingProject.LoopRangeRightMs) ChangePlayPos(editingProject.LoopRangeLeftMs); } if (updateUICounter == 0 && !IsZooming) { //Update UI every x cycles try { //For recording midi display if (IsProjectRecording && _CurrentPlayingPosMS >= RecordStartPosMS) { Dispatcher.CurrentDispatcher.Invoke(() => { Track recTrack = editingProject.GetRecordingTrack; recTrack.midiRecordingClip.ClipWidthMs = _CurrentPlayingPosMS - RecordStartPosMS; recTrack.midiRecordingClip.UpdateMidiNoteWidths(); }, DispatcherPriority.Background); } //Time code & playline display if (!IsMixingDown && !IsPianoRollPlaying) UpdatePlayPosDisplay(); if (editingProject.pianoRoll.IsVisible) { Dispatcher.CurrentDispatcher.Invoke(() => //Application.Current.Dispatcher.Invoke(() => { editingProject.pianoRoll.CurrentMidiPlayingPosMS = _CurrentPlayingPosMS; if (IsPianoRollPlaying) { if (_CurrentPlayingPosMS >= editingProject.pianoRoll.myClip.ClipRightMs) { editingProject.pianoRoll.myClip.myTrack.StopMidiNotes(); _CurrentPlayingPosMS = editingProject.pianoRoll.myClip.ClipLeftMs; } } }, DispatcherPriority.Render); } } //catch (Exception ex) { Debug.WriteLine("Problem with UI updating......................................."); } catch { } } updateUICounter += 1; if (updateUICounter >= ZoomModifiedUICounter) updateUICounter = 0; } } public double PlayPosUpdateCycle = 6; public int ZoomModifiedUICounter = 6; public double CurrentPlayPosPixels { get { return CurrentPlayingPosMS / 1000D * PixelsPerSecond * editingProject.ViewXZoomFac; } } public string PlayTimeCodeString { get { switch (IsTimePlayScale) { case true: return new TimeSpan(0, 0, 0, 0, (int)CurrentPlayingPosMS + 1000).ToString().Substring(0, 8); case false: return GetBeatMeasureString(CurrentPlayingPosMS); } } } public string TotalTimeCodeString { get { return "Total time:\n" + new TimeSpan(0, 0, 0, 0, (int)editingProject.projectEndPointMs).ToString().Substring(0, 8); } } public void UpdatePlayPosDisplay() { newPlayTimeCodeString = PlayTimeCodeString; Dispatcher.CurrentDispatcher.Invoke(() => { NotifyPropertyChanged(nameof(CurrentPlayPosPixels)); if (lastPlayTimeCodeString != newPlayTimeCodeString) NotifyPropertyChanged(nameof(PlayTimeCodeString)); lastPlayTimeCodeString = newPlayTimeCodeString; }, DispatcherPriority.ContextIdle); //Scroll if has reached right of screen double playpixpos = MsecToPixels(CurrentPlayingPosMS) * editingProject.ViewXZoomFac; double scrollLimit = TracksViewingWidthPixels - 80; if (playpixpos - TracksContentSVHorizontalScrollOffset > scrollLimit) { //Dispatcher.CurrentDispatcher.Invoke(()=> //error Application.Current.Dispatcher.Invoke(() => //Seems to be best { ScrollTracksContentSVForward(playpixpos - scrollLimit); }, DispatcherPriority.Render); } } }