animoto 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/README.md +95 -27
  2. data/lib/animoto/client.rb +48 -26
  3. data/lib/animoto/http_engines/base.rb +2 -14
  4. data/lib/animoto/http_engines/curl_adapter.rb +11 -2
  5. data/lib/animoto/http_engines/net_http_adapter.rb +15 -7
  6. data/lib/animoto/http_engines/patron_adapter.rb +1 -2
  7. data/lib/animoto/http_engines/rest_client_adapter.rb +2 -2
  8. data/lib/animoto/http_engines/typhoeus_adapter.rb +4 -3
  9. data/lib/animoto/manifests/base.rb +53 -3
  10. data/lib/animoto/manifests/directing.rb +6 -19
  11. data/lib/animoto/manifests/directing_and_rendering.rb +6 -19
  12. data/lib/animoto/manifests/rendering.rb +3 -16
  13. data/lib/animoto/manifests/storyboard_bundling.rb +40 -0
  14. data/lib/animoto/manifests/storyboard_unbundling.rb +39 -0
  15. data/lib/animoto/resources/base.rb +2 -2
  16. data/lib/animoto/resources/jobs/base.rb +8 -0
  17. data/lib/animoto/resources/jobs/directing.rb +0 -2
  18. data/lib/animoto/resources/jobs/directing_and_rendering.rb +0 -2
  19. data/lib/animoto/resources/jobs/rendering.rb +0 -2
  20. data/lib/animoto/resources/jobs/storyboard_bundling.rb +29 -0
  21. data/lib/animoto/resources/jobs/storyboard_unbundling.rb +34 -0
  22. data/lib/animoto/support/content_type.rb +1 -1
  23. data/lib/animoto/support/dynamic_class_loader.rb +1 -1
  24. data/lib/animoto/support/errors.rb +29 -0
  25. data/lib/animoto/support/hash.rb +2 -2
  26. data/lib/animoto/support/standard_envelope.rb +4 -2
  27. data/lib/animoto/support/string.rb +2 -2
  28. data/lib/animoto/support/visual.rb +1 -1
  29. data/lib/animoto.rb +1 -1
  30. data/spec/animoto/client_spec.rb +221 -9
  31. data/spec/animoto/http_engines/base_spec.rb +1 -14
  32. data/spec/animoto/manifests/rendering_spec.rb +1 -1
  33. data/spec/animoto/manifests/storyboard_bundling_spec.rb +73 -0
  34. data/spec/animoto/manifests/storyboard_unbundling_spec.rb +71 -0
  35. data/spec/animoto/resources/base_spec.rb +2 -2
  36. data/spec/animoto/resources/jobs/storyboard_bundling_spec.rb +43 -0
  37. data/spec/animoto/resources/jobs/storyboard_unbundling_spec.rb +48 -0
  38. data/spec/spec_helper.rb +4 -3
  39. metadata +14 -7
  40. data/integration/test.rb +0 -49
data/README.md CHANGED
@@ -156,8 +156,8 @@ status.
156
156
 
157
157
  # Poll the service until the directing job is done.
158
158
  while directing_job.pending?
159
- sleep(30)
160
- client.reload!(directing_job)
159
+ sleep(30)
160
+ client.reload!(directing_job)
161
161
  end
162
162
 
163
163
  # If the directing job finished successfully, there will be a "storyboard"
@@ -166,37 +166,105 @@ status.
166
166
 
167
167
  # Now it's time to render the storyboard into a video. First we create
168
168
  # a rendering manifest.
169
- manifest = Manifests::Rendering.new(
170
- storyboard,
171
- :resolution => "720p",
172
- :framerate => 24,
173
- :format => 'h264'
174
- )
175
-
176
- # Send the manifest to the API.
177
- rendering_job = client.render!(manifest)
178
-
179
- # Poll the service until the rendering job is done
180
- while rendering_job.pending?
181
- sleep(30)
182
- client.reload!(rendering_job)
183
- end
169
+ manifest = Manifests::Rendering.new(
170
+ storyboard,
171
+ :resolution => "720p",
172
+ :framerate => 24,
173
+ :format => 'h264'
174
+ )
175
+
176
+ # Send the manifest to the API.
177
+ rendering_job = client.render!(manifest)
178
+
179
+ # Poll the service until the rendering job is done
180
+ while rendering_job.pending?
181
+ sleep(30)
182
+ client.reload!(rendering_job)
183
+ end
184
184
 
