~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to release/scripts/addons/io_sequencer_edl/__init__.py

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# ##### BEGIN GPL LICENSE BLOCK #####
 
2
#
 
3
#  This program is free software; you can redistribute it and/or
 
4
#  modify it under the terms of the GNU General Public License
 
5
#  as published by the Free Software Foundation; either version 2
 
6
#  of the License, or (at your option) any later version.
 
7
#
 
8
#  This program is distributed in the hope that it will be useful,
 
9
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
#  GNU General Public License for more details.
 
12
#
 
13
#  You should have received a copy of the GNU General Public License
 
14
#  along with this program; if not, write to the Free Software Foundation,
 
15
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
16
#
 
17
# ##### END GPL LICENSE BLOCK #####
 
18
 
 
19
# <pep8 compliant>
 
20
 
 
21
bl_info = {
 
22
    "name": "Import EDL",
 
23
    "author": "Campbell Barton",
 
24
    "version": (1, 0),
 
25
    "blender": (2, 65, 0),
 
26
    "location": "Sequencer -> Track View Properties",
 
27
    "description": "Load a CMX formatted EDL into the sequencer",
 
28
    "warning": "",
 
29
    "wiki_url": "http://wiki.blender.org/index.php/Extensions:"
 
30
                "2.6/Py/Scripts/Import-Export/EDL_Import",
 
31
    "tracker_url": "",
 
32
    "category": "Import-Export"}
 
33
 
 
34
import bpy
 
35
 
 
36
 
 
37
# ImportHelper is a helper class, defines filename and
 
38
# invoke() function which calls the file selector.
 
39
from bpy_extras.io_utils import ImportHelper
 
40
from bpy.props import (StringProperty,
 
41
                       IntProperty,
 
42
                       PointerProperty,
 
43
                       CollectionProperty,
 
44
                       )
 
45
from bpy.types import Operator
 
46
 
 
47
# ----------------------------------------------------------------------------
 
48
# Main Operators
 
49
 
 
50
 
 
51
class ReloadEDL(Operator):
 
52
    bl_idname = "sequencer.import_edl_refresh"
 
53
    bl_label = "Refresh Reels"
 
54
 
 
55
    def execute(self, context):
 
56
        import os
 
57
        from . import parse_edl
 
58
 
 
59
        scene = context.scene
 
60
        edl_import_info = scene.edl_import_info
 
61
 
 
62
        filepath = edl_import_info.filepath
 
63
        dummy_fps = 25
 
64
 
 
65
        if not os.path.exists(filepath):
 
66
            self.report({'ERROR'}, "File Not Found %r" % filepath)
 
67
            return {'CANCELLED'}
 
68
 
 
69
        elist = parse_edl.EditList()
 
70
        if not elist.parse(filepath, dummy_fps):
 
71
            self.report({'ERROR'}, "Failed to parse EDL %r" % filepath)
 
72
            return {'CANCELLED'}
 
73
 
 
74
        scene = context.scene
 
75
        edl_import_info = scene.edl_import_info
 
76
        bl_reels = edl_import_info.reels
 
77
 
 
78
        data_prev = {reel.name: (reel.filepath, reel.frame_offset)
 
79
                     for reel in edl_import_info.reels}
 
80
 
 
81
        reels = elist.reels_as_dict()
 
82
        reels = [k for k in reels.keys() if k not in parse_edl.BLACK_ID]
 
83
 
 
84
        # re-create reels collection, keeping old values
 
85
        bl_reels.clear()
 
86
        for k in sorted(reels):
 
87
            reel = bl_reels.add()
 
88
            reel.name = k
 
89
            filepath, frame_offset = data_prev.get(k, (None, None))
 
90
            if filepath is not None:
 
91
                reel.filepath = filepath
 
92
                reel.frame_offset = frame_offset
 
93
 
 
94
        return {'FINISHED'}
 
95
 
 
96
 
 
97
class FindReelsEDL(Operator):
 
98
    """Scan a path for missing reel files, """ \
 
99
    """ Matching by reel name and existing filename when set"""
 
100
    bl_idname = "sequencer.import_edl_findreel"
 
101
    bl_label = "Find Missing Reel Files"
 
102
    directory = StringProperty(
 
103
            subtype='DIR_PATH',
 
104
            )
 
105
 
 
106
    @staticmethod
 
107
    def missing_reels(context):
 
108
        import os
 
109
        scene = context.scene
 
110
        edl_import_info = scene.edl_import_info
 
111
        return [reel for reel in edl_import_info.reels
 
112
                if not os.path.exists(reel.filepath)]
 
113
 
 
114
    def execute(self, context):
 
115
        import os
 
