diff --git a/lib/wavesync.rb b/lib/wavesync.rb index 67e2239..38a3a36 100644 --- a/lib/wavesync.rb +++ b/lib/wavesync.rb @@ -9,6 +9,7 @@ module Wavesync require 'wavesync/device' require 'wavesync/ui' require 'wavesync/path_resolver' +require 'wavesync/file_converter' require 'wavesync/scanner' require 'wavesync/bpm_detector' require 'wavesync/analyzer' diff --git a/lib/wavesync/file_converter.rb b/lib/wavesync/file_converter.rb new file mode 100644 index 0000000..23e37e6 --- /dev/null +++ b/lib/wavesync/file_converter.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module Wavesync + class FileConverter + def convert(audio, source_file_path, path_resolver, target_file_type, _source_sample_rate, + target_sample_rate, source_bit_depth, target_bit_depth, &before_transcode) + return false unless target_file_type || target_sample_rate || target_bit_depth + + target_path = path_resolver.resolve(source_file_path, audio, target_file_type: target_file_type) + + files_to_cleanup = path_resolver.find_files_to_cleanup(target_path, audio) + files_to_cleanup.each { |file| FileUtils.rm_f(file) } + + if target_file_type + source_converted_path = Pathname(source_file_path).sub_ext(".#{target_file_type}") + return false if source_converted_path.exist? + end + + return false if target_path.exist? + + target_path.dirname.mkpath + before_transcode&.call + + audio.transcode(target_path.to_s, target_sample_rate: target_sample_rate, + target_file_type: target_file_type, + target_bit_depth: target_bit_depth || source_bit_depth) + + true + end + end +end diff --git a/lib/wavesync/scanner.rb b/lib/wavesync/scanner.rb index 5a487ea..0d2893a 100644 --- a/lib/wavesync/scanner.rb +++ b/lib/wavesync/scanner.rb @@ -2,6 +2,7 @@ require 'fileutils' require 'streamio-ffmpeg' +require_relative 'file_converter' module Wavesync class Scanner @@ -9,6 +10,7 @@ def initialize(source_library_path) @source_library_path = File.expand_path(source_library_path) @audio_files = find_audio_files @ui = Wavesync::UI.new + @converter = FileConverter.new FFMPEG.logger = Logger.new(File::NULL) end @@ -31,8 +33,12 @@ def sync(target_library_path, device) @ui.file_progress(file) if file_type || target_sample_rate || target_bit_depth - converted = convert_file(audio, file, path_resolver, file_type, source_sample_rate, - target_sample_rate, source_bit_depth, target_bit_depth) + converted = @converter.convert(audio, file, path_resolver, file_type, source_sample_rate, + target_sample_rate, source_bit_depth, target_bit_depth) do + source_file_type = File.extname(file).delete_prefix('.') + @ui.conversion_progress(source_sample_rate, target_sample_rate, source_bit_depth, + source_file_type, file_type, target_bit_depth) + end target_path = path_resolver.resolve(file, audio, target_file_type: file_type) else copied = copy_file(audio, file, path_resolver) @@ -84,28 +90,5 @@ def safe_copy(source, target) rescue Errno::ENOENT puts 'Errno::ENOENT' end - - def convert_file(audio, source_file_path, path_resolver, target_file_type, source_sample_rate, - target_sample_rate, source_bit_depth, target_bit_depth) - return false unless target_file_type || target_sample_rate || target_bit_depth - - target_path = path_resolver.resolve(source_file_path, audio, target_file_type: target_file_type) - - files_to_cleanup = path_resolver.find_files_to_cleanup(target_path, audio) - files_to_cleanup.each { |file| FileUtils.rm_f(file) } - - return false if target_path.exist? - - target_path.dirname.mkpath - source_file_type = File.extname(source_file_path).delete_prefix('.') - @ui.conversion_progress(source_sample_rate, target_sample_rate, source_bit_depth, source_file_type, - target_file_type, target_bit_depth) - - audio.transcode(target_path.to_s, target_sample_rate: target_sample_rate, - target_file_type: target_file_type, - target_bit_depth: target_bit_depth || source_bit_depth) - - true - end end end diff --git a/test/wavesync/file_converter_test.rb b/test/wavesync/file_converter_test.rb new file mode 100644 index 0000000..d1ad29c --- /dev/null +++ b/test/wavesync/file_converter_test.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +require_relative 'test_case' +require_relative '../../lib/wavesync/file_converter' +require_relative '../../lib/wavesync/path_resolver' +require_relative '../../lib/wavesync/device' + +module Wavesync + class FileConverterTest < Wavesync::TestCase + def setup + @source_dir = Dir.mktmpdir + @target_dir = Dir.mktmpdir + @device = Device.find_by(name: 'TP-7') + + @converter = FileConverter.new + @path_resolver = PathResolver.new(@source_dir, @target_dir, @device) + end + + def teardown + FileUtils.rm_rf(@source_dir) + FileUtils.rm_rf(@target_dir) + end + + test 'convert skips when converted file already exists in source location' do + source_aiff = File.join(@source_dir, 'track.aiff') + FileUtils.touch(source_aiff) + FileUtils.touch(File.join(@source_dir, 'track.mp3')) + + audio = stub(bpm: nil) + result = @converter.convert(audio, source_aiff, @path_resolver, 'mp3', 44_100, nil, 16, nil) + + assert_equal false, result + end + + test 'convert does not skip when converted file does not exist in source location' do + source_aiff = File.join(@source_dir, 'track.aiff') + FileUtils.touch(source_aiff) + + audio = stub(bpm: nil) + audio.stubs(:transcode) + + result = @converter.convert(audio, source_aiff, @path_resolver, 'mp3', 44_100, nil, 16, nil) + + assert_equal true, result + end + + test 'convert skips when converted file already exists in target location' do + source_aiff = File.join(@source_dir, 'track.aiff') + FileUtils.touch(source_aiff) + FileUtils.touch(File.join(@target_dir, 'track.mp3')) + + audio = stub(bpm: nil) + result = @converter.convert(audio, source_aiff, @path_resolver, 'mp3', 44_100, nil, 16, nil) + + assert_equal false, result + end + end +end