diff --git a/Documentation/input/reference/api/loadsoundfont.cshtml b/Documentation/input/reference/api/loadsoundfont.cshtml index c9050cad4..3b719ac83 100644 --- a/Documentation/input/reference/api/loadsoundfont.cshtml +++ b/Documentation/input/reference/api/loadsoundfont.cshtml @@ -9,7 +9,8 @@ Since: 0.9.4

Description

- This function initiates a load of the soundfont using the given data. The supported data types is depending on the platform. AlphaTab only supports SoundFont2 encoded soundfonts for loading. + This function initiates a load of the soundfont using the given data. The supported data types is depending on the platform. AlphaTab only supports SoundFont2 encoded soundfonts for loading. To load a soundfont the player must be enabled in advance. +

Signatures

diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/ManagedUiFacade.cs b/Source/AlphaTab.CSharp/Platform/CSharp/ManagedUiFacade.cs index 02c9c4375..9bde2fa7c 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/ManagedUiFacade.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/ManagedUiFacade.cs @@ -85,6 +85,7 @@ public virtual void InitialRender() protected abstract void RenderTracks(); public abstract void BeginAppendRenderResults(RenderFinishedEventArgs renderResults); + public abstract void DestroyCursors(); public abstract Cursors CreateCursors(); public abstract void BeginInvoke(Action action); public abstract void RemoveHighlights(); diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsUiFacade.cs b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsUiFacade.cs index 7c37b7bb8..f5265a56a 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsUiFacade.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsUiFacade.cs @@ -194,6 +194,10 @@ public override void BeginAppendRenderResults(RenderFinishedEventArgs r) } + public override void DestroyCursors() + { + } + public override Cursors CreateCursors() { // no cursors for winforms, why? - It lacks of proper transparency support diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfUiFacade.cs b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfUiFacade.cs index 67abfc6c7..8d567ff7a 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfUiFacade.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfUiFacade.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Concurrent; using System.IO; +using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; @@ -191,10 +192,20 @@ public override void BeginAppendRenderResults(RenderFinishedEventArgs r) r); } + public override void DestroyCursors() + { + var element = (Panel)((FrameworkElementContainer)Api.CanvasElement).Control.Parent; + var cursors = element.Children.OfType().FirstOrDefault(c => "at-cursors".Equals(c.Tag)); + if (cursors != null) + { + element.Children.Remove(cursors); + } + } public override Cursors CreateCursors() { var cursorWrapper = new Canvas(); + cursorWrapper.Tag = "at-cursors"; cursorWrapper.HorizontalAlignment = HorizontalAlignment.Left; cursorWrapper.VerticalAlignment = VerticalAlignment.Top; diff --git a/Source/AlphaTab.JavaScript/UI/BrowserUiFacade.cs b/Source/AlphaTab.JavaScript/UI/BrowserUiFacade.cs index 6ae12b01d..4ec3a80b8 100644 --- a/Source/AlphaTab.JavaScript/UI/BrowserUiFacade.cs +++ b/Source/AlphaTab.JavaScript/UI/BrowserUiFacade.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices; using AlphaTab.Audio.Synth; using AlphaTab.Collections; using AlphaTab.Haxe; @@ -649,7 +650,13 @@ public IAlphaSynth CreateWorkerPlayer() } else { - player.Ready += () => { ((AlphaTabApi)_api).LoadSoundFontFromUrl(_api.Settings.SoundFontFile); }; + player.Ready += () => + { + if (!string.IsNullOrEmpty(_api.Settings.SoundFontFile)) + { + ((AlphaTabApi)_api).LoadSoundFontFromUrl(_api.Settings.SoundFontFile); + } + }; } return player; @@ -680,6 +687,13 @@ public void RemoveHighlights() } } + public void DestroyCursors() + { + var element = ((HtmlElementContainer)_api.Container).Element; + var cursorWrapper = element.QuerySelector(".at-cursors"); + element.RemoveChild(cursorWrapper); + } + public Cursors CreateCursors() { var element = ((HtmlElementContainer)_api.Container).Element; diff --git a/Source/AlphaTab/AlphaTabApi.cs b/Source/AlphaTab/AlphaTabApi.cs index f63a41e4e..c39511e88 100644 --- a/Source/AlphaTab/AlphaTabApi.cs +++ b/Source/AlphaTab/AlphaTabApi.cs @@ -127,6 +127,8 @@ public AlphaTabApi(IUiFacade uiFacade, TSettings settings) SetupPlayer(); } + SetupClickHandling(); + UiFacade.InitialRender(); } @@ -152,6 +154,16 @@ public virtual void Destroy() public void UpdateSettings() { Renderer.UpdateSettings(Settings); + + // enable/disable player if needed + if (Settings.EnablePlayer) + { + SetupPlayer(); + } + else + { + DestroyPlayer(); + } } /// @@ -202,7 +214,8 @@ public void RenderScore(Score score, int[] trackIndexes = null) tracks.Add(score.Tracks[0]); } } - if(trackIndexes.Length == 0) + + if (trackIndexes.Length == 0) { if (score.Tracks.Count > 0) { @@ -219,6 +232,7 @@ public void RenderScore(Score score, int[] trackIndexes = null) } } } + InternalRenderTracks(score, tracks.ToArray()); } @@ -271,6 +285,7 @@ private void InternalRenderTracks(Score score, Track[] tracks) { _trackIndexes.Add(track.Index); } + Render(); } } @@ -589,8 +604,25 @@ public bool IsLooping } } + private void DestroyPlayer() + { + if (Player == null) + { + return; + } + + Player.Destroy(); + Player = null; + DestroyCursors(); + } + private void SetupPlayer() { + if (Player != null) + { + return; + } + Player = UiFacade.CreateWorkerPlayer(); if (Player == null) { @@ -634,7 +666,11 @@ private void SetupPlayer() if (Settings.EnableCursor) { - SetupCursor(); + SetupCursors(); + } + else + { + DestroyCursors(); } } @@ -779,14 +815,30 @@ public void Stop() private int _previousTick; private PlayerState _playerState; - private BoundsLookup _cursorCache; private Beat _currentBeat; private PlayerState _previousStateForCursor; private BoundsLookup _previousCursorCache; private int _lastScroll; - private void SetupCursor() + private void DestroyCursors() + { + if (_cursorWrapper == null) + { + return; + } + + UiFacade.DestroyCursors(); + _cursorWrapper = null; + _barCursor = null; + _beatCursor = null; + _selectionWrapper = null; + + _previousTick = 0; + _playerState = PlayerState.Paused; + } + + private void SetupCursors() { // // Create cursors @@ -812,7 +864,6 @@ private void SetupCursor() // we need to update our position caches if we render a tablature Renderer.PostRenderFinished += () => { - _cursorCache = Renderer.BoundsLookup; CursorUpdateTick(_previousTick); }; @@ -837,8 +888,6 @@ private void SetupCursor() } } }; - - SetupClickHandling(); } /// @@ -876,7 +925,7 @@ private void CursorUpdateBeat(Beat beat, Beat nextBeat, double duration, bool st return; } - var cache = _cursorCache; + var cache = Renderer.BoundsLookup; if (cache == null) { return; @@ -1055,7 +1104,7 @@ private void SetupClickHandling() { CanvasElement.MouseDown += e => { - if (!e.IsLeftMouseButton) + if (!e.IsLeftMouseButton || !Settings.EnablePlayer || !Settings.EnableCursor) { return; } @@ -1064,7 +1113,7 @@ private void SetupClickHandling() var relX = e.GetX(CanvasElement); var relY = e.GetY(CanvasElement); - var beat = _cursorCache.GetBeatAtPos(relX, relY); + var beat = Renderer.BoundsLookup.GetBeatAtPos(relX, relY); if (beat != null) { _selectionStart = new SelectionInfo(beat); @@ -1075,14 +1124,14 @@ private void SetupClickHandling() CanvasElement.MouseMove += e => { - if (!_selecting) + if (!_selecting || !Settings.EnablePlayer || !Settings.EnableCursor) { return; } var relX = e.GetX(CanvasElement); var relY = e.GetY(CanvasElement); - var beat = _cursorCache.GetBeatAtPos(relX, relY); + var beat = Renderer.BoundsLookup.GetBeatAtPos(relX, relY); if (beat != null && (_selectionEnd == null || _selectionEnd.Beat != beat)) { _selectionEnd = new SelectionInfo(beat); @@ -1092,7 +1141,7 @@ private void SetupClickHandling() CanvasElement.MouseUp += e => { - if (!_selecting) + if (!_selecting || !Settings.EnablePlayer || !Settings.EnableCursor) { return; } @@ -1146,10 +1195,11 @@ private void SetupClickHandling() Renderer.PostRenderFinished += () => { - if (_selectionStart != null) + if (_selectionStart == null || !Settings.EnablePlayer || !Settings.EnableCursor) { - CursorSelectRange(_selectionStart, _selectionEnd); + return; } + CursorSelectRange(_selectionStart, _selectionEnd); }; } @@ -1167,7 +1217,7 @@ public virtual void UpdateLayout(LayoutSettings layoutSettings) private void CursorSelectRange(SelectionInfo startBeat, SelectionInfo endBeat) { - var cache = _cursorCache; + var cache = Renderer.BoundsLookup; if (cache == null) { return; @@ -1376,6 +1426,7 @@ internal void OnError(string type, Exception details) /// This event is fired when all required data for playback is loaded and ready. /// public event Action ReadyForPlayback; + private void OnReadyForPlayback() { var handler = ReadyForPlayback; @@ -1391,6 +1442,7 @@ private void OnReadyForPlayback() /// This event is fired when the playback of the whole song finished. /// public event Action PlayerFinished; + private void OnPlayerFinished() { var handler = PlayerFinished; @@ -1406,6 +1458,7 @@ private void OnPlayerFinished() /// This event is fired when the SoundFont needed for playback was loaded. /// public event Action SoundFontLoaded; + private void OnSoundFontLoaded() { var handler = SoundFontLoaded; @@ -1413,6 +1466,7 @@ private void OnSoundFontLoaded() { handler(); } + UiFacade.TriggerEvent(Container, "soundFontLoaded"); } @@ -1420,6 +1474,7 @@ private void OnSoundFontLoaded() /// This event is fired when the Midi file needed for playback was loaded. /// public event Action MidiLoaded; + private void OnMidiLoaded() { var handler = MidiLoaded; @@ -1427,6 +1482,7 @@ private void OnMidiLoaded() { handler(); } + UiFacade.TriggerEvent(Container, "midiFileLoaded"); } @@ -1434,6 +1490,7 @@ private void OnMidiLoaded() /// This event is fired when the playback state changed. /// public event Action PlayerStateChanged; + private void OnPlayerStateChanged(PlayerStateChangedEventArgs e) { var handler = PlayerStateChanged; @@ -1441,6 +1498,7 @@ private void OnPlayerStateChanged(PlayerStateChangedEventArgs e) { handler(e); } + UiFacade.TriggerEvent(Container, "playerStateChanged", e); } @@ -1448,6 +1506,7 @@ private void OnPlayerStateChanged(PlayerStateChangedEventArgs e) /// This event is fired when the current playback position of the song changed. /// public event Action PlayerPositionChanged; + private void OnPlayerPositionChanged(PositionChangedEventArgs e) { var handler = PlayerPositionChanged; @@ -1455,6 +1514,7 @@ private void OnPlayerPositionChanged(PositionChangedEventArgs e) { handler(e); } + UiFacade.TriggerEvent(Container, "positionChanged", e); } diff --git a/Source/AlphaTab/UI/IUiFacade.cs b/Source/AlphaTab/UI/IUiFacade.cs index 134a192fa..872595735 100644 --- a/Source/AlphaTab/UI/IUiFacade.cs +++ b/Source/AlphaTab/UI/IUiFacade.cs @@ -98,6 +98,11 @@ public interface IUiFacade /// Cursors CreateCursors(); + /// + /// Destroys the cursor objects that are used to highlight the currently played beats and bars. + /// + void DestroyCursors(); + /// /// Tells the UI layer to invoke the given action. ///