Skip to content

Commit

Permalink
add - brk|doc - Added Basolia instance for multi p...
Browse files Browse the repository at this point in the history
...layback

---

If you want to be able to play more than one file, this is the right time!

---

Type: add
Breaking: True
Doc Required: True
Backport Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Sep 16, 2024
1 parent 1589498 commit 1d0cf74
Show file tree
Hide file tree
Showing 18 changed files with 497 additions and 302 deletions.
80 changes: 80 additions & 0 deletions BassBoom.Basolia/BasoliaMedia.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// BassBoom Copyright (C) 2023 Aptivi
//
// This file is part of BassBoom
//
// BassBoom is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// BassBoom is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

using BassBoom.Basolia.Playback;
using BassBoom.Native;
using BassBoom.Native.Exceptions;
using BassBoom.Native.Interop.Init;
using BassBoom.Native.Interop.Output;
using System;
using System.Diagnostics;

namespace BassBoom.Basolia
{
/// <summary>
/// Basolia instance for media manipulation
/// </summary>
public unsafe class BasoliaMedia
{
internal bool bufferPlaying = false;
internal bool holding = false;
internal string radioIcy = "";
internal PlaybackState state = PlaybackState.Stopped;

internal mpg123_handle* _mpg123Handle;
internal out123_handle* _out123Handle;

/// <summary>
/// Makes a new Basolia instance and initializes the library, if necessary.
/// </summary>
/// <param name="root">Root directory that contains native library files</param>
/// <exception cref="BasoliaNativeLibraryException"></exception>
public BasoliaMedia(string root = "")
{
if (!InitBasolia.BasoliaInitialized)
InitBasolia.Init(root);

// Verify that we've actually loaded the library!
try
{
var @delegate = MpgNative.GetDelegate<NativeInit.mpg123_new>(MpgNative.libManagerMpg, nameof(NativeInit.mpg123_new));
var handle = @delegate.Invoke(null, null);
Debug.WriteLine($"Verifying mpg123 version: {MpgNative.MpgLibVersion}");
_mpg123Handle = handle;
}
catch (Exception ex)
{
throw new BasoliaNativeLibraryException($"mpg123 library path {MpgNative.mpg123LibPath} doesn't contain a valid mpg123 library. mpg123_new() was called. {ex.Message}");
}

// Do the same for the out123 library!
try
{
var @delegate = MpgNative.GetDelegate<NativeOutputLib.out123_new>(MpgNative.libManagerOut, nameof(NativeOutputLib.out123_new));
var handle = @delegate.Invoke();
Debug.WriteLine($"Verifying out123 version: {MpgNative.OutLibVersion}");
_out123Handle = handle;
}
catch (Exception ex)
{
throw new BasoliaNativeLibraryException($"out123 library path {MpgNative.out123LibPath} doesn't contain a valid out123 library. out123_new() was called. {ex.Message}");
}
}
}
}
35 changes: 25 additions & 10 deletions BassBoom.Basolia/Devices/DeviceTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,14 @@ public static class DeviceTools
/// <summary>
/// Gets a read only dictionary that lists all the drivers
/// </summary>
/// <param name="basolia">Basolia instance that contains a valid handle</param>
/// <returns>A dictionary containing the driver names and their descriptions</returns>
/// <exception cref="BasoliaException"></exception>
public static ReadOnlyDictionary<string, string> GetDrivers()
public static ReadOnlyDictionary<string, string> GetDrivers(BasoliaMedia? basolia)
{
InitBasolia.CheckInited();
if (basolia is null)
throw new BasoliaException("Basolia instance is not provided", mpg123_errors.MPG123_BAD_HANDLE);
Dictionary<string, string> drivers = [];

// We're now entering the dangerous zone
Expand All @@ -54,7 +57,7 @@ public static ReadOnlyDictionary<string, string> GetDrivers()
unsafe
{
// Query the drivers
var handle = MpgNative._out123Handle;
var handle = basolia._out123Handle;
var @delegate = MpgNative.GetDelegate<NativeOutputLib.out123_drivers>(MpgNative.libManagerOut, nameof(NativeOutputLib.out123_drivers));
int driversStatus = @delegate.Invoke(handle, ref names, ref descr);
if (driversStatus == (int)mpg123_errors.MPG123_ERR)
Expand All @@ -79,13 +82,16 @@ public static ReadOnlyDictionary<string, string> GetDrivers()
/// <summary>
/// Gets a read only dictionary that lists all the devices detected by the driver
/// </summary>
/// <param name="basolia">Basolia instance that contains a valid handle</param>
/// <param name="driver">A specific driver to use</param>
/// <param name="activeDevice">An output for the active device name</param>
/// <returns>A dictionary containing the device names and their descriptions</returns>
/// <exception cref="BasoliaException"></exception>
public static ReadOnlyDictionary<string, string> GetDevices(string driver, ref string activeDevice)
public static ReadOnlyDictionary<string, string> GetDevices(BasoliaMedia? basolia, string driver, ref string activeDevice)
{
InitBasolia.CheckInited();
if (basolia is null)
throw new BasoliaException("Basolia instance is not provided", mpg123_errors.MPG123_BAD_HANDLE);
Dictionary<string, string> devices = [];

// We're now entering the dangerous zone
Expand All @@ -95,7 +101,7 @@ public static ReadOnlyDictionary<string, string> GetDevices(string driver, ref s
unsafe
{
// Query the devices
var handle = MpgNative._out123Handle;
var handle = basolia._out123Handle;
var @delegate = MpgNative.GetDelegate<NativeOutputLib.out123_devices>(MpgNative.libManagerOut, nameof(NativeOutputLib.out123_devices));
int devicesStatus = @delegate.Invoke(handle, driver, out names, out descr, ref active);
if (devicesStatus == (int)mpg123_errors.MPG123_ERR)
Expand All @@ -119,17 +125,20 @@ public static ReadOnlyDictionary<string, string> GetDevices(string driver, ref s
/// <summary>
/// Gets the current device and driver
/// </summary>
/// <param name="basolia">Basolia instance that contains a valid handle</param>
/// <returns>Current device and driver</returns>
/// <exception cref="BasoliaException"></exception>
public static (string driver, string device) GetCurrent()
public static (string driver, string device) GetCurrent(BasoliaMedia? basolia)
{
InitBasolia.CheckInited();
if (basolia is null)
throw new BasoliaException("Basolia instance is not provided", mpg123_errors.MPG123_BAD_HANDLE);

// We're now entering the dangerous zone
unsafe
{
// Query the devices
var handle = MpgNative._out123Handle;
var handle = basolia._out123Handle;
IntPtr driverPtr = IntPtr.Zero;
IntPtr devicePtr = IntPtr.Zero;
var @delegate = MpgNative.GetDelegate<NativeOutputLib.out123_driver_info>(MpgNative.libManagerOut, nameof(NativeOutputLib.out123_driver_info));
Expand All @@ -156,11 +165,14 @@ public static (string? driver, string? device) GetCurrentCached()
/// <summary>
/// Sets the active driver
/// </summary>
/// <param name="basolia">Basolia instance that contains a valid handle</param>
/// <param name="driver">Driver to use</param>
/// <exception cref="BasoliaException"></exception>
public static void SetActiveDriver(string driver)
public static void SetActiveDriver(BasoliaMedia? basolia, string driver)
{
var driverList = GetDrivers();
if (basolia is null)
throw new BasoliaException("Basolia instance is not provided", mpg123_errors.MPG123_BAD_HANDLE);
var driverList = GetDrivers(basolia);
if (!driverList.ContainsKey(driver))
throw new BasoliaException($"Driver {driver} doesn't exist", mpg123_errors.MPG123_ERR);
activeDriver = driver;
Expand All @@ -169,13 +181,16 @@ public static void SetActiveDriver(string driver)
/// <summary>
/// Sets the active device
/// </summary>
/// <param name="basolia">Basolia instance that contains a valid handle</param>
/// <param name="driver">Driver to use</param>
/// <param name="device">Device to use</param>
/// <exception cref="BasoliaException"></exception>
public static void SetActiveDevice(string driver, string device)
public static void SetActiveDevice(BasoliaMedia? basolia, string driver, string device)
{
if (basolia is null)
throw new BasoliaException("Basolia instance is not provided", mpg123_errors.MPG123_BAD_HANDLE);
activeDevice = "";
var deviceList = GetDevices(driver, ref activeDevice);
var deviceList = GetDevices(basolia, driver, ref activeDevice);
if (string.IsNullOrEmpty(device))
return;
if (!deviceList.ContainsKey(device))
Expand Down
29 changes: 18 additions & 11 deletions BassBoom.Basolia/File/FileTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,11 @@ public static class FileTools
/// <summary>
/// Opens a media file
/// </summary>
public static void OpenFile(string path)
public static void OpenFile(BasoliaMedia? basolia, string path)
{
InitBasolia.CheckInited();
if (basolia is null)
throw new BasoliaException("Basolia instance is not provided", mpg123_errors.MPG123_BAD_HANDLE);

// Check to see if the file is open
if (IsOpened)
Expand All @@ -95,7 +97,7 @@ public static void OpenFile(string path)
unsafe
{
// Open the file
var handle = MpgNative._mpg123Handle;
var handle = basolia._mpg123Handle;
var @delegate = MpgNative.GetDelegate<NativeInput.mpg123_open>(MpgNative.libManagerMpg, nameof(NativeInput.mpg123_open));
int openStatus = @delegate.Invoke(handle, path);
if (openStatus == (int)mpg123_errors.MPG123_ERR)
Expand All @@ -108,15 +110,17 @@ public static void OpenFile(string path)
/// <summary>
/// Opens a remote radio station
/// </summary>
public static void OpenUrl(string path) =>
Task.Run(() => OpenUrlAsync(path)).Wait();
public static void OpenUrl(BasoliaMedia? basolia, string path) =>
Task.Run(() => OpenUrlAsync(basolia, path)).Wait();

/// <summary>
/// Opens a remote radio station
/// </summary>
public static async Task OpenUrlAsync(string path)
public static async Task OpenUrlAsync(BasoliaMedia? basolia, string path)
{
InitBasolia.CheckInited();
if (basolia is null)
throw new BasoliaException("Basolia instance is not provided", mpg123_errors.MPG123_BAD_HANDLE);

// Check to see if the file is open
if (IsOpened)
Expand Down Expand Up @@ -146,7 +150,7 @@ public static async Task OpenUrlAsync(string path)
unsafe
{
// Open the radio station
var handle = MpgNative._mpg123Handle;
var handle = basolia._mpg123Handle;
var @delegate = MpgNative.GetDelegate<NativeInput.mpg123_open_feed>(MpgNative.libManagerMpg, nameof(NativeInput.mpg123_open_feed));
int openStatus = @delegate.Invoke(handle);
if (openStatus == (int)mpg123_errors.MPG123_ERR)
Expand All @@ -157,29 +161,32 @@ public static async Task OpenUrlAsync(string path)
currentFile = new(true, path, await reply.Content.ReadAsStreamAsync().ConfigureAwait(false), reply.Headers, reply.Headers.GetValues("icy-name").First());

// If necessary, feed.
PlaybackTools.FeedRadio();
PlaybackTools.FeedRadio(basolia);
}

/// <summary>
/// Closes a currently opened media file
/// </summary>
public static void CloseFile()
public static void CloseFile(BasoliaMedia? basolia)
{
InitBasolia.CheckInited();
if (basolia is null)
throw new BasoliaException("Basolia instance is not provided", mpg123_errors.MPG123_BAD_HANDLE);

// Check to see if the file is open
if (!IsOpened)
throw new BasoliaException("Can't close a file or a radio station that's already closed", mpg123_errors.MPG123_BAD_FILE);

// First, stop the playing song
if (PlaybackTools.State == PlaybackState.Playing || PlaybackTools.State == PlaybackState.Paused)
PlaybackTools.Stop();
var state = PlaybackTools.GetState(basolia);
if (state == PlaybackState.Playing || state == PlaybackState.Paused)
PlaybackTools.Stop(basolia);

// We're now entering the dangerous zone
unsafe
{
// Close the file
var handle = MpgNative._mpg123Handle;
var handle = basolia._mpg123Handle;
var @delegate = MpgNative.GetDelegate<NativeInput.mpg123_close>(MpgNative.libManagerMpg, nameof(NativeInput.mpg123_close));
int closeStatus = @delegate.Invoke(handle);
if (closeStatus == (int)mpg123_errors.MPG123_ERR)
Expand Down
Loading

0 comments on commit 1d0cf74

Please sign in to comment.