encoding-dot-com 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ *~
7
+ \#*
8
+ .\#*
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Enrich Social Productions Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,56 @@
1
+ = encoding-dot-com
2
+
3
+ A client library for the encoding.com[http://www.encoding.com] API.
4
+
5
+ Supports all the actions of the encoding.com API. Example usage:
6
+
7
+ require "encoding_dot_com"
8
+
9
+ # Create an interface to the encoding.com queue with your user id and secret
10
+ queue = EncodingDotCom::Queue.new(1234, "secret")
11
+
12
+ # Create one or more output formats
13
+ format = EncodingDotCom::Format.create("output" => "flv")
14
+
15
+ # Get an media item processed. You can pass multiple output formats in a hash.
16
+ media_id = queue.add_and_process("http://source/url/here", "http://destination/url/here" => format)
17
+
18
+ queue.status(media_id) # => returns a string like "Waiting for encoder" or "Finished"
19
+ queue.info(media_id) # => returns information about an item in the queue
20
+
21
+ See the API documentation for more details - Queue is a good starting place.
22
+
23
+ By default the library uses Curb for http - there is also a Net/HTTP
24
+ adapter and it is easy to write your own.
25
+
26
+ == Dependencies
27
+
28
+ * Nokogiri
29
+ * (Optionally) curb
30
+
31
+ == TODOs
32
+
33
+ * Flesh out validations to ensure that bad data does not get submitted to
34
+ encoding.com
35
+ * Full status method
36
+
37
+ == Note on Patches/Pull Requests
38
+
39
+ * Fork the project.
40
+ * Make your feature addition or bug fix.
41
+ * Add tests for it. This is important so I don't break it in a
42
+ future version unintentionally.
43
+ * Commit, do not mess with rakefile, version, or history.
44
+ (if you want to have your own version, that is fine but
45
+ bump version in a commit by itself I can ignore when I pull)
46
+ * Send me a pull request. Bonus points for topic branches.
47
+
48
+ == Authors
49
+
50
+ * {Roland Swingler}[http://github.com/knaveofdiamonds]
51
+ * {Alan Kennedy}[http://github.com/alan]
52
+ * {Levent Ali}[http://github.com/levent]
53
+
54
+ == Copyright
55
+
56
+ Copyright (c) 2009 Enrich Social Productions Ltd. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,75 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "encoding-dot-com"
8
+ gem.summary = %Q{A ruby wrapper for the encoding.com API}
9
+ gem.description = %Q{A ruby wrapper for the encoding.com API}
10
+ gem.email = "roland.swingler@gmail.com"
11
+ gem.homepage = "http://encodingdotcom.rubyforge.org/"
12
+ gem.authors = ["Roland Swingler", "Alan Kennedy", "Levent Ali"]
13
+ gem.add_dependency "nokogiri"
14
+ gem.add_development_dependency "rspec"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb']
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :spec => :check_dependencies
34
+
35
+ begin
36
+ require 'reek/rake_task'
37
+ Reek::RakeTask.new do |t|
38
+ t.fail_on_error = true
39
+ t.verbose = false
40
+ t.source_files = 'lib/**/*.rb'
41
+ end
42
+ rescue LoadError
43
+ task :reek do
44
+ abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
45
+ end
46
+ end
47
+
48
+ begin
49
+ require 'roodi'
50
+ require 'roodi_task'
51
+ RoodiTask.new do |t|
52
+ t.verbose = false
53
+ end
54
+ rescue LoadError
55
+ task :roodi do
56
+ abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
57
+ end
58
+ end
59
+
60
+ require 'rake/rdoctask'
61
+ Rake::RDocTask.new do |rdoc|
62
+ if File.exist?('VERSION')
63
+ version = File.read('VERSION')
64
+ else
65
+ version = ""
66
+ end
67
+
68
+ rdoc.rdoc_dir = 'rdoc'
69
+ rdoc.title = "Encoding dot com #{version}"
70
+ rdoc.rdoc_files.include('README*')
71
+ rdoc.rdoc_files.include('lib/**/*.rb')
72
+ end
73
+
74
+ task :default => [:spec, :roodi]
75
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,80 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{encoding-dot-com}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Roland Swingler", "Alan Kennedy", "Levent Ali"]
12
+ s.date = %q{2009-12-07}
13
+ s.description = %q{A ruby wrapper for the encoding.com API}
14
+ s.email = %q{roland.swingler@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "encoding-dot-com.gemspec",
27
+ "lib/encoding-dot-com.rb",
28
+ "lib/encoding_dot_com.rb",
29
+ "lib/encoding_dot_com/attribute_restrictions.rb",
30
+ "lib/encoding_dot_com/errors.rb",
31
+ "lib/encoding_dot_com/flv_vp6_format.rb",
32
+ "lib/encoding_dot_com/format.rb",
33
+ "lib/encoding_dot_com/http_adapters/curb_adapter.rb",
34
+ "lib/encoding_dot_com/http_adapters/net_http_adapter.rb",
35
+ "lib/encoding_dot_com/media_info.rb",
36
+ "lib/encoding_dot_com/media_list_item.rb",
37
+ "lib/encoding_dot_com/queue.rb",
38
+ "lib/encoding_dot_com/thumbnail_format.rb",
39
+ "lib/encoding_dot_com/video_format.rb",
40
+ "spec/encoding_dot_com/http_adapters/curb_adapter_spec.rb",
41
+ "spec/encoding_dot_com/http_adapters/net_http_adapter_spec.rb",
42
+ "spec/flv_vp6_format_spec.rb",
43
+ "spec/format_spec.rb",
44
+ "spec/media_list_item_spec.rb",
45
+ "spec/queue_spec.rb",
46
+ "spec/spec_helper.rb",
47
+ "spec/thumbnail_format_spec.rb"
48
+ ]
49
+ s.homepage = %q{http://encodingdotcom.rubyforge.org/}
50
+ s.rdoc_options = ["--charset=UTF-8"]
51
+ s.require_paths = ["lib"]
52
+ s.rubygems_version = %q{1.3.5}
53
+ s.summary = %q{A ruby wrapper for the encoding.com API}
54
+ s.test_files = [
55
+ "spec/flv_vp6_format_spec.rb",
56
+ "spec/spec_helper.rb",
57
+ "spec/encoding_dot_com/http_adapters/net_http_adapter_spec.rb",
58
+ "spec/encoding_dot_com/http_adapters/curb_adapter_spec.rb",
59
+ "spec/format_spec.rb",
60
+ "spec/queue_spec.rb",
61
+ "spec/media_list_item_spec.rb",
62
+ "spec/thumbnail_format_spec.rb"
63
+ ]
64
+
65
+ if s.respond_to? :specification_version then
66
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
67
+ s.specification_version = 3
68
+
69
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
70
+ s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
71
+ s.add_development_dependency(%q<rspec>, [">= 0"])
72
+ else
73
+ s.add_dependency(%q<nokogiri>, [">= 0"])
74
+ s.add_dependency(%q<rspec>, [">= 0"])
75
+ end
76
+ else
77
+ s.add_dependency(%q<nokogiri>, [">= 0"])
78
+ s.add_dependency(%q<rspec>, [">= 0"])
79
+ end
80
+ end
@@ -0,0 +1,12 @@
1
+ require 'encoding_dot_com/errors'
2
+ require 'encoding_dot_com/queue'
3
+ require 'encoding_dot_com/attribute_restrictions'
4
+ require 'encoding_dot_com/format'
5
+ require 'encoding_dot_com/video_format'
6
+ require 'encoding_dot_com/thumbnail_format'
7
+ require 'encoding_dot_com/flv_vp6_format'
8
+ require 'encoding_dot_com/media_list_item'
9
+ require 'encoding_dot_com/media_info'
10
+ require 'encoding_dot_com/http_adapters/curb_adapter'
11
+ require 'encoding_dot_com/http_adapters/net_http_adapter'
12
+
@@ -0,0 +1,74 @@
1
+ module EncodingDotCom
2
+ module AttributeRestrictionsZune #:nodoc:
3
+ def validate_size
4
+ allowed_sizes = %w{320x120 320x180 320x0 0x120 0x180}
5
+ unless size.nil? || allowed_sizes.include?(size)
6
+ raise IllegalFormatAttribute.new("Size can only be one of #{allowed_sizes.join(',')} but was #{size}")
7
+ end
8
+ end
9
+ end
10
+
11
+ module AttributeRestrictionsIpod #:nodoc:
12
+ def validate_size
13
+ allowed_sizes = %w{320x240 640x480}
14
+ unless size.nil? || allowed_sizes.include?(size)
15
+ raise IllegalFormatAttribute.new("Size can only be one of #{allowed_sizes.join(',')} but was #{size}")
16
+ end
17
+ end
18
+ end
19
+
20
+ module AttributeRestrictionsFlv #:nodoc:
21
+ # validate_inclusion_of :audio_bitrate, %w{32k 40k 48k 56k 64k 80k 96k 112k 128k 144k 160k 192k 224k 256k 320k}
22
+ # validate_inclusion_of :video_codec, %w{flv libx264 vp6}
23
+
24
+ def validate_audio_bitrate
25
+ allowed_bitrates = %w{32k 40k 48k 56k 64k 80k 96k 112k 128k 144k 160k 192k 224k 256k 320k}
26
+ end
27
+
28
+ def validate_video_codec
29
+ allowed_codecs = %w{flv libx264 vp6}
30
+ unless video_codec.nil? || allowed_codecs.include?(video_codec)
31
+ raise IllegalFormatAttribute.new("Video codec can only be one of #{allowed_codecs.join(',')} but was #{video_codec}")
32
+ end
33
+ end
34
+ end
35
+
36
+ module AttributeRestrictionsMp4 #:nodoc:
37
+ def validate_video_codec
38
+ allowed_codecs = %w{mpeg4 libx264}
39
+ unless video_codec.nil? || allowed_codecs.include?(video_codec)
40
+ raise IllegalFormatAttribute.new("Video codec can only be one of #{allowed_codecs.join(',')} but was #{video_codec}")
41
+ end
42
+ end
43
+ end
44
+
45
+ module AttributeRestrictionsFl9 #:nodoc:
46
+ end
47
+
48
+ module AttributeRestrictionsWmv #:nodoc:
49
+ end
50
+
51
+ module AttributeRestrictions3gp #:nodoc:
52
+ end
53
+
54
+ module AttributeRestrictionsM4v #:nodoc:
55
+ end
56
+
57
+ module AttributeRestrictionsIphone #:nodoc:
58
+ end
59
+
60
+ module AttributeRestrictionsAppletv #:nodoc:
61
+ end
62
+
63
+ module AttributeRestrictionsPsp #:nodoc:
64
+ end
65
+
66
+ module AttributeRestrictionsMp3 #:nodoc:
67
+ end
68
+
69
+ module AttributeRestrictionsWma #:nodoc:
70
+ end
71
+
72
+ module AttributeRestrictionsThumbnail #:nodoc:
73
+ end
74
+ end
@@ -0,0 +1,15 @@
1
+ module EncodingDotCom
2
+ # Error raised if there is an http-level problem accessing the
3
+ # encoding.com API.
4
+ class AvailabilityError < StandardError
5
+ end
6
+
7
+ # Error raised if there is an problem with the message sent to
8
+ # encoding.com API.
9
+ class MessageError < StandardError
10
+ end
11
+
12
+ # Error raised if a format's attribute has an illegal value
13
+ class IllegalFormatAttribute < StandardError
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ module EncodingDotCom
2
+ # FLV Format that uses the VP6 codec - there are fewer attributes
3
+ # that can be set for VP6 compared to other video codecs.
4
+ class FLVVP6Format < Format #:nodoc:
5
+ allowed_attributes :output, :video_codec, :size, :destination, :bitrate, :audio_bitrate, :audio_sample_rate, :audio_channels_number, :framerate
6
+
7
+ def initialize(attributes={})
8
+ @attributes = attributes.merge("output" => "flv", "video_codec" => "vp6")
9
+ validate_attributes
10
+ end
11
+
12
+ def validate_attributes
13
+ validate_size
14
+ end
15
+
16
+ private
17
+
18
+ def validate_size
19
+ return if size.nil?
20
+ if video_codec == "vp6" && ! size.split("x").all? {|n| (n.to_i % 16) == 0 }
21
+ raise IllegalFormatAttribute.new("Dimensions #{} should be multiples of 16")
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,73 @@
1
+ module EncodingDotCom
2
+ # Base class for all formats sent to encoding.com
3
+ #
4
+ # You should create formats by calling +create+ with format attributes.
5
+ class Format
6
+ class << self
7
+ # Factory method that returns an appropriate Format. The
8
+ # +output+ attribute is required, others are optional (see the
9
+ # encoding.com documentation for full list of attributes).
10
+ def create(attributes)
11
+ if attributes["output"] == "thumbnail"
12
+ ThumbnailFormat.new(attributes)
13
+ elsif attributes["output"] == "flv" && attributes["video_codec"] == "vp6"
14
+ FLVVP6Format.new(attributes)
15
+ else
16
+ VideoFormat.new(attributes)
17
+ end
18
+ end
19
+
20
+ def allowed_attributes(*attrs) #:nodoc:
21
+ @allowed_attributes ||= []
22
+ if attrs.empty?
23
+ @allowed_attributes
24
+ else
25
+ @allowed_attributes += attrs.map {|a| a.to_s }.each { |attr| define_method(attr) { @attributes[attr] } }
26
+ end
27
+ end
28
+
29
+ def boolean_attributes(*attrs) #:nodoc:
30
+ @boolean_attributes ||= []
31
+ if attrs.empty?
32
+ @boolean_attributes
33
+ else
34
+ allowed_attributes *attrs
35
+ @boolean_attributes += attrs.map {|a| a.to_s }
36
+ end
37
+ end
38
+ end
39
+
40
+ # Builds the XML for this format.
41
+ #
42
+ # +builder+:: a Nokogiri builder, declared with a block
43
+ # +destination_url+:: where the encoded file should be placed. See
44
+ # the encoding.com documentation for details.
45
+ def build_xml(builder, destination_url=nil)
46
+ logo_attributes, other_attributes = self.class.allowed_attributes.partition {|a| a[0..3] == "logo" }
47
+
48
+ builder.format {
49
+ builder.destination destination_url
50
+ other_attributes.each do |attr|
51
+ builder.send(attr, output_value(attr)) unless @attributes[attr].nil?
52
+ end
53
+ if logo_attributes.any? {|attr| @attributes[attr] }
54
+ builder.logo {
55
+ logo_attributes.each {|attr| builder.send(attr, output_value(attr)) if @attributes[attr] }
56
+ }
57
+ end
58
+ }
59
+ end
60
+
61
+ private
62
+
63
+ # Returns a value suitable for the format XML - i.e. translates
64
+ # booleans to yes/no.
65
+ def output_value(key)
66
+ if self.class.boolean_attributes.include?(key)
67
+ (@attributes[key] ? "yes" : "no")
68
+ else
69
+ @attributes[key]
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,27 @@
1
+ module EncodingDotCom
2
+ module HttpAdapters
3
+
4
+ Response = Struct.new(:code, :body)
5
+
6
+ # Wraps the curb[http://curb.rubyforge.org/] library for use with
7
+ # the Queue.
8
+ class CurbAdapter
9
+ def initialize
10
+ require 'curb'
11
+ end
12
+
13
+ # Makes a POST request. Raises an AvailabilityError if the
14
+ # request times out or has other problems.
15
+ def post(url, parameters={})
16
+ curl = Curl::Easy.new(url) {|c| c.follow_location = true }
17
+ post_parameters = parameters.map {|k,v| Curl::PostField.content(k.to_s, v.to_s) }
18
+ begin
19
+ curl.http_post(*post_parameters)
20
+ rescue => e
21
+ raise AvailabilityError.new(e.message)
22
+ end
23
+ Response.new(curl.response_code.to_s, curl.body_str)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ module EncodingDotCom
2
+ module HttpAdapters
3
+
4
+ # Wraps the Net/HTTP library for use with the Queue.
5
+ class NetHttpAdapter
6
+ def initialize
7
+ require 'net/http'
8
+ end
9
+
10
+ # Makes a POST request. Raises an AvailabilityError if the
11
+ # request times out or has other problems.
12
+ def post(url, parameters={})
13
+ Net::HTTP.post_form(URI.parse(url), parameters)
14
+ rescue => e
15
+ raise AvailabilityError.new(e.message)
16
+ rescue Timeout::Error => e
17
+ raise AvailabilityError.new(e.message)
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ require 'parsedate'
2
+
3
+ module EncodingDotCom
4
+ # Represents information about a video or image in the encoding.com queue
5
+ class MediaInfo
6
+ attr_reader :bitrate, :duration, :video_codec, :video_bitrate, :frame_rate, :size, :pixel_aspect_ratio, :display_aspect_ratio, :audio_codec, :audio_sample_rate, :audio_channels
7
+
8
+ # Creates a MediaInfo object, given a <response> Nokogiri::XML::Node
9
+ #
10
+ # See the encoding.com documentation for GetMediaInfo action for more details
11
+ def initialize(node)
12
+ @bitrate = (node / "bitrate").text
13
+ @duration = (node / "duration").text.to_f
14
+ @video_codec = (node / "video_codec").text
15
+ @video_bitrate = (node / "video_bitrate").text
16
+ @frame_rate = (node / "frame_rate").text.to_f
17
+ @size = (node / "size").text
18
+ @pixel_aspect_ratio = (node / "pixel_aspect_ratio").text
19
+ @display_aspect_ratio = (node / "display_aspect_ratio").text
20
+ @audio_codec = (node / "audio_codec").text
21
+ @audio_sample_rate = (node / "audio_sample_rate").text.to_i
22
+ @audio_channels = (node / "audio_channels").text.to_i
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ require 'parsedate'
2
+
3
+ module EncodingDotCom
4
+
5
+ # Represents a video or image in the encoding.com queue
6
+ class MediaListItem
7
+ attr_reader :media_file, :media_id, :media_status, :create_date, :start_date, :finish_date
8
+
9
+ # Creates a MediaListItem, given a <media> Nokogiri::XML::Node
10
+ #
11
+ # See the encoding.com documentation for GetMediaList for more details
12
+ def initialize(node)
13
+ @media_file = (node / "mediafile").text
14
+ @media_id = (node / "mediaid").text.to_i
15
+ @media_status = (node / "mediastatus").text
16
+ @create_date = parse_time_node(node / "createdate")
17
+ @start_date = parse_time_node(node / "startdate")
18
+ @finish_date = parse_time_node(node / "finishdate")
19
+ end
20
+
21
+ private
22
+
23
+ def parse_time_node(node)
24
+ time_elements = ParseDate.parsedate(node.text)
25
+ Time.local *time_elements unless time_elements.all? {|e| e.nil? || e == 0 }
26
+ end
27
+ end
28
+ end