185
185
  # If the job has a video associated with it, everything worked out ok.
186
- if video = rendering_job.video
187
- # Print a link to download the video file.
188
- client.reload!(video)
189
- puts video.download_url
190
- else
191
- # Something happened during rendering...
192
- raise rendering_job.errors.first
193
- end
186
+ if video = rendering_job.video
187
+ # Print a link to download the video file.
188
+ client.reload!(video)
189
+ puts video.download_url
190
+ else
191
+ # Something happened during rendering...
192
+ raise rendering_job.errors.first
193
+ end
194
194
  else
195
195
  # Looks like there was a problem. Perhaps one of the assets wasn't
196
196
  # retrieved or was corrupt...
197
- raise directing_job.errors.first
197
+ raise directing_job.errors.first
198
198
  end
199
199
 
200
+ ### Storyboard bundling example
201
+
202
+ Bundling is a process used for exporting an Animoto storyboard. The bundling process packages
203
+ up all the information used by Animoto to render videos into a single file, the storyboard
204
+ bundle. This file is essentially just a zip file with a special structure. After a storyboard
205
+ bundle has been created and retrieved by your system, the original storyboard can be deleted.
206
+ Later, the storyboard bundle can be reconstituted into an Animoto storyboard so that videos may
207
+ be rendered.
208
+
209
+ require 'animoto/client'
210
+ include Animoto
211
+
212
+ client = Client.new("key", "secret")
213
+
214
+ # Make a directing manifest and direct it as detailed above.
215
+ # Afterwards, we can make a StoryboardBundling manifest and bundle up the
216
+ # storyboard we just made.
217
+
218
+ storyboard = directing_job.storyboard
219
+ bundling_manifest = Manifests::StoryboardBundling.new(storyboard)
220
+ bundling_job = client.bundle!(bundling_manifest)
221
+
222
+ # Poll the service until the bundling job is complete.
223
+ # As with all jobs, HTTP callbacks are also supported, but we're just
224
+ # going for a simple example here.
225
+ while bundling_job.pending?
226
+ sleep(30)
227
+ client.reload!(bundling_job)
228
+ end
229
+
230
+ # The bundle_url returned points to where you can download the storyboard
231
+ # bundle. Downloading the bundle and archiving it elsewhere is outside the
232
+ # scope of the client's functionality.
233
+ puts bundling_job.bundle_url
234
+
235
+ # After you have a handle for the storyboard bundle, the original storyboard
236
+ # can be deleted.
237
+ client.delete!(storyboard)
238
+
239
+ Turning a bundle back into a storyboard is just as simple.
240
+
241
+ require 'animoto/client'
242
+ include Animoto
243
+
244
+ client = Client.new("key", "secret")
245
+
246
+ # Make a storyboard unbundling manifest with the url to your archived storyboard bundle.
247
+ unbundling_manifest = Manifest::StoryboardUnbundling.new(:bundle_url => "http://your-storage-solution.com/path/to/your/bundle")
248
+ unbundling_job = client.unbundle!(unbundling_manifest)
249
+
250
+ # Poll the service until unbundling is complete.
251
+ while unbundling_job.pending?
252
+ sleep(30)
253
+ client.reload!(unbundling_job)
254
+ end
255
+
256
+ # Now you can use the storyboard to render a video.
257
+ rendering_manifest = Manifests::Rendering.new(
258
+ unbundling_job.storyboard,
259
+ :resolution => "720p",
260
+ :framerate => 24,
261
+ :format => 'h264'
262
+ )
263
+ rendering_job = client.render!(rendering_manifest)
264
+
265
+ # Now proceed with using your render as detailed above.
266
+
267
+
200
268
  <a name="how_to_contribute"></a>
201
269
  ## How to contribute to this client
202
270
 
@@ -229,4 +297,4 @@ IN NO EVENT SHALL ANIMOTO BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY SPECIAL, P
229
297
 
230
298
  You agree to indemnify defend and hold Animoto, its parents, subsidiaries, affiliates, officers and employees, harmless from any liabilities, claims, expenses or demands, including reasonable attorneys’ fees and costs, made by any third party due to or arising out of your use of this software, derivative works created by you, the violation of laws, rules, regulations or these terms, and the infringement of any intellectual property right by your derivative works or by you.
