matterhorn_whymper 0.0.2

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.
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