soby 0.1.0.1 → 0.1.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 +4 -4
- data/bin/soby +26 -0
- data/lib/soby.rb +82 -22
- data/lib/soby/launcher.rb +35 -42
- data/lib/soby/loader.rb +322 -0
- data/lib/soby/presentation.rb +11 -272
- metadata +12 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6b453a9c8e14b2783d83aada8be3619ce0e97af
|
4
|
+
data.tar.gz: 31cc0dd452afa715cf25d7bd6e4a4ccbd709ea49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4523a46378215e5d23a46b108c351ea5fd60b6c7e876353fdb86b2a1a74cf839c86a4dac3addfd745f55f1a266bf269bbcad137480ecd7e1a207a55c0bfc6ec6
|
7
|
+
data.tar.gz: 56f0cb54f880e1cec0c505cdd2a66e904844c015550e70ddf87434969f36b7a34102c1b03f7ddfd2a502af9c4564d895060cbdd0b4f7563bb47d4b389b0c1af0
|
data/bin/soby
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/soby'
|
4
|
+
# require 'soby'
|
5
|
+
|
6
|
+
Processing::App::SKETCH_PATH = __FILE__
|
7
|
+
$:.unshift File.dirname(__FILE__)
|
8
|
+
|
9
|
+
filename = nil
|
10
|
+
filename = ARGV[0] if ARGV[0] != nil
|
11
|
+
|
12
|
+
screen_id = 0
|
13
|
+
if ARGV[1] != nil
|
14
|
+
screen_id = ARGV[1].to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
Processing::PShapeSVG.TEXT_QUALITY = 2.0
|
18
|
+
$app = SobyPlayer.new screen_id
|
19
|
+
|
20
|
+
sleep 0.2 while not $app.ready?
|
21
|
+
|
22
|
+
if filename != nil
|
23
|
+
presentation = Soby::load_presentation ARGV[0]
|
24
|
+
Soby::start_presentation presentation
|
25
|
+
end
|
26
|
+
# Soby::auto_update presentation, __FILE__
|
data/lib/soby.rb
CHANGED
@@ -1,23 +1,25 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
require 'nokogiri' # for XML.
|
4
3
|
require 'jruby_art'
|
5
4
|
require 'jruby_art/app'
|
6
|
-
|
7
|
-
|
8
5
|
require 'java'
|
9
6
|
|
7
|
+
## Enables objects to become java for introspection in java.
|
8
|
+
|
9
|
+
require 'jruby/core_ext'
|
10
10
|
# Processing::App::SKETCH_PATH = Dir.pwd
|
11
11
|
|
12
12
|
# For the other files, we need to load the libraries
|
13
13
|
Processing::App::load_library 'video', 'toxiclibscore'
|
14
14
|
|
15
15
|
require_relative 'soby/transforms'
|
16
|
+
require_relative 'soby/loader'
|
16
17
|
require_relative 'soby/presentation'
|
17
18
|
require_relative 'soby/slide'
|
18
19
|
require_relative 'soby/cam'
|
19
20
|
require_relative 'soby/launcher'
|
20
21
|
|
22
|
+
|
21
23
|
class SobyPlayer < Processing::App
|
22
24
|
|
23
25
|
include_package 'processing.core'
|
@@ -28,42 +30,42 @@ class SobyPlayer < Processing::App
|
|
28
30
|
attr_accessor :prez, :prev_cam, :next_cam, :slides
|
29
31
|
attr_reader :is_moving, :current_slide_no
|
30
32
|
|
31
|
-
|
33
|
+
attr_reader :has_thread
|
34
|
+
attr_accessor :thread
|
35
|
+
# attr_accessor :background_max_color, :background_min_color, :background_constrain
|
32
36
|
attr_accessor :cam
|
33
37
|
|
34
38
|
def running? () @is_running end
|
35
39
|
|
36
40
|
TRANSITION_DURATION = 1000
|
37
41
|
|
38
|
-
def initialize(
|
39
|
-
@
|
40
|
-
@h = h
|
42
|
+
def initialize(screen_id)
|
43
|
+
@screen_id = screen_id
|
41
44
|
super()
|
42
45
|
end
|
43
46
|
|
47
|
+
|
44
48
|
# no Border
|
45
49
|
def init
|
46
50
|
super
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
def removeFrameBorder
|
51
|
-
frame.removeNotify
|
52
|
-
frame.setUndecorated true
|
53
|
-
frame.addNotify
|
51
|
+
getSurface.getNative.setUndecorated true
|
54
52
|
end
|
55
53
|
|
56
54
|
def settings
|
57
|
-
|
55
|
+
# todo: fullscreen ?
|
56
|
+
fullScreen P3D, @screen_id
|
58
57
|
end
|
59
58
|
|
60
59
|
def setup
|
61
60
|
@ready = false
|
62
61
|
|
62
|
+
@width = self.width
|
63
|
+
@height = self.height
|
63
64
|
init_player
|
64
65
|
|
65
66
|
@custom_setup_done = true
|
66
67
|
@ready = true
|
68
|
+
@has_thread = false
|
67
69
|
end
|
68
70
|
|
69
71
|
def ready?
|
@@ -102,9 +104,8 @@ class SobyPlayer < Processing::App
|
|
102
104
|
|
103
105
|
end
|
104
106
|
|
105
|
-
|
106
107
|
def draw
|
107
|
-
|
108
|
+
rect 0, 0, 100, millis / 1000
|
108
109
|
if not @custom_setup_done
|
109
110
|
custom_setup
|
110
111
|
@custom_setup_done = true
|
@@ -112,8 +113,6 @@ class SobyPlayer < Processing::App
|
|
112
113
|
|
113
114
|
custom_pre_draw
|
114
115
|
|
115
|
-
smooth(8)
|
116
|
-
|
117
116
|
shapeMode(CORNER)
|
118
117
|
imageMode(CORNER)
|
119
118
|
|
@@ -162,6 +161,10 @@ class SobyPlayer < Processing::App
|
|
162
161
|
pop_matrix
|
163
162
|
end
|
164
163
|
|
164
|
+
def presentation_path
|
165
|
+
File.dirname(@prez.url)
|
166
|
+
end
|
167
|
+
|
165
168
|
alias :default_display_slide_number :display_slide_number
|
166
169
|
|
167
170
|
|
@@ -182,9 +185,46 @@ class SobyPlayer < Processing::App
|
|
182
185
|
next_slide
|
183
186
|
end
|
184
187
|
|
188
|
+
if key == 'l'
|
189
|
+
# selectInput("Select a file to process:",
|
190
|
+
# "fileSelected",
|
191
|
+
# Java::JavaIo::File.new(SKETCH_ROOT))
|
192
|
+
|
193
|
+
folder = Java::JavaIo::File.new(SKETCH_ROOT)
|
194
|
+
fc = Java::javax::swing::JFileChooser.new("Soby Loader")
|
195
|
+
fc.set_dialog_title "Select your presentation"
|
196
|
+
fc.setFileFilter AppFilter.new
|
197
|
+
fc.setCurrentDirectory folder
|
198
|
+
success = fc.show_open_dialog(nil)
|
199
|
+
if success == Java::javax::swing::JFileChooser::APPROVE_OPTION
|
200
|
+
path = fc.get_selected_file.get_absolute_path
|
201
|
+
puts "User selected " + path
|
202
|
+
presentation = Soby::load_presentation path
|
203
|
+
Soby::start_presentation presentation
|
204
|
+
else
|
205
|
+
puts "No file"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
if key == 'a'
|
210
|
+
return if @has_thread
|
211
|
+
puts "Thread starting"
|
212
|
+
Soby::auto_update self
|
213
|
+
@has_thread = true
|
214
|
+
end
|
215
|
+
|
216
|
+
if key == 's'
|
217
|
+
Thread::kill @thread if @has_thread
|
218
|
+
end
|
185
219
|
# puts "slide #{@current_slide_no} "
|
186
220
|
end
|
187
221
|
|
222
|
+
java_signature 'void fileSelected(java.io.File)'
|
223
|
+
def fileSelected selection
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
|
188
228
|
def mouse_dragged
|
189
229
|
if not @is_moving
|
190
230
|
tr = PMatrix3D.new
|
@@ -208,7 +248,6 @@ class SobyPlayer < Processing::App
|
|
208
248
|
|
209
249
|
|
210
250
|
def set_prez (prez)
|
211
|
-
|
212
251
|
current_slide = @current_slide_no
|
213
252
|
|
214
253
|
# PShape.loadedImages.clear
|
@@ -252,15 +291,23 @@ class SobyPlayer < Processing::App
|
|
252
291
|
return
|
253
292
|
end
|
254
293
|
|
294
|
+
if @slides[@current_slide_no] == nil
|
295
|
+
p "ERROR invalid slide"
|
296
|
+
p "Try to go to next slide"
|
297
|
+
goto_slide(@current_slide_no + 1) unless is_last_slide
|
298
|
+
return
|
299
|
+
end
|
300
|
+
|
255
301
|
# animation
|
256
302
|
if @slides[@current_slide_no].has_next_animation?
|
257
303
|
puts "Animation Next "
|
258
304
|
anim = @slides[@current_slide_no].next_animation
|
259
305
|
anim.pshape_elem.setVisible(true)
|
260
|
-
|
261
|
-
goto_slide(@current_slide_no + 1) unless is_last_slide
|
306
|
+
return
|
262
307
|
end
|
263
308
|
|
309
|
+
goto_slide(@current_slide_no + 1) unless is_last_slide
|
310
|
+
|
264
311
|
end
|
265
312
|
|
266
313
|
def prev_slide
|
@@ -412,5 +459,18 @@ class SobyPlayer < Processing::App
|
|
412
459
|
end
|
413
460
|
private :find_scale
|
414
461
|
|
462
|
+
end
|
463
|
+
|
464
|
+
## Allow for java introspection
|
465
|
+
SobyPlayer.become_java!
|
415
466
|
|
467
|
+
## TODO: move this somewhere
|
468
|
+
class AppFilter < Java::javax::swing::filechooser::FileFilter
|
469
|
+
def accept fobj
|
470
|
+
return true if fobj.canExecute
|
471
|
+
return fobj.isDirectory
|
472
|
+
end
|
473
|
+
def getDescription
|
474
|
+
"Applications"
|
475
|
+
end
|
416
476
|
end
|
data/lib/soby/launcher.rb
CHANGED
@@ -1,52 +1,47 @@
|
|
1
|
-
|
2
1
|
module Soby
|
3
2
|
|
4
|
-
SLEEP_TIME =
|
3
|
+
SLEEP_TIME = 5
|
5
4
|
|
6
5
|
## used outside
|
7
|
-
|
8
|
-
def Soby.load_presentation (program_name, svg_name)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
|
7
|
+
# def Soby.load_presentation (program_name, svg_name)
|
8
|
+
# puts "Loading program"
|
9
|
+
# load program_name
|
10
|
+
# puts "Loading prez"
|
11
|
+
# (PresentationLoader.new($app, $app.sketchPath(svg_name), program_name)).presentation
|
12
|
+
# end
|
13
|
+
|
14
|
+
def Soby.load_presentation(svg_name)
|
15
|
+
PresentationLoader.new($app, $app.sketchPath(svg_name)).presentation
|
13
16
|
end
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
puts 'reloading sketch...'
|
32
|
-
|
33
|
-
time = Time.now
|
34
|
-
|
35
|
-
load program_name
|
36
|
-
presentation = Presentation.new($app, $app.sketchPath(svg_name), program_name)
|
37
|
-
start_presentation presentation
|
38
|
-
end
|
39
|
-
|
40
|
-
sleep SLEEP_TIME
|
41
|
-
return if $app == nil
|
18
|
+
|
19
|
+
def Soby.auto_update soby_player
|
20
|
+
|
21
|
+
puts "Sketch Root" + SKETCH_ROOT
|
22
|
+
files = find_files
|
23
|
+
svg_name = soby_player.prez.url
|
24
|
+
|
25
|
+
time = Time.now
|
26
|
+
soby_player.thread = Thread.new {
|
27
|
+
loop do
|
28
|
+
|
29
|
+
if files.find { |file| FileTest.exist?(file) && File.stat(file).mtime > time }
|
30
|
+
puts 'reloading sketch...'
|
31
|
+
time = Time.now
|
32
|
+
presentation = (PresentationLoader.new($app, svg_name)).presentation
|
33
|
+
start_presentation presentation
|
42
34
|
end
|
43
|
-
|
44
|
-
|
35
|
+
|
36
|
+
sleep SLEEP_TIME
|
37
|
+
return if $app == nil
|
38
|
+
end
|
39
|
+
}
|
45
40
|
end
|
46
|
-
|
41
|
+
|
47
42
|
|
48
43
|
## local use
|
49
|
-
|
44
|
+
|
50
45
|
def Soby.reload_presentation (presentation)
|
51
46
|
# load presentation.program
|
52
47
|
# presentation.reset
|
@@ -54,7 +49,7 @@ module Soby
|
|
54
49
|
end
|
55
50
|
|
56
51
|
def Soby.start_presentation (presentation)
|
57
|
-
$app.set_prez presentation
|
52
|
+
$app.set_prez presentation
|
58
53
|
end
|
59
54
|
|
60
55
|
def Soby.find_files_except (name)
|
@@ -64,7 +59,5 @@ module Soby
|
|
64
59
|
def Soby.find_files
|
65
60
|
Dir.glob(File.join(SKETCH_ROOT, "**/*.{svg,glsl,rb}"))
|
66
61
|
end
|
67
|
-
|
68
62
|
|
69
|
-
|
70
63
|
end
|
data/lib/soby/loader.rb
ADDED
@@ -0,0 +1,322 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'base64'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'nokogiri' # for XML.
|
5
|
+
|
6
|
+
class PresentationLoader
|
7
|
+
|
8
|
+
include_package 'processing.core'
|
9
|
+
|
10
|
+
include Soby
|
11
|
+
|
12
|
+
attr_accessor :pshape, :svg
|
13
|
+
attr_reader :debug, :url, :presentation
|
14
|
+
|
15
|
+
attr_accessor :graphics
|
16
|
+
|
17
|
+
def initialize (app, url)
|
18
|
+
@app = app
|
19
|
+
@url = url
|
20
|
+
|
21
|
+
@presentation = Presentation.new(app)
|
22
|
+
@presentation.url = @url
|
23
|
+
load_files
|
24
|
+
build_internal
|
25
|
+
end
|
26
|
+
|
27
|
+
def load_files
|
28
|
+
xml = @app.loadXML(@url)
|
29
|
+
@pshape = PShapeSVG.new(xml)
|
30
|
+
@presentation.pshape = @pshape
|
31
|
+
@svg = Nokogiri::XML(open(@url)).children[1];
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_internal
|
35
|
+
puts "Svg null, look for the error... !" if @svg == nil
|
36
|
+
return if @svg == nil
|
37
|
+
|
38
|
+
load_code
|
39
|
+
load_frames
|
40
|
+
load_videos
|
41
|
+
load_animations
|
42
|
+
end
|
43
|
+
|
44
|
+
def load_code
|
45
|
+
puts "Loading the code..."
|
46
|
+
|
47
|
+
@svg.css("text").each do |text|
|
48
|
+
|
49
|
+
return if text.attributes["id"] == nil
|
50
|
+
id = text.attributes["id"].value #get the id
|
51
|
+
|
52
|
+
title = text.css("title")
|
53
|
+
next if title == nil
|
54
|
+
|
55
|
+
is_code = title.text.match(/code/) != nil
|
56
|
+
next unless is_code
|
57
|
+
|
58
|
+
files = text.css("desc").text.split("\n")
|
59
|
+
|
60
|
+
if files == nil
|
61
|
+
puts "Source not found, check your includes in svg"
|
62
|
+
next
|
63
|
+
end
|
64
|
+
|
65
|
+
files.each do |file|
|
66
|
+
|
67
|
+
dir = File.dirname(@url)
|
68
|
+
abs_file = dir + "/" + file
|
69
|
+
puts ("Loading the code: " + abs_file)
|
70
|
+
@presentation.add_source abs_file
|
71
|
+
load abs_file
|
72
|
+
end
|
73
|
+
|
74
|
+
## Hide the text to the rendering
|
75
|
+
@pshape.getChild(id).setVisible(false)
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
def load_frames
|
81
|
+
puts "Loading the frames..."
|
82
|
+
@svg.children.each do |child|
|
83
|
+
next unless child.name =~ /frame/
|
84
|
+
|
85
|
+
## ignore if it references nothing.
|
86
|
+
attr = child.attributes
|
87
|
+
next if attr["refid"] == nil
|
88
|
+
|
89
|
+
create_slide child
|
90
|
+
end # frame
|
91
|
+
end
|
92
|
+
|
93
|
+
def create_slide child
|
94
|
+
slide = Slide.new(child)
|
95
|
+
|
96
|
+
# get the element associated with each slide...
|
97
|
+
@svg.search("[id=" + slide.refid + "]").each do |elem|
|
98
|
+
case elem.name
|
99
|
+
when "rect", "image"
|
100
|
+
add_rect_or_image_frame(elem, slide)
|
101
|
+
when "g"
|
102
|
+
add_group(elem, slide)
|
103
|
+
else
|
104
|
+
puts "Slide type not supported ! " + elem.name
|
105
|
+
end # end case
|
106
|
+
end # search
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_rect_or_image_frame(element, slide)
|
111
|
+
id = slide.title
|
112
|
+
refid = slide.refid
|
113
|
+
|
114
|
+
# set the geometry & transformation
|
115
|
+
transform = get_global_transform element
|
116
|
+
slide.set_geometry(element, transform[0])
|
117
|
+
|
118
|
+
pshape_element = @pshape.getChild(refid)
|
119
|
+
# hide the element
|
120
|
+
if pshape_element == nil
|
121
|
+
puts "Error: rect or Image ID: #{refid} not found. CHECK THE PROCESSING VERSION."
|
122
|
+
else
|
123
|
+
pshape_element.setVisible(!slide.hide) if element.name == "rect"
|
124
|
+
end
|
125
|
+
|
126
|
+
## Debug
|
127
|
+
puts "Slide #{id} created from a rect : #{refid}" if element.name == "rect"
|
128
|
+
puts "Slide #{id} created from an image: #{refid}" if element.name == "image"
|
129
|
+
@presentation.add_slide(slide)
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
def add_group(group, slide)
|
134
|
+
|
135
|
+
id = slide.title
|
136
|
+
refid = slide.refid
|
137
|
+
|
138
|
+
|
139
|
+
# TODO: Find the bounding box of any group..
|
140
|
+
# TODO: Hide the whole group ?
|
141
|
+
surf_max = 0
|
142
|
+
biggest_rect = nil
|
143
|
+
|
144
|
+
## biggest_rect surface..
|
145
|
+
group.css("rect").each do |rect|
|
146
|
+
# (group.css("rect") + group.css("image")).each do |rect|
|
147
|
+
|
148
|
+
if biggest_rect == nil
|
149
|
+
biggest_rect = rect
|
150
|
+
end
|
151
|
+
|
152
|
+
surf_rect = rect.attributes["width"].value.to_i \
|
153
|
+
* rect.attributes["height"].value.to_i
|
154
|
+
|
155
|
+
if(surf_rect > surf_max)
|
156
|
+
biggest_rect = rect
|
157
|
+
surf_max = surf_rect
|
158
|
+
end
|
159
|
+
end # rect.each
|
160
|
+
|
161
|
+
rect_id = biggest_rect.attributes["id"].value
|
162
|
+
transform = get_global_transform biggest_rect
|
163
|
+
slide.set_geometry(biggest_rect, transform[0])
|
164
|
+
|
165
|
+
# The description (code to excute) might be in the group and not in the rect.
|
166
|
+
## TODO: check if it should really be the first ?
|
167
|
+
desc = group.css("desc").first
|
168
|
+
title = group.css("title").first
|
169
|
+
|
170
|
+
if desc != nil
|
171
|
+
if title == nil || (title.text.match(/animation/) == nil and title.text.match(/video/) == nil)
|
172
|
+
puts "Group Description read #{desc.text}"
|
173
|
+
|
174
|
+
slide.description = desc.text
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
e = @pshape.getChild(rect_id)
|
179
|
+
# hide the rect
|
180
|
+
if e == nil
|
181
|
+
puts "Error: rect ID: #{rect_id} not found "
|
182
|
+
else
|
183
|
+
@pshape.getChild(rect_id).setVisible(!slide.hide)
|
184
|
+
end
|
185
|
+
|
186
|
+
puts "Slide #{id} created from a group, and the rectangle: #{rect_id}"
|
187
|
+
|
188
|
+
@presentation.add_slide(slide)
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
|
194
|
+
def load_videos
|
195
|
+
# Load the videos...
|
196
|
+
puts "Loading the videos..."
|
197
|
+
|
198
|
+
@svg.css("rect").each do |rect|
|
199
|
+
|
200
|
+
return if rect.attributes["id"] == nil
|
201
|
+
id = rect.attributes["id"].value #get the id
|
202
|
+
|
203
|
+
title = rect.css("title")
|
204
|
+
next if title == nil
|
205
|
+
|
206
|
+
is_video = title.text.match(/video/) != nil
|
207
|
+
next unless is_video
|
208
|
+
|
209
|
+
t = rect.css("desc").text.split("\n")
|
210
|
+
slide_id = t[0]
|
211
|
+
path = t[1]
|
212
|
+
|
213
|
+
puts ("Loading the video : " + path)
|
214
|
+
|
215
|
+
# Get the transformation
|
216
|
+
tr = get_global_transform rect
|
217
|
+
|
218
|
+
video = MyVideo.new(path, @presentation.slides[slide_id], tr[0], tr[1], tr[2])
|
219
|
+
|
220
|
+
if @presentation.slides[slide_id] == nil
|
221
|
+
puts "Error -> The video #{id} is linked to the slide #{slide_id} which is not found !"
|
222
|
+
else
|
223
|
+
|
224
|
+
@presentation.slides[slide_id].add_video(video)
|
225
|
+
puts "Video #{id} loaded with #{slide_id}"
|
226
|
+
end
|
227
|
+
|
228
|
+
# Hide the rect, and ... TODO replace it with a special object
|
229
|
+
# @pshape.getChild(id).setVisible(false)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
def load_animations
|
236
|
+
|
237
|
+
puts "Loading the animations..."
|
238
|
+
|
239
|
+
@svg.css("*").each do |elem|
|
240
|
+
|
241
|
+
valid = false
|
242
|
+
elem.children.each do |child|
|
243
|
+
valid = true if child.name == "title" && child.text.match(/animation/)
|
244
|
+
end
|
245
|
+
|
246
|
+
next unless valid
|
247
|
+
|
248
|
+
id = elem.attributes["id"].value
|
249
|
+
|
250
|
+
# Get the animation information
|
251
|
+
t = elem.css("desc").text.split("\n")
|
252
|
+
|
253
|
+
# 1. which slide
|
254
|
+
# 2. when
|
255
|
+
slide_id = t[0]
|
256
|
+
anim_id = t[1].to_i
|
257
|
+
|
258
|
+
animation = OpenStruct.new
|
259
|
+
animation.pshape_elem = @pshape.getChild(id)
|
260
|
+
|
261
|
+
puts "Animation found on slide #{slide_id} with element #{animation.pshape_elem}"
|
262
|
+
|
263
|
+
if @presentation.slides[slide_id] == nil
|
264
|
+
puts "Error -> The animation #{id} is linked to the slide #{slide_id} which is not found !"
|
265
|
+
else
|
266
|
+
# add the animation
|
267
|
+
@presentation.slides[slide_id].add_animation(anim_id, animation)
|
268
|
+
|
269
|
+
# hide the group !
|
270
|
+
animation.pshape_elem.setVisible(false) unless animation.pshape_elem == nil
|
271
|
+
puts "Animation #{id} loaded with #{slide_id}"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
276
|
+
|
277
|
+
|
278
|
+
class MyVideo
|
279
|
+
|
280
|
+
include_package 'processing.video'
|
281
|
+
include_package 'processing.video.Movie'
|
282
|
+
include_package 'org.gestreamer.elements'
|
283
|
+
|
284
|
+
attr_reader :matrix, :width, :height, :slide
|
285
|
+
attr_accessor :video
|
286
|
+
|
287
|
+
def initialize(path, slide, matrix, width, height)
|
288
|
+
@path = path
|
289
|
+
@width = width
|
290
|
+
@height = height
|
291
|
+
@matrix = matrix
|
292
|
+
@slide = slide
|
293
|
+
end
|
294
|
+
|
295
|
+
def play
|
296
|
+
if @video == nil
|
297
|
+
|
298
|
+
absolute_path = $app.sketchPath "" << @path
|
299
|
+
|
300
|
+
puts ("loading the video : " + absolute_path)
|
301
|
+
vid = Movie.new($app, absolute_path)
|
302
|
+
|
303
|
+
vid.play
|
304
|
+
# vid = Movie.new($app, @path)
|
305
|
+
puts "Loaded "
|
306
|
+
puts vid, vid.width, vid.height
|
307
|
+
|
308
|
+
@video = vid
|
309
|
+
true
|
310
|
+
else
|
311
|
+
false
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
end
|
316
|
+
|
317
|
+
|
318
|
+
def to_s
|
319
|
+
"Presentation loader. "
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
data/lib/soby/presentation.rb
CHANGED
@@ -7,261 +7,42 @@ class Presentation
|
|
7
7
|
|
8
8
|
include Soby
|
9
9
|
|
10
|
-
attr_accessor :
|
10
|
+
attr_accessor :slides, :pshape
|
11
11
|
attr_accessor :width, :height, :matrix, :videos
|
12
|
-
attr_reader :nb_slides, :debug
|
12
|
+
attr_reader :nb_slides, :debug
|
13
|
+
attr_reader :source_files
|
14
|
+
attr_accessor :url
|
13
15
|
|
14
16
|
attr_accessor :graphics
|
15
17
|
|
16
|
-
def initialize (app
|
18
|
+
def initialize (app)
|
17
19
|
@app = app
|
18
|
-
@url = url
|
19
|
-
@program = program
|
20
20
|
@graphics = @app.g
|
21
|
-
|
22
|
-
load_files
|
23
|
-
build_internal
|
24
|
-
end
|
25
|
-
|
26
|
-
def load_files
|
27
|
-
xml = @app.loadXML(@url)
|
28
|
-
@pshape = PShapeSVG.new(xml)
|
29
|
-
@svg = Nokogiri::XML(open(@url)).children[1];
|
30
|
-
end
|
31
|
-
|
32
|
-
def reset
|
33
|
-
load_files
|
34
|
-
build_internal
|
35
|
-
end
|
36
|
-
|
37
|
-
def width ; @pshape.getWidth; end
|
38
|
-
def height ; @pshape.getHeight; end
|
39
|
-
|
40
|
-
|
41
|
-
def build_internal
|
42
|
-
|
43
|
-
# Create the frames..
|
44
21
|
@slides = {}
|
45
22
|
@nb_slides = 0
|
46
23
|
@playing_videos = []
|
47
|
-
|
48
|
-
puts "Svg null, look for the error... !" if @svg == nil
|
49
|
-
return if @svg == nil
|
50
|
-
|
51
|
-
load_frames
|
52
|
-
load_videos
|
53
|
-
load_animations
|
24
|
+
@source_files = []
|
54
25
|
end
|
55
26
|
|
27
|
+
def add_source name ; @source_files << name ; end
|
28
|
+
def width ; @pshape.getWidth; end
|
29
|
+
def height ; @pshape.getHeight; end
|
30
|
+
|
56
31
|
def draw
|
57
32
|
@graphics.shape pshape, 0, 0
|
58
33
|
# display_videos
|
59
34
|
end
|
60
35
|
|
61
|
-
|
62
|
-
def load_frames
|
63
|
-
|
64
|
-
puts "Loading the frames..."
|
65
|
-
@svg.children.each do |child|
|
66
|
-
|
67
|
-
next unless child.name =~ /frame/
|
68
|
-
|
69
|
-
## ignore if it references nothing.
|
70
|
-
attr = child.attributes
|
71
|
-
next if attr["refid"] == nil
|
72
|
-
|
73
|
-
slide = Slide.new(child)
|
74
|
-
|
75
|
-
# get the element associated with each slide...
|
76
|
-
@svg.search("[id=" + slide.refid + "]").each do |elem|
|
77
|
-
|
78
|
-
case elem.name
|
79
|
-
when "rect", "image"
|
80
|
-
add_rect_or_image_frame(elem, slide)
|
81
|
-
when "g"
|
82
|
-
add_group(elem, slide)
|
83
|
-
else
|
84
|
-
puts "Slide type not supported ! " + elem.name
|
85
|
-
end # end case
|
86
|
-
end # search
|
87
|
-
end # frame
|
88
|
-
end
|
89
|
-
|
90
36
|
def add_slide(new_slide)
|
91
|
-
|
92
37
|
puts "Add slide, id " << new_slide.title << " numero " << new_slide.sequence
|
93
38
|
@slides[new_slide.sequence] = new_slide
|
94
39
|
@slides[new_slide.title] = new_slide
|
95
40
|
@nb_slides = @nb_slides+1
|
96
|
-
end
|
97
|
-
|
98
|
-
|
99
|
-
def add_rect_or_image_frame(element, slide)
|
100
|
-
id = slide.title
|
101
|
-
refid = slide.refid
|
102
|
-
|
103
|
-
add_slide(slide)
|
104
|
-
|
105
|
-
# set the geometry & transformation
|
106
|
-
transform = get_global_transform element
|
107
|
-
@slides[id].set_geometry(element, transform[0])
|
108
|
-
pshape_element = @pshape.getChild(refid)
|
109
|
-
|
110
|
-
# hide the element
|
111
|
-
if pshape_element == nil
|
112
|
-
puts "Error: rect or Image ID: #{refid} not found. CHECK THE PROCESSING VERSION."
|
113
|
-
else
|
114
|
-
pshape_element.setVisible(!@slides[id].hide) if element.name == "rect"
|
115
|
-
end
|
116
|
-
|
117
|
-
puts "Slide #{id} created from a rect : #{refid}" if element.name == "rect"
|
118
|
-
puts "Slide #{id} created from an image: #{refid}" if element.name == "image"
|
119
|
-
end
|
120
|
-
|
121
|
-
|
122
|
-
def add_group(group, slide)
|
123
|
-
|
124
|
-
id = slide.title
|
125
|
-
refid = slide.refid
|
126
|
-
add_slide(slide)
|
127
|
-
|
128
|
-
# TODO: Find the bounding box of any group..
|
129
|
-
# TODO: Hide the whole group ?
|
130
|
-
surf_max = 0
|
131
|
-
biggest_rect = nil
|
132
|
-
|
133
|
-
## biggest_rect surface..
|
134
|
-
group.css("rect").each do |rect|
|
135
|
-
# (group.css("rect") + group.css("image")).each do |rect|
|
136
|
-
|
137
|
-
if biggest_rect == nil
|
138
|
-
biggest_rect = rect
|
139
|
-
end
|
140
|
-
|
141
|
-
surf_rect = rect.attributes["width"].value.to_i \
|
142
|
-
* rect.attributes["height"].value.to_i
|
143
|
-
|
144
|
-
if(surf_rect > surf_max)
|
145
|
-
biggest_rect = rect
|
146
|
-
surf_max = surf_rect
|
147
|
-
end
|
148
|
-
end # rect.each
|
149
|
-
|
150
|
-
rect_id = biggest_rect.attributes["id"].value
|
151
|
-
transform = get_global_transform biggest_rect
|
152
|
-
@slides[id].set_geometry(biggest_rect, transform[0])
|
153
|
-
|
154
|
-
# The description (code to excute) might be in the group and not in the rect.
|
155
|
-
## TODO: check if it should really be the first ?
|
156
|
-
desc = group.css("desc").first
|
157
|
-
title = group.css("title").first
|
158
|
-
|
159
|
-
if desc != nil
|
160
|
-
if title == nil || (title.text.match(/animation/) == nil and title.text.match(/video/) == nil)
|
161
|
-
puts "Group Description read #{desc.text}"
|
162
|
-
|
163
|
-
@slides[id].description = desc.text
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
e = @pshape.getChild(rect_id)
|
168
|
-
# hide the rect
|
169
|
-
if e == nil
|
170
|
-
puts "Error: rect ID: #{rect_id} not found "
|
171
|
-
else
|
172
|
-
@pshape.getChild(rect_id).setVisible(!@slides[id].hide)
|
173
|
-
end
|
174
|
-
|
175
|
-
puts "Slide #{id} created from a group, and the rectangle: #{rect_id}"
|
176
41
|
|
42
|
+
p "Adding a new slide to the presentation", @nb_slides
|
177
43
|
end
|
178
44
|
|
179
45
|
|
180
|
-
|
181
|
-
|
182
|
-
def load_videos
|
183
|
-
# Load the videos...
|
184
|
-
puts "Loading the videos..."
|
185
|
-
|
186
|
-
@svg.css("rect").each do |rect|
|
187
|
-
|
188
|
-
return if rect.attributes["id"] == nil
|
189
|
-
id = rect.attributes["id"].value #get the id
|
190
|
-
|
191
|
-
title = rect.css("title")
|
192
|
-
next if title == nil
|
193
|
-
|
194
|
-
is_video = title.text.match(/video/) != nil
|
195
|
-
next unless is_video
|
196
|
-
|
197
|
-
t = rect.css("desc").text.split("\n")
|
198
|
-
slide_id = t[0]
|
199
|
-
path = t[1]
|
200
|
-
|
201
|
-
puts ("Loading the video : " + path)
|
202
|
-
|
203
|
-
# Get the transformation
|
204
|
-
tr = get_global_transform rect
|
205
|
-
|
206
|
-
video = MyVideo.new(path, @slides[slide_id], tr[0], tr[1], tr[2])
|
207
|
-
|
208
|
-
if @slides[slide_id] == nil
|
209
|
-
puts "Error -> The video #{id} is linked to the slide #{slide_id} which is not found !"
|
210
|
-
else
|
211
|
-
|
212
|
-
@slides[slide_id].add_video(video)
|
213
|
-
puts "Video #{id} loaded with #{slide_id}"
|
214
|
-
end
|
215
|
-
|
216
|
-
# Hide the rect, and ... TODO replace it with a special object
|
217
|
-
# @pshape.getChild(id).setVisible(false)
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
def load_animations
|
224
|
-
|
225
|
-
puts "Loading the animations..."
|
226
|
-
|
227
|
-
@svg.css("*").each do |elem|
|
228
|
-
|
229
|
-
valid = false
|
230
|
-
elem.children.each do |child|
|
231
|
-
valid = true if child.name == "title" && child.text.match(/animation/)
|
232
|
-
end
|
233
|
-
|
234
|
-
next unless valid
|
235
|
-
|
236
|
-
id = elem.attributes["id"].value
|
237
|
-
|
238
|
-
# Get the animation information
|
239
|
-
t = elem.css("desc").text.split("\n")
|
240
|
-
|
241
|
-
# 1. which slide
|
242
|
-
# 2. when
|
243
|
-
slide_id = t[0]
|
244
|
-
anim_id = t[1].to_i
|
245
|
-
|
246
|
-
animation = OpenStruct.new
|
247
|
-
animation.pshape_elem = @pshape.getChild(id)
|
248
|
-
|
249
|
-
puts "Animation found on slide #{slide_id} with element #{animation.pshape_elem}"
|
250
|
-
|
251
|
-
if @slides[slide_id] == nil
|
252
|
-
puts "Error -> The animation #{id} is linked to the slide #{slide_id} which is not found !"
|
253
|
-
else
|
254
|
-
# add the animation
|
255
|
-
@slides[slide_id].add_animation(anim_id, animation)
|
256
|
-
|
257
|
-
# hide the group !
|
258
|
-
animation.pshape_elem.setVisible(false) unless animation.pshape_elem == nil
|
259
|
-
puts "Animation #{id} loaded with #{slide_id}"
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
end
|
264
|
-
|
265
46
|
def display_videos
|
266
47
|
if not @app.is_moving
|
267
48
|
|
@@ -270,7 +51,6 @@ class Presentation
|
|
270
51
|
# # Display the videos
|
271
52
|
if slide_no > 0 and @slides[slide_no].has_videos?
|
272
53
|
|
273
|
-
|
274
54
|
# draw the object
|
275
55
|
@graphics.imageMode(Processing::App::CORNER)
|
276
56
|
|
@@ -306,47 +86,6 @@ class Presentation
|
|
306
86
|
end
|
307
87
|
|
308
88
|
|
309
|
-
|
310
|
-
class MyVideo
|
311
|
-
|
312
|
-
include_package 'processing.video'
|
313
|
-
include_package 'processing.video.Movie'
|
314
|
-
include_package 'org.gestreamer.elements'
|
315
|
-
|
316
|
-
attr_reader :matrix, :width, :height, :slide
|
317
|
-
attr_accessor :video
|
318
|
-
|
319
|
-
def initialize(path, slide, matrix, width, height)
|
320
|
-
@path = path
|
321
|
-
@width = width
|
322
|
-
@height = height
|
323
|
-
@matrix = matrix
|
324
|
-
@slide = slide
|
325
|
-
end
|
326
|
-
|
327
|
-
def play
|
328
|
-
if @video == nil
|
329
|
-
|
330
|
-
absolute_path = $app.sketchPath "" << @path
|
331
|
-
|
332
|
-
puts ("loading the video : " + absolute_path)
|
333
|
-
vid = Movie.new($app, absolute_path)
|
334
|
-
|
335
|
-
vid.play
|
336
|
-
# vid = Movie.new($app, @path)
|
337
|
-
puts "Loaded "
|
338
|
-
puts vid, vid.width, vid.height
|
339
|
-
|
340
|
-
@video = vid
|
341
|
-
true
|
342
|
-
else
|
343
|
-
false
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
end
|
348
|
-
|
349
|
-
|
350
89
|
def to_s
|
351
90
|
"Slides #{@slides.size}"
|
352
91
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: soby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.
|
4
|
+
version: 0.1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Laviole
|
@@ -35,10 +35,10 @@ dependencies:
|
|
35
35
|
requirements:
|
36
36
|
- - "~>"
|
37
37
|
- !ruby/object:Gem::Version
|
38
|
-
version: '
|
38
|
+
version: '1.2'
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
41
|
+
version: 1.2.4
|
42
42
|
name: jruby_art
|
43
43
|
prerelease: false
|
44
44
|
type: :runtime
|
@@ -46,19 +46,22 @@ dependencies:
|
|
46
46
|
requirements:
|
47
47
|
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: '
|
49
|
+
version: '1.2'
|
50
50
|
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version:
|
52
|
+
version: 1.2.4
|
53
53
|
description: Based on Sozi, it plays presentation using JRubyArt.
|
54
54
|
email: poqudrof@gmail.com
|
55
|
-
executables:
|
55
|
+
executables:
|
56
|
+
- soby
|
56
57
|
extensions: []
|
57
58
|
extra_rdoc_files: []
|
58
59
|
files:
|
60
|
+
- bin/soby
|
59
61
|
- lib/soby.rb
|
60
62
|
- lib/soby/cam.rb
|
61
63
|
- lib/soby/launcher.rb
|
64
|
+
- lib/soby/loader.rb
|
62
65
|
- lib/soby/presentation.rb
|
63
66
|
- lib/soby/slide.rb
|
64
67
|
- lib/soby/transforms.rb
|
@@ -66,7 +69,8 @@ homepage: https://github.com/poqudrof/Soby
|
|
66
69
|
licenses:
|
67
70
|
- LGPL
|
68
71
|
metadata: {}
|
69
|
-
post_install_message:
|
72
|
+
post_install_message: 'Use ''soby presentation.svg 1'' to run a presentation file
|
73
|
+
presentation.svg on screen #1 '
|
70
74
|
rdoc_options: []
|
71
75
|
require_paths:
|
72
76
|
- lib
|
@@ -82,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
86
|
version: '0'
|
83
87
|
requirements: []
|
84
88
|
rubyforge_project:
|
85
|
-
rubygems_version: 2.4
|
89
|
+
rubygems_version: 2.6.4
|
86
90
|
signing_key:
|
87
91
|
specification_version: 4
|
88
92
|
summary: Sozi player !
|