231
299
 
232
- [api_docs]: http://animoto.com/developer/api
300
+ [api_docs]: http://api-documentation.animoto.com/index.html
@@ -18,6 +18,8 @@ require 'animoto/resources/jobs/base'
18
18
  require 'animoto/resources/jobs/directing_and_rendering'
19
19
  require 'animoto/resources/jobs/directing'
20
20
  require 'animoto/resources/jobs/rendering'
21
+ require 'animoto/resources/jobs/storyboard_bundling'
22
+ require 'animoto/resources/jobs/storyboard_unbundling'
21
23
 
22
24
  require 'animoto/assets/base'
23
25
  require 'animoto/assets/footage'
@@ -29,6 +31,8 @@ require 'animoto/manifests/base'
29
31
  require 'animoto/manifests/directing'
30
32
  require 'animoto/manifests/directing_and_rendering'
31
33
  require 'animoto/manifests/rendering'
34
+ require 'animoto/manifests/storyboard_bundling'
35
+ require 'animoto/manifests/storyboard_unbundling'
32
36
 
33
37
  require 'animoto/http_engines/base'
34
38
  require 'animoto/response_parsers/base'
@@ -37,7 +41,7 @@ module Animoto
37
41
  class Client
38
42
 
39
43
  # The default endpoint where requests go.
40
- API_ENDPOINT = "https://api2-sandbox.animoto.com/"
44
+ API_ENDPOINT = "https://platform-sandbox.animoto.com/"
41
45
 
42
46
  # The version of the Animoto API this client targets.
43
47
  API_VERSION = 1
@@ -185,6 +189,24 @@ module Animoto
185
189
  Resources::Jobs::DirectingAndRendering.load(send_manifest(manifest, Resources::Jobs::DirectingAndRendering.endpoint, options))
186
190
  end
187
191
 
192
+ # Sends a request to bundle a storyboard.
193
+ #
194
+ # @param [Manifests::StoryboardBundling] manifest the manifest to bundle
195
+ # @param [Hash{Symbol=>Object}] options
196
+ # @return [Jobs::StoryboardBundling] a job to monitor the status of the storyboard bundling
197
+ def bundle! manifest, options = {}
198
+ Resources::Jobs::StoryboardBundling.load(send_manifest(manifest, Resources::Jobs::StoryboardBundling.endpoint, options))
199
+ end
200
+
201
+ # Sends a request to unbundle a storyboard.
202
+ #
203
+ # @param [Manifests::StoryboardUnbundling] manifest the manifest to unbundle
204
+ # @param [Hash{Symbol=>Object}] options
205
+ # @return [Jobs::StoryboardUnbundling] a job to monitor the status of the storyboard unbundling
206
+ def unbundle! manifest, options = {}
207
+ Resources::Jobs::StoryboardUnbundling.load(send_manifest(manifest, Resources::Jobs::StoryboardUnbundling.endpoint, options))
208
+ end
209
+
188
210
  # Update a resource with the latest attributes. Useful to update the state of a Job to
189
211
  # see if it's ready if you are not using HTTP callbacks.
190
212
  #
@@ -195,6 +217,15 @@ module Animoto
195
217
  resource.load(find_request(resource.class, resource.url, options))
196
218
  end
197
219
 
220
+ # Delete a resource. May not supported for all types of resources.
221
+ #
222
+ # @param [Resources::Base] resource to delete
223
+ # @param [Hash{Symbol=>Object}] options
224
+ # @return [Boolean] true if deletion was successful
225
+ def delete! resource, options = {}
226
+ request(:delete, resource.url, nil)
227
+ end
228
+
198
229
  private
199
230
 
200
231
  # Sets the API credentials from an .animotorc file. First looks for one in the current
@@ -208,7 +239,6 @@ module Animoto
208
239
  config = if File.exist?(current_path)
209
240
  YAML.load(File.read(current_path))
210
241
  elsif File.exist?(home_path)
211
- home_path = File.expand_path '~/.animotorc'
212
242
  YAML.load(File.read(home_path))
213
243
  elsif File.exist?('/etc/.animotorc')
214
244
  YAML.load(File.read('/etc/.animotorc'))
@@ -244,7 +274,7 @@ module Animoto
244
274
  :post,
