glimmer-cw-video 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +125 -0
- data/lib/glimmer-cw-video.rb +5 -0
- data/lib/views/glimmer/video.rb +287 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 10a0ed280e12d03b5c9a8a69e696043e208a58b54282d74fa8310bc4602ccbf7
|
4
|
+
data.tar.gz: 631708906e59bfb0232fd09fd20d673520dce51611fc59e16c8301fe098237d0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f8c79642df581ebef469df2b0993e5f32de0715345307652be76002a31f0ec238871a416797980db539843a5dab521649dea2f3d171dd795244944f9552b66ab
|
7
|
+
data.tar.gz: d584693154c69b17d1aaf9cd85a501a7dbc5062c787734c8832dc8ff1b6835db5451185faa0bb421d43d301cf361a86db29f5244eeed8e42c74bb23c6b9b9ff8
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2020 Andy Maleh
|
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.md
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# Video 0.1.0 - Glimmer Custom Widget
|
2
|
+
|
3
|
+
![Video Widget](images/glimmer-video-widget.png)
|
4
|
+
|
5
|
+
Glimmer custom widget for video used via `video` keyword.
|
6
|
+
|
7
|
+
## Pre-requisites
|
8
|
+
|
9
|
+
- [Glimmer](https://github.com/AndyObtiva/glimmer) application
|
10
|
+
- JRuby version required by Glimmer
|
11
|
+
- Java version required by Glimmer
|
12
|
+
|
13
|
+
## Setup
|
14
|
+
|
15
|
+
Add the following to a Glimmer application `Gemfile`:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'glimmer-cw-video', '0.1.0'
|
19
|
+
```
|
20
|
+
|
21
|
+
Run:
|
22
|
+
|
23
|
+
```
|
24
|
+
jruby -S bundle
|
25
|
+
```
|
26
|
+
|
27
|
+
(or just `bundle` if using RVM)
|
28
|
+
|
29
|
+
## Options
|
30
|
+
|
31
|
+
Passed in an options hash as arguments to `video` widget:
|
32
|
+
- `autoplay` (true [default] or false): plays video automatically as soon as loaded
|
33
|
+
- `controls` (true [default] or false): displays controls
|
34
|
+
- `looped` (true or false [default]): plays video in looped mode
|
35
|
+
- `background` (Glimmer color [default: white]): sets background color just like with any other widget
|
36
|
+
- `fit_to_width` (true [default] or false): fits video width to widget allotted width regardless of video's original size. Maintains video aspect ratio.
|
37
|
+
- `fit_to_height` (true [default] or false): fits video height to widget allotted height regardless of video's original size. Maintains video aspect ratio.
|
38
|
+
- `offset_x` (integer [default: 0]): offset from left border. Could be a negative number if you want to show only an area of the video. Useful when fit_to_width is false to pick an area of the video to display.
|
39
|
+
- `offset_y` (integer [default: 0]): offset from top border. Could be a negative number if you want to show only an area of the video. Useful when fit_to_height is false to pick an area of the video to display.
|
40
|
+
|
41
|
+
## Methods
|
42
|
+
|
43
|
+
- `#play`: plays video
|
44
|
+
- `#pause`: pauses video
|
45
|
+
- `#reload`: reloads video restarting from beginning
|
46
|
+
- `#position`: position in seconds (and fractions)
|
47
|
+
- `#position=`: seeks a new position in video
|
48
|
+
- `#duration`: length of video, maximum video position possible
|
49
|
+
- `#loaded?`: returns true when video has been initially loaded or reloaded
|
50
|
+
- `#playing?`: returns true when video is actively playing
|
51
|
+
- `#paused?`: returns true when video is not playing
|
52
|
+
- `#ended?`: returns true when video has reached the end (position == duration)
|
53
|
+
|
54
|
+
## Observer Events:
|
55
|
+
|
56
|
+
- `on_loaded`: invoked when video `#loaded?` becomes true
|
57
|
+
- `on_ended`: invoked when video `#ended?` becomes true
|
58
|
+
- `on_playing`: invoked when video `#playing?` becomes true
|
59
|
+
- `on_paused`: invoked when video `#paused?` becomes true
|
60
|
+
|
61
|
+
## Examples:
|
62
|
+
|
63
|
+
Example ([samples/hello_video.rb](samples/video/hello_video.rb)):
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
# ...
|
67
|
+
shell {
|
68
|
+
video(file: video_file)
|
69
|
+
}.open
|
70
|
+
```
|
71
|
+
|
72
|
+
Example ([samples/hello_looped_video_with_black_background.rb](samples/video/hello_looped_video_with_black_background.rb)):
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
# ...
|
76
|
+
shell {
|
77
|
+
minimum_size 1024, 640
|
78
|
+
video(file: video_file, looped: true, background: :black)
|
79
|
+
}.open
|
80
|
+
```
|
81
|
+
|
82
|
+
Example ([samples/hello_video_observers.rb](samples/video/hello_video_observers.rb)):
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
# ...
|
86
|
+
def display_video_status(video, status)
|
87
|
+
message_box = MessageBox.new(video.swt_widget.getShell)
|
88
|
+
message_box.setText(status)
|
89
|
+
message = "Video Position: #{video.position} seconds\n"
|
90
|
+
message += "Video Duration: #{video.duration} seconds"
|
91
|
+
message_box.setMessage(message)
|
92
|
+
message_box.open
|
93
|
+
end
|
94
|
+
|
95
|
+
@shell = shell {
|
96
|
+
minimum_size 800, 500
|
97
|
+
@video = video(file: video_file, background: :black) {
|
98
|
+
on_playing {
|
99
|
+
display_video_status(@video, 'Playing')
|
100
|
+
}
|
101
|
+
on_paused {
|
102
|
+
display_video_status(@video, 'Paused')
|
103
|
+
}
|
104
|
+
on_ended {
|
105
|
+
display_video_status(@video, 'Ended')
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
@shell.open
|
110
|
+
```
|
111
|
+
|
112
|
+
## Contributing to glimmer-cw-video
|
113
|
+
|
114
|
+
- Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
115
|
+
- Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
116
|
+
- Fork the project.
|
117
|
+
- Start a feature/bugfix branch.
|
118
|
+
- Commit and push until you are happy with your contribution.
|
119
|
+
- Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
120
|
+
- Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
121
|
+
|
122
|
+
## Copyright
|
123
|
+
|
124
|
+
Copyright (c) 2020 Andy Maleh. See LICENSE.txt for
|
125
|
+
further details.
|
@@ -0,0 +1,287 @@
|
|
1
|
+
require 'glimmer/ui/custom_widget'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
class Video
|
5
|
+
include Glimmer::UI::CustomWidget
|
6
|
+
include_package 'org.eclipse.swt.browser'
|
7
|
+
|
8
|
+
options :file, :url
|
9
|
+
option :autoplay, true
|
10
|
+
option :controls, true
|
11
|
+
option :looped, false
|
12
|
+
option :background, :white
|
13
|
+
option :fit_to_width, true
|
14
|
+
option :fit_to_height, true
|
15
|
+
option :offset_x, 0
|
16
|
+
option :offset_y, 0
|
17
|
+
|
18
|
+
alias autoplay? autoplay
|
19
|
+
alias controls? controls
|
20
|
+
alias looped? looped
|
21
|
+
alias fit_to_width? fit_to_width
|
22
|
+
alias fit_to_height? fit_to_height
|
23
|
+
|
24
|
+
body {
|
25
|
+
browser(:no_scroll) {
|
26
|
+
text html {
|
27
|
+
head {
|
28
|
+
style(id: "style") {
|
29
|
+
css {
|
30
|
+
body {
|
31
|
+
margin 0
|
32
|
+
padding 0
|
33
|
+
overflow :hidden
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
style(id: "style-body-background") {
|
38
|
+
css {
|
39
|
+
body {
|
40
|
+
pv 'background', browser_body_background
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
style(id: "style-body-offset-x") {
|
45
|
+
css {
|
46
|
+
body {
|
47
|
+
margin_left "#{browser_body_offset_x}px"
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
style(id: "style-body-offset-y") {
|
52
|
+
css {
|
53
|
+
body {
|
54
|
+
margin_top "#{browser_body_offset_y}px"
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
body {
|
60
|
+
video(browser_video_loop, browser_video_controls, browser_video_autoplay, id: 'video', src: source, width: browser_video_width, height: browser_video_height)
|
61
|
+
}
|
62
|
+
}
|
63
|
+
on_completed {
|
64
|
+
@completed = true
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
def source
|
70
|
+
file_source = file
|
71
|
+
if file_source
|
72
|
+
if file_source.start_with?('uri:classloader')
|
73
|
+
file_path = file_source.split(/\/\//).last
|
74
|
+
file_name = File.basename(file_source)
|
75
|
+
# supporting windows ENV['temp'] or mac/unix /tmp
|
76
|
+
tmp_dir = ENV['temp'] ? File.expand_path(ENV['temp']) : '/tmp'
|
77
|
+
tmp_dir += '/glimmer/lib/glimmer/ui/video'
|
78
|
+
FileUtils.mkdir_p(tmp_dir)
|
79
|
+
tmp_file = File.join(tmp_dir, file_name)
|
80
|
+
file_content = File.binread(file_source) rescue File.binread(file_path)
|
81
|
+
File.binwrite(tmp_file, file_content)
|
82
|
+
"file://#{tmp_file}"
|
83
|
+
else
|
84
|
+
"file://#{file_source}"
|
85
|
+
end
|
86
|
+
else
|
87
|
+
url
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def file=(a_file)
|
92
|
+
options[:file] = a_file
|
93
|
+
set_video_source
|
94
|
+
end
|
95
|
+
|
96
|
+
def url=(a_url)
|
97
|
+
options[:url] = a_url
|
98
|
+
set_video_source
|
99
|
+
end
|
100
|
+
|
101
|
+
def play
|
102
|
+
video_action('play')
|
103
|
+
end
|
104
|
+
|
105
|
+
def pause
|
106
|
+
video_action('pause')
|
107
|
+
end
|
108
|
+
|
109
|
+
def reload
|
110
|
+
video_action('load')
|
111
|
+
end
|
112
|
+
|
113
|
+
def paused?
|
114
|
+
video_attribute('paused')
|
115
|
+
end
|
116
|
+
|
117
|
+
def playing?
|
118
|
+
!paused?
|
119
|
+
end
|
120
|
+
|
121
|
+
def ended?
|
122
|
+
video_attribute('ended')
|
123
|
+
end
|
124
|
+
|
125
|
+
# Video fully loaded and ready for playback
|
126
|
+
def loaded?
|
127
|
+
!!@completed
|
128
|
+
end
|
129
|
+
|
130
|
+
def position
|
131
|
+
video_attribute('currentTime')
|
132
|
+
end
|
133
|
+
|
134
|
+
def position=(new_position)
|
135
|
+
video_attribute_set('currentTime', new_position)
|
136
|
+
end
|
137
|
+
|
138
|
+
def duration
|
139
|
+
video_attribute('duration')
|
140
|
+
end
|
141
|
+
|
142
|
+
def can_handle_observation_request?(observation_request)
|
143
|
+
result = false
|
144
|
+
if observation_request.start_with?('on_')
|
145
|
+
attribute = observation_request.sub(/^on_/, '')
|
146
|
+
result = OBSERVED_ATTRIBUTE_TO_PROPERTY_MAPPING.keys.include?(attribute)
|
147
|
+
end
|
148
|
+
result || super
|
149
|
+
end
|
150
|
+
|
151
|
+
def handle_observation_request(observation_request, &block)
|
152
|
+
if observation_request.start_with?('on_')
|
153
|
+
attribute = observation_request.sub(/^on_/, '')
|
154
|
+
if attribute == 'loaded' && !@completed
|
155
|
+
super('on_completed', &block)
|
156
|
+
elsif OBSERVED_ATTRIBUTE_TO_PROPERTY_MAPPING.keys.include?(attribute)
|
157
|
+
add_video_observer(block, OBSERVED_ATTRIBUTE_TO_PROPERTY_MAPPING[attribute])
|
158
|
+
else
|
159
|
+
super
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
class VideoObserverBrowserFunction < BrowserFunction
|
167
|
+
def initialize(video, observer_proc, attribute)
|
168
|
+
@observer_proc = observer_proc
|
169
|
+
@attribute = attribute
|
170
|
+
name = self.class.generate_name(@attribute)
|
171
|
+
super(video.swt_widget, name)
|
172
|
+
end
|
173
|
+
|
174
|
+
def function(arguments)
|
175
|
+
@observer_proc.call
|
176
|
+
rescue => e
|
177
|
+
Glimmer::Config.logger&.error "#{e.message}\n#{e.backtrace.join("\n")}"
|
178
|
+
ensure
|
179
|
+
nil
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
class << self
|
185
|
+
def generate_name(attribute)
|
186
|
+
"video#{attribute}#{generate_attribute_id(attribute)}"
|
187
|
+
end
|
188
|
+
|
189
|
+
def generate_attribute_id(attribute)
|
190
|
+
attribute_max_ids[attribute] = attribute_max_id(attribute) + 1
|
191
|
+
end
|
192
|
+
|
193
|
+
def attribute_max_id(attribute)
|
194
|
+
attribute_max_ids[attribute] ||= 0
|
195
|
+
end
|
196
|
+
|
197
|
+
def attribute_max_ids
|
198
|
+
@attribute_max_ids ||= {}
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
OBSERVED_ATTRIBUTE_TO_PROPERTY_MAPPING = {
|
204
|
+
'playing' => 'play',
|
205
|
+
'paused' => 'pause',
|
206
|
+
'ended' => 'ended',
|
207
|
+
'loaded' => 'canplay',
|
208
|
+
}
|
209
|
+
|
210
|
+
def set_video_source
|
211
|
+
run_on_completed do
|
212
|
+
video_attribute_set('src', source)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def video_action(action)
|
217
|
+
run_on_completed do
|
218
|
+
swt_widget.execute("document.getElementById('video').#{action}()")
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def video_attribute(attribute)
|
223
|
+
swt_widget.evaluate("return document.getElementById('video').#{attribute}") if @completed
|
224
|
+
end
|
225
|
+
|
226
|
+
def video_attribute_set(attribute, value)
|
227
|
+
value = "'#{value}'" if value.is_a?(String) || value.is_a?(Symbol)
|
228
|
+
run_on_completed do
|
229
|
+
swt_widget.execute("document.getElementById('video').#{attribute} = #{value}")
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def add_video_observer(observer_proc, attribute)
|
234
|
+
run_on_completed do
|
235
|
+
video_observer_browser_function = VideoObserverBrowserFunction.new(self, observer_proc, attribute)
|
236
|
+
swt_widget.execute("document.getElementById('video').addEventListener('#{attribute}', function() {#{video_observer_browser_function.getName}()})")
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def run_on_completed(&block)
|
241
|
+
if @completed
|
242
|
+
block.call
|
243
|
+
else
|
244
|
+
on_completed(&block)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def browser_video_autoplay
|
249
|
+
'autoplay' if autoplay?
|
250
|
+
end
|
251
|
+
|
252
|
+
def browser_video_controls
|
253
|
+
'controls' if controls?
|
254
|
+
end
|
255
|
+
|
256
|
+
def browser_video_loop
|
257
|
+
'loop' if looped?
|
258
|
+
end
|
259
|
+
|
260
|
+
def browser_video_width
|
261
|
+
"100%" if fit_to_width
|
262
|
+
end
|
263
|
+
|
264
|
+
def browser_video_height
|
265
|
+
"100%" if fit_to_height
|
266
|
+
end
|
267
|
+
|
268
|
+
def browser_body_background
|
269
|
+
color = background
|
270
|
+
if color.is_a?(Symbol) || color.is_a?(String)
|
271
|
+
color = color(color)
|
272
|
+
end
|
273
|
+
if color.respond_to?(:swt_color)
|
274
|
+
color = color.swt_color
|
275
|
+
end
|
276
|
+
"rgba(#{color.getRed}, #{color.getGreen}, #{color.getBlue}, #{color.getAlpha})"
|
277
|
+
end
|
278
|
+
|
279
|
+
def browser_body_offset_x
|
280
|
+
offset_x
|
281
|
+
end
|
282
|
+
|
283
|
+
def browser_body_offset_y
|
284
|
+
offset_y
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: glimmer-cw-video
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andy Maleh
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: 0.7.0
|
19
|
+
name: glimmer
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.7.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.5.0
|
33
|
+
name: rspec
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.5.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - '='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.3.9
|
47
|
+
name: jeweler
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.3.9
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
name: simplecov
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Glimmer video widget with basic functionality like play, pause, loop,
|
70
|
+
and reload. Support mp4, webm, and ogg. Works with both local files and web URLs.
|
71
|
+
email: andy.am@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files:
|
75
|
+
- LICENSE.txt
|
76
|
+
- README.md
|
77
|
+
files:
|
78
|
+
- LICENSE.txt
|
79
|
+
- README.md
|
80
|
+
- lib/glimmer-cw-video.rb
|
81
|
+
- lib/views/glimmer/video.rb
|
82
|
+
homepage: http://github.com/AndyObtiva/glimmer-cw-video
|
83
|
+
licenses:
|
84
|
+
- MIT
|
85
|
+
metadata: {}
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubygems_version: 3.0.6
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: Glimmer Custom Widget - Video
|
105
|
+
test_files: []
|