116
 
 
117
        # walk over .avi, .mov, .wav etc.
 
118
        def media_file_walker(path):
 
119
            ext_check = bpy.path.extensions_movie | bpy.path.extensions_audio
 
120
            for dirpath, dirnames, filenames in os.walk(path):
 
121
                # skip '.svn'
 
122
                if dirpath.startswith("."):
 
123
                    continue
 
124
                for filename in filenames:
 
125
                    fileonly, ext = os.path.splitext(filename)
 
126
                    ext_lower = ext.lower()
 
127
                    if ext_lower in ext_check:
 
128
                        yield os.path.join(dirpath, filename), fileonly
 
129
 
 
130
        scene = context.scene
 
131
        edl_import_info = scene.edl_import_info
 
132
 
 
133
        bl_reels = FindReelsEDL.missing_reels(context)
 
134
        assert(len(bl_reels))
 
135
 
 
136
        # Search is as follows
 
137
        # Each reel has a triple:
 
138
        #    ([search_names, ...], [(priority, found_file), ...], bl_reel)
 
139
        bl_reels_search = [(set(), [], reel) for reel in bl_reels]
 
140
 
 
141
        # first get the search names...
 
142
        for reel_names, reel_files_found, reel in bl_reels_search:
 
143
            reel_names_list = []
 
144
            reel_names_list.append(reel.name.lower())
 
145
 
 
146
            # add non-extension version of the reel name
 
147
            if "." in reel_names_list[-1]:
 
148
                reel_names_list.append(os.path.splitext(reel_names_list[-1])[0])
 
149
 
 
150
            # use the filepath if set
 
151
            reel_filepath = reel.filepath
 
152
            if reel_filepath:
 
153
                reel_filepath = os.path.basename(reel_filepath)
 
154
                reel_filepath = os.path.splitext(reel_filepath)[0]
 
155
                reel_names_list.append(reel_filepath.lower())
 
156
 
 
157
            # when '_' are found, replace with space
 
158
            reel_names_list += [reel_filepath.replace("_", " ")
 
159
                                for reel_filepath in reel_names_list
 
160
                                if "_" in reel_filepath]
 
161
            reel_names.update(reel_names_list)
 
162
 
 
163
        # debug info
 
164
        print("Searching or %d reels" % len(bl_reels_search))
 
165
        for reel_names, reel_files_found, reel in bl_reels_search:
 
166
            print("Reel: %r --> (%s)" % (reel.name, " ".join(sorted(reel_names))))
 
167
        print()
 
168
 
 
169
        for filename, fileonly in media_file_walker(self.directory):
 
170
            for reel_names, reel_files_found, reel in bl_reels_search:
 
171
                if fileonly.lower() in reel_names:
 
172
                    reel_files_found.append((0, filename))
 
173
                else:
 
174
                    # check on partial match
 
175
                    for r in reel_names:
 
176
                        if fileonly.startswith(r):
 
177
                            reel_files_found.append((1, filename))
 
178
                        if fileonly.endswith(r):
 
179
                            reel_files_found.append((2, filename))
 
180
 
 
181
        # apply back and report
 
182
        tot_done = 0
 
183
        tot_fail = 0
 
184
        for reel_names, reel_files_found, reel in bl_reels_search:
 
185
            if reel_files_found:
 
186
                # make sure partial matches end last
 
187
                reel_files_found.sort()
 
188
                reel.filepath = reel_files_found[0][1]
 
189
                tot_done += 1
 
190
            else:
 
191
                tot_fail += 1
 
192
 
 
193
        self.report({'INFO'} if tot_fail == 0 else {'WARNING'},
 
194
                    "Found %d clips, missing %d" % (tot_done, tot_fail))
 
195
 
 
196
        return {'FINISHED'}
 
197
 
 
198
    def invoke(self, context, event):
 
199
        import os
 
200
        scene = context.scene
 
201
        edl_import_info = scene.edl_import_info
 
202
 
 
203
        if not FindReelsEDL.missing_reels(context):
 
204
            self.report({'INFO'},
 
205
                        "Nothing to do, all reels point to valid files")
 
206
            return {'CANCELLED'}
 
207
 
 
208
        # default to the EDL path
 
209
        if not self.directory and edl_import_info.filepath:
 
210
            self.directory = os.path.dirname(edl_import_info.filepath)
 
211
 
 
212
        wm = context.window_manager
 
213
        wm.fileselect_add(self)
 
214
        return {"RUNNING_MODAL"}
 
215
 
 
216
 
 
217
class ImportEDL(Operator):
 
218
    """Import an EDL into the sequencer"""
 
219
    bl_idname = "sequencer.import_edl"
 
220
    bl_label = "Import Video Sequence (.edl)"
 