245
275
  u.to_s,
246
276
  response_parser.unparse(manifest.to_hash),
247
- { "Accept" => "application/#{response_parser.format}", "Content-Type" => content_type_of(manifest) },
277
+ { "Accept" => content_type_of(manifest.associated_job_class), "Content-Type" => content_type_of(manifest) },
248
278
  options
249
279
  )
250
280
  end
@@ -257,33 +287,25 @@ module Animoto
257
287
  # @param [Hash{String=>String}] headers the request headers (will be sent as-is, which means you should
258
288
  # specify "Content-Type" => "..." instead of, say, :content_type => "...")
259
289
  # @param [Hash{Symbol=>Object}] options
260
- # @return [Hash{String=>Object}] deserialized response body
261
- # @raise [Error]
290
+ # @return [Hash{String=>Object},Boolean] deserialized response body, or boolean indicating success or failure
291
+ # @raise [HTTPError] if something goes wrong with the request or response
262
292
  def request method, url, body, headers = {}, options = {}
263
- code, body = catch(:fail) do
264
- options = { :username => @key, :password => @secret }.merge(options)
265
- @logger.info "Sending request to #{url.inspect} with body #{body}"
266
- response = http_engine.request(method, url, body, headers, options)
267
- @logger.info "Received response #{response}"
268
- return response_parser.parse(response)
269
- end
270
- if code
271
- if body.empty?
272
- @logger.error "HTTP error (#{code})"
273
- raise Animoto::Error.new("HTTP error (#{code})")
293
+ options = { :username => @key, :password => @secret }.merge(options)
294
+ @logger.info "Sending request to #{url.inspect} with body #{body}"
295
+ code, response_body = http_engine.request(method, url, body, headers, options)
296
+ if method == :head
297
+ (200..299) === code || raise(Animoto::HTTPError.new(url, code))
298
+ else
299
+ case code
300
+ when 204, 205
301
+ true
302
+ when (200..299)
303
+ response_parser.parse(response_body)
274
304
  else
275
- errors = response_parser.parse(body)['response']['status']['errors']
276
- err_string = errors.collect { |e| e['message'] }.join(', ')
277
- @logger.error "Error response from server: #{err_string}"
278
- raise Animoto::Error.new(err_string)
305
+ parsed_response = begin response_body ? response_parser.parse(response_body) : nil rescue nil end
306
+ raise Animoto::HTTPError.new(url, code, parsed_response)
279
307
  end
280
- else
281
- @logger.error "Error sending request to #{url.inspect}"
282
- raise Animoto::Error
283
308
  end
284
- rescue NoMethodError => e
285
- @logger.error e.inspect
286
- raise Animoto::Error.new("Invalid response (#{e.inspect})")
287
309
  end
288
310
 
289
311
  # Creates the full content type string given a Resource class or instance
@@ -26,23 +26,11 @@ module Animoto
26
26
  # @option options [Integer] :timeout set a timeout
27
27
  # @option options [String] :username the authentication username
28
28
  # @option options [String] :password the authentication password
29
- # @return [String] the response body
29
+ # @return [Array[Integer,String]] array of status code and response body
30
30
  # @raise [AbstractMethodError] if called on the abstract class
31
31
  def request method, url, body = nil, headers = {}, options = {}
32
32
  raise AbstractMethodError
33
- end
34
-
35
- private
36
-
37
- # Checks the response and raises an error if the status isn't success.
38
- #
39
- # @param [Integer] code the HTTP status code
40
- # @param [String] body the HTTP response body
41
- # @return [void]
42
- # @raise [Animoto::Error] if the status isn't between 200 and 299
43
- def check_response code, body
44
- throw(:fail, [code,body]) unless (200..299).include?(code)
45
- end
33
+ end
46
34
  end
47
35
  end
48
36
  end
@@ -8,8 +8,7 @@ module Animoto
8
8
  def request method, url, body = nil, headers = {}, options = {}
9
9
  curl = build_curl method, url, body, headers, options
10
10
  perform curl, method, body
11
- check_response curl.response_code, curl.body_str
12
- curl.body_str
11
+ [curl.response_code, curl.body_str]
13
12
  end
14
13
 
15
14
  private
@@ -23,10 +22,14 @@ module Animoto
23
22
  # @return [Curl::Easy] the Easy instance
