From 6699a0c8ff7188f31d52f6ceaac2fb3250b1961d Mon Sep 17 00:00:00 2001 From: jwallet Date: Fri, 3 Jan 2020 22:24:40 -0500 Subject: [PATCH] Output file to spytify to only transcode to mp3 at the end of the recording now able to record proper mp3 on power saver mode - close issue #92 related issue #102 --- EspionSpotify/MediaTags/MP3Tags.cs | 19 +++- EspionSpotify/Models/OutputFile.cs | 52 +++++++++ EspionSpotify/Recorder.cs | 172 +++++++++++++++++------------ 3 files changed, 169 insertions(+), 74 deletions(-) create mode 100644 EspionSpotify/Models/OutputFile.cs diff --git a/EspionSpotify/MediaTags/MP3Tags.cs b/EspionSpotify/MediaTags/MP3Tags.cs index 759ce23d..b2c4c439 100644 --- a/EspionSpotify/MediaTags/MP3Tags.cs +++ b/EspionSpotify/MediaTags/MP3Tags.cs @@ -17,13 +17,10 @@ public async Task SaveMediaTags() { var mp3 = TagLib.File.Create(CurrentFile); - if (OrderNumberInMediaTagEnabled && Count.HasValue) - { - mp3.Tag.Track = (uint)Count.Value; - } - else if (Track.AlbumPosition != null) + var trackNumber = GetTrackNumber(); + if (trackNumber.HasValue) { - mp3.Tag.Track = (uint)Track.AlbumPosition; + mp3.Tag.Track = (uint)trackNumber.Value; } mp3.Tag.Title = Track.Title; @@ -64,6 +61,16 @@ public async Task SaveMediaTags() mp3.Dispose(); } + private int? GetTrackNumber() + { + if (OrderNumberInMediaTagEnabled && Count.HasValue) + { + return Count.Value; + } + + return Track.AlbumPosition; + } + private TagLib.Picture GetAlbumCoverToPicture(byte[] data) { if (data == null) return new TagLib.Picture(); diff --git a/EspionSpotify/Models/OutputFile.cs b/EspionSpotify/Models/OutputFile.cs new file mode 100644 index 00000000..6846d344 --- /dev/null +++ b/EspionSpotify/Models/OutputFile.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EspionSpotify.Models +{ + public class OutputFile + { + private const string SPYTIFY = "spytify"; + private const int FIRST_SONG_NAME_COUNT = 1; + + + public string Path { get; set; } + public string File { get; set; } + public int Count { get; private set; } + public string Separator { get; set; } + public string Extension { get; set; } + + public OutputFile() + { + Count = FIRST_SONG_NAME_COUNT; + } + + public void Increment() + { + Count++; + } + + public override string ToString() + { + + return $@"{Path}\{File}{GetAddedCount()}.{Extension}"; + } + + public string ToPendingFileString() + { + return $@"{Path}\{File}{GetAddedCount()}.{SPYTIFY}"; + } + + public string ToTranscodingToMP3String() + { + return $@"{Path}\{File}{GetAddedCount()}.{Extension}.{SPYTIFY}"; + } + + private string GetAddedCount() + { + return Count > FIRST_SONG_NAME_COUNT ? $"{Separator}{Count}" : ""; + } + } +} diff --git a/EspionSpotify/Recorder.cs b/EspionSpotify/Recorder.cs index 2585bcf9..14c1edf6 100644 --- a/EspionSpotify/Recorder.cs +++ b/EspionSpotify/Recorder.cs @@ -9,7 +9,7 @@ namespace EspionSpotify { - internal class Recorder: IRecorder + internal class Recorder : IRecorder { public int CountSeconds { get; set; } public bool Running { get; set; } @@ -17,8 +17,7 @@ internal class Recorder: IRecorder private readonly UserSettings _userSettings; private readonly Track _track; private readonly IFrmEspionSpotify _form; - private string _currentFile; - private string _currentFilePending; + private OutputFile _currentOutputFile; private WasapiLoopbackCapture _waveIn; private Stream _writer; private readonly FileManager _fileManager; @@ -44,10 +43,9 @@ public async void Run() _waveIn.DataAvailable += WaveIn_DataAvailable; _waveIn.RecordingStopped += WaveIn_RecordingStopped; - _currentFile = _fileManager.BuildFileName(_userSettings.OutputPath); - _currentFilePending = _fileManager.BuildSpytifyFileName(_currentFile); + _currentOutputFile = _fileManager.GetOutputFile(_userSettings.OutputPath); - _writer = GetFileWriter(_currentFilePending, _waveIn, _userSettings); + _writer = new WaveFileWriter(_currentOutputFile.ToPendingFileString(), _waveIn.WaveFormat); if (_writer == null) { @@ -56,7 +54,7 @@ public async void Run() } _waveIn.StartRecording(); - _form.WriteIntoConsole("logRecording", _fileManager.GetFileName(_currentFile)); + _form.WriteIntoConsole("logRecording", _currentOutputFile.File); while (Running) { @@ -66,107 +64,145 @@ public async void Run() _waveIn.StopRecording(); } - private void WaveIn_DataAvailable(object sender, WaveInEventArgs e) + private async void WaveIn_DataAvailable(object sender, WaveInEventArgs e) { // TODO: add buffer handler from argument - _writer.Write(e.Buffer, 0, e.BytesRecorded); + if (_writer != null) await _writer.WriteAsync(e.Buffer, 0, e.BytesRecorded); } - private void WaveIn_RecordingStopped(object sender, StoppedEventArgs e) + private async void WaveIn_RecordingStopped(object sender, StoppedEventArgs e) { if (_writer != null) { - _writer.Flush(); - _waveIn.Dispose(); + await _writer.FlushAsync(); _writer.Dispose(); + _waveIn.Dispose(); } if (CountSeconds < _userSettings.MinimumRecordedLengthSeconds) { - _form.WriteIntoConsole("logDeleting", _fileManager.GetFileName(_currentFile), _userSettings.MinimumRecordedLengthSeconds); - _fileManager.DeleteFile(_currentFilePending); + _form.WriteIntoConsole("logDeleting", _currentOutputFile.File, _userSettings.MinimumRecordedLengthSeconds); + _fileManager.DeleteFile(_currentOutputFile.ToPendingFileString()); return; } var length = TimeSpan.FromSeconds(CountSeconds).ToString(@"mm\:ss"); _form.WriteIntoConsole("logRecorded", _track.ToString(), length); - _fileManager.Rename(_currentFilePending, _currentFile); - - if (!_userSettings.MediaFormat.Equals(MediaFormat.Mp3)) return; - - var mp3TagsInfo = new MediaTags.MP3Tags() - { - Track = _track, - OrderNumberInMediaTagEnabled = _userSettings.OrderNumberInMediaTagEnabled, - Count = _userSettings.OrderNumber, - CurrentFile = _currentFile - }; - - Task.Run(async () => await mp3TagsInfo.SaveMediaTags()); + await UpdateOutputFileBasedOnMediaFormat(); } - private Stream GetFileWriter(string file, WasapiLoopbackCapture waveIn, UserSettings settings) + private Stream GetFileWriter(string file, WaveFormat waveFormat, UserSettings settings) { - if (settings.MediaFormat.Equals(MediaFormat.Mp3)) + switch (settings.MediaFormat) { - try - { - return new LameMP3FileWriter(file, waveIn.WaveFormat, settings.Bitrate); - } - catch (ArgumentException ex) - { - var resource = "logUnknownException"; - var args = ex.Message; - - if (!Directory.Exists(settings.OutputPath)) - { - resource = "logInvalidOutput"; - } - else if (ex.Message.StartsWith("Unsupported Sample Rate")) + case MediaFormat.Mp3: + try { - resource = "logUnsupportedRate"; + return new LameMP3FileWriter(file, waveFormat, settings.Bitrate); } - else if (ex.Message.StartsWith("Access to the path")) + catch (ArgumentException ex) { - resource = "logNoAccessOutput"; + LogLameMP3FileWriterArgumentException(ex, settings.OutputPath); + return null; } - else if (ex.Message.StartsWith("Unsupported number of channels")) + catch (Exception ex) { - var numberOfChannels = ex.Message.Length > 32 ? ex.Message.Remove(0, 31) : "?"; - var indexOfBreakLine = numberOfChannels.IndexOf("\r\n"); - numberOfChannels = numberOfChannels.Substring(0, indexOfBreakLine != -1 ? indexOfBreakLine : 0); - resource = "logUnsupportedNumberChannels"; - args = numberOfChannels; + LogLameMP3FileWriterException(ex); + return null; } - - _form.WriteIntoConsole(resource, args); - return null; - } - catch (Exception ex) - { - if (ex.Message.Contains("Unable to load DLL")) + case MediaFormat.Wav: + try { - _form.WriteIntoConsole("logMissingDlls"); + return new WaveFileWriter(file, waveFormat); } - else + catch (Exception ex) { _form.WriteIntoConsole("logUnknownException", ex.Message); + Console.WriteLine(ex.Message); + return null; } - Console.WriteLine(ex.Message); + default: return null; - } + } + } + + private async Task UpdateOutputFileBasedOnMediaFormat() + { + switch (_userSettings.MediaFormat) + { + case MediaFormat.Wav: + _fileManager.Rename(_currentOutputFile.ToPendingFileString(), _currentOutputFile.ToString()); + return; + case MediaFormat.Mp3: + using (var reader = new WaveFileReader(_currentOutputFile.ToPendingFileString())) + { + using (var writer = GetFileWriter(_currentOutputFile.ToTranscodingToMP3String(), _waveIn.WaveFormat, _userSettings)) + { + await reader.CopyToAsync(writer); + await writer.FlushAsync(); + } + } + + _fileManager.DeleteFile(_currentOutputFile.ToPendingFileString()); + _fileManager.Rename(_currentOutputFile.ToTranscodingToMP3String(), _currentOutputFile.ToString()); + + var mp3TagsInfo = new MediaTags.MP3Tags() + { + Track = _track, + OrderNumberInMediaTagEnabled = _userSettings.OrderNumberInMediaTagEnabled, + Count = _userSettings.OrderNumber, + CurrentFile = _currentOutputFile.ToString() + }; + await mp3TagsInfo.SaveMediaTags(); + + return; + default: + return; + } + } + + private void LogLameMP3FileWriterArgumentException(ArgumentException ex, string outputPath) + { + var resource = "logUnknownException"; + var args = ex.Message; + + if (!Directory.Exists(outputPath)) + { + resource = "logInvalidOutput"; + } + else if (ex.Message.StartsWith("Unsupported Sample Rate")) + { + resource = "logUnsupportedRate"; + } + else if (ex.Message.StartsWith("Access to the path")) + { + resource = "logNoAccessOutput"; + } + else if (ex.Message.StartsWith("Unsupported number of channels")) + { + var numberOfChannels = ex.Message.Length > 32 ? ex.Message.Remove(0, 31) : "?"; + var indexOfBreakLine = numberOfChannels.IndexOf("\r\n"); + numberOfChannels = numberOfChannels.Substring(0, indexOfBreakLine != -1 ? indexOfBreakLine : 0); + resource = "logUnsupportedNumberChannels"; + args = numberOfChannels; } - try + _form.WriteIntoConsole(resource, args); + } + + private void LogLameMP3FileWriterException(Exception ex) + { + if (ex.Message.Contains("Unable to load DLL")) { - return new WaveFileWriter(file, waveIn.WaveFormat); + _form.WriteIntoConsole("logMissingDlls"); } - catch (Exception ex) + else { - Console.WriteLine(ex.Message); - return null; + _form.WriteIntoConsole("logUnknownException", ex.Message); } + + Console.WriteLine(ex.Message); } } }