matterhorn_whymper 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MzFjMzFkMjcxNDYyMTZlZjM1NjVkMTBmMTUzNmJmNTI1N2ZiN2I1NA==
5
+ data.tar.gz: !binary |-
6
+ MmFkNTAxNDM0M2ZiM2FlMzViNTczYjYzNjcxYzI4YTNjNDNjMjhkYQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZTc5ZGRlNGNkNGZlY2NhZGI4ZDY5YTgyNWFiMzUwYWQ2NmRmNzg4ZjA5ZTM0
10
+ MmU3MjY3YjNhYzI5ZjFmYWQ2NDIwOGE1ZjExNzY0NmI0ZmNkNGI0NTNkZWQz
11
+ NzVmZjQ3Njg4MGFhOThhNDQwMTc0NzI0NWQ1NWNhNzM4NWJjNTM=
12
+ data.tar.gz: !binary |-
13
+ NDEzZjUwZDMwZjhmZWY3NWI3YjQxODk4ZWViNzEyMDJkNjY4M2EyNmVkMzNi
14
+ YmYwMjVmMjVmNTY2ZGNlZTNhNzkzOWI3ZDM1YWZmNTE3YjQ5NWYzN2U0ODJk
15
+ ZmFjY2FhMDRhYjE3M2FmNTEwNDI0NTA5NmZmZGJmYmMzNjUxYTM=
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/matterhorn.yml
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ *.bundle
20
+ *.so
21
+ *.o
22
+ *.a
23
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.rvmrc ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 1.9.3" > .rvmrc
9
+ environment_id="ruby-1.9.3-p484@matterhorn-endpoint_api"
10
+
11
+ # Uncomment the following lines if you want to verify rvm version per project
12
+ # rvmrc_rvm_version="1.25.19 (stable)" # 1.10.1 seems like a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | __rvm_awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficient compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
+ then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+ for __hook in "${rvm_path:-$HOME/.rvm}/hooks/after_use"*
27
+ do
28
+ if [[ -f "${__hook}" && -x "${__hook}" && -s "${__hook}" ]]
29
+ then \. "${__hook}" || true
30
+ fi
31
+ done
32
+ unset __hook
33
+ if (( ${rvm_use_flag:=1} >= 1 )) # display automatically
34
+ then
35
+ if [[ $- == *i* ]] # check for interactive shells
36
+ then printf "%b" "Using: $(tput setaf 2 2>/dev/null)$GEM_HOME$(tput sgr0 2>/dev/null)
37
+ " # show the user the ruby and gemset they are using in green
38
+ else printf "%b" "Using: $GEM_HOME
39
+ " # don't use colors in non-interactive shells
40
+ fi
41
+ fi
42
+ else
43
+ # If the environment file has not yet been created, use the RVM CLI to select.
44
+ rvm --create use "$environment_id" || {
45
+ echo "Failed to create RVM environment '${environment_id}'."
46
+ return 1
47
+ }
48
+ fi
49
+
50
+ # If you use bundler, this might be useful to you:
51
+ # if [[ -s Gemfile ]] && {
52
+ # ! builtin command -v bundle >/dev/null ||
53
+ # builtin command -v bundle | GREP_OPTIONS="" \grep $rvm_path/bin/bundle >/dev/null
54
+ # }
55
+ # then
56
+ # printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
57
+ # gem install bundler
58
+ # fi
59
+ # if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
60
+ # then
61
+ # bundle install | GREP_OPTIONS="" \grep -vE '^Using|Your bundle is complete'
62
+ # fi
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in matterhorn-endpoint_api.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 SWITCH / Daniel Fritschi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # Matterhorn Whymper
2
+
3
+ Ruby wrapper against the Matterhorn Endpoint API
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'matterhorn_whymper'
11
+
12
+ And then execute:
13
+
14
+ $ bundle install
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install matterhorn_whymper
19
+
20
+ ## Usage
21
+
22
+ TODO: Write usage instructions here
23
+
24
+ ## Contributing
25
+
26
+ 1. Fork it ( https://github.com/switch-ch/matterhorn_whymper/fork )
27
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
28
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
29
+ 4. Push to the branch (`git push origin my-new-feature`)
30
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task :test => :spec
8
+
@@ -0,0 +1,40 @@
1
+ module Matterhorn
2
+
3
+ class Endpoint
4
+
5
+ # --- attributes -------------------------------------------------------------
6
+
7
+ attr_reader :http_client
8
+
9
+
10
+ # --- initialization ---------------------------------------------------------
11
+
12
+ def self.open(endpoint)
13
+ if endpoint.respond_to? 'to_s'
14
+ endpoint = endpoint.to_s.capitalize
15
+ else
16
+ #TODO: error handling
17
+ end
18
+ endpoint = Object.const_get('Matterhorn').const_get('Endpoint').const_get(endpoint).new
19
+
20
+ yield endpoint
21
+
22
+ endpoint.close
23
+ end
24
+
25
+
26
+ def initialize
27
+ @http_client = Matterhorn::HttpClient.new(
28
+ MatterhornWhymper.configuration.uri
29
+ )
30
+ end
31
+
32
+
33
+ def close
34
+ http_client.close
35
+ end
36
+
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,124 @@
1
+ class Matterhorn::Endpoint::Ingest < Matterhorn::Endpoint
2
+
3
+ # --- attributes -------------------------------------------------------------
4
+
5
+
6
+ # --- end point methodes -----------------------------------------------------
7
+
8
+ def addAttachment(file, flavor)
9
+ if @media_pkg_remote.nil?
10
+ raise(Matterhorn::Error, "No media package is available!")
11
+ end
12
+ @media_pkg_local.add_attachment(file, flavor)
13
+ @media_pkg_remote = http_client.post(
14
+ "ingest/addAttachment",
15
+ { 'flavor' => flavor,
16
+ 'mediaPackage' => @media_pkg_remote,
17
+ 'BODY' => file
18
+ }
19
+ ).body
20
+ end
21
+
22
+
23
+ def addCatalog(file, flavor)
24
+ if @media_pkg_remote.nil?
25
+ raise(Matterhorn::Error, "No media package is available!")
26
+ end
27
+ @media_pkg_local.add_catalog(file, flavor)
28
+ @media_pkg_remote = http_client.post(
29
+ "ingest/addCatalog",
30
+ { 'flavor' => flavor,
31
+ 'mediaPackage' => @media_pkg_remote,
32
+ 'BODY' => file
33
+ }
34
+ ).body
35
+ end
36
+
37
+
38
+ def addDCCatalog(dublin_core)
39
+ if @media_pkg_remote.nil?
40
+ raise(Matterhorn::Error, "No media package is available!")
41
+ end
42
+ @media_pkg_local.add_dc_catalog(dublin_core)
43
+ @media_pkg_remote = http_client.post(
44
+ "ingest/addDCCatalog",
45
+ { 'flavor' => 'dublincore/episode',
46
+ 'mediaPackage' => @media_pkg_remote,
47
+ 'dublinCore' => dublin_core
48
+ }
49
+ ).body
50
+ end
51
+
52
+
53
+ def addTrack(file, flavor)
54
+ if @media_pkg_remote.nil?
55
+ raise(Matterhorn::Error, "No media package is available!")
56
+ end
57
+ @media_pkg_local.add_track(file, flavor)
58
+ @media_pkg_remote = http_client.post(
59
+ "ingest/addTrack",
60
+ { 'flavor' => flavor,
61
+ 'mediaPackage' => @media_pkg_remote,
62
+ 'BODY' => file
63
+ }
64
+ ).body
65
+ end
66
+
67
+
68
+ def createMediaPackage(path = '')
69
+ if !@media_pkg_remote.nil?
70
+ raise(Matterhorn::Error, "A media package is allready created!")
71
+ end
72
+ @media_pkg_local = Matterhorn::MediaPackage.new(path)
73
+ @media_pkg_remote = http_client.get(
74
+ "ingest/createMediaPackage"
75
+ ).body
76
+ end
77
+
78
+
79
+ def ingest(wdID = 'full', options = {})
80
+ if @media_pkg_remote.nil?
81
+ raise(Matterhorn::Error, "No media package is available!")
82
+ end
83
+ @media_pkg_local.save if !@media_pkg_local.nil?
84
+ options['mediaPackage'] = @media_pkg_remote
85
+ @workflow_inst = http_client.post(
86
+ "ingest/ingest/#{wdID}",
87
+ options
88
+ ).body
89
+ workflow_instance
90
+ end
91
+
92
+
93
+ def media_package(kind = 'local')
94
+ if kind == 'local' && !@media_pkg_local.nil?
95
+ return @media_pkg_local
96
+ elsif !@media_pkg_remote.nil?
97
+ Matterhorn::MediaPackage.new(@media_pkg_remote)
98
+ else
99
+ nil
100
+ end
101
+ end
102
+
103
+
104
+ def setTitle(title)
105
+ dublin_core = <<DUBLIN_CORE
106
+ <?xml version="1.0" encoding="UTF-8"?>
107
+ <dublincore xmlns="http://www.opencastproject.org/xsd/1.0/dublincore/" xmlns:dcterms="http://purl.org/dc/terms/">
108
+ <dcterms:title>#{title}</dcterms:title>
109
+ </dublincore>
110
+ DUBLIN_CORE
111
+ addDCCatalog(dublin_core)
112
+ end
113
+
114
+
115
+ def workflow_instance
116
+ if !@workflow_inst.nil?
117
+ Matterhorn::WorkflowInstance.new(@workflow_inst)
118
+ else
119
+ nil
120
+ end
121
+ end
122
+
123
+
124
+ end
@@ -0,0 +1,67 @@
1
+ class Matterhorn::Endpoint::Workflow < Matterhorn::Endpoint
2
+
3
+ # --- attributes -------------------------------------------------------------
4
+
5
+
6
+ # --- end point methodes -----------------------------------------------------
7
+
8
+ def instance(wi_id)
9
+ @workflow_inst = http_client.get(
10
+ "workflow/instance/#{wi_id}.xml"
11
+ ).body
12
+ workflow_instance
13
+ end
14
+
15
+
16
+ def remove(wi_id, options = {})
17
+ begin
18
+ @workflow_inst = http_client.delete(
19
+ "workflow/remove/#{wi_id}"
20
+ ).body
21
+ rescue Matterhorn::HttpClientError => ex
22
+ Rails.logger.warn { "Matterhorn::Workflow::remove | WorkflowInstance[wi_id] could not be stopped!\n" +
23
+ "#{ex.class.name}: #{ex.to_s} / backtrace:\n#{ex.backtrace.join("\n")}" }
24
+ return nil
25
+ rescue => ex
26
+ raise ex
27
+ end
28
+ end
29
+
30
+
31
+ def resume(wi_id, options = {})
32
+ options['id'] = wi_id
33
+ @workflow_inst = http_client.post(
34
+ "workflow/resume",
35
+ options
36
+ ).body
37
+ workflow_instance
38
+ end
39
+
40
+
41
+ def stop(wi_id, options = {})
42
+ begin
43
+ options['id'] = wi_id
44
+ @workflow_inst = http_client.post(
45
+ "workflow/stop",
46
+ options
47
+ ).body
48
+ workflow_instance
49
+ rescue Matterhorn::HttpClientError => ex
50
+ Rails.logger.warn { "Matterhorn::Workflow::stop | WorkflowInstance[wi_id] could not be stopped!\n" +
51
+ "#{ex.class.name}: #{ex.to_s} / backtrace:\n#{ex.backtrace.join("\n")}" }
52
+ return nil
53
+ rescue => ex
54
+ raise ex
55
+ end
56
+ end
57
+
58
+
59
+ def workflow_instance
60
+ if !@workflow_inst.nil?
61
+ Matterhorn::WorkflowInstance.new(@workflow_inst)
62
+ else
63
+ nil
64
+ end
65
+ end
66
+
67
+ end
@@ -0,0 +1,15 @@
1
+ module Matterhorn
2
+
3
+ # --- Matterhorn Exceptions ------------------------------------------------------------------------
4
+
5
+ class Matterhorn::Error < StandardError
6
+ end
7
+
8
+ class Matterhorn::HttpClientError < Matterhorn::Error
9
+ end
10
+
11
+ class Matterhorn::HttpServerError < Matterhorn::Error
12
+ end
13
+
14
+
15
+ end
@@ -0,0 +1,156 @@
1
+ require 'net/http/post/multipart'
2
+ require 'net/http/digest_auth'
3
+
4
+ module Matterhorn
5
+
6
+ class HttpClient
7
+
8
+ # --- attributes -------------------------------------------------------------
9
+
10
+ attr_reader :base_uri, :host, :port, :ssl
11
+
12
+ # --- initialization ---------------------------------------------------------
13
+
14
+ def initialize(base_uri)
15
+ @base_uri = URI.parse(base_uri)
16
+ @host = @base_uri.host
17
+ @port = @base_uri.port
18
+ @ssl = @port == 443 ? true : false
19
+ end
20
+
21
+ def close
22
+ @http_socket.finish if !@http_socket.nil? && @http_socket.started?
23
+ end
24
+
25
+ # --- http methodes ----------------------------------------------------------
26
+
27
+ def post(url, params = {}, file = nil, filename = nil, mime_type = nil)
28
+ if params.has_key?('BODY') || !file.nil?
29
+ request = multipart_post(url, params, file, filename, mime_type)
30
+ else
31
+ request = singlepart_post(url, params)
32
+ end
33
+ execute_request(request)
34
+ end
35
+
36
+
37
+ def get(url)
38
+ request = Net::HTTP::Get.new(base_uri.request_uri + url)
39
+ execute_request(request)
40
+ end
41
+
42
+
43
+ def delete(url)
44
+ request = Net::HTTP::Delete.new(base_uri.request_uri + url)
45
+ execute_request(request)
46
+ end
47
+
48
+
49
+ # ========================================================================== #
50
+ # === private section === #
51
+ # ========================================================================== #
52
+ private
53
+
54
+ def http_socket
55
+ return @http_socket if !@http_socket.nil? && @http_socket.started?
56
+ @http_socket = Net::HTTP.new(host, port)
57
+ @http_socket.use_ssl = ssl
58
+ @http_socket.start
59
+ end
60
+
61
+
62
+ def singlepart_post(url, params)
63
+ request = Net::HTTP::Post.new(base_uri.request_uri + url)
64
+ request.set_form_data(params)
65
+ MatterhornWhymper.logger.debug { "Matterhorn::Client::singlepart_post: request = #{request.to_yaml}"}
66
+ request
67
+ end
68
+
69
+
70
+ def multipart_post(url, params, file, filename, mime_type)
71
+ if file.kind_of?(String)
72
+ file = File.new(file)
73
+ elsif file.kind_of?(File)
74
+ # noting to do
75
+ elsif params['BODY'].kind_of?(String)
76
+ file = File.new(params['BODY'])
77
+ params['BODY'] = nil
78
+ elsif params['BODY'].kind_of?(File)
79
+ file = params['BODY']
80
+ params['BODY'] = nil
81
+ else
82
+ raise(Matterhorn::Error, "Matterhorn::Client::multipart_post: Neither BODY nor file exists!")
83
+ end
84
+ MatterhornWhymper.logger.debug { "Matterhorn::Client::multipart_post: file = #{file.inspect}"}
85
+ if filename.nil?
86
+ filename = File.basename(file.path)
87
+ end
88
+ if mime_type.nil?
89
+ mime_type = MIME::Types.type_for(File.basename(file.path)).first
90
+ end
91
+ params['BODY'] = UploadIO.new(file, mime_type, filename)
92
+ MatterhornWhymper.logger.debug { "Matterhorn::Client::multipart_post: params = #{params.to_yaml}"}
93
+ Net::HTTP::Post::Multipart.new(base_uri.request_uri + url, params)
94
+ end
95
+
96
+
97
+ def execute_request(request)
98
+ head = Net::HTTP::Head.new(request.path)
99
+ head['X-REQUESTED-AUTH'] = 'Digest'
100
+ head['X-Opencast-Matterhorn-Authorization'] = 'true'
101
+ digest_result = http_socket.request(head)
102
+ digest_auth = Net::HTTP::DigestAuth.new
103
+ auth = digest_auth.auth_header(base_uri, digest_result['www-authenticate'], request.method)
104
+ request.add_field('Authorization', auth)
105
+ response = http_socket.request(request)
106
+ case response.code.to_i
107
+ when 200..299
108
+ handle_2xx_ok(request, response)
109
+ when 400..499
110
+ handle_4xx_error(request, response)
111
+ when 500..599
112
+ handle_5xx_error(request, response)
113
+ else
114
+ handle_unknown_error(request, response)
115
+ end
116
+ response
117
+ end
118
+
119
+
120
+ def handle_2xx_ok(request, response)
121
+ MatterhornWhymper.logger.info { "Matterhorn::Client::execute_request:\n" + log_message(request, response) }
122
+ end
123
+
124
+ def handle_4xx_error(request, response)
125
+ MatterhornWhymper.logger.error { "Matterhorn::Client::execute_request: Client Error:\n" + log_message(request, response) }
126
+ raise(Matterhorn::HttpClientError, log_message(request, response))
127
+ end
128
+
129
+ def handle_5xx_error(request, response)
130
+ MatterhornWhymper.logger.error { "Matterhorn::Client::execute_request: Server Error:\n" + log_message(request, response) }
131
+ raise(Matterhorn::HttpServerError, log_message(request, response))
132
+ end
133
+
134
+ def handle_unknown_error(request, response)
135
+ MatterhornWhymper.logger.error { "Matterhorn::Client::execute_request: Server Error:\n" + log_message(request, response) }
136
+ raise(Matterhorn::Error, log_message(request, response))
137
+ end
138
+
139
+
140
+ def log_message(request, response)
141
+ " request = #{log_request(request)}\n" +
142
+ " response = #{log_response(response)}"
143
+ end
144
+
145
+ def log_request(request)
146
+ "#{request.method} #{request.path}"
147
+ end
148
+
149
+ def log_response(response)
150
+ "#{response.code} #{response.msg}, body:\n#{response.body}\n"
151
+ end
152
+
153
+
154
+ end
155
+
156
+ end
@@ -0,0 +1,110 @@
1
+ require 'nokogiri'
2
+
3
+ module Matterhorn
4
+
5
+ class MediaPackage
6
+
7
+ # --- const definitions ------------------------------------------------------
8
+ XML_NS_MEDIAPACKAGE = "http://mediapackage.opencastproject.org"
9
+
10
+
11
+ # --- initialization ---------------------------------------------------------
12
+
13
+ def initialize(path, xml = nil)
14
+ @path = path + (path[-1] == '/' ? '' : '/') # guarantee that path ends with a slash
15
+ if !xml.nil?
16
+ @document = Nokogiri::XML(xml)
17
+ else
18
+ @document = Nokogiri::XML::Builder.new do |xml|
19
+ xml.mediapackage('xmlns' => XML_NS_MEDIAPACKAGE) {
20
+ xml.media
21
+ xml.metadata
22
+ xml.attachments
23
+ }
24
+ end
25
+ .doc
26
+ end
27
+ MatterhornWhymper.logger.debug { "Matterhorn::MediaPackage::initialize | doc = #{to_xml}" }
28
+ end
29
+
30
+
31
+ # --- methodes ---------------------------------------------------------------
32
+
33
+ # <attachments>
34
+ # <attachment type="switchcastrecorder/metadata">
35
+ # <tags/>
36
+ # <url>metadata.plist</url>
37
+ # </attachment>
38
+ # </attachments>
39
+ def add_attachment(file, flavor)
40
+ Nokogiri::XML::Builder.with(@document.at('attachments')) do |xml|
41
+ xml.attachment(:type => flavor) {
42
+ xml.tags
43
+ xml.url file.sub(@path, '')
44
+ }
45
+ end
46
+ end
47
+
48
+
49
+ # <metadata>
50
+ # <catalog type="dublincore/episode">
51
+ # <mimetype>text/xml</mimetype>
52
+ # <tags/>
53
+ # <url>dublincore.xml</url>
54
+ # </catalog>
55
+ # </metadata>
56
+ def add_catalog(file, flavor, mimetype = 'text/xml')
57
+ Nokogiri::XML::Builder.with(@document.at('metadata')) do |xml|
58
+ xml.catalog(:type => flavor) {
59
+ xml.mimetype mimetype
60
+ xml.tags
61
+ xml.url file.sub(@path, '')
62
+ }
63
+ end
64
+ end
65
+
66
+
67
+ def add_dc_catalog(dublin_core)
68
+ filename = 'dublincore.xml'
69
+ flavor = 'dublincore/episode'
70
+ dc_doc = Nokogiri::XML(dublin_core)
71
+ dc_file = File.join(@path, filename)
72
+ File.open(dc_file, 'w') do |file|
73
+ file.write(dc_doc.to_xml)
74
+ end
75
+ add_catalog(dc_file, flavor)
76
+ end
77
+
78
+
79
+ # <media>
80
+ # <track type="presenter/source+partial">
81
+ # <tags/>
82
+ # <url>source1/mux_2013_12-17T14_51_29_738.mov</url>
83
+ # </track>
84
+ # </media>
85
+ def add_track(file, flavor)
86
+ Nokogiri::XML::Builder.with(@document.at('media')) do |xml|
87
+ xml.track(:type => flavor) {
88
+ xml.tags
89
+ xml.url file.sub(@path, '')
90
+ }
91
+ end
92
+ end
93
+
94
+
95
+ def save(path = @path)
96
+ manifest_file = File.join(path, 'manifest.xml')
97
+ File.open(manifest_file, 'w') do |file|
98
+ file.write(@document.to_xml)
99
+ end
100
+ end
101
+
102
+
103
+ def to_xml
104
+ @document.to_xml
105
+ end
106
+
107
+
108
+ end
109
+
110
+ end
@@ -0,0 +1,310 @@
1
+ module Matterhorn
2
+
3
+ class Smil
4
+
5
+ # --- const definitions ------------------------------------------------------
6
+
7
+ # --- attributes -------------------------------------------------------------
8
+ attr_reader :head, :body
9
+
10
+ # --- validations ------------------------------------------------------------
11
+
12
+
13
+ # --- callback declarations --------------------------------------------------
14
+
15
+
16
+ # --- relations --------------------------------------------------------------
17
+
18
+
19
+ # --- initialization ---------------------------------------------------------
20
+
21
+ def initialize()
22
+ @head = Smil::Head.new
23
+ @body = Smil::Body.new
24
+ end
25
+
26
+ # --- methodes ---------------------------------------------------------------
27
+
28
+ def save(smil_file)
29
+ File.open(smil_file, 'w') do |file|
30
+ file.write(self.to_xml)
31
+ end
32
+ Rails.logger.debug { "Matterhorn::Smil::save | Smil description =\n#{self.to_xml}" }
33
+ true
34
+ end
35
+
36
+
37
+ def to_xml
38
+ StringIO.open('', 'w') do |strio|
39
+ bx = Builder::XmlMarkup.new(:target=>strio, :indent=>2)
40
+ bx.instruct! :xml, :version=>'1.1', :encoding => 'UTF-8'
41
+ bx.smil(:xmlns => "http://www.w3.org/ns/SMIL") do
42
+ head.to_xml(bx)
43
+ body.to_xml(bx)
44
+ end
45
+ strio.string
46
+ end
47
+ end
48
+
49
+
50
+ # ========================================================================== #
51
+ # === protected section === #
52
+ # ========================================================================== #
53
+ protected
54
+
55
+
56
+ # ========================================================================== #
57
+ # === private section === #
58
+ # ========================================================================== #
59
+ private
60
+
61
+ end
62
+
63
+
64
+
65
+ class Smil::Head
66
+
67
+ def to_xml(builder)
68
+ builder.head do
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+
75
+
76
+ class Smil::Body
77
+
78
+ attr_reader :par_list
79
+
80
+ def initialize()
81
+ @par_list = Array.new
82
+ end
83
+
84
+ def add_par()
85
+ par = Smil::Par.new
86
+ @par_list << par
87
+ par
88
+ end
89
+
90
+
91
+ def to_xml(bx)
92
+ bx.body do
93
+ @par_list.each do |par|
94
+ par.to_xml(bx)
95
+ end
96
+ end
97
+ end
98
+
99
+ end
100
+
101
+
102
+
103
+ class Smil::Element
104
+
105
+ # --- attributes -------------------------------------------------------------
106
+ attr_reader :start_point, :end_point, :rel_begin, :duration, :parent
107
+
108
+ # --- initialization ---------------------------------------------------------
109
+ def initialize(parent = nil)
110
+ @start_point = nil
111
+ @end_point = nil
112
+ @rel_begin = nil
113
+ @duration = nil
114
+ @parent = parent
115
+ end
116
+
117
+ # --- methodes ---------------------------------------------------------------
118
+
119
+ def attr_list
120
+ attr_list = Hash.new
121
+ if !@rel_begin.nil?
122
+ attr_list[:begin] = "#{(@rel_begin * 1000).round.to_s}ms"
123
+ end
124
+ if !@duration.nil?
125
+ attr_list[:dur] = "#{(@duration * 1000).round.to_s}ms"
126
+ end
127
+ attr_list
128
+ end
129
+
130
+
131
+ # ========================================================================== #
132
+ # === protected section === #
133
+ # ========================================================================== #
134
+ protected
135
+
136
+ def start_point=(new_start_point)
137
+ if new_start_point.kind_of? String
138
+ # start_point is an absolut time position and must be in the format 2013-12-02T14:12:42.364
139
+ new_start_point = new_start_point.to_datetime.to_f
140
+ elsif new_start_point.respond_to?('to_f')
141
+ new_start_point = new_start_point.to_f
142
+ else
143
+ new_start_point = nil
144
+ end
145
+ @start_point = new_start_point
146
+ end
147
+
148
+ def end_point=(new_end_point)
149
+ if new_end_point.kind_of? String
150
+ # end_point is an absolut time position and must be in the format 2013-12-02T14:12:42.364
151
+ new_end_point = new_end_point.to_datetime.to_f
152
+ elsif new_end_point.respond_to?('to_f')
153
+ new_end_point = new_end_point.to_f
154
+ else
155
+ new_end_point = nil
156
+ end
157
+ @end_point = new_end_point
158
+ end
159
+
160
+ def rel_begin=(new_rel_begin)
161
+ if new_rel_begin.kind_of? Fixnum
162
+ new_rel_begin = new_rel_begin / 1000.0
163
+ elsif new_rel_begin.respond_to?('to_f')
164
+ new_rel_begin = new_rel_begin.to_f
165
+ else
166
+ new_rel_begin = nil
167
+ end
168
+ @rel_begin = new_rel_begin
169
+ end
170
+
171
+ def duration=(new_duration)
172
+ if new_duration.kind_of? Fixnum
173
+ # duration is in ms
174
+ new_duration = new_duration / 1000
175
+ elsif duration.respond_to?('to_f')
176
+ # duration is in s
177
+ new_duration = new_duration.to_f
178
+ else
179
+ new_duration = nil
180
+ end
181
+ @end_point = start_point + new_duration if !start_point.nil? && !new_duration.nil?
182
+ @duration = new_duration
183
+ end
184
+
185
+ def update(sub_elem)
186
+ if !sub_elem.start_point.nil? && (start_point.nil? || start_point > sub_elem.start_point)
187
+ @start_point = sub_elem.start_point
188
+ else
189
+ # do not update start_point
190
+ end
191
+
192
+ if !sub_elem.end_point.nil? && (end_point.nil? || end_point < sub_elem.end_point)
193
+ @end_point = sub_elem.end_point
194
+ else
195
+ # do not update start_point
196
+ end
197
+
198
+ if !start_point.nil? && !end_point.nil?
199
+ @duration = end_point - start_point
200
+ end
201
+ # update parent if any
202
+ parent.update(self) if !parent.nil?
203
+ propagate(self) if parent.nil?
204
+ end
205
+
206
+ def propagate(parent_elem)
207
+ end
208
+
209
+ end
210
+
211
+
212
+
213
+ class Smil::Par < Smil::Element
214
+
215
+ def initialize()
216
+ super
217
+ @seq_list = Array.new
218
+ end
219
+
220
+
221
+ def add_seq
222
+ seq = Smil::Seq.new(self)
223
+ @seq_list << seq
224
+ seq
225
+ end
226
+
227
+
228
+ def propagate(parent_elem)
229
+ @seq_list.each do |seq|
230
+ seq.propagate(self)
231
+ end
232
+ end
233
+
234
+
235
+ def to_xml(bx)
236
+ bx.par(attr_list) do
237
+ @seq_list.each do |seq|
238
+ seq.to_xml(bx)
239
+ end
240
+ end
241
+ end
242
+
243
+ end
244
+
245
+
246
+
247
+ class Smil::Seq < Smil::Element
248
+
249
+ def initialize(parent)
250
+ super(parent)
251
+ @track_list = Array.new
252
+ end
253
+
254
+ def attr_list
255
+ attrib_list = super
256
+ attrib_list.delete(:begin)
257
+ attrib_list
258
+ end
259
+
260
+ def add_track(kind, file, start_point, duration)
261
+ track = Smil::Track.new(self, kind, file, start_point, duration)
262
+ @track_list << track
263
+ update(track)
264
+ track
265
+ end
266
+
267
+ def propagate(parent_elem)
268
+ @rel_begin = start_point - parent_elem.start_point
269
+ @track_list.each do |track|
270
+ # propagate with par element
271
+ track.propagate(parent_elem)
272
+ end
273
+ end
274
+
275
+ def to_xml(bx)
276
+ bx.seq(attr_list) do
277
+ @track_list.each do |track|
278
+ track.to_xml(bx)
279
+ end
280
+ end
281
+ end
282
+
283
+ end
284
+
285
+
286
+ class Smil::Track < Smil::Element
287
+
288
+ def initialize(parent, kind, file, start_point, duration)
289
+ super(parent)
290
+ @kind = kind
291
+ @src = file
292
+ self.start_point = start_point
293
+ self.duration = duration
294
+ end
295
+
296
+ def propagate(parent_elem)
297
+ @rel_begin = start_point - parent_elem.start_point
298
+ end
299
+
300
+ def to_xml(bx)
301
+ attributes = attr_list
302
+ if !@src.nil?
303
+ attributes[:src] = @src.to_s
304
+ end
305
+ bx.tag!(@kind, attributes)
306
+ end
307
+
308
+ end
309
+
310
+ end
@@ -0,0 +1,59 @@
1
+ require 'nokogiri'
2
+
3
+ module Matterhorn
4
+
5
+ class WorkflowInstance
6
+
7
+ XML_NS_WORKFLOW = "http://workflow.opencastproject.org"
8
+
9
+ # --- const definitions ------------------------------------------------------
10
+
11
+ # --- attributes -------------------------------------------------------------
12
+
13
+ # --- validations ------------------------------------------------------------
14
+
15
+ # --- callback declarations --------------------------------------------------
16
+
17
+
18
+ # --- relations --------------------------------------------------------------
19
+
20
+
21
+ # --- initialization ---------------------------------------------------------
22
+
23
+ def initialize(xml)
24
+ @document = Nokogiri::XML(xml)
25
+ end
26
+
27
+ # --- methodes ---------------------------------------------------------------
28
+
29
+ def id
30
+ @document.xpath('/nsw:workflow/@id', {"nsw" => XML_NS_WORKFLOW}).first.value
31
+ end
32
+
33
+ def state
34
+ @document.xpath('/nsw:workflow/@state', {"nsw" => XML_NS_WORKFLOW}).first.value
35
+ end
36
+
37
+ def template
38
+ @document.xpath('/nsw:workflow/nsw:template', {"nsw" => XML_NS_WORKFLOW}).first.content
39
+ end
40
+
41
+ def to_xml
42
+ @document.to_xml
43
+ end
44
+
45
+
46
+ # ========================================================================== #
47
+ # === protected section === #
48
+ # ========================================================================== #
49
+ protected
50
+
51
+
52
+ # ========================================================================== #
53
+ # === private section === #
54
+ # ========================================================================== #
55
+ private
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,47 @@
1
+ require 'matterhorn_whymper/version'
2
+ require 'matterhorn/endpoint'
3
+ require 'matterhorn/endpoint/ingest'
4
+ require 'matterhorn/endpoint/workflow'
5
+ require 'matterhorn/http_client'
6
+ require 'matterhorn/media_package'
7
+ require 'matterhorn/error'
8
+
9
+
10
+ module MatterhornWhymper
11
+
12
+ def self.info
13
+ "Ruby wrapper against the Matterhorn Endpoint API. Version #{MatterhornWhymper::VERSION}"
14
+ end
15
+
16
+
17
+ class << self
18
+ attr_accessor :configuration, :logger
19
+ end
20
+
21
+
22
+ def self.configure
23
+ self.configuration ||= Configuration.new
24
+ if defined?(Rails)
25
+ self.logger = Rails.logger
26
+ else
27
+ require 'logger'
28
+ self.logger = Logger.new(STDOUT)
29
+ end
30
+ yield(configuration) if block_given?
31
+ end
32
+
33
+
34
+
35
+ class Configuration
36
+
37
+ attr_accessor :system_account_user, :system_account_password, :system_domain, :system_protocol
38
+
39
+ def uri
40
+ "#{system_protocol}://#{system_account_user}:#{system_account_password}@#{system_domain}"
41
+ end
42
+
43
+
44
+ end
45
+
46
+
47
+ end
@@ -0,0 +1,3 @@
1
+ module MatterhornWhymper
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'matterhorn_whymper/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "matterhorn_whymper"
8
+ spec.version = MatterhornWhymper::VERSION
9
+ spec.authors = ["Daniel Fritschi"]
10
+ spec.email = ["daniel.fritschi@switch.ch"]
11
+ spec.summary = %q{Ruby wrapper around the Matterhorn Endpoint API}
12
+ spec.description = %q{This Ruby wrapper is designed to write some ruby scripts against the
13
+ Matterhorn Endpoint API}
14
+ spec.homepage = "https://github.com/switch-ch/matterhorn_whymper"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_runtime_dependency "multipart-post", "~> 2.0"
23
+ spec.add_runtime_dependency "net-http-digest_auth", "~> 1.4"
24
+ spec.add_runtime_dependency "nokogiri", "~> 1.6"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.6"
27
+ spec.add_development_dependency "rake", "~> 10.3"
28
+ spec.add_development_dependency "rspec", "~> 2.14"
29
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe MatterhornWhymper do
4
+
5
+ it "version must be defined" do
6
+ expect(MatterhornWhymper::VERSION).not_to be nil
7
+ end
8
+
9
+ it "#info" do
10
+ expect(MatterhornWhymper.info).to include MatterhornWhymper::VERSION
11
+ end
12
+
13
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Matterhorn::Endpoint do
4
+
5
+ it "does ingest endpoint available" do
6
+ Matterhorn::Endpoint.open(:ingest) do |ingest_endpoint|
7
+ expect(ingest_endpoint).not_to be nil
8
+ expect(ingest_endpoint.class.name).to eq 'Matterhorn::Endpoint::Ingest'
9
+ end
10
+ end
11
+
12
+ it "does workflow endpoint available" do
13
+ Matterhorn::Endpoint.open(:workflow) do |workflow_endpoint|
14
+ expect(workflow_endpoint).not_to be nil
15
+ expect(workflow_endpoint.class.name).to eq 'Matterhorn::Endpoint::Workflow'
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+
22
+ describe "Ingest Mediapackages" do
23
+
24
+ it "creates a mediapackage" do
25
+ Matterhorn::Endpoint.open(:ingest) do |ingest_endpoint|
26
+ ingest_endpoint.createMediaPackage()
27
+ mp_local = ingest_endpoint.media_package
28
+ mp_remote = ingest_endpoint.media_package('remote')
29
+ expect(mp_local).not_to be nil
30
+ expect(mp_remote).not_to be nil
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,5 @@
1
+ matterhorn:
2
+ system_account_user: inser_system_user_name_here
3
+ system_account_password: insert_system_user_password_here
4
+ system_domain: mh-admin.localdomain
5
+ system_protocol: http
@@ -0,0 +1,16 @@
1
+ require 'bundler/setup'
2
+ require 'yaml'
3
+
4
+ Bundler.setup
5
+
6
+ require 'matterhorn_whymper' # and any other gems you need
7
+
8
+ RSpec.configure do |config|
9
+ MatterhornWhymper.configure do |mh_config|
10
+ mh_yml = YAML::load_file( "./spec/matterhorn.yml" )
11
+ mh_config.system_account_user = mh_yml['matterhorn']['system_account_user']
12
+ mh_config.system_account_password = mh_yml['matterhorn']['system_account_password']
13
+ mh_config.system_domain = mh_yml['matterhorn']['system_domain']
14
+ mh_config.system_protocol = mh_yml['matterhorn']['system_protocol']
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,155 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: matterhorn_whymper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Fritschi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: multipart-post
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: net-http-digest_auth
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '10.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '10.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '2.14'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '2.14'
97
+ description: ! "This Ruby wrapper is designed to write some ruby scripts against the\n
98
+ \ Matterhorn Endpoint API"
99
+ email:
100
+ - daniel.fritschi@switch.ch
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - .gitignore
106
+ - .rspec
107
+ - .rvmrc
108
+ - Gemfile
109
+ - LICENSE.txt
110
+ - README.md
111
+ - Rakefile
112
+ - lib/matterhorn/endpoint.rb
113
+ - lib/matterhorn/endpoint/ingest.rb
114
+ - lib/matterhorn/endpoint/workflow.rb
115
+ - lib/matterhorn/error.rb
116
+ - lib/matterhorn/http_client.rb
117
+ - lib/matterhorn/media_package.rb
118
+ - lib/matterhorn/smil.rb
119
+ - lib/matterhorn/workflow_instance.rb
120
+ - lib/matterhorn_whymper.rb
121
+ - lib/matterhorn_whymper/version.rb
122
+ - matterhorn_whymper.gemspec
123
+ - spec/Matterhorn_whymper_spec.rb
124
+ - spec/endpoints_spec.rb
125
+ - spec/matterhorn.yml.sample
126
+ - spec/spec_helper.rb
127
+ homepage: https://github.com/switch-ch/matterhorn_whymper
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ! '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.2.2
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Ruby wrapper around the Matterhorn Endpoint API
151
+ test_files:
152
+ - spec/Matterhorn_whymper_spec.rb
153
+ - spec/endpoints_spec.rb
154
+ - spec/matterhorn.yml.sample
155
+ - spec/spec_helper.rb