merging develop
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application '_guard-core' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('guard', '_guard-core')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'autospec' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('rspec-core', 'autospec')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'aws-rb' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('aws-sdk-v1', 'aws-rb')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'bourbon' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('bourbon', 'bourbon')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'bundler' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('bundler', 'bundler')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'coderay' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('coderay', 'coderay')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'erubis' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('erubis', 'erubis')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'fission' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('fission', 'fission')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'fog' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('fog', 'fog')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'fpm' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('fpm', 'fpm')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'guard' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('guard', 'guard')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'haml' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('haml', 'haml')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'htmldiff' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('diff-lcs', 'htmldiff')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'jam_db' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('jam_db', 'jam_db')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'jasmine' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('jasmine', 'jasmine')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'launchy' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('launchy', 'launchy')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'ldiff' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('diff-lcs', 'ldiff')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'listen' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('listen', 'listen')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'mix_cron.rb' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('jam_ruby', 'mix_cron.rb')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'nokogiri' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('nokogiri', 'nokogiri')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'pg_migrate' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('pg_migrate', 'pg_migrate')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'pry' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('pry', 'pry')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'pry-remote' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('pry-remote', 'pry-remote')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'puma' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('puma', 'puma')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'pumactl' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('puma', 'pumactl')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'rackup' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('rack', 'rackup')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'rails' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('railties', 'rails')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'rake' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('rake', 'rake')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'rdoc' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('rdoc', 'rdoc')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'recurly' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('recurly', 'recurly')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'resque' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('resque', 'resque')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'resque-scheduler' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('resque-scheduler', 'resque-scheduler')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'resque-web' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('resque', 'resque-web')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'restclient' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('rest-client', 'restclient')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'ri' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('rdoc', 'ri')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'rspec' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('rspec-core', 'rspec')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'ruby-protoc' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('ruby-protocol-buffers', 'ruby-protoc')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'rubygems-cabin-test' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('cabin', 'rubygems-cabin-test')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'sass' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('sass', 'sass')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'sass-convert' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('sass', 'sass-convert')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'scss' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('sass', 'scss')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'slimrb' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('slim', 'slimrb')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'sprockets' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('sprockets', 'sprockets')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'thor' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('thor', 'thor')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'tilt' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('tilt', 'tilt')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'tt' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('treetop', 'tt')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'unicorn' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('unicorn', 'unicorn')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'unicorn_rails' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('unicorn', 'unicorn_rails')
|
||||
|
|
@ -304,4 +304,6 @@ jam_track_searchability.sql
|
|||
harry_fox_agency.sql
|
||||
jam_track_slug.sql
|
||||
mixdown.sql
|
||||
aac_master.sql
|
||||
video_recording.sql
|
||||
jam_track_lang_idx.sql
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE jam_track_tracks ADD COLUMN preview_aac_url VARCHAR;
|
||||
ALTER TABLE jam_track_tracks ADD COLUMN preview_aac_md5 VARCHAR;
|
||||
ALTER TABLE jam_track_tracks ADD COLUMN preview_aac_length bigint;
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
ALTER TABLE crash_dumps ADD COLUMN email VARCHAR(255);
|
||||
ALTER TABLE crash_dumps ADD COLUMN description VARCHAR(10000);
|
||||
ALTER TABLE crash_dumps ADD COLUMN os VARCHAR(100);
|
||||
ALTER TABLE crash_dumps ADD COLUMN os_version VARCHAR(100);
|
||||
ALTER TABLE crash_dumps DROP CONSTRAINT crash_dumps_user_id_fkey;
|
||||
|
||||
|
|
@ -49,4 +49,13 @@ ALTER TABLE notifications ADD COLUMN jam_track_mixdown_package_id VARCHAR(64) RE
|
|||
|
||||
ALTER TABLE jam_track_mixdown_packages ADD COLUMN last_errored_at TIMESTAMP;
|
||||
ALTER TABLE jam_track_mixdown_packages ADD COLUMN queued BOOLEAN DEFAULT FALSE;
|
||||
ALTER TABLE jam_track_rights ADD COLUMN queued BOOLEAN DEFAULT FALSE;
|
||||
ALTER TABLE jam_track_mixdown_packages ADD COLUMN speed_pitched BOOLEAN DEFAULT FALSE;
|
||||
ALTER TABLE jam_track_rights ADD COLUMN queued BOOLEAN DEFAULT FALSE;
|
||||
|
||||
CREATE INDEX jam_track_rights_queued ON jam_track_rights(queued);
|
||||
CREATE INDEX jam_track_rights_signing_queued ON jam_track_rights(signing_queued_at);
|
||||
CREATE INDEX jam_track_rights_updated ON jam_track_rights(updated_at);
|
||||
|
||||
CREATE INDEX jam_track_mixdown_packages_queued ON jam_track_mixdown_packages(queued);
|
||||
CREATE INDEX jam_track_mixdown_packages_signing_queued ON jam_track_mixdown_packages(signing_queued_at);
|
||||
CREATE INDEX jam_track_mixdown_packages_updated ON jam_track_mixdown_packages(updated_at);
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE recordings ADD video BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
|
|
@ -34,6 +34,70 @@ module JamRuby
|
|||
end
|
||||
|
||||
|
||||
def synchronize_preview_dev(jam_track)
|
||||
jam_track.jam_track_tracks.each do |track|
|
||||
next if track.track_type != 'Master'
|
||||
|
||||
|
||||
most_recent_aac = nil
|
||||
most_recent_ogg = nil
|
||||
most_recent_mp3 = nil
|
||||
public_jamkazam_s3_manager.list_files(track.preview_directory).each do |s3_preview_item|
|
||||
|
||||
s3_object = public_jamkazam_s3_manager.object(s3_preview_item)
|
||||
|
||||
if s3_preview_item.end_with?('.aac')
|
||||
if most_recent_aac
|
||||
if s3_object.last_modified > most_recent_aac.last_modified
|
||||
most_recent_aac = s3_object
|
||||
end
|
||||
else
|
||||
most_recent_aac = s3_object
|
||||
end
|
||||
end
|
||||
|
||||
if s3_preview_item.end_with?('.mp3')
|
||||
if most_recent_mp3
|
||||
if s3_object.last_modified > most_recent_mp3.last_modified
|
||||
most_recent_mp3 = s3_object
|
||||
end
|
||||
else
|
||||
most_recent_mp3 = s3_object
|
||||
end
|
||||
end
|
||||
|
||||
if s3_preview_item.end_with?('.ogg')
|
||||
if most_recent_ogg
|
||||
if s3_object.last_modified > most_recent_ogg.last_modified
|
||||
most_recent_ogg = s3_object
|
||||
end
|
||||
else
|
||||
most_recent_ogg = s3_object
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if most_recent_aac
|
||||
track['preview_aac_md5'] = 'md5'
|
||||
track['preview_aac_url'] = most_recent_aac.key
|
||||
track['preview_aac_length'] = most_recent_aac.content_length
|
||||
end
|
||||
|
||||
if most_recent_mp3
|
||||
track['preview_mp3_md5'] = 'md5'
|
||||
track['preview_mp3_url'] = most_recent_mp3.key
|
||||
track['preview_mp3_length'] = most_recent_mp3.content_length
|
||||
end
|
||||
|
||||
if most_recent_ogg
|
||||
track['preview_md5'] = 'md5'
|
||||
track['preview_url'] = most_recent_ogg.key
|
||||
track['preview_length'] = most_recent_ogg.content_length
|
||||
end
|
||||
|
||||
track.save
|
||||
end
|
||||
end
|
||||
# this method was created due to Tency-sourced data having no master track
|
||||
# it goes through all audio tracks, and creates a master mix from it. (mix + normalize)
|
||||
def create_master(metadata, metalocation)
|
||||
|
|
@ -116,7 +180,6 @@ module JamRuby
|
|||
end
|
||||
|
||||
|
||||
|
||||
temp_file = File.join(tmp_dir, "temp.wav")
|
||||
output_filename = JamTrackImporter.remove_s3_special_chars("#{self.name} Master Mix.wav")
|
||||
output_file = File.join(tmp_dir, output_filename)
|
||||
|
|
@ -149,7 +212,7 @@ module JamRuby
|
|||
# now we need to upload the output back up
|
||||
s3_target = audio_path + '/' + output_filename
|
||||
@@log.debug("uploading #{output_file} to #{s3_target}")
|
||||
JamTrackImporter.song_storage_manager.upload(s3_target, output_file )
|
||||
JamTrackImporter.song_storage_manager.upload(s3_target, output_file)
|
||||
finish('success', nil)
|
||||
end
|
||||
|
||||
|
|
@ -195,7 +258,7 @@ module JamRuby
|
|||
|
||||
meta[:licensor] = vendor
|
||||
|
||||
File.open(meta_yml, 'w') {|f| f.write meta.to_yaml }
|
||||
File.open(meta_yml, 'w') { |f| f.write meta.to_yaml }
|
||||
|
||||
jamkazam_s3_manager.upload(metalocation, meta_yml)
|
||||
end
|
||||
|
|
@ -338,7 +401,7 @@ module JamRuby
|
|||
genres << Genre.find('asian')
|
||||
else
|
||||
found = Genre.find_by_id(genre)
|
||||
genres << found if found
|
||||
genres << found if found
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1166,7 +1229,7 @@ module JamRuby
|
|||
total_time = `#{total_time_command}`.to_f
|
||||
|
||||
result_code = -20
|
||||
stripped_time = total_time # default to the case where we just start the preview at the beginning
|
||||
stripped_time = total_time # default to the case where we just start the preview at the beginning
|
||||
|
||||
burp_gaps.each do |gap|
|
||||
command_strip_lead_silence = "sox \"#{ogg_44100}\" \"#{out_wav}\" silence 1 #{gap} 1%"
|
||||
|
|
@ -1218,6 +1281,53 @@ module JamRuby
|
|||
|
||||
end
|
||||
|
||||
def synchronize_aac_preview(track, tmp_dir, ogg_44100, ogg_digest)
|
||||
begin
|
||||
aac_44100 = File.join(tmp_dir, 'output-preview-44100.aac')
|
||||
convert_aac_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{ogg_44100}\" -c:a libfdk_aac -b:a 192k \"#{aac_44100}\""
|
||||
@@log.debug("converting to aac using: " + convert_aac_cmd)
|
||||
|
||||
convert_output = `#{convert_aac_cmd}`
|
||||
|
||||
aac_digest = ::Digest::MD5.file(aac_44100)
|
||||
|
||||
track["preview_aac_md5"] = aac_md5 = aac_digest.hexdigest
|
||||
|
||||
# upload 44100 aac to public location
|
||||
@@log.debug("uploading aac preview to #{track.preview_filename('aac')}")
|
||||
public_jamkazam_s3_manager.upload(track.preview_filename(aac_digest.hexdigest, 'aac'), aac_44100, content_type: 'audio/aac', content_md5: aac_digest.base64digest)
|
||||
|
||||
|
||||
track.skip_uploader = true
|
||||
|
||||
original_aac_preview_url = track["preview_aac_url"]
|
||||
|
||||
# and finally update the JamTrackTrack with the new info
|
||||
track["preview_aac_url"] = track.preview_filename(aac_md5, 'aac')
|
||||
track["preview_aac_length"] = File.new(aac_44100).size
|
||||
track["preview_start_time"] = 0
|
||||
|
||||
if !track.save
|
||||
finish("save_master_preview", track.errors.to_s)
|
||||
return false
|
||||
end
|
||||
|
||||
# if all that worked, now delete old previews, if present
|
||||
begin
|
||||
public_jamkazam_s3_manager.delete(original_aac_preview_url) if original_aac_preview_url && original_aac_preview_url != track["preview_aac_url"]
|
||||
rescue
|
||||
puts "UNABLE TO CLEANUP OLD PREVIEW URL"
|
||||
end
|
||||
rescue Exception => e
|
||||
finish("sync_master_preview_exception", e.to_s)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
def synchronize_master_preview(track, tmp_dir, ogg_44100, ogg_digest)
|
||||
|
||||
begin
|
||||
|
|
@ -1229,20 +1339,33 @@ module JamRuby
|
|||
|
||||
mp3_digest = ::Digest::MD5.file(mp3_44100)
|
||||
|
||||
aac_44100 = File.join(tmp_dir, 'output-preview-44100.aac')
|
||||
convert_aac_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{ogg_44100}\" -c:a libfdk_aac -b:a 192k \"#{aac_44100}\""
|
||||
@@log.debug("converting to aac using: " + convert_aac_cmd)
|
||||
|
||||
convert_output = `#{convert_aac_cmd}`
|
||||
|
||||
aac_digest = ::Digest::MD5.file(aac_44100)
|
||||
|
||||
|
||||
track["preview_md5"] = ogg_md5 = ogg_digest.hexdigest
|
||||
track["preview_mp3_md5"] = mp3_md5 = mp3_digest.hexdigest
|
||||
track["preview_aac_md5"] = aac_md5 = aac_digest.hexdigest
|
||||
|
||||
# upload 44100 ogg and mp3 to public location as well
|
||||
# upload 44100 ogg, mp3, aac to public location as well
|
||||
@@log.debug("uploading ogg preview to #{track.preview_filename('ogg')}")
|
||||
public_jamkazam_s3_manager.upload(track.preview_filename(ogg_digest.hexdigest, 'ogg'), ogg_44100, content_type: 'audio/ogg', content_md5: ogg_digest.base64digest)
|
||||
@@log.debug("uploading mp3 preview to #{track.preview_filename('mp3')}")
|
||||
public_jamkazam_s3_manager.upload(track.preview_filename(mp3_digest.hexdigest, 'mp3'), mp3_44100, content_type: 'audio/mpeg', content_md5: mp3_digest.base64digest)
|
||||
@@log.debug("uploading aac preview to #{track.preview_filename('aac')}")
|
||||
public_jamkazam_s3_manager.upload(track.preview_filename(aac_digest.hexdigest, 'aac'), aac_44100, content_type: 'audio/aac', content_md5: aac_digest.base64digest)
|
||||
|
||||
|
||||
track.skip_uploader = true
|
||||
|
||||
original_ogg_preview_url = track["preview_url"]
|
||||
original_mp3_preview_url = track["preview_mp3_url"]
|
||||
original_aac_preview_url = track["preview_aac_url"]
|
||||
|
||||
# and finally update the JamTrackTrack with the new info
|
||||
track["preview_url"] = track.preview_filename(ogg_md5, 'ogg')
|
||||
|
|
@ -1250,6 +1373,8 @@ module JamRuby
|
|||
# and finally update the JamTrackTrack with the new info
|
||||
track["preview_mp3_url"] = track.preview_filename(mp3_md5, 'mp3')
|
||||
track["preview_mp3_length"] = File.new(mp3_44100).size
|
||||
track["preview_aac_url"] = track.preview_filename(aac_md5, 'mp3')
|
||||
track["preview_aac_length"] = File.new(aac_44100).size
|
||||
track["preview_start_time"] = 0
|
||||
|
||||
if !track.save
|
||||
|
|
@ -1261,6 +1386,7 @@ module JamRuby
|
|||
begin
|
||||
public_jamkazam_s3_manager.delete(original_ogg_preview_url) if original_ogg_preview_url && original_ogg_preview_url != track["preview_url"]
|
||||
public_jamkazam_s3_manager.delete(original_mp3_preview_url) if original_mp3_preview_url && original_mp3_preview_url != track["preview_mp3_url"]
|
||||
public_jamkazam_s3_manager.delete(original_aac_preview_url) if original_aac_preview_url && original_aac_preview_url != track["preview_aac_url"]
|
||||
rescue
|
||||
puts "UNABLE TO CLEANUP OLD PREVIEW URL"
|
||||
end
|
||||
|
|
@ -1499,13 +1625,13 @@ module JamRuby
|
|||
|
||||
CSV.open("only_in_s3.csv", "wb") do |csv|
|
||||
only_in_s3.each do |song_id|
|
||||
csv << [ song_id, in_s3[song_id][:artist], in_s3[song_id][:song] ]
|
||||
csv << [song_id, in_s3[song_id][:artist], in_s3[song_id][:song]]
|
||||
end
|
||||
end
|
||||
|
||||
CSV.open("only_in_2k_selection.csv", "wb") do |csv|
|
||||
only_in_mapping.each do |song_id|
|
||||
csv << [ song_id, in_mapping[song_id][:artist], in_mapping[song_id][:song] ]
|
||||
csv << [song_id, in_mapping[song_id][:artist], in_mapping[song_id][:song]]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1518,6 +1644,7 @@ module JamRuby
|
|||
break
|
||||
end
|
||||
end
|
||||
|
||||
def create_masters
|
||||
iterate_song_storage do |metadata, metalocation|
|
||||
next if metadata.nil?
|
||||
|
|
@ -1584,6 +1711,38 @@ module JamRuby
|
|||
importer
|
||||
end
|
||||
|
||||
# hunts for the most recent .aac, .mp3, or .ogg file
|
||||
def synchronize_preview_dev(jam_track)
|
||||
importer = JamTrackImporter.new
|
||||
importer.name = jam_track.name
|
||||
|
||||
importer.synchronize_preview_dev(jam_track)
|
||||
|
||||
importer.finish('success', nil)
|
||||
importer
|
||||
end
|
||||
|
||||
def synchronize_jamtrack_aac_preview(jam_track)
|
||||
importer = JamTrackImporter.new
|
||||
importer.name = jam_track.name
|
||||
|
||||
track = jam_track.master_track
|
||||
|
||||
if track
|
||||
Dir.mktmpdir do |tmp_dir|
|
||||
ogg_44100 = File.join(tmp_dir, 'input.ogg')
|
||||
private_s3_manager.download(track.url_by_sample_rate(44), ogg_44100)
|
||||
ogg_44100_digest = ::Digest::MD5.file(ogg_44100)
|
||||
if importer.synchronize_aac_preview(track, tmp_dir, ogg_44100, ogg_44100_digest)
|
||||
importer.finish("success", nil)
|
||||
end
|
||||
end
|
||||
else
|
||||
importer.finish('no_master_track', nil)
|
||||
end
|
||||
importer
|
||||
end
|
||||
|
||||
def synchronize_jamtrack_master_preview(jam_track)
|
||||
importer = JamTrackImporter.new
|
||||
importer.name = jam_track.name
|
||||
|
|
@ -1606,6 +1765,30 @@ module JamRuby
|
|||
importer
|
||||
end
|
||||
|
||||
def synchronize_previews_dev
|
||||
importers = []
|
||||
|
||||
JamTrack.all.each do |jam_track|
|
||||
importers << synchronize_preview_dev(jam_track)
|
||||
end
|
||||
|
||||
@@log.info("SUMMARY")
|
||||
@@log.info("-------")
|
||||
importers.each do |importer|
|
||||
if importer
|
||||
if importer.reason == "success" || importer.reason == "no_preview_start_time"
|
||||
@@log.info("#{importer.name} #{importer.reason}")
|
||||
else
|
||||
@@log.error("#{importer.name} failed to import.")
|
||||
@@log.error("#{importer.name} reason=#{importer.reason}")
|
||||
@@log.error("#{importer.name} detail=#{importer.detail}")
|
||||
end
|
||||
else
|
||||
@@log.error("NULL IMPORTER")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def synchronize_previews
|
||||
importers = []
|
||||
|
|
@ -1632,6 +1815,33 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def synchronize_jamtrack_aac_previews
|
||||
|
||||
importers = []
|
||||
|
||||
JamTrack.all.each do |jam_track|
|
||||
importers << synchronize_jamtrack_aac_preview(jam_track)
|
||||
end
|
||||
|
||||
@@log.info("SUMMARY")
|
||||
@@log.info("-------")
|
||||
importers.each do |importer|
|
||||
if importer
|
||||
if importer.reason == "success" || importer.reason == "jam_track_exists" || importer.reason == "other_processing"
|
||||
@@log.info("#{importer.name} #{importer.reason}")
|
||||
else
|
||||
@@log.error("#{importer.name} failed to import.")
|
||||
@@log.error("#{importer.name} reason=#{importer.reason}")
|
||||
@@log.error("#{importer.name} detail=#{importer.detail}")
|
||||
end
|
||||
else
|
||||
@@log.error("NULL IMPORTER")
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def synchronize_jamtrack_master_previews
|
||||
importers = []
|
||||
|
||||
|
|
@ -1883,11 +2093,11 @@ module JamRuby
|
|||
genre4 = value[:genre4]
|
||||
genre5 = value[:genre5]
|
||||
|
||||
genres << genre1.downcase.strip if genre1
|
||||
genres << genre2.downcase.strip if genre2
|
||||
genres << genre3.downcase.strip if genre3
|
||||
genres << genre4.downcase.strip if genre4
|
||||
genres << genre5.downcase.strip if genre5
|
||||
genres << genre1.downcase.strip if genre1
|
||||
genres << genre2.downcase.strip if genre2
|
||||
genres << genre3.downcase.strip if genre3
|
||||
genres << genre4.downcase.strip if genre4
|
||||
genres << genre5.downcase.strip if genre5
|
||||
|
||||
value[:genres] = genres
|
||||
end
|
||||
|
|
|
|||
|
|
@ -121,6 +121,10 @@ module JamRuby
|
|||
s3_bucket.objects[filename].exists?
|
||||
end
|
||||
|
||||
def object(filename)
|
||||
s3_bucket.objects[filename]
|
||||
end
|
||||
|
||||
def length(filename)
|
||||
s3_bucket.objects[filename].content_length
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module JamRuby
|
|||
before_validation(:on => :create) do
|
||||
self.created_at ||= Time.now
|
||||
self.id = SecureRandom.uuid
|
||||
self.uri = "dump/#{self.id}-#{self.created_at.to_i}"
|
||||
self.uri = "dumps/#{created_at.strftime('%Y-%m-%d')}/#{self.id}"
|
||||
end
|
||||
|
||||
def user_email
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def mixdowns_for_user(user)
|
||||
JamTrackMixdown.where(user_id: user.id, jam_track_id: self.id).order('created_at DESC')
|
||||
JamTrackMixdown.where(user_id: user.id).where(jam_track_id: self.id)
|
||||
end
|
||||
|
||||
def short_plan_code
|
||||
|
|
@ -466,7 +466,6 @@ module JamRuby
|
|||
|
||||
def generate_slug
|
||||
self.slug = sluggarize(original_artist) + '-' + sluggarize(name)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ module JamRuby
|
|||
validates :jam_track, presence: true
|
||||
validates :settings, presence: true
|
||||
|
||||
validates_uniqueness_of :name, scope: :jam_track_id
|
||||
validates_uniqueness_of :name, scope: :user_id
|
||||
|
||||
validate :verify_settings
|
||||
validate :verify_max_mixdowns
|
||||
|
|
@ -49,10 +49,13 @@ module JamRuby
|
|||
|
||||
# the user has to specify at least at least one tweak to volume, speed, pitch, pan. otherwise there is nothing to do
|
||||
|
||||
tweaked = false
|
||||
all_quiet = true
|
||||
|
||||
parsed = JSON.parse(self.settings)
|
||||
specified_track_count = parsed["tracks"] ? parsed["tracks"].length : 0
|
||||
|
||||
tweaked = false
|
||||
all_quiet = jam_track.stem_tracks.length == 0 ? false : jam_track.stem_tracks.length == specified_track_count # we already say 'all_quiet is false' if the user did not specify as many tracks as there are on the JamTrack, because omission implies 'include this track'
|
||||
|
||||
|
||||
if parsed["speed"]
|
||||
tweaked = true
|
||||
end
|
||||
|
|
@ -83,7 +86,7 @@ module JamRuby
|
|||
if all_quiet
|
||||
errors.add(:settings, 'are all muted')
|
||||
end
|
||||
if !tweaked
|
||||
if !tweaked && !parsed['full']
|
||||
errors.add(:settings, 'have nothing specified')
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -37,19 +37,15 @@ module JamRuby
|
|||
|
||||
MAX_JAM_TRACK_DOWNLOADS = 1000
|
||||
|
||||
def estimated_queue_time
|
||||
def self.estimated_queue_time
|
||||
jam_track_signing_count = JamTrackRight.where(queued: true).count
|
||||
mixdowns = JamTrackMixdownPackage.select('count(queued) as queue_count, count(speed_pitched) as speed_pitch_count').where(queued: true).first
|
||||
total_mixdowns = mixdowns['queue_count']
|
||||
slow_mixdowns = mixdowns['speed_pitch_count']
|
||||
mixdowns = JamTrackMixdownPackage.unscoped.select('count(CASE WHEN queued THEN 1 ELSE NULL END) as queue_count, count(CASE WHEN speed_pitched THEN 1 ELSE NULL END) as speed_pitch_count').where(queued: true).first
|
||||
total_mixdowns = mixdowns['queue_count'].to_i
|
||||
slow_mixdowns = mixdowns['speed_pitch_count'].to_i
|
||||
fast_mixdowns = total_mixdowns - slow_mixdowns
|
||||
|
||||
guess = APP_CONFIG.estimated_jam_track_time * jam_track_signing_count + APP_CONFIG.estimated_fast_mixdown_time * fast_mixdowns + APP_CONFIG.estimated_slow_mixdown_time * slow_mixdowns
|
||||
|
||||
# knock off about a minute based on number of nodes
|
||||
guess = guess - ((APP_CONFIG.num_signing_nodes - 1) * 60)
|
||||
guess = 0 if guess < 0
|
||||
|
||||
Stats.write('web.jam_track.queue_time', {value: guess / 60.0, jam_tracks: jam_track_signing_count, slow_mixdowns: slow_mixdowns, fast_mixdowns: fast_mixdowns})
|
||||
guess
|
||||
end
|
||||
|
|
@ -66,6 +62,7 @@ module JamRuby
|
|||
def self.create(mixdown, file_type, sample_rate, encrypt_type)
|
||||
|
||||
package = JamTrackMixdownPackage.new
|
||||
package.speed_pitched = mixdown.will_pitch_shift?
|
||||
package.jam_track_mixdown = mixdown
|
||||
package.file_type = file_type
|
||||
package.sample_rate = sample_rate
|
||||
|
|
@ -148,11 +145,14 @@ module JamRuby
|
|||
self.signing_queued_at = Time.now
|
||||
self.signing_started_at = nil
|
||||
self.last_signed_at = nil
|
||||
self.queued = true
|
||||
self.save
|
||||
|
||||
queue_time = JamTrackMixdownPackage.estimated_queue_time
|
||||
|
||||
# is_pitch_speed_shifted?
|
||||
Resque.enqueue(JamTrackMixdownPackager, self.id)
|
||||
true
|
||||
return queue_time
|
||||
rescue Exception => e
|
||||
puts "e: #{e}"
|
||||
# implies redis is down. we don't update started_at by bailing out here
|
||||
|
|
@ -166,8 +166,7 @@ module JamRuby
|
|||
if state == 'SIGNED' || state == 'SIGNING' || state == 'QUEUED'
|
||||
false
|
||||
else
|
||||
enqueue
|
||||
true
|
||||
return enqueue
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -233,10 +232,10 @@ module JamRuby
|
|||
def self.stats
|
||||
stats = {}
|
||||
|
||||
result = JamTrackMixdownPackage.select('count(id) as total, count(CASE WHEN signing THEN 1 ELSE NULL END) as signing_count').first
|
||||
result = JamTrackMixdownPackage.unscoped.select('count(id) as total, count(CASE WHEN signing THEN 1 ELSE NULL END) as signing_count')
|
||||
|
||||
stats['count'] = result['total'].to_i
|
||||
stats['signing_count'] = result['signing_count'].to_i
|
||||
stats['count'] = result[0]['total'].to_i
|
||||
stats['signing_count'] = result[0]['signing_count'].to_i
|
||||
stats
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ module JamRuby
|
|||
|
||||
def finish_errored(error_reason, error_detail, sample_rate)
|
||||
self.last_signed_at = Time.now
|
||||
self.queued = false
|
||||
self.error_count = self.error_count + 1
|
||||
self.error_reason = error_reason
|
||||
self.error_detail = error_detail
|
||||
|
|
@ -85,6 +86,7 @@ module JamRuby
|
|||
|
||||
def finish_sign(length, md5, bitrate)
|
||||
self.last_signed_at = Time.now
|
||||
self.queued = false
|
||||
if bitrate==48
|
||||
self.length_48 = length
|
||||
self.md5_48 = md5
|
||||
|
|
@ -120,7 +122,7 @@ module JamRuby
|
|||
|
||||
def enqueue(sample_rate=48)
|
||||
begin
|
||||
JamTrackRight.where(:id => self.id).update_all(:signing_queued_at => Time.now, :signing_started_at_44 => nil, :signing_started_at_48 => nil, :last_signed_at => nil)
|
||||
JamTrackRight.where(:id => self.id).update_all(:signing_queued_at => Time.now, :signing_started_at_44 => nil, :signing_started_at_48 => nil, :last_signed_at => nil, :queued => true)
|
||||
Resque.enqueue(JamTracksBuilder, self.id, sample_rate)
|
||||
true
|
||||
rescue Exception => e
|
||||
|
|
|
|||
|
|
@ -49,7 +49,11 @@ module JamRuby
|
|||
# md5-'ed because we cache forever
|
||||
def preview_filename(md5, ext='ogg')
|
||||
original_name = "#{File.basename(self["url_44"], ".ogg")}-preview-#{md5}.#{ext}"
|
||||
"jam_track_previews/#{jam_track.original_artist}/#{jam_track.name}/#{original_name}"
|
||||
"#{preview_directory}/#{original_name}"
|
||||
end
|
||||
|
||||
def preview_directory
|
||||
"jam_track_previews/#{jam_track.original_artist}/#{jam_track.name}"
|
||||
end
|
||||
|
||||
def has_preview?
|
||||
|
|
@ -58,7 +62,16 @@ module JamRuby
|
|||
|
||||
# generates a URL that points to a public version of the preview
|
||||
def preview_public_url(media_type='ogg')
|
||||
url = media_type == 'ogg' ? self[:preview_url] : self[:preview_mp3_url]
|
||||
case media_type
|
||||
when 'ogg'
|
||||
url = self[:preview_url]
|
||||
when 'mp3'
|
||||
url = self[:preview_mp3_url]
|
||||
when 'aac'
|
||||
url = self[:preview_aac_url]
|
||||
else
|
||||
raise "unknown media_type #{media_type}"
|
||||
end
|
||||
if url
|
||||
s3_public_manager.public_url(url,{ :secure => true})
|
||||
else
|
||||
|
|
@ -154,6 +167,7 @@ module JamRuby
|
|||
|
||||
# input is the original ogg file for the track. tmp_dir is where this code can safely generate output stuff and have it cleaned up later
|
||||
def process_preview(input, tmp_dir)
|
||||
raise "Does not include AAC generation. Must be updated before used."
|
||||
uuid = SecureRandom.uuid
|
||||
output = File.join(tmp_dir, "#{uuid}.ogg")
|
||||
output_mp3 = File.join(tmp_dir, "#{uuid}.mp3")
|
||||
|
|
@ -176,7 +190,6 @@ module JamRuby
|
|||
# now create mp3 off of ogg preview
|
||||
|
||||
convert_mp3_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{output}\" -ab 192k \"#{output_mp3}\""
|
||||
|
||||
@@log.debug("converting to mp3 using: " + convert_mp3_cmd)
|
||||
|
||||
convert_output = `#{convert_mp3_cmd}`
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
# Start recording a session.
|
||||
def self.start(music_session, owner)
|
||||
def self.start(music_session, owner, record_video: false)
|
||||
recording = nil
|
||||
# Use a transaction and lock to avoid races.
|
||||
music_session.with_lock do
|
||||
|
|
@ -213,6 +213,7 @@ module JamRuby
|
|||
recording.music_session = music_session
|
||||
recording.owner = owner
|
||||
recording.band = music_session.band
|
||||
recording.video = record_video
|
||||
|
||||
if recording.save
|
||||
GoogleAnalyticsEvent.report_band_recording(recording.band)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ module JamRuby
|
|||
@mixdown_package.signing = true
|
||||
@mixdown_package.should_retry = false
|
||||
@mixdown_package.last_step_at = last_step_at
|
||||
@mixdown_package.queued = false
|
||||
@mixdown_package.save
|
||||
|
||||
SubscriptionMessage.mixdown_signing_job_change(@mixdown_package)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ module JamRuby
|
|||
signing_started_model_symbol = bitrate == 48 ? :signing_started_at_48 : :signing_started_at_44
|
||||
signing_state_symbol = bitrate == 48 ? :signing_48 : :signing_44
|
||||
last_step_at = Time.now
|
||||
JamTrackRight.where(:id => @jam_track_right.id).update_all(signing_started_model_symbol => signing_started_at, :should_retry => false, packaging_steps: total_steps, current_packaging_step: 0, last_step_at: last_step_at, signing_state_symbol => true)
|
||||
JamTrackRight.where(:id => @jam_track_right.id).update_all(signing_started_model_symbol => signing_started_at, :should_retry => false, packaging_steps: total_steps, current_packaging_step: 0, last_step_at: last_step_at, signing_state_symbol => true, queued: false)
|
||||
# because we are skipping 'after_save', we have to keep the model current for the notification. A bit ugly...
|
||||
@jam_track_right.current_packaging_step = 0
|
||||
@jam_track_right.packaging_steps = total_steps
|
||||
|
|
@ -50,6 +50,7 @@ module JamRuby
|
|||
@jam_track_right[signing_state_symbol] = true
|
||||
@jam_track_right.should_retry = false
|
||||
@jam_track_right.last_step_at = Time.now
|
||||
@jam_track_right.queued = false
|
||||
SubscriptionMessage.jam_track_signing_job_change(@jam_track_right)
|
||||
JamRuby::JamTracksManager.save_jam_track_right_jkz(@jam_track_right, self.bitrate)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@ module JamRuby
|
|||
|
||||
def perform
|
||||
# this needs more testing
|
||||
|
||||
# let's make sure jobs don't stay falsely queued for too long. 1 hour seems more than enough
|
||||
JamTrackRight.where("queued = true AND (NOW() - signing_queued_at > '1 hour'::INTERVAL OR NOW() - updated_at > '1 hour'::INTERVAL)").update_all(queued:false)
|
||||
JamTrackMixdownPackage.unscoped.where("queued = true AND (NOW() - signing_queued_at > '1 hour'::INTERVAL OR NOW() - updated_at > '1 hour'::INTERVAL)").update_all(queued:false)
|
||||
|
||||
return
|
||||
#JamTrackRight.ready_to_clean.each do |jam_track_right|
|
||||
# log.debug("deleting files for jam_track_right #{jam_track_right.id}")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe JamTrackMixdown do
|
||||
|
||||
let(:user) {FactoryGirl.create(:user)}
|
||||
let(:jam_track) {FactoryGirl.create(:jam_track)}
|
||||
let(:settings) { {speed:5} }
|
||||
|
||||
it "can be created (factory girl)" do
|
||||
mixdown = FactoryGirl.create(:jam_track_mixdown)
|
||||
|
||||
mixdown = JamTrackMixdown.find(mixdown.id)
|
||||
mixdown.settings.should eq('{"speed":5}')
|
||||
end
|
||||
|
||||
it "can be created" do
|
||||
mixdown = JamTrackMixdown.create('abc', 'description', user, jam_track, settings)
|
||||
mixdown.errors.any?.should == false
|
||||
end
|
||||
|
||||
it "index" do
|
||||
query, start, count = JamTrackMixdown.index({id: jam_track}, user)
|
||||
|
||||
query.length.should eq(0)
|
||||
start.should be_nil
|
||||
count.should eq(0)
|
||||
|
||||
mixdown = FactoryGirl.create(:jam_track_mixdown, user: user, jam_track: jam_track)
|
||||
|
||||
query, start, count = JamTrackMixdown.index({id: jam_track}, user)
|
||||
query[0].should eq(mixdown)
|
||||
start.should be_nil
|
||||
count.should eq(1)
|
||||
end
|
||||
|
||||
describe "settings" do
|
||||
it "validates empty settings" do
|
||||
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {}.to_json)
|
||||
invalid.save
|
||||
invalid.errors.any?.should be_true
|
||||
invalid.errors["settings"].should eq(["have nothing specified"])
|
||||
end
|
||||
|
||||
it "validates speed numeric" do
|
||||
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"speed": "5"}.to_json)
|
||||
invalid.save
|
||||
invalid.errors.any?.should be_true
|
||||
invalid.errors["settings"].should eq(["has non-integer speed"])
|
||||
end
|
||||
|
||||
it "validates pitch numeric" do
|
||||
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"pitch": "5"}.to_json)
|
||||
invalid.save
|
||||
invalid.errors.any?.should be_true
|
||||
invalid.errors["settings"].should eq(["has non-integer pitch"])
|
||||
end
|
||||
|
||||
it "validates speed not-float" do
|
||||
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"speed": 5.5}.to_json)
|
||||
invalid.save
|
||||
invalid.errors.any?.should be_true
|
||||
invalid.errors["settings"].should eq(["has non-integer speed"])
|
||||
end
|
||||
|
||||
it "validates pitch not-float" do
|
||||
invalid = FactoryGirl.build(:jam_track_mixdown, settings: {"pitch": 10.5}.to_json)
|
||||
invalid.save
|
||||
invalid.errors.any?.should be_true
|
||||
invalid.errors["settings"].should eq(["has non-integer pitch"])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
mixdown.settings.should eq('{}')
|
||||
end
|
||||
|
||||
it "can be created" do
|
||||
mixdown = JamTrackMixdown.create('abc', user, jam_track, {})
|
||||
mixdown.errors.any?.should == false
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -12,7 +12,6 @@ describe JamTrackMixdownPackage do
|
|||
|
||||
package = JamTrackMixdownPackage.create(mixdown, JamTrackMixdownPackage::FILE_TYPE_OGG, 48, 'jkz')
|
||||
|
||||
puts package.errors.inspect
|
||||
package.errors.any?.should == false
|
||||
end
|
||||
|
||||
|
|
@ -34,12 +33,12 @@ describe JamTrackMixdownPackage do
|
|||
end
|
||||
|
||||
it "signing" do
|
||||
package = FactoryGirl.create(:jam_track_mixdown_package, signing_started_at: Time.now, packaging_steps: 3, current_packaging_step:0, last_step_at:Time.now)
|
||||
package = FactoryGirl.create(:jam_track_mixdown_package, signing:true, signing_started_at: Time.now, packaging_steps: 3, current_packaging_step:0, last_step_at:Time.now)
|
||||
package.signing_state.should eq('SIGNING')
|
||||
end
|
||||
|
||||
it "signing timeout" do
|
||||
package = FactoryGirl.create(:jam_track_mixdown_package, signing_started_at: Time.now - 100, packaging_steps: 3, current_packaging_step:0, last_step_at:Time.now)
|
||||
package = FactoryGirl.create(:jam_track_mixdown_package, signing: true, signing_started_at: Time.now - (APP_CONFIG.signing_job_signing_max_time + 1), packaging_steps: 3, current_packaging_step:0, last_step_at:Time.now)
|
||||
package.signing_state.should eq('SIGNING_TIMEOUT')
|
||||
end
|
||||
|
||||
|
|
@ -49,7 +48,7 @@ describe JamTrackMixdownPackage do
|
|||
end
|
||||
|
||||
it "signing timeout" do
|
||||
package = FactoryGirl.create(:jam_track_mixdown_package, signing_queued_at: Time.now - (APP_CONFIG.signing_job_queue_max_time + 1))
|
||||
package = FactoryGirl.create(:jam_track_mixdown_package, signing_queued_at: Time.now - (APP_CONFIG.mixdown_job_queue_max_time + 1))
|
||||
package.signing_state.should eq('QUEUED_TIMEOUT')
|
||||
end
|
||||
end
|
||||
|
|
@ -74,6 +73,30 @@ describe JamTrackMixdownPackage do
|
|||
end
|
||||
|
||||
describe "estimated_queue_time" do
|
||||
it "succeeds with no data" do
|
||||
JamTrackMixdownPackage.estimated_queue_time.should eq(0)
|
||||
end
|
||||
|
||||
it "mixdown packages of different sorts" do
|
||||
package = FactoryGirl.create(:jam_track_mixdown_package, speed_pitched: true)
|
||||
JamTrackMixdownPackage.estimated_queue_time.should eq(0)
|
||||
|
||||
package.queued = true
|
||||
package.save!
|
||||
JamTrackMixdownPackage.estimated_queue_time.should eq(APP_CONFIG.estimated_slow_mixdown_time * 1)
|
||||
|
||||
package.speed_pitched = false
|
||||
package.save!
|
||||
|
||||
JamTrackMixdownPackage.estimated_queue_time.should eq(APP_CONFIG.estimated_fast_mixdown_time * 1)
|
||||
|
||||
right = FactoryGirl.create(:jam_track_right)
|
||||
JamTrackMixdownPackage.estimated_queue_time.should eq(APP_CONFIG.estimated_fast_mixdown_time * 1)
|
||||
|
||||
right.queued = true
|
||||
right.save!
|
||||
JamTrackMixdownPackage.estimated_queue_time.should eq(APP_CONFIG.estimated_fast_mixdown_time * 1 + APP_CONFIG.estimated_jam_track_time * 1)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ def app_config
|
|||
end
|
||||
|
||||
def signing_job_queue_max_time
|
||||
20 # 20 seconds
|
||||
600 # 20 seconds
|
||||
end
|
||||
|
||||
def one_free_jamtrack_per_user
|
||||
|
|
@ -226,6 +226,18 @@ def app_config
|
|||
2
|
||||
end
|
||||
|
||||
def signing_job_signing_max_time
|
||||
300
|
||||
end
|
||||
|
||||
def mixdown_job_queue_max_time
|
||||
600
|
||||
end
|
||||
|
||||
def mixdown_step_max_time
|
||||
300
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def audiomixer_workspace_path
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ gem 'react-rails-img'
|
|||
source 'https://rails-assets.org' do
|
||||
gem 'rails-assets-reflux'
|
||||
gem 'rails-assets-classnames'
|
||||
gem 'rails-assets-react-select'
|
||||
gem 'rails-assets-react-select', '0.6.7'
|
||||
end
|
||||
|
||||
#group :development, :production do
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 606 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 642 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 806 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 837 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -23,6 +23,7 @@
|
|||
var mode = null;
|
||||
|
||||
// heartbeat
|
||||
var startHeartbeatTimeout = null;
|
||||
var heartbeatInterval = null;
|
||||
var heartbeatMS = null;
|
||||
var connection_expire_time = null;
|
||||
|
|
@ -79,6 +80,7 @@
|
|||
function initiateReconnect(activeElementVotes, in_error) {
|
||||
var initialConnect = !!activeElementVotes;
|
||||
|
||||
console.log("activeElementVotes", activeElementVotes)
|
||||
freezeInteraction = activeElementVotes && ((activeElementVotes.dialog && activeElementVotes.dialog.freezeInteraction === true) || (activeElementVotes.screen && activeElementVotes.screen.freezeInteraction === true));
|
||||
|
||||
if (in_error) {
|
||||
|
|
@ -104,6 +106,12 @@
|
|||
heartbeatInterval = null;
|
||||
}
|
||||
|
||||
// stop the heartbeat start delay from happening
|
||||
if (startHeartbeatTimeout != null) {
|
||||
clearTimeout(startHeartbeatTimeout);
|
||||
startHeartbeatTimeout = null;
|
||||
}
|
||||
|
||||
// stop checking for heartbeat acks
|
||||
if (heartbeatAckCheckInterval != null) {
|
||||
clearTimeout(heartbeatAckCheckInterval);
|
||||
|
|
@ -236,9 +244,41 @@
|
|||
heartbeatMS = payload.heartbeat_interval * 1000;
|
||||
connection_expire_time = payload.connection_expire_time * 1000;
|
||||
logger.info("loggedIn(): clientId=" + app.clientId + " heartbeat=" + payload.heartbeat_interval + "s expire_time=" + payload.connection_expire_time + 's');
|
||||
heartbeatInterval = context.setInterval(_heartbeat, heartbeatMS);
|
||||
heartbeatAckCheckInterval = context.setInterval(_heartbeatAckCheck, 1000);
|
||||
lastHeartbeatAckTime = new Date(new Date().getTime() + heartbeatMS); // add a little forgiveness to server for initial heartbeat
|
||||
|
||||
// add some randomness to help move heartbeats apart from each other
|
||||
|
||||
// send 1st heartbeat somewhere between 0 - 0.5 of the connection expire time
|
||||
var randomStartTime = connection_expire_time * (Math.random() / 2)
|
||||
|
||||
if (startHeartbeatTimeout) {
|
||||
logger.warn("start heartbeat timeout is active; should be null")
|
||||
clearTimeout(startHeartbeatTimeout)
|
||||
}
|
||||
|
||||
if (heartbeatInterval != null) {
|
||||
logger.warn("heartbeatInterval is active; should be null")
|
||||
clearInterval(heartbeatInterval);
|
||||
heartbeatInterval = null;
|
||||
}
|
||||
|
||||
if (heartbeatAckCheckInterval != null) {
|
||||
logger.warn("heartbeatAckCheckInterval is active; should be null")
|
||||
clearInterval(heartbeatAckCheckInterval);
|
||||
heartbeatAckCheckInterval = null;
|
||||
}
|
||||
|
||||
startHeartbeatTimeout = setTimeout(function() {
|
||||
if(server.connected) {
|
||||
heartbeatInterval = context.setInterval(_heartbeat, heartbeatMS);
|
||||
heartbeatAckCheckInterval = context.setInterval(_heartbeatAckCheck, 1000);
|
||||
lastHeartbeatAckTime = new Date(new Date().getTime() + heartbeatMS); // add a little forgiveness to server for initial heartbeat
|
||||
}
|
||||
}, randomStartTime)
|
||||
|
||||
logger.info("starting heartbeat timer in " + randomStartTime/1000 + 's')
|
||||
|
||||
|
||||
|
||||
connectDeferred.resolve();
|
||||
$self.triggerHandler(EVENTS.CONNECTION_UP)
|
||||
|
||||
|
|
@ -295,6 +335,11 @@
|
|||
logger.debug(payload.error_code + ": no longer reconnecting")
|
||||
server.noReconnect = true; // stop trying to log in!!
|
||||
}
|
||||
else if (payload.error_code == 'no_reconnect') {
|
||||
logger.debug(payload.error_code + ": no longer reconnecting")
|
||||
server.noReconnect = true; // stop trying to log in!!
|
||||
context.JK.Banner.showAlert("Misbehaved Client", "Please restart your application in order to continue using JamKazam.")
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////
|
||||
|
|
@ -384,7 +429,7 @@
|
|||
}
|
||||
|
||||
function formatDelaySecs(secs) {
|
||||
return $('<span class="countdown-seconds"><span class="countdown">' + secs + '</span> ' + (secs == 1 ? ' second.<span style="visibility:hidden">s</span>' : 'seconds.') + '</span>');
|
||||
return $('<span class="countdown-seconds"><span class="countdown">' + secs + '</span> ' + (secs == 1 ? ' second.<span style="visibility:hidden">s</span>' : 'seconds.') + '</span>');
|
||||
}
|
||||
|
||||
function setCountdown($parent) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ context.JK.AccountJamTracks = class AccountJamTracks
|
|||
@screen = $('#account-jamtracks')
|
||||
|
||||
beforeShow:() =>
|
||||
rest.getPurchasedJamTracks({})
|
||||
rest.getPurchasedJamTracks({limit: 40})
|
||||
.done(@populateJamTracks)
|
||||
.fail(@app.ajaxError);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,13 @@
|
|||
// remove all display errors
|
||||
$('#recording-finished-dialog form .error-text').remove()
|
||||
$('#recording-finished-dialog form .error').removeClass("error")
|
||||
console.log("save video?", recording)
|
||||
if(recording.video) {
|
||||
$dialog.find('.save-video').show()
|
||||
}
|
||||
else {
|
||||
$dialog.find('.save-video').hide()
|
||||
}
|
||||
removeGoogleLoginErrors()
|
||||
}
|
||||
|
||||
|
|
@ -103,6 +110,14 @@
|
|||
}
|
||||
|
||||
function afterHide() {
|
||||
if(recording && recording.video) {
|
||||
var name = $('#recording-finished-dialog form input[name=name]').val();
|
||||
name = name.replace(/[^A-Za-z0-9\-\ ]/g, '');
|
||||
var keep = $('#recording-finished-dialog form input[name=save_video]').is(':checked')
|
||||
logger.debug("VideoDecision rid:" + recording.id + ", name=" + name + ", keep=" + keep)
|
||||
context.jamClient.VideoDecision(recording.id, name, keep)
|
||||
}
|
||||
|
||||
recording = null;
|
||||
playbackControls.stopMonitor();
|
||||
context.jamClient.ClosePreviewRecording();
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
var $self = $(this);
|
||||
|
||||
var disabled = false;
|
||||
var playbackPlaying = false;
|
||||
var playbackDurationMs = 0;
|
||||
var playbackPositionMs = 0;
|
||||
|
|
@ -173,6 +174,11 @@
|
|||
}
|
||||
|
||||
$playButton.on('click', function (e) {
|
||||
|
||||
if (disabled) {
|
||||
logger.debug("PlaybackControls are disabled; ignoring start button")
|
||||
return;
|
||||
}
|
||||
startPlay();
|
||||
return false;
|
||||
});
|
||||
|
|
@ -484,6 +490,10 @@
|
|||
playbackPlaying = false;
|
||||
}
|
||||
|
||||
function setDisabled(_disabled) {
|
||||
disabled = _disabled;
|
||||
}
|
||||
|
||||
this.update = update;
|
||||
this.setPlaybackMode = setPlaybackMode;
|
||||
this.startMonitor = startMonitor;
|
||||
|
|
@ -492,6 +502,7 @@
|
|||
this.onPlayStopEvent = onPlayStopEvent;
|
||||
this.onPlayStartEvent = onPlayStartEvent;
|
||||
this.onPlayPauseEvent = onPlayPauseEvent;
|
||||
this.setDisabled = setDisabled;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,11 @@ MixerActions = reactContext.MixerActions
|
|||
MediaPlaybackStore = reactContext.MediaPlaybackStore
|
||||
SessionActions = reactContext.SessionActions
|
||||
MediaPlaybackActions = reactContext.MediaPlaybackActions
|
||||
JamTrackStore = reactContext.JamTrackStore
|
||||
|
||||
mixins.push(Reflux.listenTo(MixerStore,"onInputsChanged"))
|
||||
mixins.push(Reflux.listenTo(MediaPlaybackStore, 'onMediaStateChanged'))
|
||||
mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackStateChanged'))
|
||||
|
||||
|
||||
@MediaControls = React.createClass({
|
||||
|
|
@ -29,6 +31,10 @@ mixins.push(Reflux.listenTo(MediaPlaybackStore, 'onMediaStateChanged'))
|
|||
mixins: mixins
|
||||
tempos : [ 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 63, 66, 69, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 126, 132, 138, 144, 152, 160, 168, 176, 184, 192, 200, 208 ]
|
||||
|
||||
onJamTrackStateChanged: (jamTrackState) ->
|
||||
@monitorControls(@state.controls, @state.mediaSummary, jamTrackState)
|
||||
@setState({jamTrackState: jamTrackState})
|
||||
|
||||
onMediaStateChanged: (changes) ->
|
||||
if changes.playbackStateChanged
|
||||
if @state.controls?
|
||||
|
|
@ -53,7 +59,7 @@ mixins.push(Reflux.listenTo(MediaPlaybackStore, 'onMediaStateChanged'))
|
|||
mediaSummary = mixers.mediaSummary
|
||||
metro = mixers.metro
|
||||
|
||||
@monitorControls(@state.controls, mediaSummary)
|
||||
@monitorControls(@state.controls, mediaSummary, @state.jamTrackState)
|
||||
@setState({mediaSummary: mediaSummary, metro: metro})
|
||||
|
||||
@updateMetronomeDetails(metro, @state.initializedMetronomeControls)
|
||||
|
|
@ -69,10 +75,10 @@ mixins.push(Reflux.listenTo(MediaPlaybackStore, 'onMediaStateChanged'))
|
|||
logger.debug("settingcricket", mode)
|
||||
$root.find('#metronome-playback-select').metronomeSetPlaybackMode(mode)
|
||||
|
||||
monitorControls: (controls, mediaSummary) ->
|
||||
monitorControls: (controls, mediaSummary, jamTrackState) ->
|
||||
|
||||
if mediaSummary.mediaOpen || mediaSummary.jamTrack?
|
||||
if mediaSummary.jamTrack?
|
||||
if mediaSummary.mediaOpen || mediaSummary.jamTrack? || jamTrackState?.jamTrack?
|
||||
if mediaSummary.jamTrackOpen? || mediaSummary.jamTrack? || jamTrackState?.jamTrack?
|
||||
controls.startMonitor(PLAYBACK_MONITOR_MODE.JAMTRACK)
|
||||
else if mediaSummary.backingTrackOpen
|
||||
controls.startMonitor(PLAYBACK_MONITOR_MODE.MEDIA_FILE)
|
||||
|
|
@ -200,13 +206,19 @@ mixins.push(Reflux.listenTo(MediaPlaybackStore, 'onMediaStateChanged'))
|
|||
|
||||
$root = jQuery(this.getDOMNode())
|
||||
controls = context.JK.PlaybackControls($root, {mediaActions: MediaPlaybackActions})
|
||||
controls.setDisabled(@props.disabled)
|
||||
|
||||
mediaSummary = MixerStore.mixers.mediaSummary
|
||||
metro = MixerStore.mixers.metro
|
||||
jamTrackState = JamTrackStore.getState()
|
||||
|
||||
@monitorControls(controls, mediaSummary)
|
||||
@monitorControls(controls, mediaSummary, jamTrackState)
|
||||
|
||||
@tryPrepareMetronome(metro)
|
||||
|
||||
@setState({mediaSummary: mediaSummary, controls: controls, metro: metro})
|
||||
@setState({mediaSummary: mediaSummary, controls: controls, metro: metro, jamTrackState: jamTrackState})
|
||||
|
||||
componentWillUpdate: (nextProps) ->
|
||||
|
||||
@state.controls.setDisabled(nextProps.disabled) if @state.controls?
|
||||
})
|
||||
|
|
@ -16,8 +16,10 @@ if window.opener?
|
|||
|
||||
|
||||
if accessOpener
|
||||
AppActions = window.opener.AppActions
|
||||
SessionActions = window.opener.SessionActions
|
||||
MixerActions = window.opener.MixerActions
|
||||
MixerStore = window.opener.MixerStore
|
||||
JamTrackActions = window.opener.JamTrackActions
|
||||
JamTrackMixdownActions = window.opener.JamTrackMixdownActions
|
||||
#JamTrackMixdownStore = window.opener.JamTrackMixdownStore
|
||||
|
|
@ -33,10 +35,8 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
|
||||
mixins: mixins
|
||||
|
||||
onMixersChanged: (sessionMixers) ->
|
||||
updateFromMixerHelper: (mixers, session) ->
|
||||
|
||||
session = sessionMixers.session
|
||||
mixers = sessionMixers.mixers
|
||||
|
||||
# the backend delete/adds the metronome rapidly when the user hits play. this is custom code to deal with that
|
||||
|
||||
|
|
@ -49,16 +49,20 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
metronome: mixers.metronome
|
||||
recordingName: mixers.recordingName()
|
||||
jamTrackName: mixers.jamTrackName()
|
||||
jamTrackMixdown: session.jamTrackMixdown()
|
||||
|
||||
@setState(media: state, downloadingJamTrack: session.downloadingJamTrack)
|
||||
return {media: state, downloadingJamTrack: session.downloadingJamTrack}
|
||||
|
||||
onMixersChanged: (sessionMixers) ->
|
||||
session = sessionMixers.session
|
||||
mixers = sessionMixers.mixers
|
||||
|
||||
@setState(@updateFromMixerHelper(mixers, session))
|
||||
|
||||
onMediaStateChanged: (changes) ->
|
||||
if changes.currentTimeChanged && @root?
|
||||
@setState({time: changes.time})
|
||||
|
||||
onJamTrackMixdownChanged: (changes) ->
|
||||
@setState({mixdown: changes})
|
||||
|
||||
onJamTrackChanged: (changes) ->
|
||||
logger.debug("PopupMediaControls: jamtrack changed", changes)
|
||||
@setState({jamTrackState: changes})
|
||||
|
|
@ -69,19 +73,32 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
SessionActions.showNativeMetronomeGui()
|
||||
|
||||
getInitialState: () ->
|
||||
{
|
||||
|
||||
if accessOpener
|
||||
|
||||
state = @updateFromMixerHelper(MixerStore.mixers, MixerStore.session)
|
||||
state.jamTrackState = JamTrackStore.getState()
|
||||
return state
|
||||
else
|
||||
|
||||
return {
|
||||
media: @props.media,
|
||||
mixdown: @props.mixdown,
|
||||
jamTrackState: @props.jamTrackState,
|
||||
creatingMixdown: false,
|
||||
createMixdownErrors: null,
|
||||
editingMixdownId: null,
|
||||
downloadingJamTrack: @props.downloadingJamTrack
|
||||
downloadingJamTrack: @props.downloadingJamTrack,
|
||||
jamTrackMixdown: {}
|
||||
}
|
||||
|
||||
close: () ->
|
||||
window.close()
|
||||
|
||||
help: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
AppActions.openExternalUrl($(e.target).attr('href'))
|
||||
|
||||
render: () ->
|
||||
|
||||
|
|
@ -95,235 +112,268 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
mediaName = @state.media.recordedTracks[0].recordingName
|
||||
closeLinkText = 'close recording'
|
||||
header = `<h3>{mediaType}: {mediaName}</h3>`
|
||||
else if @state.jamTrackState.jamTrack?
|
||||
jamTrack = @state.jamTrackState.jamTrack
|
||||
mediaType = "JamTrack"
|
||||
mediaName = jamTrack.name
|
||||
closeLinkText = 'CLOSE JAMTRACK'
|
||||
else if @state.media.mediaSummary.jamTrackOpen || @state.jamTrackState.jamTrack?
|
||||
if @state.media.mediaSummary.isOpener || @state.jamTrackState.jamTrack?
|
||||
# if you opened the JamTrack, then you get all the good info
|
||||
jamTrack = @state.jamTrackState.jamTrack
|
||||
mediaType = "JamTrack"
|
||||
mediaName = jamTrack.name
|
||||
closeLinkText = 'CLOSE JAMTRACK'
|
||||
helpLink = 'https://jamkazam.desk.com/customer/portal/articles/2138903-using-custom-mixes-to-slow-tempo-change-pitch'
|
||||
|
||||
selectedMixdown = jamTrack.activeMixdown
|
||||
|
||||
|
||||
selectedMixdown = jamTrack.activeMixdown
|
||||
if selectedMixdown?
|
||||
jamTrackTypeHeader = 'Custom Mix'
|
||||
|
||||
|
||||
if selectedMixdown?
|
||||
jamTrackTypeHeader = 'Custom Mix'
|
||||
|
||||
disabled = true
|
||||
if selectedMixdown.client_state?
|
||||
switch selectedMixdown.client_state
|
||||
when 'cant_open'
|
||||
disabled = true
|
||||
if selectedMixdown.client_state?
|
||||
switch selectedMixdown.client_state
|
||||
when 'cant_open'
|
||||
customMixName = `<h5>{selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
|
||||
when 'keying_timeout'
|
||||
customMixName = `<h5>{selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
|
||||
when 'download_fail'
|
||||
customMixName = `<h5>{selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
|
||||
when 'keying'
|
||||
customMixName = `<h5>Loading selected mix... <img src="/assets/shared/spinner.gif" /></h5>`
|
||||
when 'downloading'
|
||||
customMixName = `<h5>Loading selected mix... <img src="/assets/shared/spinner.gif" /></h5>`
|
||||
when 'ready'
|
||||
customMixName = `<h5>{selectedMixdown.name}</h5>`
|
||||
disabled = false
|
||||
else
|
||||
if selectedMixdown.myPackage
|
||||
customMixName = `<h5>Creating mixdown... <img src="/assets/shared/spinner.gif" /></h5>`
|
||||
else
|
||||
customMixName = `<h5>{selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
|
||||
when 'keying_timeout'
|
||||
customMixName = `<h5>{selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
|
||||
when 'download_fail'
|
||||
customMixName = `<h5>{selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
|
||||
when 'keying'
|
||||
customMixName = `<h5>Loading selected mix... <img src="/assets/shared/spinner.gif" /></h5>`
|
||||
when 'downloading'
|
||||
customMixName = `<h5>Loading selected mix... <img src="/assets/shared/spinner.gif" /></h5>`
|
||||
when 'ready'
|
||||
customMixName = `<h5>{selectedMixdown.name}</h5>`
|
||||
disabled = false
|
||||
|
||||
else
|
||||
customMixName = `<h5>Creating mixdown... <img src="/assets/shared/spinner.gif" /></h5>`
|
||||
if SessionStore.downloadingJamTrack
|
||||
downloader = `<img src="/assets/shared/spinner.gif" />`
|
||||
|
||||
else
|
||||
if SessionStore.downloadingJamTrack
|
||||
downloader = `<img src="/assets/shared/spinner.gif" />`
|
||||
jamTrackTypeHeader = `<span>Full JamTrack {downloader}</span>`
|
||||
|
||||
jamTrackTypeHeader = `<span>Full JamTrack {downloader}</span>`
|
||||
header = `
|
||||
<div className="header">
|
||||
<h3>{mediaType}: {mediaName}</h3>
|
||||
<h4>{jamTrackTypeHeader}</h4>
|
||||
{customMixName}
|
||||
</div>`
|
||||
|
||||
header = `
|
||||
<div className="header">
|
||||
<h3>{mediaType}: {mediaName}</h3>
|
||||
<h4>{jamTrackTypeHeader}</h4>
|
||||
{customMixName}
|
||||
</div>`
|
||||
myMixes = null
|
||||
if @state.showMyMixes
|
||||
myMixdowns = []
|
||||
|
||||
myMixes = null
|
||||
if @state.showMyMixes
|
||||
myMixdowns = []
|
||||
boundPlayClick = this.jamTrackPlay.bind(this, jamTrack);
|
||||
|
||||
boundPlayClick = this.jamTrackPlay.bind(this, jamTrack);
|
||||
|
||||
active = jamTrack.last_mixdown_id == null
|
||||
|
||||
myMixdowns.push `
|
||||
<div key="full-track" className={classNames({'full-track': true, 'mixdown-display': true, 'active' : active})}>
|
||||
<div className="mixdown-name">
|
||||
Full JamTrack
|
||||
</div>
|
||||
<div className="mixdown-actions">
|
||||
<img src="/assets/content/icon_open@2X.png" className="mixdown-play" onClick={boundPlayClick}/>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
for mixdown in jamTrack.mixdowns
|
||||
boundPlayClick = this.mixdownPlay.bind(this, mixdown);
|
||||
boundEditClick = this.mixdownEdit.bind(this, mixdown);
|
||||
boundSaveClick = this.mixdownSave.bind(this, mixdown);
|
||||
boundDeleteClick = this.mixdownDelete.bind(this, mixdown);
|
||||
boundErrorClick = this.mixdownError.bind(this, mixdown);
|
||||
boundEditKeydown = this.onEditKeydown.bind(this, mixdown);
|
||||
|
||||
mixdown_package = mixdown.myPackage
|
||||
|
||||
active = mixdown.id == jamTrack.last_mixdown_id
|
||||
|
||||
editing = mixdown.id == @state.editingMixdownId
|
||||
|
||||
# if there is a package, check it's state; otherwise let the user enqueue it
|
||||
if mixdown_package
|
||||
switch mixdown_package.signing_state
|
||||
when 'QUIET_TIMEOUT'
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
when 'QUIET'
|
||||
action = `<img src="/assets/shared/spinner.gif" className="mixdown-play"/>`
|
||||
when 'QUEUED'
|
||||
action = `<img src="/assets/shared/spinner.gif" className="mixdown-play"/>`
|
||||
when 'QUEUED_TIMEOUT'
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
when 'SIGNING'
|
||||
action = `<img src="/assets/shared/spinner.gif" className="mixdown-play"/>`
|
||||
when 'SIGNING_TIMEOUT'
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
when 'SIGNED'
|
||||
action = `<img src="/assets/content/icon_open@2X.png" className="mixdown-play" onClick={boundPlayClick}/>`
|
||||
when 'ERROR'
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
else
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
|
||||
if editing
|
||||
mixdownName = `<input className="edit-name" type="text" defaultValue={mixdown.name} onKeyDown={boundEditKeydown} />`
|
||||
editIcon = `<img src="/assets/content/icon-save@2X.png" className="mixdown-edit" onClick={boundSaveClick}/>`
|
||||
else
|
||||
mixdownName = mixdown.name
|
||||
editIcon = `<img src="/assets/content/icon-edit@2X.png" className="mixdown-edit" onClick={boundEditClick}/>`
|
||||
active = jamTrack.last_mixdown_id == null
|
||||
|
||||
myMixdowns.push `
|
||||
<div key={mixdown.id} className={classNames({'mixdown-display': true, 'active' : active})}>
|
||||
<div className="mixdown-name">
|
||||
{mixdownName}
|
||||
</div>
|
||||
<div className="mixdown-actions">
|
||||
{action}
|
||||
<div key="full-track" className={classNames({'full-track': true, 'mixdown-display': true, 'active' : active})}>
|
||||
<div className="mixdown-name">
|
||||
Full JamTrack
|
||||
</div>
|
||||
<div className="mixdown-actions">
|
||||
<img src="/assets/content/icon_open@2X.png" className="mixdown-play" onClick={boundPlayClick}/>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
{editIcon}
|
||||
for mixdown in jamTrack.mixdowns
|
||||
boundPlayClick = this.mixdownPlay.bind(this, mixdown);
|
||||
boundEditClick = this.mixdownEdit.bind(this, mixdown);
|
||||
boundSaveClick = this.mixdownSave.bind(this, mixdown);
|
||||
boundDeleteClick = this.mixdownDelete.bind(this, mixdown);
|
||||
boundErrorClick = this.mixdownError.bind(this, mixdown);
|
||||
boundEditKeydown = this.onEditKeydown.bind(this, mixdown);
|
||||
|
||||
<img src ="/assets/content/icon-delete@2X.png" className="mixdown-delete" onClick={boundDeleteClick} />
|
||||
</div>
|
||||
</div>`
|
||||
mixdown_package = mixdown.myPackage
|
||||
|
||||
myMixes = `<div key="my-mixes" className="my-mixes">{myMixdowns}</div>`
|
||||
active = mixdown.id == jamTrack.last_mixdown_id
|
||||
|
||||
mixControls = null
|
||||
if @state.showCustomMixes
|
||||
editing = mixdown.id == @state.editingMixdownId
|
||||
|
||||
nameClassData = {field: true}
|
||||
if @state.createMixdownErrors?
|
||||
# if there is a package, check it's state; otherwise let the user enqueue it
|
||||
if mixdown_package
|
||||
switch mixdown_package.signing_state
|
||||
when 'QUIET_TIMEOUT'
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
when 'QUIET'
|
||||
action = `<img src="/assets/shared/spinner.gif" className="mixdown-play"/>`
|
||||
when 'QUEUED'
|
||||
action = `<img src="/assets/shared/spinner.gif" className="mixdown-play"/>`
|
||||
when 'QUEUED_TIMEOUT'
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
when 'SIGNING'
|
||||
action = `<img src="/assets/shared/spinner.gif" className="mixdown-play"/>`
|
||||
when 'SIGNING_TIMEOUT'
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
when 'SIGNED'
|
||||
action = `<img src="/assets/content/icon_open@2X.png" className="mixdown-play" onClick={boundPlayClick}/>`
|
||||
when 'ERROR'
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
else
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
|
||||
errorHtml = context.JK.reactErrors(@state.createMixdownErrors, {name: 'Mix Name', settings: 'Settings', jam_track: 'JamTrack'})
|
||||
if editing
|
||||
mixdownName = `<input className="edit-name" type="text" defaultValue={mixdown.name} onKeyDown={boundEditKeydown} />`
|
||||
editIcon = `<img src="/assets/content/icon-save@2X.png" className="mixdown-edit" onClick={boundSaveClick}/>`
|
||||
else
|
||||
mixdownName = mixdown.name
|
||||
editIcon = `<img src="/assets/content/icon-edit@2X.png" className="mixdown-edit" onClick={boundEditClick}/>`
|
||||
|
||||
createMixClasses = classNames({'button-orange' : true, 'create-mix-btn' : true, 'disabled' : @state.creatingMixdown})
|
||||
mixControls = `
|
||||
<div key="create-mix" className="create-mix">
|
||||
<p>Use the JamTrack controls on the session screen to set levels, mute/unmute, or pan any of the parts of the JamTrack as you like. You can also use the controls below to adjust the tempo or pitch of the JamTrack. Then give your custom mix a name, and click the Create Mix button. Please note that changing the tempo or pitch of the JamTrack may take a long time, and won't be ready right away.</p>
|
||||
<div className="field">
|
||||
<label>Change Tempo:</label>
|
||||
<select name="mix-speed">
|
||||
<option value="">No change</option>
|
||||
<option value="separator-1">------------</option>
|
||||
<option value="-5">Slower by 5%</option>
|
||||
<option value="-10">Slower by 10%</option>
|
||||
<option value="-15">Slower by 15%</option>
|
||||
<option value="-20">Slower by 20%</option>
|
||||
<option value="-25">Slower by 25%</option>
|
||||
<option value="-30">Slower by 30%</option>
|
||||
<option value="-35">Slower by 35%</option>
|
||||
<option value="-40">Slower by 40%</option>
|
||||
<option value="-45">Slower by 45%</option>
|
||||
<option value="-50">Slower by 50%</option>
|
||||
<option value="-60">Slower by 60%</option>
|
||||
<option value="-70">Slower by 70%</option>
|
||||
<option value="-80">Slower by 80%</option>
|
||||
<option value="separator-2">------------</option>
|
||||
<option value="5">Faster by 5%</option>
|
||||
<option value="10">Faster by 10%</option>
|
||||
<option value="15">Faster by 15%</option>
|
||||
<option value="20">Faster by 20%</option>
|
||||
<option value="30">Faster by 30%</option>
|
||||
<option value="40">Faster by 40%</option>
|
||||
<option value="50">Faster by 50%</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>Change Pitch:</label>
|
||||
<select name="mix-pitch">
|
||||
<option value="">No change</option>
|
||||
<option value="separator-1">---------------</option>
|
||||
<option value="-1">Down 1 Semitone</option>
|
||||
<option value="-2">Down 2 Semitones</option>
|
||||
<option value="-3">Down 3 Semitones</option>
|
||||
<option value="-4">Down 4 Semitones</option>
|
||||
<option value="-5">Down 5 Semitones</option>
|
||||
<option value="-6">Down 6 Semitones</option>
|
||||
<option value="-7">Down 7 Semitones</option>
|
||||
<option value="-8">Down 8 Semitones</option>
|
||||
<option value="-9">Down 9 Semitones</option>
|
||||
<option value="-10">Down 10 Semitones</option>
|
||||
<option value="-11">Down 11 Semitones</option>
|
||||
<option value="-12">Down 12 Semitones</option>
|
||||
<option value="separator-2">---------------</option>
|
||||
<option value="1">Up 1 Semitone</option>
|
||||
<option value="2">Up 2 Semitones</option>
|
||||
<option value="3">Up 3 Semitones</option>
|
||||
<option value="4">Up 4 Semitones</option>
|
||||
<option value="5">Up 5 Semitones</option>
|
||||
<option value="6">Up 6 Semitones</option>
|
||||
<option value="7">Up 7 Semitones</option>
|
||||
<option value="8">Up 8 Semitones</option>
|
||||
<option value="9">Up 9 Semitones</option>
|
||||
<option value="10">Up 10 Semitones</option>
|
||||
<option value="11">Up 11 Semitones</option>
|
||||
<option value="12">Up 12 Semitones</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={classNames(nameClassData)}>
|
||||
<label>Mix Name:</label>
|
||||
<input type="text" name="mix-name"/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<a className={createMixClasses} onClick={this.createMix}>CREATE MIX</a>
|
||||
{errorHtml}
|
||||
</div>
|
||||
<div className="clearall"/>
|
||||
myMixdowns.push `
|
||||
<div key={mixdown.id} className={classNames({'mixdown-display': true, 'active' : active})}>
|
||||
<div className="mixdown-name">
|
||||
{mixdownName}
|
||||
</div>
|
||||
<div className="mixdown-actions">
|
||||
{action}
|
||||
|
||||
{editIcon}
|
||||
|
||||
<img src ="/assets/content/icon-delete@2X.png" className="mixdown-delete" onClick={boundDeleteClick} />
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
myMixes = `<div key="my-mixes" className="my-mixes">{myMixdowns}</div>`
|
||||
|
||||
mixControls = null
|
||||
if @state.showCustomMixes
|
||||
|
||||
nameClassData = {field: true}
|
||||
if @state.createMixdownErrors?
|
||||
|
||||
errorHtml = context.JK.reactErrors(@state.createMixdownErrors, {name: 'Mix Name', settings: 'Settings', jam_track: 'JamTrack'})
|
||||
|
||||
createMixClasses = classNames({'button-orange' : true, 'create-mix-btn' : true, 'disabled' : @state.creatingMixdown})
|
||||
|
||||
if !selectedMixdown?
|
||||
mixControls = `
|
||||
<div key="create-mix" className="create-mix">
|
||||
<p>Use the JamTrack controls on the session screen to set levels, mute/unmute, or pan any of the parts of the JamTrack as you like. You can also use the controls below to adjust the tempo or pitch of the JamTrack. Then give your custom mix a name, and click the Create Mix button. Please note that changing the tempo or pitch of the JamTrack may take a long time, and won't be ready right away.</p>
|
||||
<div className="field">
|
||||
<label>Change Tempo:</label>
|
||||
<select name="mix-speed">
|
||||
<option value="">No change</option>
|
||||
<option value="separator-1">------------</option>
|
||||
<option value="-5">Slower by 5%</option>
|
||||
<option value="-10">Slower by 10%</option>
|
||||
<option value="-15">Slower by 15%</option>
|
||||
<option value="-20">Slower by 20%</option>
|
||||
<option value="-25">Slower by 25%</option>
|
||||
<option value="-30">Slower by 30%</option>
|
||||
<option value="-35">Slower by 35%</option>
|
||||
<option value="-40">Slower by 40%</option>
|
||||
<option value="-45">Slower by 45%</option>
|
||||
<option value="-50">Slower by 50%</option>
|
||||
<option value="-60">Slower by 60%</option>
|
||||
<option value="-70">Slower by 70%</option>
|
||||
<option value="-80">Slower by 80%</option>
|
||||
<option value="separator-2">------------</option>
|
||||
<option value="5">Faster by 5%</option>
|
||||
<option value="10">Faster by 10%</option>
|
||||
<option value="15">Faster by 15%</option>
|
||||
<option value="20">Faster by 20%</option>
|
||||
<option value="30">Faster by 30%</option>
|
||||
<option value="40">Faster by 40%</option>
|
||||
<option value="50">Faster by 50%</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>Change Pitch:</label>
|
||||
<select name="mix-pitch">
|
||||
<option value="">No change</option>
|
||||
<option value="separator-1">---------------</option>
|
||||
<option value="-1">Down 1 Semitone</option>
|
||||
<option value="-2">Down 2 Semitones</option>
|
||||
<option value="-3">Down 3 Semitones</option>
|
||||
<option value="-4">Down 4 Semitones</option>
|
||||
<option value="-5">Down 5 Semitones</option>
|
||||
<option value="-6">Down 6 Semitones</option>
|
||||
<option value="-7">Down 7 Semitones</option>
|
||||
<option value="-8">Down 8 Semitones</option>
|
||||
<option value="-9">Down 9 Semitones</option>
|
||||
<option value="-10">Down 10 Semitones</option>
|
||||
<option value="-11">Down 11 Semitones</option>
|
||||
<option value="-12">Down 12 Semitones</option>
|
||||
<option value="separator-2">---------------</option>
|
||||
<option value="1">Up 1 Semitone</option>
|
||||
<option value="2">Up 2 Semitones</option>
|
||||
<option value="3">Up 3 Semitones</option>
|
||||
<option value="4">Up 4 Semitones</option>
|
||||
<option value="5">Up 5 Semitones</option>
|
||||
<option value="6">Up 6 Semitones</option>
|
||||
<option value="7">Up 7 Semitones</option>
|
||||
<option value="8">Up 8 Semitones</option>
|
||||
<option value="9">Up 9 Semitones</option>
|
||||
<option value="10">Up 10 Semitones</option>
|
||||
<option value="11">Up 11 Semitones</option>
|
||||
<option value="12">Up 12 Semitones</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={classNames(nameClassData)}>
|
||||
<label>Mix Name:</label>
|
||||
<input type="text" name="mix-name"/>
|
||||
</div>
|
||||
<div className="field">
|
||||
<a className={createMixClasses} onClick={this.createMix}>CREATE MIX</a>
|
||||
{errorHtml}
|
||||
</div>
|
||||
<div className="clearall"/>
|
||||
|
||||
</div>`
|
||||
else
|
||||
|
||||
mixControls =
|
||||
`<div key="no-full-mix-open" className="create-mix not-active">
|
||||
<p>To create a custom mix, you must open the Full JamTrack in the My Mixes section above.</p>
|
||||
</div>`
|
||||
|
||||
if @state.showMyMixes
|
||||
showMyMixesText = `<a onClick={this.toggleMyMixes}>hide my mixes <div className="details-arrow arrow-up" /></a>`
|
||||
else
|
||||
showMyMixesText = `<a onClick={this.toggleMyMixes}>show my mixes <div className="details-arrow arrow-down" /></a>`
|
||||
|
||||
if @state.showCustomMixes
|
||||
showMixControlsText = `<a onClick={this.toggleCustomMixes}>hide mix controls <div className="details-arrow arrow-up" /></a>`
|
||||
else
|
||||
showMixControlsText = `<a onClick={this.toggleCustomMixes}>show mix controls <div className="details-arrow arrow-down" /></a>`
|
||||
|
||||
|
||||
extraControls = `
|
||||
<div className="extra-controls">
|
||||
<h4>My Mixes {showMyMixesText}</h4>
|
||||
<ReactCSSTransitionGroup transitionName="session-track-list" transitionAppear={true}>
|
||||
{myMixes}
|
||||
</ReactCSSTransitionGroup>
|
||||
<h4 className="custom-mix-header">Create Custom Mix {showMixControlsText}</h4>
|
||||
<ReactCSSTransitionGroup transitionName="session-track-list" transitionAppear={true}>
|
||||
{mixControls}
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>`
|
||||
else
|
||||
|
||||
mediaType = "JamTrack"
|
||||
mediaName = @state.media.jamTrackName
|
||||
closeLinkText = 'CLOSE JAMTRACK'
|
||||
|
||||
# implies we have a mixdown
|
||||
if @state.media.jamTrackMixdown.id?
|
||||
jamTrackTypeHeader = 'Custom Mix'
|
||||
else
|
||||
jamTrackTypeHeader = 'Full JamTrack'
|
||||
|
||||
header = `
|
||||
<div className="header">
|
||||
<h3>{mediaType}: {mediaName}</h3>
|
||||
<h4>{jamTrackTypeHeader}</h4>
|
||||
{customMixName}
|
||||
</div>`
|
||||
|
||||
|
||||
if @state.showMyMixes
|
||||
showMyMixesText = 'hide my mixes'
|
||||
else
|
||||
showMyMixesText = 'show my mixes'
|
||||
|
||||
if @state.showCustomMixes
|
||||
showMixControlsText = 'hide mix controls'
|
||||
else
|
||||
showMixControlsText = 'show mix controls'
|
||||
|
||||
|
||||
extraControls = `
|
||||
<div className="extra-controls">
|
||||
<h4>My Mixes <a onClick={this.toggleMyMixes}>{showMyMixesText}</a></h4>
|
||||
<ReactCSSTransitionGroup transitionName="session-track-list" transitionAppear={true}>
|
||||
{myMixes}
|
||||
</ReactCSSTransitionGroup>
|
||||
<h4 className="custom-mix-header">Create Custom Mix <a onClick={this.toggleCustomMixes}>{showMixControlsText}</a></h4>
|
||||
<ReactCSSTransitionGroup transitionName="session-track-list" transitionAppear={true}>
|
||||
{mixControls}
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>`
|
||||
>>>>>>> develop
|
||||
|
||||
else if @state.media.mediaSummary.backingTrackOpen
|
||||
mediaType = "Audio File"
|
||||
|
|
@ -348,11 +398,17 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
else
|
||||
mediaType = ""
|
||||
|
||||
if helpLink?
|
||||
helpButton = `<a className="help-link button-grey" href={helpLink} onClick={this.help}>HELP</a>`
|
||||
|
||||
`<div className="media-controls-popup">
|
||||
{header}
|
||||
<MediaControls />
|
||||
<MediaControls disabled={this.state.downloadingJamTrack || this.disableLoading}/>
|
||||
{extraControls}
|
||||
<a className="close-link button-orange" onClick={this.close}>{closeLinkText}</a>
|
||||
<div className="actions">
|
||||
{helpButton}
|
||||
<a className="close-link button-orange" onClick={this.close}>{closeLinkText}</a>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
windowUnloaded: () ->
|
||||
|
|
@ -436,7 +492,23 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
return unless action?
|
||||
|
||||
if confirm(action)
|
||||
JamTrackMixdownActions.enqueueMixdown(mixdown)
|
||||
JamTrackMixdownActions.enqueueMixdown(mixdown, @enqueueDone)
|
||||
|
||||
enqueueDone: (enqueued) ->
|
||||
@promptEstimate(enqueued)
|
||||
|
||||
promptEstimate: (enqueued) ->
|
||||
time = enqueued.queue_time
|
||||
|
||||
if time == 0
|
||||
alert("Your custom mix will take about 1 minute to be created.")
|
||||
else
|
||||
guess = Math.ceil(time / 60.0)
|
||||
if guess == 1
|
||||
msg = '1 minute'
|
||||
else
|
||||
msg = "#{guess} minutes"
|
||||
alert("Your custom mix will take about #{msg} to be created.")
|
||||
|
||||
createMix: (e) ->
|
||||
e.preventDefault()
|
||||
|
|
@ -478,6 +550,8 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
# automatically close the create custom mix area
|
||||
@setState({creatingMixdown: false, showCustomMixes: false, showMyMixes: true})
|
||||
|
||||
@promptEstimate(created)
|
||||
|
||||
createMixdownFail: (jqXHR) ->
|
||||
logger.debug("create mixdown fail (within PopupMediaControls)", jqXHR.status)
|
||||
@setState({creatingMixdown: false})
|
||||
|
|
@ -533,13 +607,12 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
|
||||
window.resizeTo(width, height + offset)
|
||||
|
||||
componentWillUpdate: (nextProps, nextState) ->
|
||||
|
||||
computeDisableLoading: (state) ->
|
||||
@disableLoading = false
|
||||
|
||||
return unless nextState?
|
||||
|
||||
selectedMixdown = nextState?.jamTrackState?.jamTrack?.activeMixdown
|
||||
selectedMixdown = state?.jamTrackState?.jamTrack?.activeMixdown
|
||||
|
||||
mixdownDownloading = false
|
||||
if selectedMixdown?
|
||||
|
|
@ -552,5 +625,10 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
|
||||
@disableLoading = SessionStore.downloadingJamTrack || mixdownDownloading
|
||||
|
||||
componentWillMount: () ->
|
||||
@computeDisableLoading(@state)
|
||||
|
||||
componentWillUpdate: (nextProps, nextState) ->
|
||||
@computeDisableLoading(nextState)
|
||||
|
||||
})
|
||||
|
|
@ -1,24 +1,40 @@
|
|||
context = window
|
||||
logger = context.JK.logger
|
||||
|
||||
NoVideoRecordActive = 0
|
||||
WebCamRecordActive = 1
|
||||
ScreenRecordActive = 2
|
||||
|
||||
mixins = []
|
||||
|
||||
# make sure this is actually us opening the window, not someone else (by checking for MixerStore)
|
||||
|
||||
# this check ensures we attempt to listen if this component is created in a popup
|
||||
reactContext = if window.opener? then window.opener else window
|
||||
|
||||
accessOpener = false
|
||||
if window.opener?
|
||||
try
|
||||
m = window.opener.MixerStore
|
||||
accessOpener = true
|
||||
catch e
|
||||
reactContext = window
|
||||
|
||||
MixerStore = reactContext.MixerStore
|
||||
RecordingStore = reactContext.RecordingStore
|
||||
VideoStore = reactContext.VideoStore
|
||||
|
||||
if accessOpener
|
||||
mixins.push(Reflux.listenTo(window.opener.RecordingStore,"onRecordingStateChanged"))
|
||||
mixins.push(Reflux.listenTo(RecordingStore,"onRecordingStateChanged"))
|
||||
# mixins.push(Reflux.listenTo(MixerStore,"onMixersChanged"))
|
||||
|
||||
@PopupRecordingStartStop = React.createClass({
|
||||
|
||||
mixins: mixins
|
||||
|
||||
#onMixersChanged: (mixers) ->
|
||||
# this.setState(chatMixer: mixers.chatMixer)
|
||||
|
||||
onRecordingStateChanged: (recordingState) ->
|
||||
this.setState(isRecording: recordingState.isRecording, recordedOnce: this.state.recordedOnce || recordingState.isRecording)
|
||||
|
||||
|
|
@ -26,13 +42,39 @@ if accessOpener
|
|||
if this.state.isRecording
|
||||
window.opener.RecordingActions.stopRecording()
|
||||
else
|
||||
window.opener.RecordingActions.startRecording()
|
||||
recordChat = false
|
||||
recordVideo = NoVideoRecordActive
|
||||
|
||||
$root = $(this.getDOMNode())
|
||||
|
||||
if @inputType != 'audio-only'
|
||||
|
||||
if $root.find('#recording-selection').val() == 'video-window'
|
||||
recordVideo = ScreenRecordActive
|
||||
else
|
||||
recordVideo = WebCamRecordActive
|
||||
|
||||
|
||||
recordChat = $root.find('#include-chat').is(':checked')
|
||||
|
||||
|
||||
# if the video window isn't open, but a video option was selected...
|
||||
if recordVideo != NoVideoRecordActive && !VideoStore.videoShared
|
||||
logger.debug("prevent video from opening", VideoStore)
|
||||
context.JK.prodBubble($root.find('.control'), 'video-window-not-open', {}, {positions:['bottom']})
|
||||
return
|
||||
logger.debug("@inputType, @udiotye", recordChat, recordVideo)
|
||||
window.opener.RecordingActions.startRecording(recordVideo, recordChat)
|
||||
|
||||
onNoteShowHide: () ->
|
||||
|
||||
$root = $(this.getDOMNode())
|
||||
audioVideoValue = $root.find('input[name="recording-input-type"]').val()
|
||||
console.log("audio video value", audioVideoValue)
|
||||
this.setState(showNote: !this.state.showNote)
|
||||
|
||||
getInitialState: () ->
|
||||
{isRecording: window.ParentIsRecording, showNote: true, recordedOnce: false}
|
||||
{isRecording: window.ParentIsRecording, showNote: true, recordedOnce: false, chatMixer: MixerStore.mixers?.chatMixer}
|
||||
|
||||
render: () ->
|
||||
|
||||
|
|
@ -53,16 +95,33 @@ if accessOpener
|
|||
</div>
|
||||
</div>`
|
||||
|
||||
recordingJSX = `<div className="recording-options">
|
||||
<div className="field">
|
||||
<input type="radio" name="recording-input-type" id="recording-input-both" defaultChecked="checked" />
|
||||
<label htmlFor="recording-input-both">Record both video and audio</label>
|
||||
<div className="clearall"></div>
|
||||
|
||||
chatHelp = `<a href="#" onClick={this.onChatHelp} className="chat-help">[?]</a>`
|
||||
|
||||
recordingJSX =
|
||||
`<div className="recording-options">
|
||||
<div className="video-settings">
|
||||
<h3>Recording Type</h3>
|
||||
<div className="field">
|
||||
<input type="radio" name="recording-input-type" id="recording-input-audio" value="audio-only" defaultChecked="checked" />
|
||||
<label htmlFor="recording-input-audio">Audio only</label>
|
||||
<div className="clearall"></div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<input type="radio" name="recording-input-type" id="recording-input-both" value="audio-video" />
|
||||
<label htmlFor="recording-input-both">Audio and video</label>
|
||||
<div className="clearall"></div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<select className="easydropdown" name="recording-selection" id="recording-selection">
|
||||
<option value="video-window">Record session video window</option>
|
||||
<option value="webcam-only">Record my webcam only</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<input type="radio" name="recording-input-type" id="recording-input-audio" />
|
||||
<label htmlFor="recording-input-audio">Record audio only</label>
|
||||
<div className="clearall"></div>
|
||||
|
||||
<div className="audio-settings">
|
||||
<input type="checkbox" name="include-chat" id="include-chat" /><label htmlFor="include-chat">Include voice chat in recorded audio {chatHelp}</label>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
|
|
@ -108,6 +167,20 @@ if accessOpener
|
|||
windowUnloaded: () ->
|
||||
window.opener.RecordingActions.recordingControlsClosed()
|
||||
|
||||
onChatHelp: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
context.JK.prodBubble($(e.target), 'vid-record-chat-input', {}, {positions:['left']})
|
||||
trackInputType: (e) ->
|
||||
$checkedType = $(e.target);
|
||||
@inputType = $checkedType.val()
|
||||
logger.debug("updated @inputType",e.target, @inputType)
|
||||
|
||||
trackAudioType: (e) ->
|
||||
$checkedType = $(e.target);
|
||||
@audioType = $checkedType.val()
|
||||
logger.debug("updated @audioType", @inputType)
|
||||
|
||||
componentDidMount: () ->
|
||||
$(window).unload(@windowUnloaded)
|
||||
|
||||
|
|
@ -116,6 +189,21 @@ if accessOpener
|
|||
$recordingType = $root.find('input[type="radio"]')
|
||||
context.JK.checkbox($recordingType)
|
||||
|
||||
@inputType = 'audio-only'
|
||||
@audioType = 'audio-only'
|
||||
|
||||
$root.find('input[name="recording-input-type"]').on('ifChanged', @trackInputType)
|
||||
$root.find('input[name="recording-input-chat-option"]').on('ifChanged', @trackAudioType)
|
||||
|
||||
$recordingRegion = $root.find('#recording-selection')
|
||||
#console.log("$recordingou", $recordingRegion)
|
||||
#context.JK.dropdown($recordingRegion)
|
||||
|
||||
$includeChat = $root.find('#include-chat')
|
||||
context.JK.checkbox($includeChat)
|
||||
|
||||
|
||||
|
||||
@resizeWindow()
|
||||
|
||||
# this is necessary due to whatever the client's rendering behavior is.
|
||||
|
|
@ -124,6 +212,9 @@ if accessOpener
|
|||
componentDidUpdate: () ->
|
||||
@resizeWindow()
|
||||
|
||||
$root = jQuery(this.getDOMNode())
|
||||
$includeChat = $root.find('#include-chat')
|
||||
|
||||
resizeWindow: () =>
|
||||
$container = $('#minimal-container')
|
||||
width = $container.width()
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
Reflux.listenTo(@JamTrackStore, "onJamTrackStateChanged")]
|
||||
|
||||
onJamTrackStateChanged: (jamTrackState) ->
|
||||
@setState({jamTrackState: jamTrackState})
|
||||
|
||||
if jamTrackState.fullTrackActivated || jamTrackState.opened && jamTrackState.jamTrack.activeMixdown == null
|
||||
@loadJamTrack(jamTrackState.jamTrack)
|
||||
else if jamTrackState.closed
|
||||
|
|
@ -29,6 +31,7 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
|
||||
SessionActions.closeMedia(true)
|
||||
|
||||
|
||||
#inputsChangedProcessed: (state) ->
|
||||
|
||||
|
||||
|
|
@ -225,12 +228,12 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
|
||||
contents = closeOptions
|
||||
|
||||
else if this.state.mediaSummary.mediaOpen
|
||||
else if this.state.mediaSummary.mediaOpen || @state.jamTrackState?.jamTrack?
|
||||
|
||||
# give the users options to close it
|
||||
if this.state.mediaSummary.recordingOpen
|
||||
mediaType = "Recording"
|
||||
else if this.state.mediaSummary.jamTrackOpen
|
||||
else if this.state.mediaSummary.jamTrackOpen || @state.jamTrackState?.jamTrack?
|
||||
mediaType = "JamTrack"
|
||||
else if this.state.mediaSummary.backingTrackOpen
|
||||
mediaType = "Audio File"
|
||||
|
|
@ -308,7 +311,7 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
|
||||
|
||||
getInitialState:() ->
|
||||
{mediaSummary:{mediaOpen: false}, isRecording: false, backingTracks: [], jamTracks: [], recordedTracks: [], metronome: null}
|
||||
{mediaSummary:{mediaOpen: false}, isRecording: false, backingTracks: [], jamTracks: [], recordedTracks: [], metronome: null, jamTrackState: {}}
|
||||
|
||||
onAppInit: (app) ->
|
||||
@app = app
|
||||
|
|
@ -343,7 +346,7 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
@handlePopup()
|
||||
|
||||
handlePopup: () ->
|
||||
if @state.mediaSummary.userNeedsMediaControls
|
||||
if @state.mediaSummary.userNeedsMediaControls || @state.jamTrackState?.jamTrack?
|
||||
unless @childWindow?
|
||||
logger.debug("opening media control window")
|
||||
@childWindow = window.open("/popups/media-controls", 'Media Controls', 'scrollbars=yes,toolbar=no,status=no,height=155,width=350')
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ SessionActions = @SessionActions
|
|||
|
||||
beforeDisconnect: () ->
|
||||
@logger.debug("session beforeDisconnect")
|
||||
return { freezeInteraction: true };
|
||||
|
||||
onAllowLeaveSession: () ->
|
||||
@allowLeave = true
|
||||
|
|
|
|||
|
|
@ -2,4 +2,5 @@ context = window
|
|||
|
||||
@AppActions = Reflux.createActions({
|
||||
appInit: {}
|
||||
openExternalUrl: {}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
backingTracks = @session.backingTracks()
|
||||
recordedJamTracks = @session.recordedJamTracks()
|
||||
jamTracks = @session.jamTracks()
|
||||
jamTrackMixdown = @session.jamTrackMixdown()
|
||||
|
||||
###
|
||||
with mixer info, we use these to decide what kind of tracks are open in the backend
|
||||
|
|
@ -92,6 +93,7 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
@metronomeTrackMixers = []
|
||||
@adhocTrackMixers = []
|
||||
|
||||
|
||||
groupByType = (mixers, isLocalMixer) =>
|
||||
for mixer in mixers
|
||||
mediaType = mixer.media_type
|
||||
|
|
@ -106,7 +108,10 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
|
||||
isJamTrack = false;
|
||||
|
||||
if jamTracks
|
||||
if mixer.id == jamTrackMixdown.id
|
||||
isJamTrack = true;
|
||||
|
||||
if !isJamTrack && jamTracks
|
||||
# check if the ID matches that of an open jam track
|
||||
for jamTrack in jamTracks
|
||||
if mixer.id == jamTrack.id
|
||||
|
|
@ -186,6 +191,8 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
backingTrackOpen: @backingTracks.length > 0
|
||||
metronomeOpen: @session.isMetronomeOpen()
|
||||
|
||||
|
||||
|
||||
# figure out if any media is open
|
||||
mediaOpenSummary = false
|
||||
for mediaType, mediaOpen of @mediaSummary
|
||||
|
|
@ -352,6 +359,10 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
else
|
||||
logger.debug("MixerHelper: full jamtrack is active")
|
||||
|
||||
if jamTrackMixers.length == 1
|
||||
logger.warn("ignoring wrong amount of mixers for JamTrack in Full Track mode")
|
||||
return _jamTracks
|
||||
|
||||
for jamTrack in jamTracks
|
||||
mixer = null
|
||||
preMasteredClass = ""
|
||||
|
|
|
|||
|
|
@ -8,5 +8,9 @@ logger = context.JK.logger
|
|||
|
||||
onAppInit: (app) ->
|
||||
@trigger(app)
|
||||
|
||||
onOpenExternalUrl: (href) ->
|
||||
|
||||
context.JK.popExternalLink(href)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -177,7 +177,9 @@ JamTrackActions = @JamTrackActions
|
|||
, null, true)
|
||||
|
||||
when 'unknown'
|
||||
if @jamTrack.activeMixdown.client_state != 'downloading'
|
||||
# we need to check if @keyCheckTimeout exists; because if it does, we don't want to download while keying.
|
||||
# 'unknown' is tricky here because the file probably is actually on disk, but the bridge API can say unknown until you've tried to key at least once
|
||||
if @jamTrack.activeMixdown.client_state != 'downloading' && !@keyCheckTimeout?
|
||||
@jamTrack.activeMixdown.client_state = 'downloading'
|
||||
logger.debug("JamTrackStore: initiating download of mixdown")
|
||||
context.jamClient.JamTrackDownload(@jamTrack.id, @jamTrack.activeMixdown.id, context.JK.currentUserId,
|
||||
|
|
@ -501,6 +503,8 @@ JamTrackActions = @JamTrackActions
|
|||
|
||||
downloadFailureCallback: (errorMsg) ->
|
||||
|
||||
logger.debug("mixdown download failed", errorMsg);
|
||||
|
||||
if @jamTrack?.activeMixdown?
|
||||
@jamTrack.activeMixdown.client_state = 'download_fail'
|
||||
@reportError(@jamTrack.activeMixdown)
|
||||
|
|
|
|||
|
|
@ -23,8 +23,15 @@ logger = context.JK.logger
|
|||
@recordingModel = recordingModel
|
||||
this.trigger({isRecording: @recordingModel.isRecording()})
|
||||
|
||||
onStartRecording: () ->
|
||||
@recordingModel.startRecording()
|
||||
onStartRecording: (recordVideo, recordChat) ->
|
||||
|
||||
frameRate = context.jamClient.GetCurrentVideoFrameRate() || 30;
|
||||
|
||||
NoVideoRecordActive = 0
|
||||
WebCamRecordActive = 1
|
||||
ScreenRecordActive = 2
|
||||
logger.debug("onStartRecording: recordVideo: #{recordVideo}, recordChat: #{recordChat} frameRate: #{frameRate}")
|
||||
@recordingModel.startRecording(recordVideo, recordChat, frameRate)
|
||||
|
||||
onStopRecording: () ->
|
||||
@recordingModel.stopRecording()
|
||||
|
|
@ -67,7 +74,7 @@ logger = context.JK.logger
|
|||
|
||||
popupRecordingControls: () ->
|
||||
logger.debug("poupRecordingControls")
|
||||
@recordingWindow = window.open("/popups/recording-controls", 'Recording', 'scrollbars=yes,toolbar=no,status=no,height=315,width=350')
|
||||
@recordingWindow = window.open("/popups/recording-controls", 'Recording', 'scrollbars=yes,toolbar=no,status=no,height=315,width=340')
|
||||
@recordingWindow.ParentRecordingStore = context.RecordingStore
|
||||
@recordingWindow.ParentIsRecording = @recordingModel.isRecording()
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
return context.JK.dkeys(groupedTracks);
|
||||
}
|
||||
|
||||
function startRecording() {
|
||||
function startRecording(recordVideo, recordChat, recordFramerate) {
|
||||
|
||||
$self.triggerHandler('startingRecording', {});
|
||||
|
||||
|
|
@ -88,14 +88,15 @@
|
|||
|
||||
context.RecordingActions.startingRecording({isRecording: false})
|
||||
|
||||
currentRecording = rest.startRecording({"music_session_id": sessionId})
|
||||
// 0 indicates the NoVideoRecordActive mode; so anything but that means video got recorded
|
||||
currentRecording = rest.startRecording({"music_session_id": sessionId, record_video: recordVideo != 0})
|
||||
.done(function(recording) {
|
||||
currentRecordingId = recording.id;
|
||||
currentOrLastRecordingId = recording.id;
|
||||
|
||||
// ask the backend to start the session.
|
||||
var groupedTracks = groupTracksToClient(recording);
|
||||
jamClient.StartRecording(recording["id"], groupedTracks, 0, false, 0);
|
||||
jamClient.StartRecording(recording["id"], groupedTracks, recordVideo, recordChat, recordFramerate);
|
||||
})
|
||||
.fail(function(jqXHR) {
|
||||
var details = { clientId: app.clientId, reason: 'rest', detail: arguments, isRecording: false }
|
||||
|
|
|
|||
|
|
@ -53,5 +53,9 @@
|
|||
.signed_in_to_google {
|
||||
color: yellow;
|
||||
}
|
||||
|
||||
.save-video {
|
||||
margin-top:10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,10 +33,21 @@ body.media-controls-popup.popup {
|
|||
margin-bottom:5px;
|
||||
}
|
||||
|
||||
.close-link {
|
||||
.actions {
|
||||
position:relative;
|
||||
margin-top:20px;
|
||||
font-size:11px;
|
||||
margin-bottom:10px;
|
||||
|
||||
}
|
||||
|
||||
.help-link {
|
||||
position:absolute;
|
||||
left:-6px;
|
||||
top:0;
|
||||
}
|
||||
.close-link {
|
||||
|
||||
}
|
||||
|
||||
.display-metronome {
|
||||
|
|
@ -183,6 +194,10 @@ body.media-controls-popup.popup {
|
|||
border-width:1px 0;
|
||||
padding: 7px 0 20px;
|
||||
|
||||
&.not-active {
|
||||
padding:7px 0 7px;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height:125%;
|
||||
color:$ColorTextTypical;
|
||||
|
|
@ -222,4 +237,27 @@ body.media-controls-popup.popup {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.arrow-down {
|
||||
float:none;
|
||||
margin-left:5px;
|
||||
margin-top:0;
|
||||
margin-right:0;
|
||||
border-top: 4px solid #fc0;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
display:inline-block;
|
||||
padding-top:1px;
|
||||
}
|
||||
.arrow-up {
|
||||
float:none;
|
||||
margin-right:0;
|
||||
margin-left:5px;
|
||||
margin-bottom:2px;
|
||||
border-bottom: 4px solid #fc0;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
display:inline-block;
|
||||
padding-top:1px;
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@
|
|||
*= require client/ftue
|
||||
*= require client/help
|
||||
*= require icheck/minimal/minimal
|
||||
*= require easydropdown
|
||||
*= require easydropdown_jk
|
||||
*= require_directory .
|
||||
*= require client/metronomePlaybackModeSelect
|
||||
*= require_directory ../client/react-components
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ body.recording-start-stop {
|
|||
}
|
||||
|
||||
.recording-start-stop {
|
||||
padding-left:44px;
|
||||
padding-left:30px;
|
||||
}
|
||||
|
||||
.control-holder {
|
||||
width:100%;
|
||||
margin: 1em 0;
|
||||
margin: 10px 0 20px;
|
||||
}
|
||||
|
||||
.helper {
|
||||
|
|
@ -24,7 +24,20 @@ body.recording-start-stop {
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.audio-settings {
|
||||
margin-top:40px;
|
||||
|
||||
label {
|
||||
display:inline;
|
||||
margin-left:6px;
|
||||
}
|
||||
|
||||
.icheckbox_minimal {
|
||||
vertical-align:middle;
|
||||
}
|
||||
}
|
||||
.control {
|
||||
margin-left:20px;
|
||||
width:231px;
|
||||
height:34px;
|
||||
@include border_box_sizing;
|
||||
|
|
@ -38,7 +51,10 @@ body.recording-start-stop {
|
|||
color:#ccc;
|
||||
}
|
||||
|
||||
|
||||
.chat-help {
|
||||
text-decoration:none;
|
||||
outline:0;
|
||||
}
|
||||
.control img {
|
||||
vertical-align:middle;
|
||||
margin-right:5px;
|
||||
|
|
@ -59,12 +75,16 @@ body.recording-start-stop {
|
|||
|
||||
.field {
|
||||
height:18px;
|
||||
&:nth-child(1) {
|
||||
&:nth-of-type(1) {
|
||||
|
||||
}
|
||||
&:nth-child(2) {
|
||||
&:nth-of-type(2) {
|
||||
margin-top:9px;
|
||||
}
|
||||
&:nth-of-type(3) {
|
||||
margin-top: 10px;
|
||||
padding-left: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.note-show-hide {
|
||||
|
|
@ -77,12 +97,22 @@ body.recording-start-stop {
|
|||
}
|
||||
|
||||
.important-note {
|
||||
margin-top:30px;
|
||||
margin-top:15px;
|
||||
line-height:150%;
|
||||
font-size:12px;
|
||||
width:260px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size:14px;
|
||||
font-weight:bold;
|
||||
margin-bottom:6px;
|
||||
}
|
||||
|
||||
.video-settings {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
a.note-show-hide {
|
||||
margin-top:5px;
|
||||
text-decoration:underline;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ class ApiJamTrackMixdownsController < ApiController
|
|||
|
||||
enqueued = @package.enqueue_if_needed
|
||||
log.debug("jamtrack mixdown #{enqueued ? "ENQUEUED" : "NOT ENQUEUED"}: mixdown_package=#{@package.id} ")
|
||||
@queue_time = enqueued ? enqueued : 0
|
||||
return
|
||||
else
|
||||
render :json => { :message => "download limit surpassed", :errors=>@package.errors }, :status => 403
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class ApiRecordingsController < ApiController
|
|||
|
||||
raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless music_session.users.exists?(current_user)
|
||||
|
||||
@recording = Recording.start(music_session, current_user)
|
||||
@recording = Recording.start(music_session, current_user, record_video: params[:record_video])
|
||||
|
||||
if @recording.errors.any?
|
||||
response.status = :unprocessable_entity
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class ApiSearchController < ApiController
|
|||
|
||||
def index
|
||||
if 1 == params[Search::PARAM_MUSICIAN].to_i || 1 == params[Search::PARAM_BAND].to_i
|
||||
query = parasobj.clone
|
||||
query = params.clone
|
||||
query[:remote_ip] = request.remote_ip
|
||||
if 1 == query[Search::PARAM_MUSICIAN].to_i
|
||||
@search = Search.musician_filter(query, current_user)
|
||||
|
|
|
|||