phocoder-rails 0.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.autotest +46 -0
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +44 -0
- data/LICENSE.txt +20 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +56 -0
- data/VERSION +5 -0
- data/app/controllers/phocoder_controller.rb +118 -0
- data/app/helpers/phocoder_helper.rb +320 -0
- data/app/models/encodable_job.rb +91 -0
- data/app/views/phocoder/_offline_video_embed.html.erb +19 -0
- data/app/views/phocoder/_thumbnail_update.html.erb +3 -0
- data/app/views/phocoder/_video_embed.html.erb +23 -0
- data/app/views/phocoder/multi_thumbnail_update.json.erb +7 -0
- data/app/views/phocoder/thumbnail_update.js.erb +9 -0
- data/config/routes.rb +8 -0
- data/lib/generators/phocoder_rails/model_update_generator.rb +52 -0
- data/lib/generators/phocoder_rails/scaffold_generator.rb +94 -0
- data/lib/generators/phocoder_rails/setup_generator.rb +33 -0
- data/lib/generators/phocoder_rails/templates/controller.rb +71 -0
- data/lib/generators/phocoder_rails/templates/helper.rb +5 -0
- data/lib/generators/phocoder_rails/templates/migration.rb +24 -0
- data/lib/generators/phocoder_rails/templates/model.rb +20 -0
- data/lib/generators/phocoder_rails/templates/model_migration.rb +56 -0
- data/lib/generators/phocoder_rails/templates/model_thumbnail.rb +5 -0
- data/lib/generators/phocoder_rails/templates/model_update_migration.rb +64 -0
- data/lib/generators/phocoder_rails/templates/phocodable.yml +28 -0
- data/lib/generators/phocoder_rails/templates/views/_form.html.erb.tt +23 -0
- data/lib/generators/phocoder_rails/templates/views/index.html.erb.tt +26 -0
- data/lib/generators/phocoder_rails/templates/views/new.html.erb.tt +5 -0
- data/lib/generators/phocoder_rails/templates/views/show.html.erb.tt +12 -0
- data/lib/phocoder_rails.rb +12 -0
- data/lib/phocoder_rails/acts_as_phocodable.rb +1153 -0
- data/lib/phocoder_rails/engine.rb +24 -0
- data/lib/phocoder_rails/errors.rb +46 -0
- data/phocoder-rails.gemspec +219 -0
- data/public/images/building.gif +0 -0
- data/public/images/error.png +0 -0
- data/public/images/play_small.png +0 -0
- data/public/images/storing.gif +0 -0
- data/public/images/waiting.gif +0 -0
- data/public/javascripts/phocodable.js +110 -0
- data/public/javascripts/video-js-2.0.2/.DS_Store +0 -0
- data/public/javascripts/video-js-2.0.2/LICENSE.txt +165 -0
- data/public/javascripts/video-js-2.0.2/README.markdown +202 -0
- data/public/javascripts/video-js-2.0.2/demo-subtitles.srt +13 -0
- data/public/javascripts/video-js-2.0.2/demo.html +101 -0
- data/public/javascripts/video-js-2.0.2/skins/hu.css +116 -0
- data/public/javascripts/video-js-2.0.2/skins/tube.css +111 -0
- data/public/javascripts/video-js-2.0.2/skins/vim.css +89 -0
- data/public/javascripts/video-js-2.0.2/video-js.css +242 -0
- data/public/javascripts/video-js-2.0.2/video.js +1758 -0
- data/public/stylesheets/phocodable.css +19 -0
- data/spec/controllers/phocoder_controller_spec.rb +123 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +7 -0
- data/spec/dummy/app/controllers/images_controller.rb +72 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/images_helper.rb +5 -0
- data/spec/dummy/app/models/image.rb +20 -0
- data/spec/dummy/app/models/image_thumbnail.rb +5 -0
- data/spec/dummy/app/models/image_upload.rb +11 -0
- data/spec/dummy/app/views/images/_form.html.erb +23 -0
- data/spec/dummy/app/views/images/index.html.erb +26 -0
- data/spec/dummy/app/views/images/new.html.erb +5 -0
- data/spec/dummy/app/views/images/show.html.erb +12 -0
- data/spec/dummy/app/views/layouts/application.html.erb +18 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +45 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +8 -0
- data/spec/dummy/config/environments/development.rb +26 -0
- data/spec/dummy/config/environments/production.rb +49 -0
- data/spec/dummy/config/environments/test.rb +40 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +60 -0
- data/spec/dummy/db/migrate/001_create_image_uploads.rb +37 -0
- data/spec/dummy/db/migrate/20110523165213_add_parent_type_to_image_uploads.rb +11 -0
- data/spec/dummy/db/migrate/20110523165522_create_encodable_jobs.rb +24 -0
- data/spec/dummy/db/migrate/20111101024507_create_images.rb +56 -0
- data/spec/dummy/db/schema.rb +99 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/index.html +239 -0
- data/spec/dummy/public/javascripts/application.js +2 -0
- data/spec/dummy/public/javascripts/controls.js +965 -0
- data/spec/dummy/public/javascripts/dragdrop.js +974 -0
- data/spec/dummy/public/javascripts/effects.js +1123 -0
- data/spec/dummy/public/javascripts/jquery-1.6.4.js +9046 -0
- data/spec/dummy/public/javascripts/prototype.js +6001 -0
- data/spec/dummy/public/javascripts/rails.js +175 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/engine_spec.rb +12 -0
- data/spec/fixtures/big_eye_tiny.jpg +0 -0
- data/spec/fixtures/octologo.png +0 -0
- data/spec/fixtures/test.txt +2 -0
- data/spec/fixtures/video-test.mov +0 -0
- data/spec/helpers/phocoder_helper_spec.rb +421 -0
- data/spec/integration/navigation_spec.rb +10 -0
- data/spec/models/acts_as_phocodable_spec.rb +664 -0
- data/spec/models/encodable_job_spec.rb +50 -0
- data/spec/phocoder_rails_spec.rb +8 -0
- data/spec/routing/phocoder_routing_spec.rb +19 -0
- data/spec/spec_helper.rb +75 -0
- metadata +375 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class <%= name.classify %> < ActiveRecord::Base
|
|
2
|
+
|
|
3
|
+
acts_as_phocodable :thumbnail_class => "<%= name.classify %>Thumbnail",
|
|
4
|
+
:thumbnails => [
|
|
5
|
+
{:label=>"small",:width=>100,:height=>100 },
|
|
6
|
+
{:label=>"medium",:width=>400,:height=>400,
|
|
7
|
+
:frame=>{ :width=>20, :bottom=>50, :color=>'003' },
|
|
8
|
+
:annotations=>[
|
|
9
|
+
{:text=>"Annotation Testing",:pointsize=>30,:fill_color=>'fff',:gravity=>"South",:y=>10},
|
|
10
|
+
{:text=>"Howdy!",:pointsize=>10,:fill_color=>'ccc',:gravity=>"North",:y=>5}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
|
|
15
|
+
:videos => [ {:label => 'mp4',:video_codec=>"h264" }, #, :thumbnails=>{ :number=>1, :start_at_first_frame=>1 }
|
|
16
|
+
{:label => 'webm', :video_codec=>"vp8" },
|
|
17
|
+
{:label => 'ogv', :video_codec=>"theora" }
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
class Create<%= name.classify.pluralize %> < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
|
|
4
|
+
create_table :<%= name.pluralize %> do |t|
|
|
5
|
+
t.string "filename"
|
|
6
|
+
t.string "content_type"
|
|
7
|
+
t.integer "duration_in_ms"
|
|
8
|
+
t.integer "width"
|
|
9
|
+
t.integer "height"
|
|
10
|
+
t.integer "file_size"
|
|
11
|
+
t.string "upload_host"
|
|
12
|
+
t.datetime "created_at"
|
|
13
|
+
t.datetime "updated_at"
|
|
14
|
+
t.datetime "taken_at"
|
|
15
|
+
t.float "lat"
|
|
16
|
+
t.float "lng"
|
|
17
|
+
t.string "encodable_status"
|
|
18
|
+
|
|
19
|
+
t.timestamps
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
add_index :<%= name.pluralize %>, :id
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
create_table :<%= name.singularize %>_thumbnails do |t|
|
|
26
|
+
t.string "filename"
|
|
27
|
+
t.string "content_type"
|
|
28
|
+
t.integer "duration_in_ms"
|
|
29
|
+
t.integer "width"
|
|
30
|
+
t.integer "height"
|
|
31
|
+
t.integer "file_size"
|
|
32
|
+
t.string "upload_host"
|
|
33
|
+
t.datetime "created_at"
|
|
34
|
+
t.datetime "updated_at"
|
|
35
|
+
t.datetime "taken_at"
|
|
36
|
+
t.float "lat"
|
|
37
|
+
t.float "lng"
|
|
38
|
+
t.string "encodable_status"
|
|
39
|
+
|
|
40
|
+
t.string "thumbnail"
|
|
41
|
+
t.integer "parent_id"
|
|
42
|
+
t.string "parent_type"
|
|
43
|
+
|
|
44
|
+
t.timestamps
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
add_index :<%= name.singularize %>_thumbnails, :id
|
|
48
|
+
add_index :<%= name.singularize %>_thumbnails, :parent_id
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.down
|
|
53
|
+
drop_table :<%= name.pluralize %>
|
|
54
|
+
drop_table :<%= name.singularize %>_thumbnails
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
class Make<%= name.classify.pluralize %>Encodable < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
add_column :<%= name.pluralize %>, :filename, :string
|
|
6
|
+
add_column :<%= name.pluralize %>, :content_type, :string
|
|
7
|
+
add_column :<%= name.pluralize %>, :duration_in_ms, :integer
|
|
8
|
+
add_column :<%= name.pluralize %>, :width, :integer
|
|
9
|
+
add_column :<%= name.pluralize %>, :height, :integer
|
|
10
|
+
add_column :<%= name.pluralize %>, :file_size, :integer
|
|
11
|
+
add_column :<%= name.pluralize %>, :upload_host, :string
|
|
12
|
+
add_column :<%= name.pluralize %>, :taken_at, :datetime
|
|
13
|
+
add_column :<%= name.pluralize %>, :lat, :float
|
|
14
|
+
add_column :<%= name.pluralize %>, :lng, :float
|
|
15
|
+
add_column :<%= name.pluralize %>, :encodable_status, :string
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
create_table :<%= name.singularize %>_thumbnails do |t|
|
|
20
|
+
t.string "filename"
|
|
21
|
+
t.string "content_type"
|
|
22
|
+
t.integer "duration_in_ms"
|
|
23
|
+
t.integer "width"
|
|
24
|
+
t.integer "height"
|
|
25
|
+
t.integer "file_size"
|
|
26
|
+
t.string "upload_host"
|
|
27
|
+
t.datetime "created_at"
|
|
28
|
+
t.datetime "updated_at"
|
|
29
|
+
t.datetime "taken_at"
|
|
30
|
+
t.float "lat"
|
|
31
|
+
t.float "lng"
|
|
32
|
+
t.string "encodable_status"
|
|
33
|
+
|
|
34
|
+
t.string "thumbnail"
|
|
35
|
+
t.integer "parent_id"
|
|
36
|
+
t.string "parent_type"
|
|
37
|
+
|
|
38
|
+
t.timestamps
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
add_index :<%= name.singularize %>_thumbnails, :id
|
|
42
|
+
add_index :<%= name.singularize %>_thumbnails, :parent_id
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.down
|
|
47
|
+
|
|
48
|
+
remove_column :<%= name.pluralize %>, :filename
|
|
49
|
+
remove_column :<%= name.pluralize %>, :content_type
|
|
50
|
+
remove_column :<%= name.pluralize %>, :duration_in_ms
|
|
51
|
+
remove_column :<%= name.pluralize %>, :width
|
|
52
|
+
remove_column :<%= name.pluralize %>, :height
|
|
53
|
+
remove_column :<%= name.pluralize %>, :file_size
|
|
54
|
+
remove_column :<%= name.pluralize %>, :upload_host
|
|
55
|
+
remove_column :<%= name.pluralize %>, :created_at
|
|
56
|
+
remove_column :<%= name.pluralize %>, :updated_at
|
|
57
|
+
remove_column :<%= name.pluralize %>, :taken_at
|
|
58
|
+
remove_column :<%= name.pluralize %>, :lat
|
|
59
|
+
remove_column :<%= name.pluralize %>, :lng
|
|
60
|
+
remove_column :<%= name.pluralize %>, :encodable_status
|
|
61
|
+
|
|
62
|
+
drop_table :<%= name.singularize %>_thumbnails
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
development:
|
|
2
|
+
phocoder_api_key: asdf
|
|
3
|
+
zencoder_api_key: asdf
|
|
4
|
+
base_url: http://your.host.test.com
|
|
5
|
+
storeage_mode : s3
|
|
6
|
+
s3_bucket_name: bucket.name
|
|
7
|
+
s3_access_key_id: asdf
|
|
8
|
+
s3_secret_access_key: asdf
|
|
9
|
+
|
|
10
|
+
test:
|
|
11
|
+
phocoder_api_key: asdf
|
|
12
|
+
zencoder_api_key: asdf
|
|
13
|
+
phocoder_url: http://photoapi.chaos.webapeel.com
|
|
14
|
+
base_url: http://your.host.test.com
|
|
15
|
+
storeage_mode : local
|
|
16
|
+
s3_bucket_name: bucket.name
|
|
17
|
+
s3_access_key_id: asdf
|
|
18
|
+
s3_secret_access_key: asdf
|
|
19
|
+
|
|
20
|
+
production:
|
|
21
|
+
phocoder_api_key: asdf
|
|
22
|
+
zencoder_api_key: asdf
|
|
23
|
+
base_url: http://your.host.test.com
|
|
24
|
+
storeage_mode : s3
|
|
25
|
+
processing_mode : resque
|
|
26
|
+
s3_bucket_name: bucket.name
|
|
27
|
+
s3_access_key_id: asdf
|
|
28
|
+
s3_secret_access_key: asdf
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<%%= form_for( @<%= file_name.singularize %>, :html => { :multipart => true } ) do |f| %>
|
|
2
|
+
|
|
3
|
+
<%% if @<%= file_name.singularize %>.errors.any? %>
|
|
4
|
+
<div id="error_explanation">
|
|
5
|
+
<h2><%%= pluralize(@<%= file_name.singularize %>.errors.count, "error") %> prohibited this encodable from being saved:</h2>
|
|
6
|
+
<ul>
|
|
7
|
+
<%% @<%= file_name.singularize %>.errors.full_messages.each do |msg| %>
|
|
8
|
+
<li><%%= msg %></li>
|
|
9
|
+
<%% end %>
|
|
10
|
+
</ul>
|
|
11
|
+
</div>
|
|
12
|
+
<%% end %>
|
|
13
|
+
|
|
14
|
+
<div class="field">
|
|
15
|
+
<%%= f.label :file, "Upload image file" %>
|
|
16
|
+
<%%= f.file_field :file %>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div class="actions">
|
|
20
|
+
<%%= f.submit %>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<%% end %>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<h1>Listing <%= file_name %></h1>
|
|
2
|
+
|
|
3
|
+
<table>
|
|
4
|
+
<tr>
|
|
5
|
+
<th>Filename</th>
|
|
6
|
+
<th></th>
|
|
7
|
+
<th></th>
|
|
8
|
+
|
|
9
|
+
</tr>
|
|
10
|
+
|
|
11
|
+
<%% @<%= file_name %>.each do |<%= file_name.singularize %>| %>
|
|
12
|
+
<tr>
|
|
13
|
+
<td>
|
|
14
|
+
<%%= phocoder_thumbnail <%= file_name.singularize %>,"small",false %><br/>
|
|
15
|
+
<%%= <%= file_name.singularize %>.filename %>
|
|
16
|
+
</td>
|
|
17
|
+
<td><%%= link_to 'Show', <%= file_name.singularize %> %></td>
|
|
18
|
+
|
|
19
|
+
<td><%%= link_to 'Destroy', <%= file_name.singularize %>, :confirm => 'Are you sure?', :method => :delete %></td>
|
|
20
|
+
</tr>
|
|
21
|
+
<%% end %>
|
|
22
|
+
</table>
|
|
23
|
+
|
|
24
|
+
<br />
|
|
25
|
+
|
|
26
|
+
<%%= link_to 'New <%= file_name.singularize %>', new_<%= file_name.singularize %>_path %>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module PhocoderRails
|
|
2
|
+
require 'phocoder_rails/engine' if defined?(Rails)
|
|
3
|
+
|
|
4
|
+
require 'active_record'
|
|
5
|
+
#require 'action_pack'
|
|
6
|
+
#require 'active_support'
|
|
7
|
+
require 'aws/s3'
|
|
8
|
+
|
|
9
|
+
require 'phocoder_rails/acts_as_phocodable'
|
|
10
|
+
require 'phocoder_rails/errors'
|
|
11
|
+
#require 'phocoder_rails/base'
|
|
12
|
+
end
|
|
@@ -0,0 +1,1153 @@
|
|
|
1
|
+
module ActsAsPhocodable
|
|
2
|
+
|
|
3
|
+
require 'phocoder'
|
|
4
|
+
require 'zencoder'
|
|
5
|
+
require 'open-uri'
|
|
6
|
+
# Storeage mode controls how uploads are handled.
|
|
7
|
+
# Valid options are:
|
|
8
|
+
# offline : For development mode with no net connection. No processing.
|
|
9
|
+
# local : To store images locally but use Phocoder for processing.
|
|
10
|
+
# s3 : Store image in S3 and use Phocoder for processing.
|
|
11
|
+
# Set this options either in evnironment.rb or
|
|
12
|
+
# in environments/development.rb etc...
|
|
13
|
+
|
|
14
|
+
mattr_accessor :storeage_mode
|
|
15
|
+
self.storeage_mode = "local"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Processing mode controls when images get sent to phocoder
|
|
19
|
+
# Valid options are:
|
|
20
|
+
# automatic : Send to phocoder as soon as the file is stored.
|
|
21
|
+
# With 'local' storage mode, this submits the job
|
|
22
|
+
# to phocoder while the user is still waiting.
|
|
23
|
+
# delayed : Handle storage/phocoding in a background process.
|
|
24
|
+
# spawn : Use the Spawn library to fork a new process to store/phocode.
|
|
25
|
+
mattr_accessor :processing_mode
|
|
26
|
+
self.processing_mode = "automatic"
|
|
27
|
+
|
|
28
|
+
# This is used as the base address for phocoder notifications.
|
|
29
|
+
# When storeage_mode == "local" this is also used to point
|
|
30
|
+
# phocoder at the file.
|
|
31
|
+
# It should only be the host.domain portion of the URL
|
|
32
|
+
# no path components.
|
|
33
|
+
mattr_accessor :base_url
|
|
34
|
+
self.base_url = "http://your-domain.com"
|
|
35
|
+
|
|
36
|
+
# The bucket for storing s3 files
|
|
37
|
+
mattr_accessor :s3_bucket_name
|
|
38
|
+
self.s3_bucket_name = "your-bucket"
|
|
39
|
+
|
|
40
|
+
# The access_key_id for storing s3 files
|
|
41
|
+
mattr_accessor :s3_access_key_id
|
|
42
|
+
self.s3_access_key_id = "your-access-key-id"
|
|
43
|
+
|
|
44
|
+
# The secret_access_key for storing s3 files
|
|
45
|
+
mattr_accessor :s3_secret_access_key
|
|
46
|
+
self.s3_secret_access_key = "your-secret-access-key"
|
|
47
|
+
|
|
48
|
+
# The javascript library to use for updates
|
|
49
|
+
# either 'prototype' or 'jquery'
|
|
50
|
+
mattr_accessor :javascript_library
|
|
51
|
+
self.javascript_library = 'prototype'
|
|
52
|
+
|
|
53
|
+
# The local directory where files should be stored
|
|
54
|
+
mattr_accessor :local_base_dir
|
|
55
|
+
self.local_base_dir = '/tmp'
|
|
56
|
+
|
|
57
|
+
# The config file that tells phocoder where to find
|
|
58
|
+
# config options.
|
|
59
|
+
mattr_accessor :config_file
|
|
60
|
+
self.config_file = "config/phocodable.yml"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# The list of image content types that are considered web safe
|
|
64
|
+
# These can be displayed directly, skipping processing if in offline mode
|
|
65
|
+
mattr_accessor :web_safe_image_types
|
|
66
|
+
self.web_safe_image_types = [
|
|
67
|
+
'image/jpeg',
|
|
68
|
+
'image/jpg',
|
|
69
|
+
'image/gif',
|
|
70
|
+
'image/png',
|
|
71
|
+
'image/x-png',
|
|
72
|
+
'image/jpg',
|
|
73
|
+
'application/png',
|
|
74
|
+
'application/x-png'
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
# The list of image content types that are not considered web safe
|
|
78
|
+
# These can not be displayed directly
|
|
79
|
+
mattr_accessor :other_image_types
|
|
80
|
+
self.other_image_types = [
|
|
81
|
+
'image/pjpeg',
|
|
82
|
+
'image/x-ms-bmp',
|
|
83
|
+
'image/bmp',
|
|
84
|
+
'image/x-bmp',
|
|
85
|
+
'image/x-bitmap',
|
|
86
|
+
'image/x-xbitmap',
|
|
87
|
+
'image/x-win-bitmap',
|
|
88
|
+
'image/x-windows-bmp',
|
|
89
|
+
'image/ms-bmp',
|
|
90
|
+
'application/bmp',
|
|
91
|
+
'application/x-bmp',
|
|
92
|
+
'application/x-win-bitmap',
|
|
93
|
+
'application/preview',
|
|
94
|
+
'image/jp_',
|
|
95
|
+
'application/jpg',
|
|
96
|
+
'application/x-jpg',
|
|
97
|
+
'image/pipeg',
|
|
98
|
+
'image/vnd.swiftview-jpeg',
|
|
99
|
+
'image/x-xbitmap',
|
|
100
|
+
'image/gi_',
|
|
101
|
+
'image/x-citrix-pjpeg',
|
|
102
|
+
'image/x-nikon-nef',
|
|
103
|
+
'image/tiff',
|
|
104
|
+
'image/x-olympus-orf',
|
|
105
|
+
'image/x-dcraw'
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
# The list of content types that will trigger image handling.
|
|
109
|
+
def image_types
|
|
110
|
+
web_safe_image_types + other_image_types
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
# The list of content types that will trigger video handling.
|
|
115
|
+
mattr_accessor :video_types
|
|
116
|
+
self.video_types = [
|
|
117
|
+
'application/x-flash-video',
|
|
118
|
+
'video/avi',
|
|
119
|
+
'video/mp4',
|
|
120
|
+
'video/ogg',
|
|
121
|
+
'video/quicktime',
|
|
122
|
+
'video/3gp',
|
|
123
|
+
'video/3gpp',
|
|
124
|
+
'video/vnd.objectvideo',
|
|
125
|
+
'video/x-ms-wmv',
|
|
126
|
+
'video/x-ms-asf',
|
|
127
|
+
'video/x-ms-wvx',
|
|
128
|
+
'video/x-ms-wm',
|
|
129
|
+
'video/x-ms-wmx'
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
# Mapping for generating a file extension
|
|
133
|
+
# based on the codec passed in for zencoder
|
|
134
|
+
mattr_accessor :video_extensions
|
|
135
|
+
self.video_extensions = {
|
|
136
|
+
"h264" => "mp4",
|
|
137
|
+
"vp6" => "vp6",
|
|
138
|
+
"vp8" => "webm",
|
|
139
|
+
"theora" => "ogv",
|
|
140
|
+
"mpeg4" => "mpg",
|
|
141
|
+
"wmv" => "wmv"
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
# TODO : This needs to be fixed.
|
|
145
|
+
# It currently matches anything with an 'x' in it
|
|
146
|
+
mattr_accessor :label_size_regex
|
|
147
|
+
self.label_size_regex = /(\d*)x(\d*)(pad|crop|stretch|preserve)?/ #
|
|
148
|
+
|
|
149
|
+
mattr_accessor :size_string_regex
|
|
150
|
+
self.size_string_regex = /(\d*)x(\d*)([!>]?)/
|
|
151
|
+
|
|
152
|
+
def image?(content_type)
|
|
153
|
+
image_types.include?(content_type)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def web_safe?(content_type)
|
|
157
|
+
web_safe_image_types.include?(content_type)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def video?(content_type)
|
|
161
|
+
video_types.include?(content_type)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
#def self.storeage_mode
|
|
166
|
+
# @@storeage_mode
|
|
167
|
+
#end
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def acts_as_phocodable(options = { })
|
|
171
|
+
|
|
172
|
+
include InstanceMethods
|
|
173
|
+
include Spawn
|
|
174
|
+
attr_reader :saved_file
|
|
175
|
+
attr_accessor :phocoding
|
|
176
|
+
after_save :save_local_file
|
|
177
|
+
before_destroy :cleanup #:remove_local_file,:destroy_thumbnails,:remove_s3_file
|
|
178
|
+
|
|
179
|
+
include ActiveSupport::Callbacks
|
|
180
|
+
|
|
181
|
+
define_callbacks :local_file_saved, :file_saved, :file_ready, :phocode_hdr, :phocode_composite, :phocode_tone_mapping
|
|
182
|
+
|
|
183
|
+
#cattr_accessor :phocoder_options
|
|
184
|
+
#self.phocoder_options = options
|
|
185
|
+
|
|
186
|
+
cattr_accessor :phocoder_thumbnails
|
|
187
|
+
self.phocoder_thumbnails = options[:thumbnails] ||= []
|
|
188
|
+
|
|
189
|
+
cattr_accessor :zencoder_videos
|
|
190
|
+
self.zencoder_videos = options[:videos] ||= []
|
|
191
|
+
|
|
192
|
+
cattr_accessor :thumbnail_class
|
|
193
|
+
self.thumbnail_class = options[:thumbnail_class] ? options[:thumbnail_class].constantize : self
|
|
194
|
+
|
|
195
|
+
cattr_accessor :parent_class
|
|
196
|
+
self.parent_class = options[:parent_class] ? options[:parent_class].constantize : self
|
|
197
|
+
|
|
198
|
+
has_many :thumbnails, :class_name => "::#{self.thumbnail_class.name}",:as => :parent
|
|
199
|
+
if self.thumbnail_class != self.parent_class
|
|
200
|
+
#we have to do this to get the poster for videos covered
|
|
201
|
+
belongs_to :parent, :polymorphic => true
|
|
202
|
+
else
|
|
203
|
+
belongs_to :parent, :class_name => "::#{self.parent_class.name}" ,:foreign_key => "parent_id"
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
has_many :encodable_jobs, :as => :encodable
|
|
208
|
+
|
|
209
|
+
scope :top_level, where({:parent_id=>nil}) if respond_to?(:parent_id)
|
|
210
|
+
scope :top_level, where({}) if !respond_to?(:parent_id)
|
|
211
|
+
# we can't just call this next scope 'parents' because that is already
|
|
212
|
+
# taken and returns an array of parent classes of the ruby object
|
|
213
|
+
scope :parent_items, where({:parent_id=>nil}) if respond_to?(:parent_id)
|
|
214
|
+
scope :parent_items, where({}) if !respond_to?(:parent_id)
|
|
215
|
+
|
|
216
|
+
scope :thumbnails, where("#{base_class.table_name}.parent_id is not null")
|
|
217
|
+
|
|
218
|
+
#just a writer, the reader is below
|
|
219
|
+
cattr_accessor :phocodable_configuration
|
|
220
|
+
read_phocodable_configuration
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def config
|
|
224
|
+
return phocodable_configuration if !phocodable_configuration.blank?
|
|
225
|
+
self.read_phocodable_configuration
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def validates_phocodable
|
|
229
|
+
validates_presence_of :content_type, :filename, :if=>lambda{ parent_id.blank? }
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def update_from_phocoder(params)
|
|
233
|
+
Rails.logger.debug "tying to call update from phocoder for params = #{params.to_json}"
|
|
234
|
+
if !params[:output].blank?
|
|
235
|
+
Rails.logger.debug "find_by_phocoder_output_id #{params[:output][:id]}"
|
|
236
|
+
iu = find_by_phocoder_output_id params[:output][:id]
|
|
237
|
+
Rails.logger.debug "the item = #{iu}"
|
|
238
|
+
img_params = params[:output]
|
|
239
|
+
iu.filename = File.basename(params[:output][:url]) #if iu.filename.blank?
|
|
240
|
+
if ActsAsPhocodable.storeage_mode == "local"
|
|
241
|
+
iu.save_url(params[:output][:url])
|
|
242
|
+
end
|
|
243
|
+
else
|
|
244
|
+
iu = find_by_phocoder_input_id params[:input][:id]
|
|
245
|
+
img_params = params[:input]
|
|
246
|
+
end
|
|
247
|
+
[:file_size,:width,:height,:taken_at,:lat,:lng].each do |att|
|
|
248
|
+
setter = att.to_s + "="
|
|
249
|
+
if iu.respond_to? setter and !img_params[att].blank?
|
|
250
|
+
iu.send setter, img_params[att]
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
#iu.file_size = img_params[:file_size]
|
|
255
|
+
#iu.width = img_params[:width]
|
|
256
|
+
#iu.height = img_params[:height]
|
|
257
|
+
iu.phocoder_status = "ready"
|
|
258
|
+
iu.save
|
|
259
|
+
iu
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
# Updating from zencoder is a two pass operation.
|
|
264
|
+
# This method gets called for each output when it's ready.
|
|
265
|
+
# Once all outputs are ready, we call parent.check_zencoder_details
|
|
266
|
+
def update_from_zencoder(params)
|
|
267
|
+
Rails.logger.debug "tying to call update from zencoder for params = #{params}"
|
|
268
|
+
iu = find_by_zencoder_output_id params[:output][:id]
|
|
269
|
+
if params[:output][:url].match /%2F(.*)\?/
|
|
270
|
+
iu.filename = $1
|
|
271
|
+
else
|
|
272
|
+
iu.filename = File.basename(params[:output][:url].match(/(.*)\??/)[1])
|
|
273
|
+
end
|
|
274
|
+
#iu.filename = File.basename(params[:output][:url].match(/(.*)\??/)[1]) if iu.filename.blank?
|
|
275
|
+
if ActsAsPhocodable.storeage_mode == "local"
|
|
276
|
+
iu.save_url(params[:output][:url])
|
|
277
|
+
end
|
|
278
|
+
iu.zencoder_status = "ready"
|
|
279
|
+
iu.save
|
|
280
|
+
iu.parent.check_zencoder_details
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def thumbnail_attributes_for(thumbnail_name = "small")
|
|
284
|
+
atts = self.phocoder_thumbnails.select{|atts| atts[:label] == thumbnail_name }.first
|
|
285
|
+
if atts.blank?
|
|
286
|
+
atts = create_atts_from_size_string(thumbnail_name)
|
|
287
|
+
end
|
|
288
|
+
if atts.blank?
|
|
289
|
+
raise ThumbnailAttributesNotFoundError.new("No thumbnail attributes were found for label '#{thumbnail_name}'")
|
|
290
|
+
end
|
|
291
|
+
atts
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def create_label_from_size_string(size_string)
|
|
295
|
+
if size_string.match ActsAsPhocodable.size_string_regex
|
|
296
|
+
size_string = size_string.gsub("!","crop")
|
|
297
|
+
size_string = size_string.gsub(">","preserve")
|
|
298
|
+
end
|
|
299
|
+
size_string
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def create_atts_from_size_string(label_string)
|
|
303
|
+
match = label_string.match ActsAsPhocodable.label_size_regex
|
|
304
|
+
return nil if match.blank?
|
|
305
|
+
atts = {}
|
|
306
|
+
if !match[1].blank?
|
|
307
|
+
atts[:width] = match[1]
|
|
308
|
+
end
|
|
309
|
+
if !match[2].blank?
|
|
310
|
+
atts[:height] = match[2]
|
|
311
|
+
end
|
|
312
|
+
if !match[3].blank?
|
|
313
|
+
atts[:aspect_mode] = match[3]
|
|
314
|
+
end
|
|
315
|
+
atts[:label] = label_string
|
|
316
|
+
#atts[:label] = "#{atts[:width]}x#{atts[:height]}"
|
|
317
|
+
#atts[:label] += "_#{atts[:aspect_mode]}" if atts[:aspect_mode]
|
|
318
|
+
atts
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def read_phocodable_configuration
|
|
324
|
+
config_path = File.join(::Rails.root.to_s, ActsAsPhocodable.config_file)
|
|
325
|
+
puts "looking for a config in #{config_path}"
|
|
326
|
+
self.phocodable_configuration = YAML.load(ERB.new(File.read(config_path)).result)[::Rails.env.to_s].symbolize_keys
|
|
327
|
+
self.apply_phocodable_configuration
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def apply_phocodable_configuration
|
|
331
|
+
if self.phocodable_configuration[:base_url]
|
|
332
|
+
ActsAsPhocodable.base_url = phocodable_configuration[:base_url]
|
|
333
|
+
end
|
|
334
|
+
if self.phocodable_configuration[:storeage_mode]
|
|
335
|
+
ActsAsPhocodable.storeage_mode = phocodable_configuration[:storeage_mode]
|
|
336
|
+
end
|
|
337
|
+
if self.phocodable_configuration[:processing_mode]
|
|
338
|
+
ActsAsPhocodable.processing_mode = phocodable_configuration[:processing_mode]
|
|
339
|
+
end
|
|
340
|
+
if self.phocodable_configuration[:s3_bucket_name]
|
|
341
|
+
ActsAsPhocodable.s3_bucket_name = phocodable_configuration[:s3_bucket_name]
|
|
342
|
+
end
|
|
343
|
+
if self.phocodable_configuration[:s3_access_key_id]
|
|
344
|
+
ActsAsPhocodable.s3_access_key_id = phocodable_configuration[:s3_access_key_id]
|
|
345
|
+
end
|
|
346
|
+
if self.phocodable_configuration[:s3_secret_access_key]
|
|
347
|
+
ActsAsPhocodable.s3_secret_access_key = phocodable_configuration[:s3_secret_access_key]
|
|
348
|
+
end
|
|
349
|
+
if self.phocodable_configuration[:javascript_library]
|
|
350
|
+
ActsAsPhocodable.javascript_library = phocodable_configuration[:javascript_library]
|
|
351
|
+
end
|
|
352
|
+
if self.phocodable_configuration[:local_base_dir]
|
|
353
|
+
ActsAsPhocodable.local_base_dir = phocodable_configuration[:local_base_dir]
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
if self.phocodable_configuration[:phocoder_url]
|
|
358
|
+
::Phocoder.base_url = phocodable_configuration[:phocoder_url]
|
|
359
|
+
end
|
|
360
|
+
if self.phocodable_configuration[:phocoder_api_key]
|
|
361
|
+
::Phocoder.api_key = phocodable_configuration[:phocoder_api_key]
|
|
362
|
+
end
|
|
363
|
+
if self.phocodable_configuration[:zencoder_api_key]
|
|
364
|
+
::Zencoder.api_key = phocodable_configuration[:zencoder_api_key]
|
|
365
|
+
end
|
|
366
|
+
if ActsAsPhocodable.storeage_mode == "s3"
|
|
367
|
+
self.establish_aws_connection
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def establish_aws_connection
|
|
372
|
+
AWS::S3::Base.establish_connection!(
|
|
373
|
+
:access_key_id => ActsAsPhocodable.s3_access_key_id,
|
|
374
|
+
:secret_access_key => ActsAsPhocodable.s3_secret_access_key
|
|
375
|
+
)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
module InstanceMethods
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def image?
|
|
388
|
+
self.class.image?(content_type)
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def web_safe?
|
|
392
|
+
self.class.web_safe?(content_type)
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def video?
|
|
396
|
+
self.class.video?(content_type)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
def encode
|
|
400
|
+
if image?
|
|
401
|
+
phocode
|
|
402
|
+
elsif video?
|
|
403
|
+
zencode
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
def recode
|
|
408
|
+
reload #make sure that we have current thumbs
|
|
409
|
+
destroy_thumbnails
|
|
410
|
+
reload
|
|
411
|
+
encode
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
def ready?
|
|
415
|
+
if ActsAsPhocodable.storeage_mode == "offline"
|
|
416
|
+
true
|
|
417
|
+
#elsif image?
|
|
418
|
+
# return phocoder_status=='ready'
|
|
419
|
+
#elsif video?
|
|
420
|
+
# return zencoder_status=='ready'
|
|
421
|
+
#else
|
|
422
|
+
# return false
|
|
423
|
+
else
|
|
424
|
+
return encodable_status == "ready"
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
def error?
|
|
429
|
+
if ActsAsPhocodable.storeage_mode == "offline"
|
|
430
|
+
false
|
|
431
|
+
#elsif image?
|
|
432
|
+
# return phocoder_status=='failed'
|
|
433
|
+
#elsif video?
|
|
434
|
+
# return zencoder_status=='failed'
|
|
435
|
+
#else
|
|
436
|
+
# true
|
|
437
|
+
else
|
|
438
|
+
return encodable_status == "ready"
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
def create_thumbnails_from_response(response_thumbs,job_id)
|
|
443
|
+
new_thumbs = []
|
|
444
|
+
response_thumbs.each do |thumb_params|
|
|
445
|
+
puts "creating a thumb for #{thumb_params["label"]}"
|
|
446
|
+
# we do this the long way around just in case some of these
|
|
447
|
+
# atts are attr_protected
|
|
448
|
+
thumb = nil
|
|
449
|
+
if respond_to?(:parent_id) and !self.parent_id.blank?
|
|
450
|
+
Rails.logger.debug "trying to create a thumb from the parent "
|
|
451
|
+
thumb = self.parent.thumbnails.new()
|
|
452
|
+
self.parent.thumbnails << thumb
|
|
453
|
+
else
|
|
454
|
+
Rails.logger.debug "trying to create a thumb from myself "
|
|
455
|
+
thumb = self.thumbnails.new()
|
|
456
|
+
self.thumbnails << thumb
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
thumb.thumbnail = thumb_params["label"]
|
|
461
|
+
thumb.filename = thumb_params["filename"]
|
|
462
|
+
thumb.width = thumb_params["width"]
|
|
463
|
+
thumb.height = thumb_params["height"]
|
|
464
|
+
tjob = thumb.encodable_jobs.new
|
|
465
|
+
|
|
466
|
+
tjob.phocoder_output_id = thumb_params["id"]
|
|
467
|
+
tjob.phocoder_job_id = job_id
|
|
468
|
+
#thumb.parent_id = self.id
|
|
469
|
+
tjob.phocoder_status = "phocoding"
|
|
470
|
+
thumb.encodable_jobs << tjob
|
|
471
|
+
thumb.encodable_status = "phocoding"
|
|
472
|
+
thumb.save
|
|
473
|
+
new_thumbs << thumb
|
|
474
|
+
Rails.logger.debug " thumb.errors = #{thumb.errors.to_json}"
|
|
475
|
+
puts " thumb.errors = #{thumb.errors.to_json}"
|
|
476
|
+
end
|
|
477
|
+
new_thumbs
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
def clear_phocoding
|
|
481
|
+
phocoding = false
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
def dedupe_input_thumbs(input_thumbs)
|
|
485
|
+
needed_thumbs = []
|
|
486
|
+
input_thumbs.each do |it|
|
|
487
|
+
t = thumbnails.find_by_thumbnail(it[:label])
|
|
488
|
+
if t.blank?
|
|
489
|
+
needed_thumbs << it
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
needed_thumbs
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
def phocode(input_thumbs = self.parent_class.phocoder_thumbnails)
|
|
496
|
+
puts " input_thumbs.count = #{input_thumbs.size}"
|
|
497
|
+
input_thumbs = dedupe_input_thumbs(input_thumbs)
|
|
498
|
+
puts " after dedupe input_thumbs.count = #{input_thumbs.size}"
|
|
499
|
+
#if self.thumbnails.count >= self.class.phocoder_thumbnails.size
|
|
500
|
+
# raise "This item already has thumbnails!"
|
|
501
|
+
# return
|
|
502
|
+
#end
|
|
503
|
+
|
|
504
|
+
return if input_thumbs.size == 0
|
|
505
|
+
# We do this because sometimes save will get called more than once
|
|
506
|
+
# during a single request
|
|
507
|
+
return if phocoding
|
|
508
|
+
phocoding = true
|
|
509
|
+
|
|
510
|
+
Rails.logger.debug "trying to phocode for #{Phocoder.base_url} "
|
|
511
|
+
Rails.logger.debug "callback url = #{callback_url}"
|
|
512
|
+
response = Phocoder::Job.create(phocoder_params(input_thumbs))
|
|
513
|
+
Rails.logger.debug "the phocode response = #{response.to_json}" if Rails.env != "test"
|
|
514
|
+
puts "the phocode response = #{response.to_json}" if Rails.env != "test"
|
|
515
|
+
job = self.encodable_jobs.new
|
|
516
|
+
job.phocoder_input_id = response.body["job"]["inputs"].first["id"]
|
|
517
|
+
job.phocoder_job_id = response.body["job"]["id"]
|
|
518
|
+
job.phocoder_status = "phocoding"
|
|
519
|
+
self.encodable_jobs << job
|
|
520
|
+
self.encodable_status = "phocoding" unless self.encodable_status == "ready" # the unless clause allows new thumbs to be created on the fly without jacking with the status
|
|
521
|
+
self.save #false need to do save(false) here if we're calling phocode on after_save
|
|
522
|
+
response_thumbs = response.body["job"]["thumbnails"]
|
|
523
|
+
Rails.logger.debug "trying to decode #{response_thumbs.size} response_thumbs = #{response_thumbs.to_json}"
|
|
524
|
+
puts "trying to decode #{response_thumbs.size} response_thumbs = #{response_thumbs.to_json}"
|
|
525
|
+
create_thumbnails_from_response(response_thumbs,response.body["job"]["id"])
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def phocode_hdr
|
|
529
|
+
#if self.thumbnails.count >= self.class.phocoder_thumbnails.size
|
|
530
|
+
# raise "This item already has thumbnails!"
|
|
531
|
+
# return
|
|
532
|
+
#end
|
|
533
|
+
|
|
534
|
+
# We do this because sometimes save will get called more than once
|
|
535
|
+
# during a single request
|
|
536
|
+
return if phocoding
|
|
537
|
+
phocoding = true
|
|
538
|
+
run_callbacks :phocode_hdr do
|
|
539
|
+
Rails.logger.debug "trying to phocode for #{Phocoder.base_url} "
|
|
540
|
+
Rails.logger.debug "callback url = #{callback_url}"
|
|
541
|
+
response = Phocoder::Job.create(phocoder_hdr_params)
|
|
542
|
+
Rails.logger.debug "the response from phocode_hdr = #{response.body.to_json}"
|
|
543
|
+
job = self.encodable_jobs.new
|
|
544
|
+
job.phocoder_output_id = response.body["job"]["hdr"]["id"]
|
|
545
|
+
job.phocoder_job_id = response.body["job"]["id"]
|
|
546
|
+
job.phocoder_status = "phocoding"
|
|
547
|
+
self.encodable_jobs << job
|
|
548
|
+
self.encodable_status = "phocoding"
|
|
549
|
+
self.save #false need to do save(false) here if we're calling phocode on after_save
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
def phocode_tone_mapping
|
|
556
|
+
#if self.thumbnails.count >= self.class.phocoder_thumbnails.size
|
|
557
|
+
# raise "This item already has thumbnails!"
|
|
558
|
+
# return
|
|
559
|
+
#end
|
|
560
|
+
|
|
561
|
+
# We do this because sometimes save will get called more than once
|
|
562
|
+
# during a single request
|
|
563
|
+
return if phocoding
|
|
564
|
+
phocoding = true
|
|
565
|
+
run_callbacks :phocode_tone_mapping do
|
|
566
|
+
destroy_thumbnails
|
|
567
|
+
Rails.logger.debug "trying to phocode for #{Phocoder.base_url} "
|
|
568
|
+
Rails.logger.debug "callback url = #{callback_url}"
|
|
569
|
+
response = Phocoder::Job.create(phocoder_tone_mapping_params)
|
|
570
|
+
Rails.logger.debug "tone_mapping response = #{response.body.to_json}"
|
|
571
|
+
puts "tone_mapping response = #{response.body.to_json}"
|
|
572
|
+
job = self.encodable_jobs.new
|
|
573
|
+
job.phocoder_output_id = response.body["job"]["tone_mapping"]["id"]
|
|
574
|
+
job.phocoder_job_id = response.body["job"]["id"]
|
|
575
|
+
job.phocoder_status = "phocoding"
|
|
576
|
+
self.encodable_jobs << job
|
|
577
|
+
self.encodable_status = "phocoding"
|
|
578
|
+
self.save #false need to do save(false) here if we're calling phocode on after_save
|
|
579
|
+
response_thumbs = response.body["job"]["thumbnails"]
|
|
580
|
+
Rails.logger.debug "trying to decode #{response_thumbs.size} response_thumbs = #{response_thumbs.to_json}"
|
|
581
|
+
create_thumbnails_from_response(response_thumbs,response.body["job"]["id"])
|
|
582
|
+
end
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
def phocode_composite
|
|
587
|
+
#if self.thumbnails.count >= self.class.phocoder_thumbnails.size
|
|
588
|
+
# raise "This item already has thumbnails!"
|
|
589
|
+
# return
|
|
590
|
+
#end
|
|
591
|
+
|
|
592
|
+
# We do this because sometimes save will get called more than once
|
|
593
|
+
# during a single request
|
|
594
|
+
return if phocoding
|
|
595
|
+
phocoding = true
|
|
596
|
+
run_callbacks :phocode_composite do
|
|
597
|
+
destroy_thumbnails
|
|
598
|
+
Rails.logger.debug "trying to phocode for #{Phocoder.base_url} "
|
|
599
|
+
Rails.logger.debug "callback url = #{callback_url}"
|
|
600
|
+
response = Phocoder::Job.create(phocoder_composite_params)
|
|
601
|
+
Rails.logger.debug "composite response = #{response.body.to_json}"
|
|
602
|
+
puts "composite response = #{response.body.to_json}"
|
|
603
|
+
job = self.encodable_jobs.new
|
|
604
|
+
job.phocoder_output_id = response.body["job"]["composite"]["id"]
|
|
605
|
+
job.phocoder_job_id = response.body["job"]["id"]
|
|
606
|
+
job.phocoder_status = "phocoding"
|
|
607
|
+
self.encodable_jobs << job
|
|
608
|
+
self.encodable_status = "phocoding"
|
|
609
|
+
self.save #false need to do save(false) here if we're calling phocode on after_save
|
|
610
|
+
response_thumbs = response.body["job"]["thumbnails"]
|
|
611
|
+
Rails.logger.debug "trying to decode #{response_thumbs.size} response_thumbs = #{response_thumbs.to_json}"
|
|
612
|
+
puts "trying to decode #{response_thumbs.size} response_thumbs = #{response_thumbs.to_json}"
|
|
613
|
+
create_thumbnails_from_response(response_thumbs,response.body["job"]["id"])
|
|
614
|
+
end
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
def zencode
|
|
619
|
+
# We do this because sometimes save will get called more than once
|
|
620
|
+
# during a single request
|
|
621
|
+
return if @zencoding
|
|
622
|
+
@zencoding = true
|
|
623
|
+
|
|
624
|
+
Rails.logger.debug "trying to zencode!!!!!"
|
|
625
|
+
Rails.logger.debug "callback url = #{callback_url}"
|
|
626
|
+
response = Zencoder::Job.create(zencoder_params)
|
|
627
|
+
Rails.logger.debug "response from Zencoder = #{response.body.to_json}"
|
|
628
|
+
job = self.encodable_jobs.new
|
|
629
|
+
job.zencoder_job_id = response.body["id"]
|
|
630
|
+
self.encodable_jobs << job
|
|
631
|
+
|
|
632
|
+
response.body["outputs"].each do |output_params|
|
|
633
|
+
thumb = self.thumbnails.new()
|
|
634
|
+
thumb.thumbnail = output_params["label"]
|
|
635
|
+
|
|
636
|
+
tjob = thumb.encodable_jobs.new
|
|
637
|
+
tjob.zencoder_output_id = output_params["id"]
|
|
638
|
+
tjob.zencoder_url = output_params["url"]
|
|
639
|
+
tjob.zencoder_job_id = response.body["id"]
|
|
640
|
+
tjob.zencoder_status = "zencoding"
|
|
641
|
+
thumb.encodable_jobs << tjob
|
|
642
|
+
|
|
643
|
+
self.thumbnails << thumb
|
|
644
|
+
thumb.encodable_status = "zencoding"
|
|
645
|
+
thumb.save
|
|
646
|
+
puts " thumb.errors = #{thumb.errors.to_json}"
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
self.save
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
def phocoder_extension
|
|
653
|
+
if self.content_type.blank?
|
|
654
|
+
".jpg"
|
|
655
|
+
else
|
|
656
|
+
self.content_type.match(/png/) ? ".png" : ".jpg"
|
|
657
|
+
end
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
def phocoder_params(input_thumbs = self.parent_class.phocoder_thumbnails)
|
|
661
|
+
{:input => {:url => self.public_url, :notifications=>[{:url=>callback_url }] },
|
|
662
|
+
:thumbnails => phocoder_thumbnail_params(input_thumbs)
|
|
663
|
+
}
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
def phocoder_thumbnail_params(input_thumbs = self.parent_class.phocoder_thumbnails)
|
|
667
|
+
input_thumbs.map{|thumb|
|
|
668
|
+
thumb_filename = thumb[:label] + "_" + File.basename(self.filename,File.extname(self.filename)) + phocoder_extension
|
|
669
|
+
base_url = ActsAsPhocodable.storeage_mode == "s3" ? "s3://#{self.s3_bucket_name}/#{self.thumbnail_resource_dir}/" : ""
|
|
670
|
+
th = thumb.clone
|
|
671
|
+
th[:base_url] = base_url if !base_url.blank?
|
|
672
|
+
th.merge({
|
|
673
|
+
:filename=>thumb_filename,
|
|
674
|
+
:notifications=>[{:url=>thumbnail_callback_url }]
|
|
675
|
+
})
|
|
676
|
+
}
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
def phocoder_hdr_params
|
|
681
|
+
{ }
|
|
682
|
+
end
|
|
683
|
+
|
|
684
|
+
def phocoder_tone_mapping_params
|
|
685
|
+
{ }
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
def phocoder_composite_params
|
|
689
|
+
{ }
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
def zencoder_params
|
|
693
|
+
base_url = ActsAsPhocodable.storeage_mode == "s3" ? "s3://#{self.s3_bucket_name}/#{self.thumbnail_resource_dir}/" : ""
|
|
694
|
+
params = {:input => self.public_url ,
|
|
695
|
+
:outputs => self.class.zencoder_videos.map{|video|
|
|
696
|
+
vid_filename = self.new_zencoder_filename( video[:video_codec] )
|
|
697
|
+
vid = video.clone
|
|
698
|
+
if vid[:thumbnails] and vid[:thumbnails].is_a? Array
|
|
699
|
+
vid[:thumbnails].each do |thumb|
|
|
700
|
+
thumb[:base_url] = base_url if !base_url.blank?
|
|
701
|
+
end
|
|
702
|
+
elsif vid[:thumbnails]
|
|
703
|
+
vid[:thumbnails][:base_url] = base_url if !base_url.blank?
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
vid[:base_url] = base_url if !base_url.blank?
|
|
707
|
+
vid.merge({
|
|
708
|
+
:filename=>vid_filename,
|
|
709
|
+
:public=>1,
|
|
710
|
+
:notifications=>[{:url=>zencoder_thumbnail_callback_url }]
|
|
711
|
+
})
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
params[:outputs][0][:thumbnails] = { :number=>1, :start_at_first_frame=>1,:public=>1 }
|
|
715
|
+
params[:outputs][0][:thumbnails][:base_url] = base_url if !base_url.blank?
|
|
716
|
+
Rails.logger.debug "for zencoder the params = #{params.to_json}"
|
|
717
|
+
#puts "for zencoder the params = #{params.to_json}"
|
|
718
|
+
params
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
def new_zencoder_filename(format)
|
|
722
|
+
filename + "." + self.class.video_extensions[format]
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
def check_zencoder_details
|
|
727
|
+
# we don't get a lot of info from zencoder, so we have to ask for details
|
|
728
|
+
shouldCheck = true
|
|
729
|
+
thumbnails.each do |t|
|
|
730
|
+
if t.encodable_status != 'ready'
|
|
731
|
+
shouldCheck = false
|
|
732
|
+
end
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
return if !shouldCheck
|
|
736
|
+
|
|
737
|
+
details = Zencoder::Job.details(self.encodable_jobs.last.zencoder_job_id)
|
|
738
|
+
|
|
739
|
+
#puts "in check_zencoder_details the details.body = #{details.body.to_json}"
|
|
740
|
+
|
|
741
|
+
if details.body["job"]["state"] != 'finished'
|
|
742
|
+
self.encodable_jobs.last.zencoder_status = details.body["job"]["state"]
|
|
743
|
+
save
|
|
744
|
+
return
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
self.encodable_jobs.last.zencoder_status = self.encodable_status = "ready"
|
|
748
|
+
self.width = details.body["job"]["input_media_file"]["width"]
|
|
749
|
+
self.height = details.body["job"]["input_media_file"]["height"]
|
|
750
|
+
self.duration_in_ms = details.body["job"]["input_media_file"]["duration_in_ms"]
|
|
751
|
+
self.file_size = details.body["job"]["input_media_file"]["file_size_bytes"]
|
|
752
|
+
self.save
|
|
753
|
+
|
|
754
|
+
#puts "the output files = #{details.body["job"]["output_media_files"]}"
|
|
755
|
+
|
|
756
|
+
update_zencoder_outputs(details)
|
|
757
|
+
|
|
758
|
+
# Now create the image thumb
|
|
759
|
+
create_zencoder_image_thumb(details)
|
|
760
|
+
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
def update_zencoder_outputs(details)
|
|
765
|
+
details.body["job"]["output_media_files"].each do |output|
|
|
766
|
+
#puts "updating for output = #{output.to_json}"
|
|
767
|
+
job = EncodableJob.find_by_zencoder_output_id output["id"]
|
|
768
|
+
thumb = job.encodable
|
|
769
|
+
thumb.width = output["width"]
|
|
770
|
+
thumb.height = output["height"]
|
|
771
|
+
thumb.file_size = output["file_size_bytes"]
|
|
772
|
+
thumb.duration_in_ms = output["duration_in_ms"]
|
|
773
|
+
thumb.save
|
|
774
|
+
end
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
def create_zencoder_image_thumb(details)
|
|
778
|
+
|
|
779
|
+
# for now we should only have one thumbnail
|
|
780
|
+
output = details.body["job"]["thumbnails"].first
|
|
781
|
+
return if output.blank?
|
|
782
|
+
thumb = thumbnails.new
|
|
783
|
+
thumb.thumbnail = "poster"
|
|
784
|
+
thumb.width = output["width"]
|
|
785
|
+
thumb.height = output["height"]
|
|
786
|
+
thumb.file_size = output["file_size_bytes"]
|
|
787
|
+
thumb.filename = "frame_0000.png" #File.basename(output["url"])
|
|
788
|
+
thumb.content_type = "image/png"
|
|
789
|
+
if ActsAsPhocodable.storeage_mode == "local"
|
|
790
|
+
thumb.save_url(output["url"])
|
|
791
|
+
end
|
|
792
|
+
thumb.save
|
|
793
|
+
#now get thumbnails for the poster
|
|
794
|
+
thumb.phocode
|
|
795
|
+
end
|
|
796
|
+
|
|
797
|
+
def phocodable_config
|
|
798
|
+
puts "looking for config!"
|
|
799
|
+
self.class.config
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
def phocodable?
|
|
803
|
+
true
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
def save_url(url)
|
|
807
|
+
Rails.logger.debug "We are about to download : #{url} to #{local_dir} - #{local_path}"
|
|
808
|
+
FileUtils.mkdir_p(local_dir) if !File.exists?(local_dir)
|
|
809
|
+
FileUtils.touch local_path
|
|
810
|
+
writeOut = open(local_path, "wb")
|
|
811
|
+
writeOut.write(open(url).read)
|
|
812
|
+
writeOut.close
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
def destroy_thumbnails
|
|
816
|
+
if self.class.phocoder_thumbnails.size == 0 and self.class.zencoder_videos.size == 0
|
|
817
|
+
puts "we're skipping destory_thumbnails since we don't do any processing "
|
|
818
|
+
return
|
|
819
|
+
end
|
|
820
|
+
#puts "calling destory thumbnails for #{self.thumbnails.count} - #{self.thumbnails.size}"
|
|
821
|
+
self.thumbnails.each do |thumb|
|
|
822
|
+
thumb.destroy
|
|
823
|
+
end
|
|
824
|
+
#puts "calling destory thumbnails for #{self.thumbnails.count}"
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
def create_atts_from_size_string(label_string)
|
|
828
|
+
self.class.create_atts_from_size_string(label_string)
|
|
829
|
+
end
|
|
830
|
+
|
|
831
|
+
def thumbnail_attributes_for(thumbnail_name)
|
|
832
|
+
self.class.thumbnail_attributes_for(thumbnail_name)
|
|
833
|
+
end
|
|
834
|
+
|
|
835
|
+
def thumbnail_for(thumbnail_hash_or_name)
|
|
836
|
+
thumbnail_name = thumbnail_hash_or_name.is_a?(Hash) ? thumbnail_hash_or_name[:label] : thumbnail_hash_or_name
|
|
837
|
+
if thumbnail_name and thumbnail_name.match ActsAsPhocodable.size_string_regex
|
|
838
|
+
thumbnail_name = self.class.create_label_from_size_string(thumbnail_name)
|
|
839
|
+
end
|
|
840
|
+
if thumbnail_name.blank? and thumbnail_hash_or_name.is_a?(Hash)
|
|
841
|
+
thumbnail_name = "#{thumbnail_hash_or_name[:width]}x#{thumbnail_hash_or_name[:height]}"
|
|
842
|
+
puts "thumbnail_name = #{thumbnail_name}"
|
|
843
|
+
thumbnail_hash_or_name[:label] = thumbnail_name
|
|
844
|
+
end
|
|
845
|
+
thumb = thumbnails.find_by_thumbnail(thumbnail_name)
|
|
846
|
+
if thumb.blank? and ActsAsPhocodable.storeage_mode == "offline"
|
|
847
|
+
thumb = self
|
|
848
|
+
elsif thumb.blank? and thumbnail_hash_or_name.is_a? Hash
|
|
849
|
+
thumb = self.phocode([thumbnail_hash_or_name]).first
|
|
850
|
+
elsif thumb.blank? and thumbnail_hash_or_name.is_a?(String) and thumbnail_hash_or_name.match ActsAsPhocodable.label_size_regex
|
|
851
|
+
atts = create_atts_from_size_string(thumbnail_name)
|
|
852
|
+
thumb = self.phocode([atts]).first
|
|
853
|
+
end
|
|
854
|
+
if thumb.blank?
|
|
855
|
+
raise ThumbnailNotFoundError.new("No thumbnail was found for label '#{thumbnail_name}'")
|
|
856
|
+
end
|
|
857
|
+
thumb
|
|
858
|
+
#a dirty hack for now to keep things working.
|
|
859
|
+
#Remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
860
|
+
#Go back to just returning the thumb
|
|
861
|
+
#thumb.blank? ? self : thumb
|
|
862
|
+
end
|
|
863
|
+
|
|
864
|
+
def get_thumbnail(thumbnail_name)
|
|
865
|
+
thumbnail_for(thumbnail_name)
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
def file=(new_file)
|
|
869
|
+
return if new_file.nil?
|
|
870
|
+
Rails.logger.debug "we got a new file of class = #{new_file.class}"
|
|
871
|
+
cleanup
|
|
872
|
+
if new_file.is_a? File
|
|
873
|
+
self.filename = File.basename new_file.path
|
|
874
|
+
self.content_type = MIME::Types.type_for(self.filename).first.content_type
|
|
875
|
+
self.file_size = new_file.size
|
|
876
|
+
else
|
|
877
|
+
self.filename = new_file.original_filename
|
|
878
|
+
self.content_type = new_file.content_type
|
|
879
|
+
self.file_size = new_file.size
|
|
880
|
+
end
|
|
881
|
+
|
|
882
|
+
if new_file.respond_to? :tempfile
|
|
883
|
+
@saved_file = new_file.tempfile
|
|
884
|
+
else
|
|
885
|
+
@saved_file = new_file
|
|
886
|
+
end
|
|
887
|
+
end
|
|
888
|
+
|
|
889
|
+
#compatability method for attachment_fu
|
|
890
|
+
def uploaded_data=(data)
|
|
891
|
+
self.file = data
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
def save_local_file
|
|
895
|
+
return if @saved_file.blank?
|
|
896
|
+
puts "saving the local file!!!!!!"
|
|
897
|
+
Rails.logger.debug "==================================================================================================="
|
|
898
|
+
Rails.logger.debug "about to save the local file"
|
|
899
|
+
run_callbacks :file_saved do
|
|
900
|
+
run_callbacks :local_file_saved do
|
|
901
|
+
FileUtils.mkdir_p local_dir
|
|
902
|
+
FileUtils.cp @saved_file.path, local_path
|
|
903
|
+
FileUtils.chmod 0755, local_path
|
|
904
|
+
self.encodable_status = "local"
|
|
905
|
+
if self.respond_to? :upload_host
|
|
906
|
+
self.upload_host = %x{hostname}.strip
|
|
907
|
+
end
|
|
908
|
+
@saved_file = nil
|
|
909
|
+
@saved_a_new_file = true
|
|
910
|
+
self.save
|
|
911
|
+
end
|
|
912
|
+
if ActsAsPhocodable.storeage_mode == "s3" and ActsAsPhocodable.processing_mode == "automatic"
|
|
913
|
+
self.save_s3_file
|
|
914
|
+
end
|
|
915
|
+
if ActsAsPhocodable.storeage_mode == "s3" and ActsAsPhocodable.processing_mode == "spawn"
|
|
916
|
+
spawn do # :method => :thread # <-- I think that should be set at the config/environment level
|
|
917
|
+
Rails.logger.debug "------------beginning of spawn block"
|
|
918
|
+
puts "------------beginning of spawn block"
|
|
919
|
+
self.save_s3_file
|
|
920
|
+
Rails.logger.debug "------------end of spawn block"
|
|
921
|
+
puts "------------end of spawn block"
|
|
922
|
+
end
|
|
923
|
+
end
|
|
924
|
+
if ActsAsPhocodable.storeage_mode == "local" and ActsAsPhocodable.processing_mode == "automatic"
|
|
925
|
+
self.encode
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
end
|
|
929
|
+
end
|
|
930
|
+
|
|
931
|
+
def fire_ready_callback
|
|
932
|
+
run_callbacks :file_ready do
|
|
933
|
+
end
|
|
934
|
+
end
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
def cleanup
|
|
938
|
+
#puts "calling cleanup!"
|
|
939
|
+
destroy_thumbnails
|
|
940
|
+
remove_local_file
|
|
941
|
+
if ActsAsPhocodable.storeage_mode == "s3"
|
|
942
|
+
remove_s3_file
|
|
943
|
+
end
|
|
944
|
+
end
|
|
945
|
+
|
|
946
|
+
def remove_local_file
|
|
947
|
+
if local_path and File.exists? local_path
|
|
948
|
+
FileUtils.rm local_path
|
|
949
|
+
if Dir.glob(File.join(local_dir,"*")).size == 0
|
|
950
|
+
FileUtils.rmdir local_dir
|
|
951
|
+
end
|
|
952
|
+
end
|
|
953
|
+
end
|
|
954
|
+
|
|
955
|
+
def path_id
|
|
956
|
+
|
|
957
|
+
#puts "parent_id = #{parent_id}"
|
|
958
|
+
#puts "parent = #{parent}"
|
|
959
|
+
if respond_to?(:parent_id)
|
|
960
|
+
parent_id.blank? ? id : parent.path_id
|
|
961
|
+
else
|
|
962
|
+
id
|
|
963
|
+
end
|
|
964
|
+
end
|
|
965
|
+
|
|
966
|
+
def resource_dir
|
|
967
|
+
File.join(self.class.table_name, path_id.to_s )
|
|
968
|
+
end
|
|
969
|
+
|
|
970
|
+
def thumbnail_resource_dir
|
|
971
|
+
File.join(self.thumbnail_class.table_name, path_id.to_s )
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
def local_dir
|
|
975
|
+
File.join(ActsAsPhocodable.local_base_dir,resource_dir)
|
|
976
|
+
end
|
|
977
|
+
|
|
978
|
+
def local_path
|
|
979
|
+
filename.blank? ? nil : File.join(local_dir,filename)
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
def local_url
|
|
983
|
+
filename.blank? ? nil : File.join("/",resource_dir,filename)
|
|
984
|
+
end
|
|
985
|
+
|
|
986
|
+
# This should generate a fully qualified http://something-something
|
|
987
|
+
# type of a reference. Depending on storeage_mode/base_url settings.
|
|
988
|
+
def public_url
|
|
989
|
+
puts "our base_url = #{base_url} and our local_url = #{local_url}"
|
|
990
|
+
if ActsAsPhocodable.storeage_mode == "local" or ActsAsPhocodable.storeage_mode == "offline"
|
|
991
|
+
base_url + local_url
|
|
992
|
+
else
|
|
993
|
+
s3_url
|
|
994
|
+
end
|
|
995
|
+
end
|
|
996
|
+
|
|
997
|
+
def public_filename
|
|
998
|
+
public_url
|
|
999
|
+
end
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
def callback_url
|
|
1003
|
+
self.base_url + self.notification_callback_path
|
|
1004
|
+
end
|
|
1005
|
+
|
|
1006
|
+
def zencoder_callback_url
|
|
1007
|
+
self.base_url + self.zencoder_notification_callback_path
|
|
1008
|
+
end
|
|
1009
|
+
|
|
1010
|
+
def thumbnail_callback_url
|
|
1011
|
+
self.base_url + self.thumbnail_notification_callback_path
|
|
1012
|
+
end
|
|
1013
|
+
|
|
1014
|
+
def zencoder_thumbnail_callback_url
|
|
1015
|
+
self.base_url + self.zencoder_thumbnail_notification_callback_path
|
|
1016
|
+
end
|
|
1017
|
+
|
|
1018
|
+
def notification_callback_path
|
|
1019
|
+
"/phocoder/phocoder_notifications/#{self.class.name}/#{self.id}.json"
|
|
1020
|
+
end
|
|
1021
|
+
|
|
1022
|
+
def zencoder_notification_callback_path
|
|
1023
|
+
"/phocoder/zencoder_notifications/#{self.class.name}/#{self.id}.json"
|
|
1024
|
+
end
|
|
1025
|
+
|
|
1026
|
+
def thumbnail_notification_callback_path
|
|
1027
|
+
"/phocoder/phocoder_notifications/#{self.thumbnail_class.name}/#{self.id}.json"
|
|
1028
|
+
end
|
|
1029
|
+
|
|
1030
|
+
def zencoder_thumbnail_notification_callback_path
|
|
1031
|
+
"/phocoder/zencoder_notifications/#{self.thumbnail_class.name}/#{self.id}.json"
|
|
1032
|
+
end
|
|
1033
|
+
|
|
1034
|
+
def base_url
|
|
1035
|
+
self.class.base_url
|
|
1036
|
+
end
|
|
1037
|
+
|
|
1038
|
+
def s3_key
|
|
1039
|
+
filename.blank? ? nil : File.join(resource_dir,filename)
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
def s3_url
|
|
1043
|
+
"http://#{s3_bucket_name}.s3.amazonaws.com/#{s3_key}"
|
|
1044
|
+
end
|
|
1045
|
+
|
|
1046
|
+
def s3_bucket_name
|
|
1047
|
+
self.class.s3_bucket_name
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
def save_s3_file
|
|
1051
|
+
#I don't think we need this return check anymore.
|
|
1052
|
+
#return if !@saved_a_new_file
|
|
1053
|
+
#@saved_a_new_file = false
|
|
1054
|
+
AWS::S3::S3Object.store(
|
|
1055
|
+
s3_key,
|
|
1056
|
+
open(local_path),
|
|
1057
|
+
s3_bucket_name,
|
|
1058
|
+
:access => :public_read
|
|
1059
|
+
)
|
|
1060
|
+
self.encodable_status = "s3"
|
|
1061
|
+
self.save
|
|
1062
|
+
obj_data = AWS::S3::S3Object.find(s3_key,s3_bucket_name)
|
|
1063
|
+
Rails.logger.debug "----------------------------------------------------------------------------------------------------"
|
|
1064
|
+
if obj_data.size == file_size # it made it into s3 safely
|
|
1065
|
+
Rails.logger.debug " we are about to remove local file!"
|
|
1066
|
+
remove_local_file
|
|
1067
|
+
else
|
|
1068
|
+
msg = "The file was not saved to S3 sucessfully. Orig size: #{file_size} - S3 size: #{obj_data.size}"
|
|
1069
|
+
Rails.logger.debug msg
|
|
1070
|
+
raise ActsAsPhocodable::Error.new msg
|
|
1071
|
+
end
|
|
1072
|
+
self.encode
|
|
1073
|
+
end
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
def remove_s3_file
|
|
1077
|
+
#puts "trying to delete #{s3_key} #{s3_bucket_name}"
|
|
1078
|
+
#if ActsAsPhocodable.storeage_mode == "s3"
|
|
1079
|
+
AWS::S3::S3Object.delete s3_key, s3_bucket_name
|
|
1080
|
+
#end
|
|
1081
|
+
rescue Exception => e
|
|
1082
|
+
#this probably means that the file never made it to S3
|
|
1083
|
+
end
|
|
1084
|
+
|
|
1085
|
+
# Sanitizes a filename.
|
|
1086
|
+
def filename=(new_name)
|
|
1087
|
+
write_attribute :filename, sanitize_filename(new_name)
|
|
1088
|
+
end
|
|
1089
|
+
|
|
1090
|
+
def sanitize_filename(filename)
|
|
1091
|
+
return unless filename
|
|
1092
|
+
filename.strip.tap do |name|
|
|
1093
|
+
# NOTE: File.basename doesn't work right with Windows paths on Unix
|
|
1094
|
+
# get only the filename, not the whole path
|
|
1095
|
+
name.gsub! /^.*(\\|\/)/, ''
|
|
1096
|
+
|
|
1097
|
+
# Finally, replace all non alphanumeric, underscore or periods with underscore
|
|
1098
|
+
name.gsub! /[^A-Za-z0-9\.\-]/, '_'
|
|
1099
|
+
end
|
|
1100
|
+
end
|
|
1101
|
+
|
|
1102
|
+
# Calculate the width for the target thumbnail atts
|
|
1103
|
+
def calc_width(thumbnail_atts)
|
|
1104
|
+
tw = thumbnail_atts[:width].blank? ? 100000 : thumbnail_atts[:width].to_f
|
|
1105
|
+
th = thumbnail_atts[:height].blank? ? 100000 : thumbnail_atts[:height].to_f
|
|
1106
|
+
w = width.to_f
|
|
1107
|
+
h = height.to_f
|
|
1108
|
+
if w <= tw and h <= th
|
|
1109
|
+
w.round
|
|
1110
|
+
elsif w > h
|
|
1111
|
+
if (h * ( tw / w )).round < tw
|
|
1112
|
+
tw .round
|
|
1113
|
+
else
|
|
1114
|
+
(h * ( tw / w )).round
|
|
1115
|
+
end
|
|
1116
|
+
else
|
|
1117
|
+
if (w * ( th / h )).round < tw
|
|
1118
|
+
(w * ( th / h )).round
|
|
1119
|
+
else
|
|
1120
|
+
tw.round
|
|
1121
|
+
end
|
|
1122
|
+
end
|
|
1123
|
+
end #end calc_width
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
def calc_height(thumbnail_atts)
|
|
1127
|
+
tw = thumbnail_atts[:width].blank? ? 100000 : thumbnail_atts[:width].to_f
|
|
1128
|
+
th = thumbnail_atts[:height].blank? ? 100000 : thumbnail_atts[:height].to_f
|
|
1129
|
+
w = width.to_f
|
|
1130
|
+
h = height.to_f
|
|
1131
|
+
if w <= tw and h <= th
|
|
1132
|
+
h.round
|
|
1133
|
+
elsif w > h
|
|
1134
|
+
if (h * ( tw / w )).round < th
|
|
1135
|
+
(h * ( tw / w )).round
|
|
1136
|
+
else
|
|
1137
|
+
th.round
|
|
1138
|
+
end
|
|
1139
|
+
else
|
|
1140
|
+
if (w * ( th / h )).round < tw
|
|
1141
|
+
th.round
|
|
1142
|
+
else
|
|
1143
|
+
(h * ( tw / w )).round
|
|
1144
|
+
end
|
|
1145
|
+
end
|
|
1146
|
+
end #end calc_height
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
end#module InstanceMethods
|
|
1151
|
+
|
|
1152
|
+
end
|
|
1153
|
+
ActiveRecord::Base.extend ActsAsPhocodable
|