24
23
  def build_curl method, url, body, headers, options
25
24
  ::Curl::Easy.new(url) do |c|
25
+ c.http_auth_types = Curl::CURLAUTH_BASIC
26
26
  c.username = options[:username]
27
27
  c.password = options[:password]
28
28
  c.timeout = options[:timeout]
29
29
  c.post_body = body
30
+ c.ssl_verify_host = false
31
+ c.ssl_verify_peer = false
32
+ c.proxy_url = options[:proxy]
30
33
  headers.each { |header, value| c.headers[header] = value }
31
34
  end
32
35
  end
@@ -39,10 +42,16 @@ module Animoto
39
42
  # @return [void]
40
43
  def perform curl, method, body
41
44
  case method
45
+ when :head
46
+ curl.http_head
42
47
  when :get
43
48
  curl.http_get
44
49
  when :post
45
50
  curl.http_post(body)
51
+ when :put
52
+ curl.http_put(body)
53
+ when :delete
54
+ curl.http_delete
46
55
  end
47
56
  end
48
57
  end
@@ -7,18 +7,20 @@ module Animoto
7
7
 
8
8
  # A map of HTTP verb symbols to the Net::HTTP classes that handle them.
9
9
  HTTP_METHOD_MAP = {
10
- :get => Net::HTTP::Get,
11
- :post => Net::HTTP::Post
10
+ :head => Net::HTTP::Head,
11
+ :get => Net::HTTP::Get,
12
+ :post => Net::HTTP::Post,
13
+ :put => Net::HTTP::Put,
14
+ :delete => Net::HTTP::Delete
12
15
  }
13
16
 
14
17
  # @return [String]
15
18
  def request method, url, body = nil, headers = {}, options = {}
16
19
  uri = URI.parse(url)
17
- http = build_http uri
20
+ http = build_http uri, options
18
21
  req = build_request method, uri, body, headers, options
19
22
  response = http.request req
20
- check_response response.code.to_i, response.body
21
- response.body
23
+ [response.code.to_i, response.body]
22
24
  end
23
25
 
24
26
  private
@@ -27,8 +29,14 @@ module Animoto
27
29
  #
28
30
  # @param [URI] uri a URI object of the request URL
29
31
  # @return [Net::HTTP] the HTTP object
30
- def build_http uri
31
- http = Net::HTTP.new uri.host, uri.port
32
+ def build_http uri, options
33
+ http = if options[:proxy]
34
+ proxy_uri = URI.parse(options[:proxy])
35
+ Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new uri.host, uri.port
36
+ else
37
+ Net::HTTP.new uri.host, uri.port
38
+ end
39
+ http.read_timeout = options[:timeout]
32
40
  http.use_ssl = true
33
41
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
34
42
  http
@@ -8,8 +8,7 @@ module Animoto
8
8
  def request method, url, body = nil, headers = {}, options = {}
9
9
  session = build_session options
10
10
  response = session.request method, url, headers, :data => body
11
- check_response response.status, response.body
12
- response.body
11
+ [response.status, response.body]
13
12
  end
14
13
 
15
14
  private
@@ -6,6 +6,7 @@ module Animoto
6
6
 
7
7
  # @return [String]
8
8
  def request method, url, body = nil, headers = {}, options = {}
9
+ RestClient.proxy = options[:proxy]
9
10
  response = ::RestClient::Request.execute({
10
11
  :method => method,
11
12
  :url => url,
@@ -15,8 +16,7 @@ module Animoto
15
16
  :password => options[:password],
16
17
  :timeout => options[:timeout]
17
18
  })
18
- check_response response.code, response.body
19
- response.body
19
+ [response.code, response.body]
20
20
  end
21
21
  end
22
22
  end
@@ -12,10 +12,11 @@ module Animoto
12
12
  :headers => headers,
13
13
  :timeout => options[:timeout],
14
14
  :username => options[:username],
15
- :password => options[:password]
15
+ :password => options[:password],
16
+ :disable_ssl_peer_verification => true,
17
+ :proxy => options[:proxy]
16
18
  })
17
- check_response response.code, response.body
18
- response.body
19
+ [response.code, response.body]
19
20
  end
20
21
  end
21
22
  end
@@ -4,12 +4,40 @@ module Animoto
4
4
  # @abstract
5
5
  class Base
6
6
  include Support::ContentType
