def load(): """ If docs fail to load, new ones are created and saved. """ prefs_file_path = utils.get_hidden_user_dir_path() + PREFS_DOC recents_file_path = utils.get_hidden_user_dir_path() + RECENT_DOC global prefs, recent_projects try: f = open(prefs_file_path) prefs = pickle.load(f) except: prefs = EditorPreferences() write_file = file(prefs_file_path, "wb") pickle.dump(prefs, write_file) try: f = open(recents_file_path) recent_projects = pickle.load(f) except: recent_projects = utils.EmptyClass() recent_projects.projects = [] write_file = file(recents_file_path, "wb") pickle.dump(recent_projects, write_file) # version of program may have different prefs objects and # we may need to to update prefs on disk if user has e.g. # installed later version of Flowblade current_prefs = EditorPreferences() if len(prefs.__dict__) != len(current_prefs.__dict__): current_prefs.__dict__.update(prefs.__dict__) prefs = current_prefs write_file = file(prefs_file_path, "wb") pickle.dump(prefs, write_file) print "prefs updated to new version, new param count:", len(prefs.__dict__)
def load(): """ If docs fail to load, new ones are created and saved. """ prefs_file_path = userfolders.get_config_dir() + PREFS_DOC recents_file_path = userfolders.get_config_dir() + RECENT_DOC global prefs, recent_projects try: prefs = utils.unpickle(prefs_file_path) except: prefs = EditorPreferences() with atomicfile.AtomicFileWriter(prefs_file_path, "wb") as afw: write_file = afw.get_file() pickle.dump(prefs, write_file) # Override deprecated preferences to default values. prefs.delta_overlay = True prefs.auto_play_in_clip_monitor = False prefs.empty_click_exits_trims = True prefs.quick_enter_trims = True prefs.remember_monitor_clip_frame = True try: recent_projects = utils.unpickle(recents_file_path) except: recent_projects = utils.EmptyClass() recent_projects.projects = [] with atomicfile.AtomicFileWriter(recents_file_path, "wb") as afw: write_file = afw.get_file() pickle.dump(recent_projects, write_file) # Remove non-existing projects from recents list remove_list = [] for proj_path in recent_projects.projects: if os.path.isfile(proj_path) == False: remove_list.append(proj_path) if len(remove_list) > 0: for proj_path in remove_list: recent_projects.projects.remove(proj_path) with atomicfile.AtomicFileWriter(recents_file_path, "wb") as afw: write_file = afw.get_file() pickle.dump(recent_projects, write_file) # Versions of program may have different prefs objects and # we may need to to update prefs on disk if user has e.g. # installed later version of Flowblade. current_prefs = EditorPreferences() if len(prefs.__dict__) != len(current_prefs.__dict__): current_prefs.__dict__.update(prefs.__dict__) prefs = current_prefs with atomicfile.AtomicFileWriter(prefs_file_path, "wb") as afw: write_file = afw.get_file() pickle.dump(prefs, write_file) print("prefs updated to new version, new param count:", len(prefs.__dict__))
def create_editable_property_for_affine_blend(clip, editable_properties): # Build a custom object that duck types for TransitionEditableProperty to use in editor # ep = utils.EmptyClass() # pack real properties to go ep.x = [ep for ep in editable_properties if ep.name == "x"][0] ep.y = [ep for ep in editable_properties if ep.name == "y"][0] ep.x_scale = [ep for ep in editable_properties if ep.name == "x scale"][0] ep.y_scale = [ep for ep in editable_properties if ep.name == "y scale"][0] ep.rotation = [ep for ep in editable_properties if ep.name == "rotation"][0] ep.opacity = [ep for ep in editable_properties if ep.name == "opacity"][0] # Screen width and height are needeed for frei0r conversions ep.profile_width = current_sequence().profile.width() ep.profile_height = current_sequence().profile.height() # duck type methods, using opacity is not meaningful, any property with clip member could do ep.get_clip_tline_pos = lambda: ep.opacity.clip.clip_in # clip is compositor, compositor in and out points straight in timeline frames ep.get_clip_length = lambda: ep.opacity.clip.clip_out - ep.opacity.clip.clip_in + 1 ep.get_input_range_adjustment = lambda: Gtk.Adjustment( value=float(100), lower=float(0), upper=float(100), step_incr=float(1)) ep.get_display_name = lambda: "Opacity" ep.get_pixel_aspect_ratio = lambda: (float(current_sequence( ).profile.sample_aspect_num()) / current_sequence().profile. sample_aspect_den()) ep.get_in_value = lambda out_value: out_value # hard coded for opacity 100 -> 100 range ep.write_out_keyframes = lambda w_kf: rotating_ge_write_out_keyframes( ep, w_kf) ep.update_prop_value = lambda: rotating_ge_update_prop_value( ep ) # This is needed to get good update after adding kfs with fade buttons, iz all kinda fugly # We need this to reinit GUI components after programmatically added kfs. # duck type members x_tokens = ep.x.value.split(";") y_tokens = ep.y.value.split(";") x_scale_tokens = ep.x_scale.value.split(";") y_scale_tokens = ep.y_scale.value.split(";") rotation_tokens = ep.rotation.value.split(";") opacity_tokens = ep.opacity.value.split(";") value = "" for i in range( 0, len(x_tokens) ): # these better match, same number of keyframes for all values, or this will not work frame, x = x_tokens[i].split("=") frame, y = y_tokens[i].split("=") frame, x_scale = x_scale_tokens[i].split("=") frame, y_scale = y_scale_tokens[i].split("=") frame, rotation = rotation_tokens[i].split("=") frame, opacity = opacity_tokens[i].split("=") frame_str = str(frame) + "=" + str(x) + ":" + str(y) + ":" + str( x_scale) + ":" + str(y_scale) + ":" + str(rotation) + ":" + str( opacity) value += frame_str + ";" ep.value = value.strip(";") return ep
def make_tailer_state(): """Return the tailer state "struct" """ s = utils.EmptyClass() s.entries_received = 0 # how many entries were put in the global doc queue s.entries_written = 0 # how many entries were written to the output file s.alive = True # is this thread still alive (i.e. working)? s.last_received_ts = None # timestamp of the latest received doc s.last_get_none_ts = None # last time this thread didn't get anything from the tailing cursor return s
def run(self): callbacks = utils.EmptyClass() callbacks.set_render_progress_gui = set_render_progress_gui callbacks.save_render_start_time = save_render_start_time callbacks.exit_render_gui = exit_render_gui callbacks.maybe_open_rendered_file_in_bin = maybe_open_rendered_file_in_bin PLAYER().set_render_callbacks(callbacks) PLAYER().start_rendering(self.render_consumer, self.start_frame, self.end_frame)
def _create_rotion_geometry_editor(clip, editable_properties): # Build a custom object that duck types for TransitionEditableProperty to use in editor ep = utils.EmptyClass() # pack real properties to go ep.x = filter(lambda ep: ep.name == "x", editable_properties)[0] ep.y = filter(lambda ep: ep.name == "y", editable_properties)[0] ep.x_scale = filter(lambda ep: ep.name == "x scale", editable_properties)[0] ep.y_scale = filter(lambda ep: ep.name == "y scale", editable_properties)[0] ep.rotation = filter(lambda ep: ep.name == "rotation", editable_properties)[0] ep.opacity = filter(lambda ep: ep.name == "opacity", editable_properties)[0] # Screen width and height are needeed for frei0r conversions ep.profile_width = current_sequence().profile.width() ep.profile_height = current_sequence().profile.height() # duck type methods, using opacity is not meaningful, any property with clip member could do ep.get_clip_tline_pos = lambda: ep.opacity.clip.clip_in # clip is compositor, compositor in and out points staright in timeline frames ep.get_clip_length = lambda: ep.opacity.clip.clip_out - ep.opacity.clip.clip_in + 1 ep.get_input_range_adjustment = lambda: Gtk.Adjustment( float(100), float(0), float(100), float(1)) ep.get_display_name = lambda: "Opacity" ep.get_pixel_aspect_ratio = lambda: (float(current_sequence( ).profile.sample_aspect_num()) / current_sequence().profile. sample_aspect_den()) ep.get_in_value = lambda out_value: out_value # hard coded for opacity 100 -> 100 range ep.write_out_keyframes = lambda w_kf: keyframeeditor.rotating_ge_write_out_keyframes( ep, w_kf) # duck type members x_tokens = ep.x.value.split(";") y_tokens = ep.y.value.split(";") x_scale_tokens = ep.x_scale.value.split(";") y_scale_tokens = ep.y_scale.value.split(";") rotation_tokens = ep.rotation.value.split(";") opacity_tokens = ep.opacity.value.split(";") value = "" for i in range( 0, len(x_tokens) ): # these better match, same number of keyframes for all values, or this will not work frame, x = x_tokens[i].split("=") frame, y = y_tokens[i].split("=") frame, x_scale = x_scale_tokens[i].split("=") frame, y_scale = y_scale_tokens[i].split("=") frame, rotation = rotation_tokens[i].split("=") frame, opacity = opacity_tokens[i].split("=") frame_str = str(frame) + "=" + str(x) + ":" + str(y) + ":" + str( x_scale) + ":" + str(y_scale) + ":" + str(rotation) + ":" + str( opacity) value += frame_str + ";" ep.value = value.strip(";") kf_edit = keyframeeditor.RotatingGeometryEditor(ep, False) return kf_edit
def make_tailer_state(): """Return the tailer state "struct" """ s = utils.EmptyClass() s.entries_received = 0 s.entries_written = 0 s.alive = True s.last_received_ts = None s.last_get_none_ts = None return s
def _create_coords(self): self.coords = utils.EmptyClass() panel_w = self.widget.get_allocation().width panel_h = self.widget.get_allocation().height self.coords.screen_h = panel_h * self.y_fract self.coords.screen_w = self.coords.screen_h * self.screen_ratio * self.pixel_aspect_ratio self.coords.orig_x = (panel_w - self.coords.screen_w) / 2.0 self.coords.orig_y = (panel_h - self.coords.screen_h) / 2.0 self.coords.x_scale = self.source_width / self.coords.screen_w self.coords.y_scale = self.source_height / self.coords.screen_h
def autosaves_many_recovery_dialog(): autosaves_file_names = get_autosave_files() now = time.time() autosaves = [] for a_file_name in autosaves_file_names: autosave_path = utils.get_hidden_user_dir_path() + AUTOSAVE_DIR + a_file_name autosave_object = utils.EmptyClass() autosave_object.age = now - os.stat(autosave_path).st_mtime autosave_object.path = autosave_path autosaves.append(autosave_object) autosaves = sorted(autosaves, key=lambda autosave_object: autosave_object.age) dialogs.autosaves_many_recovery_dialog(autosaves_many_dialog_callback, autosaves, gui.editor_window.window) return False
def create_widgets(def_profile_index, disable_audio=True, create_container_file_panel=False): """ Widgets for editing render properties and viewing render progress. """ global widgets, disable_audio_encoding, default_profile_index default_profile_index = def_profile_index if disable_audio: disable_audio_encoding = True widgets = utils.EmptyClass() widgets.file_panel = RenderFilePanel(create_container_file_panel) widgets.profile_panel = RenderProfilePanel(_out_profile_changed) widgets.encoding_panel = RenderEncodingPanel(widgets.file_panel.extension_label) widgets.profile_panel.out_profile_combo.fill_options() _display_default_profile()
GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Flowblade Movie Editor. If not, see <http://www.gnu.org/licenses/>. """ from gi.repository import Gtk from gi.repository import GObject from gi.repository import Pango from editorstate import PROJECT import guicomponents import guiutils import utils widgets = utils.EmptyClass() PROJECT_INFO_PANEL_HEIGHT = 200 PROJECT_TOP_LEVEL_PANE_HEIGHT = 150 def get_project_info_panel(): project_name_label = Gtk.Label(label=PROJECT().name) name_row = guiutils.get_left_justified_box([project_name_label]) name_panel = guiutils.get_named_frame(_("Name"), name_row, 4) profile = PROJECT().profile desc_label = Gtk.Label(label=profile.description()) info_box = guicomponents.get_profile_info_small_box(profile) vbox = Gtk.VBox() vbox.pack_start(guiutils.get_left_justified_box([desc_label]), False, True,
def show_reverse_dialog(media_file, default_range_render, _response_callback): folder, file_name = os.path.split(media_file.path) if media_file.is_proxy_file: folder, file_name = os.path.split(media_file.second_file_path) name, ext = os.path.splitext(file_name) dialog = Gtk.Dialog(_("Render Reverse Motion Video File"), gui.editor_window.window, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, (Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT, _("Render").encode('utf-8'), Gtk.ResponseType.ACCEPT)) media_file_label = Gtk.Label(label=_("Source Media File: ")) media_name = Gtk.Label(label="<b>" + media_file.name + "</b>") media_name.set_use_markup(True) SOURCE_PAD = 8 SOURCE_HEIGHT = 20 mf_row = guiutils.get_left_justified_box([media_file_label, guiutils.pad_label(SOURCE_PAD, SOURCE_HEIGHT), media_name]) mark_in = Gtk.Label(label=_("<b>not set</b>")) mark_out = Gtk.Label(label=_("<b>not set</b>")) if media_file.mark_in != -1: mark_in = Gtk.Label(label="<b>" + utils.get_tc_string(media_file.mark_in) + "</b>") if media_file.mark_out != -1: mark_out = Gtk.Label(label="<b>" + utils.get_tc_string(media_file.mark_out) + "</b>") mark_in.set_use_markup(True) mark_out.set_use_markup(True) fb_widgets = utils.EmptyClass() fb_widgets.file_name = Gtk.Entry() fb_widgets.file_name.set_text(name + "_REVERSE") fb_widgets.extension_label = Gtk.Label() fb_widgets.extension_label.set_size_request(45, 20) name_row = Gtk.HBox(False, 4) name_row.pack_start(fb_widgets.file_name, True, True, 0) name_row.pack_start(fb_widgets.extension_label, False, False, 4) fb_widgets.out_folder = Gtk.FileChooserButton(_("Select Target Folder")) fb_widgets.out_folder.set_action(Gtk.FileChooserAction.SELECT_FOLDER) fb_widgets.out_folder.set_current_folder(folder) label = Gtk.Label(label=_("Speed %:")) adjustment = Gtk.Adjustment(float(-100), float(-600), float(-1), float(1)) fb_widgets.hslider = Gtk.HScale() fb_widgets.hslider.set_adjustment(adjustment) fb_widgets.hslider.set_draw_value(False) spin = Gtk.SpinButton() spin.set_numeric(True) spin.set_adjustment(adjustment) fb_widgets.hslider.set_digits(0) spin.set_digits(0) slider_hbox = Gtk.HBox(False, 4) slider_hbox.pack_start(fb_widgets.hslider, True, True, 0) slider_hbox.pack_start(spin, False, False, 4) slider_hbox.set_size_request(450,35) hbox = Gtk.HBox(False, 2) hbox.pack_start(guiutils.pad_label(8, 8), False, False, 0) hbox.pack_start(slider_hbox, False, False, 0) profile_selector = ProfileSelector() profile_selector.fill_options() profile_selector.widget.set_sensitive(True) fb_widgets.out_profile_combo = profile_selector.widget quality_selector = RenderQualitySelector() fb_widgets.quality_cb = quality_selector.widget # Encoding encoding_selector = RenderEncodingSelector(quality_selector, fb_widgets.extension_label, None) encoding_selector.encoding_selection_changed() fb_widgets.encodings_cb = encoding_selector.widget objects_list = Gtk.TreeStore(str, bool) objects_list.append(None, [_("Full Source Length"), True]) if media_file.mark_in != -1 and media_file.mark_out != -1: range_available = True else: range_available = False objects_list.append(None, [_("Source Mark In to Mark Out"), range_available]) fb_widgets.render_range = Gtk.ComboBox.new_with_model(objects_list) renderer_text = Gtk.CellRendererText() fb_widgets.render_range.pack_start(renderer_text, True) fb_widgets.render_range.add_attribute(renderer_text, "text", 0) fb_widgets.render_range.add_attribute(renderer_text, 'sensitive', 1) if default_range_render == False: fb_widgets.render_range.set_active(0) else: fb_widgets.render_range.set_active(1) fb_widgets.render_range.show() # To update rendered length display clip_length = _get_rendered_slomo_clip_length(media_file, fb_widgets.render_range, 100) clip_length_label = Gtk.Label(label=utils.get_tc_string(clip_length)) fb_widgets.hslider.connect("value-changed", _reverse_speed_changed, media_file, fb_widgets.render_range, clip_length_label) fb_widgets.render_range.connect("changed", _reverse_range_changed, media_file, fb_widgets.hslider, clip_length_label) # Build gui vbox = Gtk.VBox(False, 2) vbox.pack_start(mf_row, False, False, 0) vbox.pack_start(guiutils.get_left_justified_box([Gtk.Label(label=_("Source Mark In: ")), guiutils.pad_label(SOURCE_PAD, SOURCE_HEIGHT), mark_in]), False, False, 0) vbox.pack_start(guiutils.get_left_justified_box([Gtk.Label(label=_("Source Mark Out: ")), guiutils.pad_label(SOURCE_PAD, SOURCE_HEIGHT), mark_out]), False, False, 0) vbox.pack_start(guiutils.pad_label(18, 12), False, False, 0) vbox.pack_start(label, False, False, 0) vbox.pack_start(hbox, False, False, 0) vbox.pack_start(guiutils.pad_label(18, 12), False, False, 0) vbox.pack_start(guiutils.get_two_column_box(Gtk.Label(label=_("Target File:")), name_row, 120), False, False, 0) vbox.pack_start(guiutils.get_two_column_box(Gtk.Label(label=_("Target Folder:")), fb_widgets.out_folder, 120), False, False, 0) vbox.pack_start(guiutils.get_two_column_box(Gtk.Label(label=_("Target Profile:")), fb_widgets.out_profile_combo, 200), False, False, 0) vbox.pack_start(guiutils.get_two_column_box(Gtk.Label(label=_("Target Encoding:")), fb_widgets.encodings_cb, 200), False, False, 0) vbox.pack_start(guiutils.get_two_column_box(Gtk.Label(label=_("Target Quality:")), fb_widgets.quality_cb, 200), False, False, 0) vbox.pack_start(guiutils.pad_label(18, 12), False, False, 0) vbox.pack_start(guiutils.get_two_column_box(Gtk.Label(label=_("Render Range:")), fb_widgets.render_range, 180), False, False, 0) vbox.pack_start(guiutils.get_two_column_box(Gtk.Label(label=_("Rendered Clip Length:")), clip_length_label, 180), False, False, 0) alignment = guiutils.set_margins(vbox, 6, 24, 24, 24) dialog.vbox.pack_start(alignment, True, True, 0) dialogutils.set_outer_margins(dialog.vbox) dialogutils.default_behaviour(dialog) dialog.connect('response', _response_callback, fb_widgets, media_file) dialog.show_all()