221
 
 
222
    def execute(self, context):
 
223
        import os
 
224
        from . import import_edl
 
225
        scene = context.scene
 
226
        edl_import_info = scene.edl_import_info
 
227
 
 
228
        filepath = edl_import_info.filepath
 
229
        reel_filepaths = {reel.name: reel.filepath
 
230
                          for reel in edl_import_info.reels}
 
231
        reel_offsets = {reel.name: reel.frame_offset
 
232
                        for reel in edl_import_info.reels}
 
233
 
 
234
        if not os.path.exists(filepath):
 
235
            self.report({'ERROR'}, "File Not Found %r" % filepath)
 
236
            return {'CANCELLED'}
 
237
 
 
238
        msg = import_edl.load_edl(
 
239
                scene, filepath,
 
240
                reel_filepaths, reel_offsets,
 
241
                edl_import_info.frame_offset)
 
242
 
 
243
        if msg:
 
244
            self.report({'WARNING'}, msg)
 
245
 
 
246
        return {'FINISHED'}
 
247
 
 
248
 
 
249
# ----------------------------------------------------------------------------
 
250
# Persistent Scene Data Types (store EDL import info)
 
251
 
 
252
class EDLReelInfo(bpy.types.PropertyGroup):
 
253
    name = StringProperty(
 
254
            name="Name",
 
255
            )
 
256
    filepath = StringProperty(
 
257
            name="Video File",
 
258
            subtype='FILE_PATH',
 
259
            )
 
260
    frame_offset = IntProperty(
 
261
            name="Frame Offset",
 
262
            )
 
263
 
 
264
 
 
265
class EDLImportInfo(bpy.types.PropertyGroup):
 
266
    filepath = StringProperty(
 
267
            subtype='FILE_PATH',
 
268
            )
 
269
    reels = bpy.props.CollectionProperty(
 
270
            type=EDLReelInfo,
 
271
            )
 
272
    frame_offset = IntProperty(
 
273
            name="Global Frame Offset",
 
274
            )
 
275
 
 
276
# ----------------------------------------------------------------------------
 
277
# Panel to show EDL Import UI
 
278
 
 
279
 
 
280
class SEQUENCER_PT_import_edl(bpy.types.Panel):
 
281
    bl_label = "EDL Import"
 
282
    bl_space_type = 'SEQUENCE_EDITOR'
 
283
    bl_region_type = 'UI'
 
284
 
 
285
    def draw(self, context):
 
286
        layout = self.layout
 
287
 
 
288
        scene = context.scene
 
289
        edl_import_info = scene.edl_import_info
 
290
 
 
291
        layout.operator(ImportEDL.bl_idname)
 
292
 
 
293
        col = layout.column(align=True)
 
294
        col.prop(edl_import_info, "frame_offset")
 
295
        col.prop(edl_import_info, "filepath", text="")
 
296
        col.operator(ReloadEDL.bl_idname, icon='FILE_REFRESH')
 
297
 
 
298
        box = layout.box()
 
299
        reel = None
 
300
        for reel in scene.edl_import_info.reels:
 
301
            col = box.column(align=True)
 
302
            col.label(text=reel.name)
 
303
            col.prop(reel, "filepath", text="")
 
304
            col.prop(reel, "frame_offset")
 
305
 
 
306
        if reel is None:
 
307
            box.label("Empty (No EDL Data)")
 
308
 
 
309
        box.operator(FindReelsEDL.bl_idname, icon='EXTERNAL_DATA')
 
310
 
 
311
 
 
312
def register():
 
313
    bpy.utils.register_class(ReloadEDL)
 
314
    bpy.utils.register_class(FindReelsEDL)
 
315
    bpy.utils.register_class(ImportEDL)
 
316
    bpy.utils.register_class(SEQUENCER_PT_import_edl)
 
317
 
 
318
    # edl_import_info
 
319
    bpy.utils.register_class(EDLReelInfo)
 
320
    bpy.utils.register_class(EDLImportInfo)
 
321
    bpy.types.Scene.edl_import_info = PointerProperty(type=EDLImportInfo)
 
322
 
 
323
 
 
324
def unregister():
 
325
    bpy.utils.unregister_class(ReloadEDL)
 
326
    bpy.utils.unregister_class(FindReelsEDL)
 
327
    bpy.utils.unregister_class(ImportEDL)
 
328
    bpy.utils.unregister_class(SEQUENCER_PT_import_edl)
 
329
 
 
330
    # edl_import_info
 
331
    bpy.utils.unregister_class(EDLImportInfo)
 
332
    bpy.utils.unregister_class(EDLReelInfo)
 
333
    del bpy.types.Scene.edl_import_info