Skip to content

Commit

Permalink
add - Duration seeking added
Browse files Browse the repository at this point in the history
We've added seeking support!

---

You can now seek using the slider on the bottom.

---

Type: add
Breaking: False
Doc Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Sep 4, 2023
1 parent f009aa7 commit b0df334
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 12 deletions.
47 changes: 46 additions & 1 deletion BassBoom.Basolia/Format/AudioInfoTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
using BassBoom.Basolia.File;
using BassBoom.Basolia.Playback;
using System;
using BassBoom.Native.Interop.Output;
using System.Diagnostics;
using BassBoom.Native.Interop.LowLevel;

namespace BassBoom.Basolia.Format
{
Expand All @@ -40,7 +43,7 @@ public static int GetDuration(bool scan)

// Check to see if the file is open
if (!FileTools.IsOpened)
throw new BasoliaException("Can't play a file that's not open", mpg123_errors.MPG123_BAD_FILE);
throw new BasoliaException("Can't query a file that's not open", mpg123_errors.MPG123_BAD_FILE);

// Check to see if we're playing
if (PlaybackTools.Playing && !InitBasolia._fugitive)
Expand Down Expand Up @@ -79,5 +82,47 @@ public static TimeSpan GetDurationSpan(bool scan)
long seconds = durationSamples / rate;
return TimeSpan.FromSeconds(seconds);
}

public static int GetFrameSize()
{
int frameSize;
InitBasolia.CheckInited();

// Check to see if the file is open
if (!FileTools.IsOpened)
throw new BasoliaException("Can't query a file that's not open", mpg123_errors.MPG123_BAD_FILE);

unsafe
{
var outHandle = Mpg123Instance._out123Handle;

// Get the output format to get the frame size
int getStatus = NativeOutputLib.out123_getformat(outHandle, null, null, null, out frameSize);
if (getStatus != (int)out123_error.OUT123_OK)
throw new BasoliaOutException($"Can't get the output.", (out123_error)getStatus);
Debug.WriteLine($"Got frame size {frameSize}");
}
return frameSize;
}

public static int GetBufferSize()
{
int bufferSize;
InitBasolia.CheckInited();

// Check to see if the file is open
if (!FileTools.IsOpened)
throw new BasoliaException("Can't query a file that's not open", mpg123_errors.MPG123_BAD_FILE);

unsafe
{
var handle = Mpg123Instance._mpg123Handle;

// Now, buffer the entire music file and create an empty array based on its size
bufferSize = NativeLowIo.mpg123_outblock(handle);
Debug.WriteLine($"Buffer size is {bufferSize}");
}
return bufferSize;
}
}
}
23 changes: 23 additions & 0 deletions BassBoom.Basolia/Playback/PlaybackPositioningTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,28 @@ public static void SeekToTheBeginning()
throw new BasoliaException("Can't seek to the beginning of the file", mpg123_errors.MPG123_LSEEK_FAILED);
}
}

/// <summary>
/// Gets the current duration of the file (samples)
/// </summary>
public static void SeekToFrame(int frame)
{
InitBasolia.CheckInited();

// Check to see if the file is open
if (!FileTools.IsOpened)
throw new BasoliaException("Can't seek a file that's not open", mpg123_errors.MPG123_BAD_FILE);

// We're now entering the dangerous zone
unsafe
{
var handle = Mpg123Instance._mpg123Handle;

// Get the length
int status = NativePositioning.mpg123_seek(handle, frame, 0);
if (status == (int)mpg123_errors.MPG123_ERR)
throw new BasoliaException($"Can't seek to frame #{frame} of the file", (mpg123_errors)status);
}
}
}
}
9 changes: 2 additions & 7 deletions BassBoom.Basolia/Playback/PlaybackTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,9 @@ public static void Play()
if (startStatus != (int)out123_error.OUT123_OK)
throw new BasoliaOutException($"Can't start the output.", (out123_error)startStatus);

