1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 from mediagoblin
import mg_globals
as mgg
23 from mediagoblin
.processing
import create_pub_filepath
, \
26 from mediagoblin
.media_types
.stl
import model_loader
29 _log
= logging
.getLogger(__name__
)
30 SUPPORTED_FILETYPES
= ['stl', 'obj']
33 def sniff_handler(media_file
, **kw
):
34 if kw
.get('media') is not None:
35 name
, ext
= os
.path
.splitext(kw
['media'].filename
)
36 clean_ext
= ext
[1:].lower()
38 if clean_ext
in SUPPORTED_FILETYPES
:
39 _log
.info('Found file extension in supported filetypes')
42 _log
.debug('Media present, extension not found in {0}'.format(
45 _log
.warning('Need additional information (keyword argument \'media\')'
46 ' to be able to handle sniffing')
51 def blender_render(config
):
53 Called to prerender a model.
55 arg_string
= "blender -b blender_render.blend -F "
56 arg_string
+="JPEG -P blender_render.py"
57 env
= {"RENDER_SETUP" : json
.dumps(config
), "DISPLAY":":0"}
58 subprocess
.call(arg_string
.split(" "), env
=env
)
61 def process_stl(entry
):
63 Code to process an stl or obj model.
66 workbench
= mgg
.workbench_manager
.create_workbench()
67 # Conversions subdirectory to avoid collisions
68 conversions_subdir
= os
.path
.join(
69 workbench
.dir, 'conversions')
70 os
.mkdir(conversions_subdir
)
71 queued_filepath
= entry
.queued_media_file
72 queued_filename
= workbench
.localized_file(
73 mgg
.queue_store
, queued_filepath
, 'source')
74 name_builder
= FilenameBuilder(queued_filename
)
76 ext
= queued_filename
.lower().strip()[-4:]
77 if ext
.startswith("."):
82 # Attempt to parse the model file and divine some useful
83 # information about it.
84 with
open(queued_filename
, 'rb') as model_file
:
85 model
= model_loader
.auto_detect(model_file
, ext
)
87 # generate preview images
88 greatest
= [model
.width
, model
.height
, model
.depth
]
90 greatest
= greatest
[-1]
92 def snap(name
, camera
, width
=640, height
=640, project
="ORTHO"):
93 path
= create_pub_filepath(entry
, name_builder
.fill(name
))
94 render_file
= mgg
.public_store
.get_file(path
, "wb")
96 "model_path" : queued_filename
,
98 "camera_coord" : camera
,
99 "camera_focus" : model
.average
,
100 "camera_clip" : greatest
*10,
101 "greatest" : greatest
,
102 "projection" : project
,
105 "out_file" : render_file
.name
,
112 "{basename}.thumb.jpg",
113 [0, greatest
*-1.5, greatest
],
114 mgg
.global_config
['media:thumb']['max_width'],
115 mgg
.global_config
['media:thumb']['max_height'],
118 perspective_path
= snap(
119 "{basename}.perspective.jpg",
120 [0, greatest
*-1.5, greatest
], project
="PERSP")
123 "{basename}.top.jpg",
124 [model
.average
[0], model
.average
[1], greatest
*2])
126 frontview_path
= snap(
127 "{basename}.front.jpg",
128 [model
.average
[0], greatest
*-2, model
.average
[2]])
130 sideview_path
= snap(
131 "{basename}.side.jpg",
132 [greatest
*-2, model
.average
[1], model
.average
[2]])
137 # Save the public file stuffs
138 model_filepath
= create_pub_filepath(
139 entry
, name_builder
.fill('{basename}{ext}'))
141 with mgg
.public_store
.get_file(model_filepath
, 'wb') as model_file
:
142 with
open(queued_filename
, 'rb') as queued_file
:
143 model_file
.write(queued_file
.read())
146 # Remove queued media file from storage and database
147 mgg
.queue_store
.delete_file(queued_filepath
)
148 entry
.queued_media_file
= []
150 # Insert media file information into database
151 media_files_dict
= entry
.setdefault('media_files', {})
152 media_files_dict
[u
'original'] = model_filepath
153 media_files_dict
[u
'thumb'] = thumb_path
154 media_files_dict
[u
'perspective'] = perspective_path
155 media_files_dict
[u
'top'] = topview_path
156 media_files_dict
[u
'side'] = sideview_path
157 media_files_dict
[u
'front'] = frontview_path
159 # Put model dimensions into the database
161 "center_x" : model
.average
[0],
162 "center_y" : model
.average
[1],
163 "center_z" : model
.average
[2],
164 "width" : model
.width
,
165 "height" : model
.height
,
166 "depth" : model
.depth
,
168 entry
.media_data_init(**dimensions
)
171 workbench
.destroy_self()