openshot.code team mailing list archive
-
openshot.code team
-
Mailing list archive
-
Message #00005
[Branch ~openshot.code/openshot/main] Rev 500: Applied a patch from Emil that fixes bug #534284, Thumbnail is for first frame of original clip. ...
------------------------------------------------------------
revno: 500
committer: Andy Finch <we.rocked.in79@xxxxxxxxx>
branch nick: openshot
timestamp: Tue 2011-08-16 20:51:22 +0100
message:
Applied a patch from Emil that fixes bug #534284, Thumbnail is for first frame of original clip. Now when cutting a clip on the timeline, another thumbnail is generated for the first frame of the second clip for both videos and image sequences. For a fuller description of Emil's patch, see the bug description. This patch also rebuilds the thumbnails if they are lost, so fixing bug #512516.
modified:
openshot/classes/clip.py
openshot/classes/files.py
openshot/classes/open_project.py
openshot/windows/ClipProperties.py
openshot/windows/MainGTK.py
--
lp:openshot
https://code.launchpad.net/~openshot.code/openshot/main
Your team OpenShot Code is subscribed to branch lp:openshot.
To unsubscribe from this branch go to https://code.launchpad.net/~openshot.code/openshot/main/+edit-subscription
=== modified file 'openshot/classes/clip.py'
--- openshot/classes/clip.py 2011-08-10 20:50:17 +0000
+++ openshot/classes/clip.py 2011-08-16 19:51:22 +0000
@@ -57,6 +57,10 @@
self.file_object = file_object # the file object that this clip is linked to
self.unique_id = str(uuid.uuid1())
self.rotation = 0.0
+ self.thumb_location = ""
+
+ # Update the thumbnail of the clip and the location
+ self.update_thumbnail()
# init key-frame dictionary
self.keyframes = {"start" : keyframe(0, 100.0, 100.0, 0.0, 0.0, 1.0),
@@ -75,7 +79,73 @@
# end_time = 25.0
# position_on_track = 3.0
-
+ def update_thumbnail(self):
+ """Updates the thumbnail of the clip to make it reflect the first frame.
+ Creates a new thumbnail if there is none, gives it a new thumbnail path
+ if it is empty."""
+
+ # Initialize variables
+ project = self.parent.parent.project
+ thumbnailer = project.thumbnailer
+ fps = self.file_object.fps
+ start_frame = int(float(fps) * self.start_time)
+ file_type = self.file_object.file_type
+
+ # Remove the thumbnail, if it can be removed
+ self.remove_thumbnail()
+
+ # If it cannot be exchanged for the file thumbnail
+ if start_frame and (file_type == "video" or file_type == "image sequence"):
+
+ # If it already has a thumbnail location, just update the thumbnail
+ if self.thumb_location and not self.thumb_location == self.file_object.thumb_location:
+ (dir_name, file_name) = os.path.split(self.thumb_location)
+
+ # The shortened path to the thumbnail. %d is escaped to provide image sequence support
+ new_name = "thumbnail/" + file_name.replace("%d","%%d")
+
+ # The whole path. %d shouldn't be escaped here.
+ path = project.folder + "/thumbnail/" + file_name
+
+ # If the clip needs a new thumbnail location
+ else:
+
+ # Split the file name
+ (dir_name, file_name) = os.path.split(self.file_object.name)
+ (file_base_name, ext) = os.path.splitext(file_name)
+
+ # Escape some characters
+ ext = ext.replace(".", "")
+
+ # Loop to find an unoccupied name. Start at 2, since the file thumbnail starts at 1
+ i = 2
+ while(True):
+ path = project.folder + "/thumbnail/" + file_base_name + "_" + ext + "_" + str(i) + ".png"
+ if not os.path.exists(path):
+ break
+ i += 1
+
+ # The shortened path to the thumbnail. %d is escaped to provide image sequence support
+ new_name = "thumbnail/" + file_base_name.replace("%d","%%d") + "_" + ext + "_" + str(i) + ".png"
+
+ # Create the new thumbnail
+ thumbnailer.get_thumb_at_frame(self.file_object.name, start_frame, new_name)
+
+ # Update the path to the thumbnail
+ self.thumb_location = path
+ print "thumb " + self.thumb_location
+
+ elif not file_type == "audio":
+ # Use the file thumbnail instead, to avoid creating a new
+ self.thumb_location = self.file_object.thumb_location
+
+
+ def remove_thumbnail(self):
+ """Removes the thumbnail from the hard drive, if it isn't shared with a file"""
+ # Removes the thumbnail used by this clip if it is valid and isn't used by a file
+ if self.thumb_location and os.path.exists(self.thumb_location) and not self.thumb_location == self.file_object.thumb_location:
+ os.remove(self.thumb_location)
+
def length(self):
# calculate the length of this clip (in decimal seconds)
length = self.end_time - self.start_time
@@ -114,6 +184,50 @@
self.effects.append(new_effect)
self.parent.parent.project.set_project_modified(is_modified=True, refresh_xml=True, type = _("Added effect") + " " + service)
+
+ def get_thumbnail(self, width, height):
+ """Get and resize the pixbuf thumbnail for a clip"""
+
+ # get the thumbnail (or load default)
+ try:
+ if self.thumb_location:
+ pbThumb = gtk.gdk.pixbuf_new_from_file(self.thumb_location)
+ pbThumb = pbThumb.add_alpha(False, 255, 255, 255)
+
+ # Mask the corner of the thumbnail image (for a nice rounding effect)
+ corner_mask = gtk.gdk.pixbuf_new_from_file(os.path.join(self.file_object.project.IMAGE_DIR, 'thumbnail_mask.png'))
+ corner_mask.composite(pbThumb,
+ 0,
+ 0,
+ 320,
+ 240,
+ 0,
+ 0,
+ 1.0,
+ 1.0,
+ gtk.gdk.INTERP_NEAREST,
+ 255)
+
+ # replace corner with transparency
+ pbThumb = pbThumb.add_alpha(True, 255, 0, 202)
+
+
+ else:
+ # Load the No Thumbnail Picture
+ if self.file_object.file_type == "audio":
+ pbThumb = gtk.gdk.pixbuf_new_from_file(os.path.join(self.file_object.project.IMAGE_DIR, "AudioThumbnail.png"))
+ else:
+ pbThumb = gtk.gdk.pixbuf_new_from_file(os.path.join(self.file_object.project.IMAGE_DIR, "NoThumbnail.png"))
+ except:
+
+ # Load the No Thumbnail Picture
+ if self.file_object.file_type == "audio":
+ pbThumb = gtk.gdk.pixbuf_new_from_file(os.path.join(self.file_object.project.IMAGE_DIR, "AudioThumbnail.png"))
+ else:
+ pbThumb = gtk.gdk.pixbuf_new_from_file(os.path.join(self.file_object.project.IMAGE_DIR, "NoThumbnail.png"))
+
+ # resize thumbnail
+ return pbThumb.scale_simple(width, height, gtk.gdk.INTERP_BILINEAR)
def Remove_Effect(self, unique_id):
# Remove an effect from the list
@@ -1230,7 +1344,7 @@
# ///////////////////////////////////////////////////////
if has_regular_images == False:
# get the thumbnail image
- pbThumb = self.file_object.get_thumbnail(theme_settings["clip"]["thumbnail"]["w"], theme_settings["clip"]["thumbnail"]["h"])
+ pbThumb = self.get_thumbnail(theme_settings["clip"]["thumbnail"]["w"], theme_settings["clip"]["thumbnail"]["h"])
# create canvas image object
imgThumb = goocanvas.Image (parent = GroupClip,
@@ -1976,6 +2090,14 @@
child_num = parent.find_child (item)
parent.remove_child (child_num)
+ # Initialize variables
+ pixels_per_second = self.parent.parent.get_pixels_per_second()
+ center_of_clip = (self.position_on_track * pixels_per_second) + ((self.length() * pixels_per_second) / 2)
+
+ # If the clip was dragged on the left side, update the thumbnail to reflect the changes
+ if event.x_root < center_of_clip:
+ self.update_thumbnail()
+
# re-render the clip at it's new size
self.RenderClip()
=== modified file 'openshot/classes/files.py'
--- openshot/classes/files.py 2011-08-11 21:59:28 +0000
+++ openshot/classes/files.py 2011-08-16 19:51:22 +0000
@@ -104,6 +104,26 @@
# resize thumbnail
return pbThumb.scale_simple(width, height, gtk.gdk.INTERP_BILINEAR)
+ def update_thumbnail(self):
+
+ # Initialize variables
+ project = self.project
+ thumbnailer = project.thumbnailer
+ file_type = self.file_type
+
+ # Audio files have a common thumbnail
+ if not file_type == "audio":
+
+ # Split the file name
+ (dir_name, file_name) = os.path.split(self.name)
+ (file_base_name, ext) = os.path.splitext(file_name)
+ ext = ext.replace(".", "")
+
+ # The shortened path to the thumbnail
+ new_name = "thumbnail/" + file_base_name + "_" + ext + "_1.png"
+
+ # Create the new thumbnail
+ thumbnailer.get_thumb_at_frame(self.name, new_name=new_name)
########################################################################
class OpenShotFolder:
@@ -442,8 +462,10 @@
for clip in reversed(track.clips):
# does clip match file
if clip.file_object == item:
- # delete clip
+ # delete clip and remove thumbnail
track.clips.remove(clip)
+ clip.remove_thumbnail()
+
# remove from file collection
self.items.remove(item)
else:
=== modified file 'openshot/classes/open_project.py'
--- openshot/classes/open_project.py 2011-01-13 07:33:37 +0000
+++ openshot/classes/open_project.py 2011-08-16 19:51:22 +0000
@@ -95,6 +95,26 @@
if missing_transitions:
messagebox.show("OpenShot", _("The following transition(s) no longer exist.") + "\n\n" + missing_transitions)
+ # Recreate the thumbnail folder if it is missing
+ if not os.path.exists(project_object.folder + "/thumbnail"):
+ os.makedirs(project_object.folder + "/thumbnail")
+
+ # Recreate missing thumbnails for files
+ for item in items:
+ if isinstance(item, files.OpenShotFile):
+ if not os.path.exists(item.thumb_location):
+ item.update_thumbnail()
+
+ # Recreate missing thumbnails for clips
+ for sequence in project_object.sequences:
+ for track in sequence.tracks:
+ for clip in track.clips:
+ # Code to keep pre 1.4.0 .osp files compatible. May be removed later.
+ if not hasattr(clip, "thumb_location"):
+ clip.thumb_location = ""
+
+ if not os.path.exists(clip.thumb_location) and not clip.file_object.file_type == "audio":
+ clip.update_thumbnail()
# mark XML as refreshable
project_object.set_project_modified(is_modified=False, refresh_xml=True)
=== modified file 'openshot/windows/ClipProperties.py'
--- openshot/windows/ClipProperties.py 2011-08-10 20:13:08 +0000
+++ openshot/windows/ClipProperties.py 2011-08-16 19:51:22 +0000
@@ -891,6 +891,9 @@
# update keyframes
clip_object.keyframes = self.keyframes
+ # Update the thumbnail
+ clip_object.update_thumbnail()
+
if localcboDirection.lower() == _("Reverse").lower():
clip_object.reversed = True
else:
=== modified file 'openshot/windows/MainGTK.py'
--- openshot/windows/MainGTK.py 2011-08-11 20:33:40 +0000
+++ openshot/windows/MainGTK.py 2011-08-16 19:51:22 +0000
@@ -2253,7 +2253,7 @@
#this will be the new name of the snapshot image file
new_name = fileBaseName + str(intNum) + ".png"
#extract the frame
- self.project.thumbnailer.get_thumb_at_frame(clip.file_object.name, int(frame_position), new_name)
+ self.project.thumbnailer.get_thumb_at_frame(clip.file_object.name, int(frame_position), new_name, True)
#add the file to the project in the project folder
self.project.project_folder.AddFile(self.project.folder + "/" + new_name)
#refresh the tree
@@ -3535,6 +3535,7 @@
# render timeline
self.project.Render()
+
def on_mnuClipEditTitle_activate(self, event, *args):
#print "on_mnuClipEditTitle_activate"
@@ -3575,6 +3576,9 @@
child_num = parent.find_child (self.selected_clip_item)
parent.remove_child (child_num)
+ # Remove the thumbnail
+ self.selected_clip.remove_thumbnail()
+
# mark project as modified
self.project.set_project_modified(is_modified=True, refresh_xml=True, type = _("Removed clip"))
@@ -3696,6 +3700,9 @@
new_clip.keyframes = copy.deepcopy(self.selected_clip.keyframes)
new_clip.effects = copy.deepcopy(self.selected_clip.effects)
+ # Update the thumbnail
+ new_clip.update_thumbnail()
+
# mark project as modified
self.project.set_project_modified(is_modified=True, refresh_xml=True, type="Duplicated clip")