7
-
7
+
8
8
  # @return [String]
9
9
  def self.infer_content_type
10
10
  super + '_manifest'
11
11
  end
12
-
12
+
13
+ # Returns the Resources::Jobs::Base descendant class associated with this manifest class
14
+ # (that is, the type of job returned when a manifest of this type is posted).
15
+ #
16
+ # @example
17
+ # Manifests::Directing.associated_job_class # => Resources::Jobs::Directing
18
+ # @return [Class] the associated job class
19
+ def self.associated_job_class
20
+ Resources::Jobs.const_get(self.name.split('::').last)
21
+ end
22
+
23
+ # A URL to receive a callback after directing is finished.
24
+ # @return [String]
25
+ attr_accessor :http_callback_url
26
+
27
+ # The format of the callback; either 'xml' or 'json'.
28
+ # @return [String]
29
+ attr_accessor :http_callback_format
30
+
31
+ # Creates a new manifest
32
+ #
33
+ # @param [Hash{Symbol=>Object}] options
34
+ # @option options [String] :http_callback_url a URL to receive a callback when this job is done
35
+ # @option options [String] :http_callback_format the format of the callback
36
+ def initialize options = {}
37
+ @http_callback_url = options[:http_callback_url]
38
+ @http_callback_format = options[:http_callback_format]
39
+ end
40
+
13
41
  # Returns a representation of this manifest as a Hash, used to populate
14
42
  # request bodies when directing, rendering, etc.
15
43
  #
@@ -17,7 +45,29 @@ module Animoto
17
45
  def to_hash
18
46
  {}
19
47
  end
20
-
48
+
49
+ # Returns the Resources::Jobs::Base descendant class associated with this manifest (that is,
50
+ # the type of job that will be returned when this manifest is posted).
51
+ #
52
+ # @return [Class] the associated job class
53
+ def associated_job_class
54
+ self.class.associated_job_class
55
+ end
56
+
57
+ private
58
+
59
+ # Helper method to put the standard HTTP callback information into the manifest hash
60
+ #
61
+ # @param [Hash{String=>Object}] job_hash the hash version of the 'job' portion of this manifest
62
+ # @return [void]
63
+ # @raise [ArgumentError] if a callback url is specified but not the format
64
+ def add_callback_information job_hash
65
+ if http_callback_url
66
+ raise ArgumentError, "You must specify a http_callback_format (either 'xml' or 'json')" if http_callback_format.nil?
67
+ job_hash['http_callback'] = http_callback_url
68
+ job_hash['http_callback_format'] = http_callback_format
69
+ end
70
+ end
21
71
  end
22
72
  end
23
73
  end
@@ -11,14 +11,6 @@ module Animoto
11
11
  # @return [String]
12
12
  attr_accessor :pacing
13
13
 
14
- # A URL to receive a callback after directing is finished.
15
- # @return [String]
16
- attr_accessor :http_callback_url
17
-
18
- # The format of the callback; either 'xml' or 'json'.
19
- # @return [String]
20
- attr_accessor :http_callback_format
21
-
22
14
  # The array of Visual objects in this manifest.
23
15
  # @return [Array<Support::Visual>]
24
16
  attr_reader :visuals
@@ -40,13 +32,12 @@ module Animoto
40
32
  # @option options [String] :http_callback_format the format of the callback
41
33
  # @return [Manifests::Directing] the manifest
42
34
  def initialize options = {}
35
+ super
43
36
  @title = options[:title]
44
37
  @pacing = options[:pacing] || 'default'
45
38
  @style = 'original'
46
39
  @visuals = []
47
40
  @song = nil
48
- @http_callback_url = options[:http_callback_url]
49
- @http_callback_format = options[:http_callback_format]
50
41
  end
51
42
 
52
43
  # Adds a TitleCard to this manifest.
@@ -55,7 +46,7 @@ module Animoto
55
46
  # @return [Assets::TitleCard] the new TitleCard
56
47
  # @see Animoto::Assets::TitleCard#initialize
57
48
  def add_title_card *args
58
- card = Assets::TitleCard.new *args
49
+ card = Assets::TitleCard.new(*args)
59
50
  @visuals << card
60
51
  card
61
52
  end
@@ -66,7 +57,7 @@ module Animoto
66
57
  # @return [Assets::Image] the new Image
