faster socket, clean up on plugin

This commit is contained in:
Michal Courson
2026-02-26 17:38:50 -05:00
parent ad07bf7fe6
commit 8c83819a17
16 changed files with 74 additions and 513 deletions

View File

@ -22,11 +22,11 @@
"volume": 0.25 "volume": 0.25
}, },
{ {
"endTime": 27.516843118383072, "endTime": 28.566433566433446,
"filename": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\audio-service\\recordings\\audio_capture_20260220_200442.wav", "filename": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\audio-service\\recordings\\audio_capture_20260220_200442.wav",
"name": "Clip 20260220_200442", "name": "Clip 20260220_200442",
"playbackType": "playOverlap", "playbackType": "playOverlap",
"startTime": 25.120307988450435, "startTime": 25.664335664335663,
"volume": 0.64 "volume": 0.64
} }
] ]

View File

@ -1,7 +1,6 @@
sounddevice==0.5.1 Flask==3.1.3
numpy==1.22.3 flask_cors==6.0.2
python-osc==1.9.3 flask_socketio==5.6.1
scipy==1.10.1 numpy==2.4.2
comtypes==1.4.8 scipy==1.17.1
pycaw==20240210 sounddevice==0.5.5
Flask==3.1.2

View File

@ -19,7 +19,7 @@ import threading
app = Flask(__name__) app = Flask(__name__)
CORS(app) CORS(app)
socketio = SocketIO(app, cors_allowed_origins="*") socketio = SocketIO(app, cors_allowed_origins="*", logger=True, engineio_logger=True, async_mode='eventlet')
@socketio.on('connect') @socketio.on('connect')
def handle_connect(): def handle_connect():
@ -31,6 +31,14 @@ def record_clip(data):
io = AudioIO() io = AudioIO()
io.save_last_n_seconds(); io.save_last_n_seconds();
@socketio.on('play_clip')
def play_clip(data):
io = AudioIO()
print(f"Received play_clip event with data: {data}")
if data:
io.play_clip(data)
def main(): def main():
# Create argument parser # Create argument parser
parser = argparse.ArgumentParser(description='Audio Recording Service') parser = argparse.ArgumentParser(description='Audio Recording Service')
@ -65,8 +73,9 @@ def main():
app.register_blueprint(device_bp) app.register_blueprint(device_bp)
app.register_blueprint(metadata_bp) app.register_blueprint(metadata_bp)
app.register_blueprint(settings_bp) app.register_blueprint(settings_bp)
print(f"Starting Flask server on port {settings.get_settings('http_port')}")
# app.run(host='127.0.0.1', port=settings.get_settings('http_port'), debug=False, use_reloader=True) # app.run(host='127.0.0.1', port=settings.get_settings('http_port'), debug=False, use_reloader=True)
socketio.run(app, host='127.0.0.1', port=settings.get_settings('http_port'), debug=False, use_reloader=True) socketio.run(app, host='127.0.0.1', port=settings.get_settings('http_port'), debug=False, use_reloader=True, allow_unsafe_werkzeug=True)

View File

@ -1,9 +1,5 @@
import sounddevice as sd import sounddevice as sd
import numpy as np import numpy as np
import comtypes
import comtypes.client
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
import json import json
class WindowsAudioManager: class WindowsAudioManager:

View File