// Get the output format to get the frame size
int getStatus = NativeOutputLib.out123_getformat(outHandle, null, null, null, out int frameSize);
if (getStatus != (int)out123_error.OUT123_OK)
throw new BasoliaOutException($"Can't get the output.", (out123_error)getStatus);
Debug.WriteLine($"Got frame size {frameSize}");

// Now, buffer the entire music file and create an empty array based on its size
var bufferSize = NativeLowIo.mpg123_outblock(handle);
var frameSize = AudioInfoTools.GetFrameSize();
var bufferSize = AudioInfoTools.GetBufferSize();
Debug.WriteLine($"Buffer size is {bufferSize}");
var buffer = stackalloc byte[bufferSize];
var bufferPtr = new IntPtr(buffer);
Expand Down
4 changes: 2 additions & 2 deletions BassBoom/Views/MainView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@
</StackPanel>
<StackPanel
DockPanel.Dock="Bottom"
Margin="15"
Margin="15,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom">
<ProgressBar Name="durationRemain" HorizontalAlignment="Stretch"></ProgressBar>
<Slider Name="durationRemain" HorizontalAlignment="Stretch"></Slider>
</StackPanel>
</DockPanel>
</UserControl>
23 changes: 21 additions & 2 deletions BassBoom/Views/MainView.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Primitives;
using Avalonia.Interactivity;
using Avalonia.Threading;
using BassBoom.Basolia;
Expand All @@ -30,6 +31,7 @@
using MsBox.Avalonia.Enums;
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
Expand All @@ -39,12 +41,15 @@ namespace BassBoom.Views;

public partial class MainView : UserControl
{
internal bool sliderUpdatedByCode = false;

public MainView()
{
InitializeComponent();
DataContext = new BassBoomData(this);
PathToMp3.TextChanged += CheckPath;
DetermineDevice.IsCheckedChanged += MakeDeviceDeterministic;
durationRemain.ValueChanged += HandleDurationValueChange;
}

internal void EnablePlay()
Expand All @@ -68,6 +73,14 @@ private void CheckPath(object sender, TextChangedEventArgs e) =>

private void MakeDeviceDeterministic(object sender, RoutedEventArgs e) =>
((BassBoomData)DataContext).HandleDeviceButtons();

private void HandleDurationValueChange(object sender, RangeBaseValueChangedEventArgs e)
{
if (sliderUpdatedByCode)
return;
Debug.WriteLine($"Changed. {e.OldValue} -> {e.NewValue}");
PlaybackPositioningTools.SeekToFrame((int)e.NewValue);
}
}

public class BassBoomData
Expand Down Expand Up @@ -129,6 +142,9 @@ public async Task PlayAsync()
view.StopButton.IsEnabled = true;
duration = AudioInfoTools.GetDuration(true);
durationSpan = AudioInfoTools.GetDurationSpan(true).ToString();
view.durationRemain.Maximum = duration;
view.durationRemain.IsSnapToTickEnabled = true;
view.durationRemain.TickFrequency = AudioInfoTools.GetBufferSize();
sliderUpdate.Start(view);
await PlaybackTools.PlayAsync();
}
Expand Down Expand Up @@ -340,17 +356,20 @@ private static void UpdateSlider(object obj)
SpinWait.SpinUntil(() => PlaybackTools.Playing);
var view = (MainView)obj;
Dispatcher.UIThread.Invoke(() => {
view.sliderUpdatedByCode = true;
view.durationRemain.Value = 0;
view.GotDurationLabel.Text = $"00:00:00/{durationSpan}";
view.sliderUpdatedByCode = false;
});
while (PlaybackTools.Playing)
{
int position = PlaybackPositioningTools.GetCurrentDuration();
string positionSpan = PlaybackPositioningTools.GetCurrentDurationSpan().ToString();
double remaining = 100 * (position / (double)duration);
Dispatcher.UIThread.Invoke(() => {
view.durationRemain.Value = remaining;
view.sliderUpdatedByCode = true;
view.durationRemain.Value = position;
view.GotDurationLabel.Text = $"{positionSpan}/{durationSpan}";
view.sliderUpdatedByCode = false;
});
}
}
Expand Down

0 comments on commit b0df334

Please sign in to comment.