67
58
  # @see Animoto::Assets::Image#initialize
68
59
  def add_image *args
69
- image = Assets::Image.new *args
60
+ image = Assets::Image.new(*args)
70
61
  @visuals << image
71
62
  image
72
63
  end
@@ -77,7 +68,7 @@ module Animoto
77
68
  # @return [Assets::Footage] the new Footage
78
69
  # @see Animoto::Assets::Footage#initialize
79
70
  def add_footage *args
80
- footage = Assets::Footage.new *args
71
+ footage = Assets::Footage.new(*args)
81
72
  @visuals << footage
82
73
  footage
83
74
  end
@@ -89,7 +80,7 @@ module Animoto
89
80
  # @return [Assets::Song] the new Song
90
81
  # @see Animoto::Assets::Song#initialize
91
82
  def add_song *args
92
- @song = Assets::Song.new *args
83
+ @song = Assets::Song.new(*args)
93
84
  end
94
85
 
95
86
  # Adds a visual/song to this manifest.
@@ -124,11 +115,7 @@ module Animoto
124
115
  def to_hash options = {}
125
116
  hash = { 'directing_job' => { 'directing_manifest' => {} } }
126
117
  job = hash['directing_job']
127
- if http_callback_url
128
- raise ArgumentError, "You must specify a http_callback_format (either 'xml' or 'json')" if http_callback_format.nil?
129
- job['http_callback'] = http_callback_url
130
- job['http_callback_format'] = http_callback_format
131
- end
118
+ add_callback_information job
132
119
  manifest = job['directing_manifest']
133
120
  manifest['style'] = style
134
121
  manifest['pacing'] = pacing if pacing
@@ -13,14 +13,6 @@ module Animoto
13
13
  # @return [Manifests::Rendering]
14
14
  attr_reader :rendering_manifest
15
15
 
16
- # A URL to receive a callback after directing is finished.
17
- # @return [String]
18
- attr_accessor :http_callback_url
19
-
20
- # The format of the callback; either 'xml' or 'json'.
21
- # @return [String]
22
- attr_accessor :http_callback_format
23
-
24
16
  # Creates a new directing-and-rendering manifest.
25
17
  #
26
18
  # @param [Hash{Symbol=>Object}] options
@@ -31,12 +23,11 @@ module Animoto
31
23
  # @option options [String] :format the format of the rendered video
32
24
  # @option options [String] :http_callback_url a URL to receive a callback when this job is done
33
25
  # @option options [String] :http_callback_format the format of the callback
34
- def initialize options = {}
26
+ # @return [Manifests::DirectingAndRendering] the manifest
27
+ def initialize options = {}
28
+ super
35
29
  @directing_manifest = Manifests::Directing.new(options.only(:title, :pacing))
36
30
  @rendering_manifest = Manifests::Rendering.new(options.only(:resolution, :framerate, :format))
37
-
38
- @http_callback_url = options[:http_callback_url]
39
- @http_callback_format = options[:http_callback_format]
40
31
  end
41
32
 
42
33
  # Delegates method calls to the underlying directing or rendering manifests if
@@ -46,9 +37,9 @@ module Animoto
46
37
  def method_missing *args
47
38
  name = args.first
48
39
  if directing_manifest.respond_to?(name)
49
- directing_manifest.__send__ *args
40
+ directing_manifest.__send__(*args)
50
41
  elsif rendering_manifest.respond_to?(name)
51
- rendering_manifest.__send__ *args
42
+ rendering_manifest.__send__(*args)
52
43
  else
53
44
  super
54
45
  end
@@ -63,11 +54,7 @@ module Animoto
63
54
  def to_hash options = {}
64
55
  hash = { 'directing_and_rendering_job' => {} }
65
56
  job = hash['directing_and_rendering_job']
66
- if http_callback_url
67
- raise ArgumentError, "You must specify a http_callback_format (either 'xml' or 'json')" if http_callback_format.nil?
68
- job['http_callback'] = http_callback_url
69
- job['http_callback_format'] = http_callback_format
70
- end
57
+ add_callback_information job
71
58
  job['directing_manifest'] = self.directing_manifest.to_hash['directing_job']['directing_manifest']
72
59
  job['rendering_manifest'] = self.rendering_manifest.to_hash['rendering_job']['rendering_manifest']
73
60
  hash