@ -112,9 +112,6 @@ const createWindow = async () => {
registerFileIpcHandlers(); registerFileIpcHandlers();
const pythonManager = new PythonSubprocessManager('src/main.py');
pythonManager.start();
// Remove this if your app does not use auto updates // Remove this if your app does not use auto updates
// eslint-disable-next-line // eslint-disable-next-line
new AppUpdater(); new AppUpdater();
@ -135,6 +132,8 @@ app.on('window-all-closed', () => {
app app
.whenReady() .whenReady()
.then(() => { .then(() => {
const pythonManager = new PythonSubprocessManager('src/main.py');
pythonManager.start();
createWindow(); createWindow();
app.on('activate', () => { app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the // On macOS it's common to re-create a window in the app when the

View File

@ -40,7 +40,7 @@ export default class PythonSubprocessManager {
}, },
); );
this.process.stdout.on('data', (data: Buffer) => { this.process.stdout.on('data', (data: Buffer) => {
console.log(`Python stdout: ${data.toString()}`); // console.log(`Python stdout: ${data.toString()}`);
}); });
this.process.stderr.on('data', (data: Buffer) => { this.process.stderr.on('data', (data: Buffer) => {
// console.error(`Python stderr: ${data.toString()}`); // console.error(`Python stderr: ${data.toString()}`);

View File

@ -1,13 +1,14 @@
using System; using BarRaider.SdTools;
using Newtonsoft.Json;
using SocketIOClient;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using static System.Runtime.InteropServices.JavaScript.JSType;
using SocketIOClient;
using BarRaider.SdTools;
using System.Runtime.CompilerServices;
namespace ClipTrimDotNet.Client namespace ClipTrimDotNet.Client
{ {
@ -78,44 +79,32 @@ namespace ClipTrimDotNet.Client
return Task.CompletedTask; return Task.CompletedTask;
}); });
Task.Run(async () => await socket.ConnectAsync()); socket.OnDisconnected += (sender, e) =>
//Task.Run(ShortPoll); {
Logger.Instance.LogMessage(TracingLevel.INFO, $"Socket disconnected: {e}");
Task.Run(async () => await Connect());
};
Task.Run(async () => await Connect());
} }
public async Task Connect()
{
while (!socket.Connected)
{
try
{
await socket.ConnectAsync();
}
catch
{
//public async Task ShortPoll() }
//{ }
// while (true) }
// {
// await GetMetadata();
// await Task.Delay(TimeSpan.FromSeconds(5)); await Task.Delay(TimeSpan.FromSeconds(5));
// }
//}
public List<CollectionMetaData> Collections { get; private set; } = new List<CollectionMetaData>(); public List<CollectionMetaData> Collections { get; private set; } = new List<CollectionMetaData>();
public int SelectedCollection { get; private set; } = -1; public int SelectedCollection { get; private set; } = -1;
public int PageIndex { get; private set; } = 0; public int PageIndex { get; private set; } = 0;
//private async Task GetMetadata()
//{
// try
// {
// var response = await httpClient.GetAsync("meta");
// if (response.IsSuccessStatusCode)
// {
// var json = await response.Content.ReadAsStringAsync();
// dynamic collections = JsonConvert.DeserializeObject(json);
// collections = collections.collections;
// Collections = JsonConvert.DeserializeObject<List<CollectionMetaData>>(collections.ToString());
// }
// }
// catch (Exception ex)
// {
// //Logger.Instance.LogMessage(TracingLevel.INFO, $"Error pinging ClipTrim API: {ex.Message}");
// return;
// }
//}
public List<string> GetCollectionNames() public List<string> GetCollectionNames()
{ {
@ -134,6 +123,7 @@ namespace ClipTrimDotNet.Client
public ClipMetadata? GetClipByPagedIndex(int index) public ClipMetadata? GetClipByPagedIndex(int index)
{ {
SelectedCollection = Collections.FindIndex(x => x.Name == GlobalSettings.Instance.ProfileName);
if (SelectedCollection == -1) return null; if (SelectedCollection == -1) return null;
int clipIndex = PageIndex * 10 + index; int clipIndex = PageIndex * 10 + index;
var collection = Collections[SelectedCollection]; var collection = Collections[SelectedCollection];
@ -147,12 +137,8 @@ namespace ClipTrimDotNet.Client
public async void PlayClip(ClipMetadata? metadata) public async void PlayClip(ClipMetadata? metadata)
{ {
if (metadata == null) return; if (metadata == null) return;
Logger.Instance.LogMessage(TracingLevel.INFO, $"playing clip:");
//var response = await httpClient.PostAsync("playback/start", new StringContent(JsonConvert.SerializeObject(metadata), Encoding.UTF8, "application/json")); await socket.EmitAsync("play_clip", new List<object>() { metadata });
//if (!response.IsSuccessStatusCode)
//{
// //Logger.Instance.LogMessage(TracingLevel.INFO, $"Error playing clip: {response.ReasonPhrase}");
//}
} }
} }
} }

View File

@ -10,28 +10,6 @@ using Newtonsoft.Json.Linq;
namespace ClipTrimDotNet namespace ClipTrimDotNet
{ {
public class FileEntry
{
public FileEntry()
{
Volume = 1.0;
Playtype = "Play/Overlap";
}
[JsonProperty(PropertyName = "Volume")]
public double Volume { get; set; }
[JsonProperty(PropertyName = "Playtype")]
public string Playtype { get; set; }
}
public class CollectionEntry
{
public CollectionEntry()
{
Files = new Dictionary<string, FileEntry>();
}
[JsonProperty(PropertyName = "Files")]
public Dictionary<string, FileEntry> Files { get; set; }
}
public class GlobalSettings public class GlobalSettings
{ {
public static GlobalSettings? _inst; public static GlobalSettings? _inst;
@ -50,59 +28,18 @@ namespace ClipTrimDotNet
public static GlobalSettings CreateDefaultSettings() public static GlobalSettings CreateDefaultSettings()
{ {
GlobalSettings instance = new GlobalSettings(); GlobalSettings instance = new GlobalSettings();
instance.BasePath = null;
instance.ProfileName = null; instance.ProfileName = null;
instance.Collections = new Dictionary<string, CollectionEntry>();
return instance; return instance;
} }
[FilenameProperty]
[JsonProperty(PropertyName = "basePath")]
public string? BasePath { get; set; }
[JsonProperty(PropertyName = "profileName")] [JsonProperty(PropertyName = "profileName")]
public string? ProfileName { get; set; } public string? ProfileName { get; set; }
[JsonProperty(PropertyName = "outputDevice")]
public string? OutputDevice { get; set; }
[JsonProperty(PropertyName = "collections")]
public Dictionary<string, CollectionEntry> Collections { get; set; }
public void SetCurrentProfile(string profile) public void SetCurrentProfile(string profile)
{ {
ProfileName = profile; ProfileName = profile;
if(!Collections.ContainsKey(profile))
{
Collections.Add(profile, new CollectionEntry());
}
}
public FileEntry GetFileOptionsInCurrentProfile(string filename)
{
if(!Collections.TryGetValue(ProfileName, out CollectionEntry collection))
{
return new FileEntry();
}
if(!collection.Files.TryGetValue(filename, out FileEntry file))
{
return new FileEntry();
}
//Logger.Instance.LogMessage(TracingLevel.INFO, "fetched file settings " + filename + JsonConvert.SerializeObject(file));
return file;
}
public void SetFileOptionsCurrentProfile(string filename, FileEntry file)
{
//Logger.Instance.LogMessage(TracingLevel.INFO, "SetFileOptionsCurrentProfile ");
if (!Collections.TryGetValue(ProfileName, out CollectionEntry collection))
{
return;
}
//Logger.Instance.LogMessage(TracingLevel.INFO, "SetFileOptionsCurrentProfile 2");
//collection.Files[filename] = file;
Collections[ProfileName].Files[filename] = file;
} }
} }
} }

View File

@ -20,53 +20,15 @@ namespace ClipTrimDotNet
private ClipMetadata? metadata; private ClipMetadata? metadata;
private KeyCoordinates coordinates; private KeyCoordinates coordinates;
private class PluginSettings
{
public static PluginSettings CreateDefaultSettings()
{
PluginSettings instance = new PluginSettings();
instance.Path = null;
instance.PlayType = "Play/Overlap";
instance.Index = 0;
instance.Volume = 1;
return instance;
}
[FilenameProperty]
[JsonPropertyName("path")]
public string? Path { get; set; }
[JsonPropertyName("index")]
public int? Index { get; set; }
[JsonPropertyName("playtype")]
public string PlayType { get; set; }
[JsonPropertyName("volume")]
public double Volume { get; set; }
}
#region Private Members
private PluginSettings settings;
#endregion
public Player(SDConnection connection, InitialPayload payload) : base(connection, payload) public Player(SDConnection connection, InitialPayload payload) : base(connection, payload)
{ {
if (payload.Settings == null || payload.Settings.Count == 0)
{
this.settings = PluginSettings.CreateDefaultSettings();
SaveSettings();
}
else
{
this.settings = payload.Settings.ToObject<PluginSettings>();
}
this.coordinates = payload.Coordinates; this.coordinates = payload.Coordinates;
GlobalSettingsManager.Instance.RequestGlobalSettings(); GlobalSettingsManager.Instance.RequestGlobalSettings();
CheckFile(); CheckFile();
} }
private void Instance_OnReceivedGlobalSettings(object sender, ReceivedGlobalSettingsPayload e) public void Instance_OnReceivedGlobalSettings(object sender, ReceivedGlobalSettingsPayload e)
{ {
Tools.AutoPopulateSettings(GlobalSettings.Instance, e.Settings); Tools.AutoPopulateSettings(GlobalSettings.Instance, e.Settings);
} }
@ -78,77 +40,17 @@ namespace ClipTrimDotNet
private async void CheckFile() private async void CheckFile()
{ {
//if (settings == null || GlobalSettings.Instance.ProfileName ==null) return;
metadata = ClipTrimClient.Instance.GetClipByPagedIndex(GetIndex()); metadata = ClipTrimClient.Instance.GetClipByPagedIndex(GetIndex());
await Connection.SetTitleAsync($"{metadata?.Name ?? ""}"); await Connection.SetTitleAsync($"{metadata?.Name ?? ""}");
//Logger.Instance.LogMessage(TracingLevel.INFO, $"Set title to {metadata?.Name ?? ""}");
return;
//var files = Directory.GetFiles(Path.Combine(Path.GetDirectoryName(GlobalSettings.Instance.BasePath), GlobalSettings.Instance.ProfileName), "*.wav", SearchOption.TopDirectoryOnly)
// .OrderBy(file => File.GetCreationTime(file))
// .ToArray();
//int? i = this.settings.Index;
//string new_path = "";
//if (i != null && i >= 0 && i < files.Length)
//{
// new_path = files[i ?? 0];
//}
//await Connection.SetTitleAsync(Path.GetFileNameWithoutExtension(new_path));
//if (new_path != settings.Path)
//{
// settings.Path = new_path;
// if(new_path != "")
// {
// FileEntry opts = GlobalSettings.Instance.GetFileOptionsInCurrentProfile(new_path);
// settings.Volume = opts.Volume;
// settings.PlayType = opts.Playtype;
// }
// await SaveSettings();
//}
}
private async void Connection_OnApplicationDidLaunch(object sender, BarRaider.SdTools.Wrappers.SDEventReceivedEventArgs<BarRaider.SdTools.Events.ApplicationDidLaunch> e)
{
}
private void Connection_OnTitleParametersDidChange(object sender, SDEventReceivedEventArgs<BarRaider.SdTools.Events.TitleParametersDidChange> e)
{
//titleParameters = e.Event?.Payload?.TitleParameters;
//userTitle = e.Event?.Payload?.Title;
} }
public override void Dispose() public override void Dispose()
{ {
Connection.OnTitleParametersDidChange -= Connection_OnTitleParametersDidChange;
Connection.OnApplicationDidLaunch -= Connection_OnApplicationDidLaunch;
//Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called");
} }
public override void KeyPressed(KeyPayload payload) public override void KeyPressed(KeyPayload payload)
{ {
//Logger.Instance.LogMessage(TracingLevel.INFO, "Key Pressedd");
Tools.AutoPopulateSettings(settings, payload.Settings);
// Logger.Instance.LogMessage(TracingLevel.INFO, JsonConvert.SerializeObject(settings));
ClipTrimClient.Instance.PlayClip(metadata); ClipTrimClient.Instance.PlayClip(metadata);
//try
//{
// WavPlayer.Instance.Play(settings.Path, GlobalSettings.Instance.OutputDevice, settings.Volume, settings.PlayType == "Play/Overlap" ? WavPlayer.PlayMode.PlayOverlap : WavPlayer.PlayMode.PlayStop);
//}
//catch
//{
//}
}
public override void KeyReleased(KeyPayload payload) {
} }
@ -156,19 +58,8 @@ namespace ClipTrimDotNet
CheckFile(); CheckFile();
} }
public override async void ReceivedSettings(ReceivedSettingsPayload payload)
{
//Logger.Instance.LogMessage(TracingLevel.INFO, "Player rec settings");
Tools.AutoPopulateSettings(settings, payload.Settings);
GlobalSettings.Instance.SetFileOptionsCurrentProfile(settings.Path, new FileEntry() { Playtype = settings.PlayType, Volume = settings.Volume });
await Connection.SetGlobalSettingsAsync(JObject.FromObject(GlobalSettings.Instance));
//SaveSettings();
//CheckFile();
}
public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) {
//Logger.Instance.LogMessage(TracingLevel.INFO, "ReceivedGlobalSettings");
if (payload.Settings == null || payload.Settings.Count == 0) if (payload.Settings == null || payload.Settings.Count == 0)
{ {
var inst = GlobalSettings.Instance; var inst = GlobalSettings.Instance;
@ -178,17 +69,17 @@ namespace ClipTrimDotNet
{ {
GlobalSettings.Instance = payload.Settings.ToObject<GlobalSettings>(); GlobalSettings.Instance = payload.Settings.ToObject<GlobalSettings>();
} }
//CheckFile();
} }
#region Private Methods public override void KeyReleased(KeyPayload payload)
private Task SaveSettings()
{ {
return Connection.SetSettingsAsync(JObject.FromObject(settings));
}
public override void ReceivedSettings(ReceivedSettingsPayload payload)
{
} }
#endregion
} }
} }

View File

@ -49,7 +49,7 @@ namespace ClipTrimDotNet
} }
else else
{ {
this.settings = payload.Settings.ToObject<PluginSettings>(); this.settings = payload.Settings.ToObject<PluginSettings>()!;
} }
GlobalSettingsManager.Instance.RequestGlobalSettings(); GlobalSettingsManager.Instance.RequestGlobalSettings();
Connection.OnSendToPlugin += Connection_OnSendToPlugin; Connection.OnSendToPlugin += Connection_OnSendToPlugin;
@ -62,57 +62,33 @@ namespace ClipTrimDotNet
await Connection.SetTitleAsync(settings.ProfileName + " B"); await Connection.SetTitleAsync(settings.ProfileName + " B");
} }
private async void Connection_OnSendToPlugin(object sender, SDEventReceivedEventArgs<BarRaider.SdTools.Events.SendToPlugin> e) private async void Connection_OnSendToPlugin(object? sender, SDEventReceivedEventArgs<BarRaider.SdTools.Events.SendToPlugin> e)
{ {
//Logger.Instance.LogMessage(TracingLevel.INFO, "get profiles"); //Logger.Instance.LogMessage(TracingLevel.INFO, "get profiles");
if (e.Event.Payload["event"].ToString() == "getProfiles") if (e.Event.Payload["event"] is null) return;
if (e.Event.Payload["event"]!.ToString() == "getProfiles")
{ {
//string basePath = "C:\\Users\\mickl\\Music\\clips";
//var files = Directory.GetDirectories(basePath, "*", SearchOption.TopDirectoryOnly).Select(x => Path.GetFileNameWithoutExtension(x)).Where(x => x != "original");
var files = ClipTrimClient.Instance.GetCollectionNames(); var files = ClipTrimClient.Instance.GetCollectionNames();
var items = files.Select(x => new DataSourceItem { label = x, value = x}); var items = files.Select(x => new DataSourceItem { label = x, value = x});
var obj = new JObject(); var obj = new JObject
obj["event"] = "getProfiles"; {
obj["items"] = JArray.FromObject(items); ["event"] = "getProfiles",
//Logger.Instance.LogMessage(TracingLevel.INFO, "get profiles return " + JsonConvert.SerializeObject(obj)); ["items"] = JArray.FromObject(items)
};
await Connection.SendToPropertyInspectorAsync(obj); await Connection.SendToPropertyInspectorAsync(obj);
} }
//if (e.Event.Payload["event"].ToString() == "getOutputDevices")
//{
// List<WaveOutCapabilities> devices = new List<WaveOutCapabilities>();
// for (int n = -1; n < WaveOut.DeviceCount; n++)
// {
// var caps = WaveOut.GetCapabilities(n);
// devices.Add(caps);
// }
// var items = devices.Select(x => new DataSourceItem { label = x.ProductName, value = x.ProductName });
// var obj = new JObject();
// obj["event"] = "getOutputDevices";
// obj["items"] = JArray.FromObject(items);
// //Logger.Instance.LogMessage(TracingLevel.INFO, "get devices return " + JsonConvert.SerializeObject(obj));
// await Connection.SendToPropertyInspectorAsync(obj);
//}
} }
private void Connection_OnTitleParametersDidChange(object sender, SDEventReceivedEventArgs<BarRaider.SdTools.Events.TitleParametersDidChange> e)
{
}
public override void Dispose() public override void Dispose()
{ {
Connection.OnTitleParametersDidChange -= Connection_OnTitleParametersDidChange;
//Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called");
} }
public override async void KeyPressed(KeyPayload payload) public override async void KeyPressed(KeyPayload payload)
{ {
//Logger.Instance.LogMessage(TracingLevel.INFO, "KeyPressed"); GlobalSettings.Instance.SetCurrentProfile(settings.ProfileName??"");
//Logger.Instance.LogMessage(TracingLevel.INFO, JsonConvert.SerializeObject(settings));
//Logger.Instance.LogMessage(TracingLevel.INFO, JsonConvert.SerializeObject(GlobalSettings.Instance));
ClipTrimClient.Instance.SetSelectedCollectionByName(settings.ProfileName);
GlobalSettings.Instance.SetCurrentProfile(settings.ProfileName);
//Logger.Instance.LogMessage(TracingLevel.INFO, JsonConvert.SerializeObject(GlobalSettings.Instance));
await Connection.SetGlobalSettingsAsync(JObject.FromObject(GlobalSettings.Instance)); await Connection.SetGlobalSettingsAsync(JObject.FromObject(GlobalSettings.Instance));
await Connection.SwitchProfileAsync("ClipTrim"); await Connection.SwitchProfileAsync("ClipTrim");
@ -132,25 +108,18 @@ namespace ClipTrimDotNet
{ {
Tools.AutoPopulateSettings(settings, payload.Settings); Tools.AutoPopulateSettings(settings, payload.Settings);
SaveSettings(); SaveSettings();
//tTitle();
//CheckFile();
} }
public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload)
{ {
//Logger.Instance.LogMessage(TracingLevel.INFO, "ReceivedGlobalSettings");
if (payload.Settings == null || payload.Settings.Count == 0) if (payload.Settings == null || payload.Settings.Count == 0)
{ {
var inst = GlobalSettings.Instance; var inst = GlobalSettings.Instance;
//GlobalSettingsManager.Instance.SetGlobalSettings(JObject.FromObject(inst));
} }
else else
{ {
GlobalSettings.Instance = payload.Settings.ToObject<GlobalSettings>(); GlobalSettings.Instance = payload.Settings.ToObject<GlobalSettings>();
} }
//CheckFile();
} }
#region Private Methods #region Private Methods

View File

@ -11,7 +11,7 @@
<!-- <!--
Learn more about property inspector components at https://sdpi-components.dev/docs/components Learn more about property inspector components at https://sdpi-components.dev/docs/components
--> -->
<sdpi-item label="Index"> <!--<sdpi-item label="Index">
<sdpi-select setting="index" placeholder="file index"> <sdpi-select setting="index" placeholder="file index">
<option value="0">0</option> <option value="0">0</option>
<option value="1">1</option> <option value="1">1</option>
@ -39,7 +39,7 @@
</sdpi-item> </sdpi-item>
<sdpi-item label="Volume"> <sdpi-item label="Volume">
<sdpi-range setting="volume" min=".1" max="1" , step="0.05"></sdpi-range> <sdpi-range setting="volume" min=".1" max="1" , step="0.05"></sdpi-range>
</sdpi-item> </sdpi-item>-->
</body> </body>
</html> </html>

View File

@ -16,7 +16,7 @@
show-refresh="true" show-refresh="true"
placeholder="Select a ClipTrim page"></sdpi-select> placeholder="Select a ClipTrim page"></sdpi-select>
</sdpi-item> </sdpi-item>
<sdpi-item label="Base Path"> <!--<sdpi-item label="Base Path">
<sdpi-file setting="basePath" <sdpi-file setting="basePath"
global="true" global="true"
webkitdirectory webkitdirectory
@ -29,6 +29,6 @@
datasource="getOutputDevices" datasource="getOutputDevices"
show-refresh="true" show-refresh="true"
placeholder="Select an Ouput Device"></sdpi-select> placeholder="Select an Ouput Device"></sdpi-select>
</sdpi-item> </sdpi-item>-->
</body> </body>
</html> </html>

View File

@ -1,225 +0,0 @@
//using System;
//using System.Collections.Concurrent;
//using System.Collections.Generic;
//using System.Linq;
//using System.ServiceModel.Security;
//using System.Threading.Tasks;
//using BarRaider.SdTools;
//using NAudio.Wave;
//using NAudio.Wave.SampleProviders;
//using Newtonsoft.Json;
//class CachedSound
//{
// public byte[] AudioData { get; private set; }
// public WaveFormat WaveFormat { get; private set; }
// public CachedSound(string audioFileName)
// {
// using (var audioFileReader = new AudioFileReader(audioFileName))
// {
// // TODO: could add resampling in here if required
// WaveFormat = audioFileReader.WaveFormat;
// var wholeFile = new List<byte>((int)(audioFileReader.Length));
// var readBuffer = new byte[audioFileReader.WaveFormat.SampleRate * audioFileReader.WaveFormat.Channels*4];
// int samplesRead;
// while ((samplesRead = audioFileReader.Read(readBuffer, 0, readBuffer.Length)) > 0)
// {
// wholeFile.AddRange(readBuffer.Take(samplesRead));
// }
// AudioData = wholeFile.ToArray();
// }
// //Logger.Instance.LogMessage(TracingLevel.INFO, $"AudioData Length {AudioData.Length}");
// }
//}
//class CachedSoundSampleProvider : IWaveProvider
//{
// private readonly CachedSound cachedSound;
// private long position;
// ~CachedSoundSampleProvider() {
// //Logger.Instance.LogMessage(TracingLevel.INFO, $"Cache destructor");
// }
// public CachedSoundSampleProvider(CachedSound cachedSound)
// {
// this.cachedSound = cachedSound;
// position = 0;
// }
// public int Read(byte[] buffer, int offset, int count)
// {
// //Logger.Instance.LogMessage(TracingLevel.INFO, $"Read1 byte");
// var availableSamples = cachedSound.AudioData.Length - position;
// var samplesToCopy = Math.Min(availableSamples, count);
// try
// {
// //Logger.Instance.LogMessage(TracingLevel.INFO, $"{cachedSound.AudioData.GetType()} {buffer.GetType()}");
// Array.Copy(cachedSound.AudioData, position, buffer, offset, samplesToCopy);
// }
// catch (Exception ex)
// {
// //Logger.Instance.LogMessage(TracingLevel.INFO, $"{ex.ToString()}");
// }
// //Logger.Instance.LogMessage(TracingLevel.INFO, $"Read3");
// position += samplesToCopy;
// //Logger.Instance.LogMessage(TracingLevel.INFO, $"Sending {samplesToCopy} samples");
// return (int)samplesToCopy;
// }
// public WaveFormat WaveFormat => cachedSound.WaveFormat;
//}
//public class WavPlayer
//{
// private static WavPlayer? instance;
// public static WavPlayer Instance
// {
// get
// {
// instance ??= new WavPlayer();
// return instance;
// }
// }
// public enum PlayMode
// {
// PlayOverlap,
// PlayStop
// }
// private readonly ConcurrentDictionary<string, List<Tuple<WaveOutEvent, IWaveProvider>>> _activePlayers;
// public WavPlayer()
// {
// _activePlayers = new ConcurrentDictionary<string, List<Tuple<WaveOutEvent, IWaveProvider>>>();
// }
// public void Play(string filePath, string id, double volume, PlayMode mode)
// {
// if (string.IsNullOrWhiteSpace(filePath))
// throw new ArgumentException("File path cannot be null or empty.", nameof(filePath));
// if (mode == PlayMode.PlayOverlap)
// {
// PlayWithOverlap(filePath, id, volume);
// }
// else if (mode == PlayMode.PlayStop)
// {
// PlayWithStop(filePath, id, volume);
// }
// else
// {
// throw new ArgumentOutOfRangeException(nameof(mode), "Invalid play mode specified.");
// }
// }
// private void PlayWithOverlap(string filePath, string id, double volume)
// {
// try
// {
// //Logger.Instance.LogMessage(TracingLevel.INFO, "Play overlap");
// var player = CreatePlayer(filePath, id);
// if (!_activePlayers.ContainsKey(filePath))
// {
// _activePlayers[filePath] = new List<Tuple<WaveOutEvent, IWaveProvider>>();
// }
// _activePlayers[filePath].Add(player);
// player.Item1.Volume = (float)volume;
// player.Item1.Play();
// }
// catch(Exception ex)
// {
// //Logger.Instance.LogMessage(TracingLevel.INFO, ex.ToString());
// }
// //var playersToDispose = _activePlayers[filePath].Where(x => x.Item1.PlaybackState == PlaybackState.Stopped).ToList();
// //foreach (var p in playersToDispose)
// //{
// // p.Item1.Stop();
// // p.Item1.Dispose();
// //}
// //_activePlayers[filePath].RemoveAll(x => x.Item1.PlaybackState == PlaybackState.Stopped);
// }
// private void PlayWithStop(string filePath, string id, double volume)
// {
// if (_activePlayers.TryGetValue(filePath, out var players))
// {
// // Stop and dispose all current players for this file
// if (players.Any(x => x.Item1.PlaybackState == PlaybackState.Playing))
// {
// var playersToDispose = players.ToList();
// foreach (var player in playersToDispose)
// {
// player.Item1.Stop();
// player.Item1.Dispose();
// }
// }
// else
// {
// PlayWithOverlap(filePath, id, volume);
// }
// }
// else
// {
// // Start a new player
// PlayWithOverlap(filePath, id, volume);
// }
// _activePlayers[filePath].RemoveAll(x => x.Item1.PlaybackState == PlaybackState.Stopped);
// }
// private Tuple<WaveOutEvent, IWaveProvider> CreatePlayer(string filePath, string name)
// {
// var reader = new CachedSoundSampleProvider(new CachedSound(filePath));
// //var reader = new AudioFileReader(filePath);
// int number = -1;
// for (int i = 0; i < WaveOut.DeviceCount; ++i)
// {
// if (WaveOut.GetCapabilities(i).ProductName == name)
// {
// number = i;
// }
// }
// var player = new WaveOutEvent() { DeviceNumber = number };
// player.Init(reader);
// return new Tuple<WaveOutEvent, IWaveProvider>(player, reader);
// }
// private void CleanupPlayer(string filePath)
// {
// if (_activePlayers.TryGetValue(filePath, out var players))
// {
// var playersToDispose = players.ToList();
// foreach (var p in playersToDispose)
// {
// p.Item1.Stop();
// p.Item1.Dispose();
// }
// }
// _activePlayers[filePath].RemoveAll(x => x.Item1.PlaybackState == PlaybackState.Stopped);
// }
// public void StopAll()
// {
// foreach (var players in _activePlayers.Values)
// {
// var playersToDispose = players.ToList();
// foreach (var player in playersToDispose)
// {
// player.Item1.Stop();
// player.Item1.Dispose();
// }
// players.Clear();
// }
// _activePlayers.Clear();
// }
//}