require 'json' require 'tempfile' require 'open3' require 'fileutils' require 'open-uri' module JamRuby # Interact with external python tools to create the JKZ class JamTracksManager @@log = Logging.logger[JamTracksManager] class << self def save_jam_track_jkz(user, jam_track, bitrate=48) jam_track_right = jam_track.right_for_user(user) raise ArgumentError if jam_track_right.nil? save_jam_track_right_jkz(jam_track_right, bitrate) end def save_jam_track_right_jkz(jam_track_right, bitrate=48) jam_track = jam_track_right.jam_track py_root = APP_CONFIG.jamtracks_dir Dir.mktmpdir do |tmp_dir| jam_file_opts="" jam_track.jam_track_tracks.each do |jam_track_track| next if jam_track_track.track_type != "Track" # master mixes do not go into the JKZ # use the jam_track_track ID as the filename.ogg/.wav, because it's important metadata nm = jam_track_track.id + File.extname(jam_track_track.filename) track_filename = File.join(tmp_dir, nm) track_url = jam_track_track.sign_url(120, bitrate) copy_url_to_file(track_url, track_filename) copy_url_to_file(track_url, File.join(".", nm)) jam_file_opts << " -i '#{track_filename}+#{jam_track_track.part}'" end #puts "LS + " + `ls -la '#{tmp_dir}'` sku=jam_track.id title=jam_track.name output_jkz=File.join(tmp_dir, "#{title.parameterize}.jkz") py_file = File.join(py_root, "jkcreate.py") version = jam_track.version @@log.info "Executing python source in #{py_file}, outputting to #{tmp_dir} (#{output_jkz})" # From http://stackoverflow.com/questions/690151/getting-output-of-system-calls-in-ruby/5970819#5970819: cli = "python #{py_file} -D -k #{sku} -p #{tmp_dir}/pkey.pem -s #{tmp_dir}/skey.pem #{jam_file_opts} -o #{output_jkz} -t '#{title}' -V '#{version}'" Open3.popen3(cli) do |stdin, stdout, stderr, wait_thr| pid = wait_thr.pid exit_status = wait_thr.value err = stderr.read(1000) out = stdout.read(1000) #puts "stdout: #{out}, stderr: #{err}" raise ArgumentError, "Error calling python script: #{err}" if err.present? raise ArgumentError, "Error calling python script: #{out}" if out && (out.index("No track files specified") || out.index("Cannot find file")) #raise ArgumentError, "output_jkz is empty #{output_jkz}" unless File.exists?(output_jkz) if bitrate==48 jam_track_right.url_48.store!(File.open(output_jkz, "rb")) else jam_track_right.url_44.store!(File.open(output_jkz, "rb")) end jam_track_right.signed=true jam_track_right.downloaded_since_sign=false jam_track_right.private_key=File.read("#{tmp_dir}/skey.pem") jam_track_right.save! end end # mktmpdir jam_track_right end # save_jam_track_jkz def copy_url_to_file(url, filename) uri = URI(url) open(filename, 'w+b') do |io| Net::HTTP.start(uri.host, uri.port) do |http| request = Net::HTTP::Get.new uri http.request request do |response| response_code = response.code.to_i unless response_code >= 200 && response_code <= 299 @@log.info "Response from server was #{response_code} / #{response.message}" raise "bad status code: #{response_code}. body: #{response.body}" end response.read_body do |chunk| io.write chunk end end end end end # copy_url_to_file end # self end # class end # module