def _tworoll_init_failed_window(): primary_txt = _("Initializing TWO ROLL TRIM failed") secondary_txt = _( "You are attempting TWO ROLL TRIM at a position in the timeline\nwhere it can't be performed." ) dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window)
def _no_audio_tracks_mixing_info(): primary_txt = _("Only Video Track mix / fades available") secondary_txt = _( "Unfortunately rendered mixes and fades can currently\nonly be applied on clips on Video Tracks." ) dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window)
def _cover_blank_from_next(data, called_from_next_clip=False): clip, track, item_id, item_data = data if not called_from_next_clip: clip_index = movemodes.selected_range_out + 1 blank_index = movemodes.selected_range_in if clip_index < 0: # we are not getting a legal clip index return cover_clip = track.clips[clip_index] else: clip_index = track.clips.index(clip) + 1 blank_index = clip_index - 1 cover_clip = track.clips[clip_index] # Check that clip covers blank area total_length = 0 for i in range(movemodes.selected_range_in, movemodes.selected_range_out + 1): total_length += track.clips[i].clip_length() if total_length > cover_clip.clip_in: # handle not long enough to cover blanks primary_txt = _("Next clip does not have enough material to cover blank area") secondary_txt = _("Requested edit can't be done.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return # Do edit movemodes.clear_selected_clips() data = {"track":track, "clip":cover_clip, "blank_index":blank_index} action = edit.trim_start_over_blanks(data) action.do_edit()
def sync_compositor(compositor): track = current_sequence().tracks[ compositor.transition. b_track] # b_track is source track where origin clip is origin_clip = None for clip in track.clips: if clip.id == compositor.origin_clip_id: origin_clip = clip if origin_clip == None: dialogutils.info_message( _("Origin clip not found!"), _("Clip used to create this Compositor has been removed\nor moved to different track." ), gui.editor_window.window) return clip_index = track.clips.index(origin_clip) clip_start = track.clip_start(clip_index) clip_end = clip_start + origin_clip.clip_out - origin_clip.clip_in # Auto fades need to go to start or end of clips and maintain their lengths if compositor.transition.info.auto_fade_compositor == True: if compositor.transition.info.name == "##auto_fade_in": clip_end = clip_start + compositor.get_length() - 1 else: clip_start = clip_end - compositor.get_length() + 1 data = { "compositor": compositor, "clip_in": clip_start, "clip_out": clip_end } action = edit.move_compositor_action(data) action.do_edit()
def _show_defaults_length_error_dialog(): parent_window = gui.editor_window.window primary_txt = _("Clip too short for Auto Fades!") secondary_txt = _( "The Clip is too short to add the user set default fades on Compositor creation." ) dialogutils.info_message(primary_txt, secondary_txt, parent_window)
def _show_three_poimt_edit_not_defined(): primary_txt = _("3 point edit not defined!") secondary_txt = _( "You need to set Timeline Range using Mark In and Mark Out buttons\nto perform this edit." ) dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window)
def _gmic_clip_create_dialog_callback(dialog, response_id, data): if response_id != Gtk.ResponseType.ACCEPT: dialog.destroy() else: script_select, media_file_select = data script_file = script_select.get_filename() media_file = media_file_select.get_filename() dialog.destroy() if script_file == None or media_file == None: dialogutils.info_message( _("NOt all required files were defined"), _("Select all files asked for in dialog for succesful container clip creation." ), gui.editor_window.window) return container_clip_data = ContainerClipData(appconsts.CONTAINER_CLIP_GMIC, script_file, media_file) container_clip = GMicContainerClip( PROJECT().next_media_file_id, container_clip_data.get_unrendered_media_name(), container_clip_data) PROJECT().add_container_clip_media_object(container_clip) _update_gui_for_media_object_add()
def _tline_audio_sync_dialog_callback(dialog, response_id, data): if response_id != Gtk.ResponseType.ACCEPT: dialog.destroy() return dialog.destroy() sync_move_frames = _tline_sync_data.clip_tline_media_offset - _tline_sync_data.media_offset_frames over_in = _tline_sync_data.origin_clip_start_in_tline + sync_move_frames over_out = over_in + (_tline_sync_data.origin_clip.clip_out - _tline_sync_data.origin_clip.clip_in) + 1 # We're not not supporting case where clip would start before timeline start. if over_in < 0: primary_txt = _("Audio sync move not possible") secondary_txt = _("Clip starts ") + str(over_in) + _(" frames before timeline start if it is moved \nto be in audio sync with the specified clip.\n\n") + \ _("You need to move forward or shorten the clips in question to make the operation succeed.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return data = {"track":_tline_sync_data.origin_track, "over_in":over_in, "over_out":over_out, "selected_range_in":_tline_sync_data.origin_clip_index, "selected_range_out":_tline_sync_data.origin_clip_index, "move_edit_done_func":None} action = edit.overwrite_move_action(data) action.do_edit()
def _show_trimview_info(): editorpersistance.prefs.trim_view_message_shown = True editorpersistance.save() primary_txt = _("On some systems Trim View may update slowly") secondary_txt = _("<b>Trim View</b> works best with SSDs and relatively powerful processors.\n\n") + \ _("Select <b>'Trim View Off'</b> or<b>'Trim View Single Side Edits Only'</b> options\nif performance is not satisfactory.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window)
def _tline_audio_sync_dialog_callback(dialog, response_id, data): if response_id != Gtk.ResponseType.ACCEPT: dialog.destroy() return dialog.destroy() sync_move_frames = _tline_sync_data.clip_tline_media_offset - _tline_sync_data.media_offset_frames over_in = _tline_sync_data.origin_clip_start_in_tline + sync_move_frames over_out = over_in + (_tline_sync_data.origin_clip.clip_out - _tline_sync_data.origin_clip.clip_in) + 1 # We're not not supporting case where clip would start before timeline start. if over_in < 0: primary_txt = _("Audio sync move not possible") secondary_txt = _("Clip starts ") + str(over_in) + _(" frames before timeline start if it is moved \nto be in audio sync with the specified clip.\n\n") + \ _("You need to move forward or shorten the clips in question to make the operation succeed.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return data = { "track": _tline_sync_data.origin_track, "over_in": over_in, "over_out": over_out, "selected_range_in": _tline_sync_data.origin_clip_index, "selected_range_out": _tline_sync_data.origin_clip_index, "move_edit_done_func": None } action = edit.overwrite_move_action(data) action.do_edit()
def show_three_point_edit_not_defined(): primary_txt = _("3 point edit not defined!") secondary_txt = _( "You need to set Mark In and Mark Out on Timeline or Clip and\nadditional Mark In on Timeline or Clip to perform this edit." ) dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window)
def _ardour_export_dialog_callback(dialog, response_id, session_folder): if response_id != Gtk.ResponseType.ACCEPT: dialog.destroy() return folder_path = session_folder.get_filenames()[0] if not (os.listdir(folder_path) == []): dialog.destroy() primary_txt = _("Selected folder contains files") secondary_txt = _( "When exporting audio to Ardour, the selected folder\nhas to be empty." ) dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return # name = name_entry.get_text() dialog.destroy() xml_save_path = userfolders.get_cache_dir() + "ardour_export.xml" global _xml_render_player _xml_render_player = renderconsumer.XMLRenderPlayer( xml_save_path, _ardour_xml_render_done, None, PROJECT().c_seq, PROJECT(), PLAYER()) _xml_render_player.ardour_session_folder = folder_path _xml_render_player.start()
def _compositor_menu_item_activated(widget, data): action_id, compositor = data if action_id == "open in editor": compositeeditor.set_compositor(compositor) elif action_id == "delete": compositor.selected = False data = {"compositor": compositor} action = edit.delete_compositor_action(data) action.do_edit() elif action_id == "sync with origin": track = current_sequence().tracks[ compositor.transition. b_track] # b_track is source track where origin clip is origin_clip = None for clip in track.clips: if clip.id == compositor.origin_clip_id: origin_clip = clip if origin_clip == None: dialogutils.info_message( _("Origin clip not found!"), _("Clip used to create this Compositor has been removed\nor moved to different track." ), gui.editor_window.window) return clip_index = track.clips.index(origin_clip) clip_start = track.clip_start(clip_index) clip_end = clip_start + origin_clip.clip_out - origin_clip.clip_in data = { "compositor": compositor, "clip_in": clip_start, "clip_out": clip_end } action = edit.move_compositor_action(data) action.do_edit()
def _save_as_dialog_callback(dialog, response_id): if response_id == Gtk.ResponseType.ACCEPT: filenames = dialog.get_filenames() dialog.destroy() target_project.last_save_path = filenames[0] target_project.name = os.path.basename(filenames[0]) # Test that saving is not IOError try: filehandle = open(target_project.last_save_path, 'w') filehandle.close() except IOError as ioe: primary_txt = "I/O error({0})".format(ioe.errno) secondary_txt = ioe.strerror + "." dialogutils.warning_message(primary_txt, secondary_txt, linker_window, is_info=False) return # Relink and save _relink_project_media_paths() persistance.save_project(target_project, target_project.last_save_path) dialogutils.info_message( _("Relinked version of the Project saved!"), _("To test the project, close this tool and open the relinked version in Flowblade." ), linker_window) else: dialog.destroy()
def _compositor_menu_item_activated(widget, data): action_id, compositor = data if action_id == "open in editor": compositeeditor.set_compositor(compositor) elif action_id == "delete": compositor.selected = False data = {"compositor":compositor} action = edit.delete_compositor_action(data) action.do_edit() elif action_id == "sync with origin": track = current_sequence().tracks[compositor.transition.b_track] # b_track is source track where origin clip is origin_clip = None for clip in track.clips: if clip.id == compositor.origin_clip_id: origin_clip = clip if origin_clip == None: dialogutils.info_message(_("Origin clip not found!"), _("Clip used to create this Compositor has been removed\nor moved to different track."), gui.editor_window.window) return clip_index = track.clips.index(origin_clip) clip_start = track.clip_start(clip_index) clip_end = clip_start + origin_clip.clip_out - origin_clip.clip_in data = {"compositor":compositor,"clip_in":clip_start,"clip_out":clip_end} action = edit.move_compositor_action(data) action.do_edit()
def _cover_blank_from_next(data, called_from_next_clip=False): clip, track, item_id, item_data = data if not called_from_next_clip: clip_index = movemodes.selected_range_out + 1 blank_index = movemodes.selected_range_in if clip_index < 0: # we are not getting a legal clip index return cover_clip = track.clips[clip_index] else: clip_index = track.clips.index(clip) + 1 blank_index = clip_index - 1 cover_clip = track.clips[clip_index] # Check that clip covers blank area total_length = 0 for i in range(movemodes.selected_range_in, movemodes.selected_range_out + 1): total_length += track.clips[i].clip_length() if total_length > cover_clip.clip_in: # handle not long enough to cover blanks primary_txt = _( "Next clip does not have enough material to cover blank area") secondary_txt = _("Requested edit can't be done.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return # Do edit movemodes.clear_selected_clips() data = {"track": track, "clip": cover_clip, "blank_index": blank_index} action = edit.trim_start_over_blanks(data) action.do_edit()
def _save_as_dialog_callback(dialog, response_id): if response_id == Gtk.ResponseType.ACCEPT: filenames = dialog.get_filenames() dialog.destroy() target_project.last_save_path = filenames[0] target_project.name = os.path.basename(filenames[0]) # Test that saving is not IOError try: filehandle = open( target_project.last_save_path, 'w' ) filehandle.close() except IOError as ioe: primary_txt = "I/O error({0})".format(ioe.errno) secondary_txt = ioe.strerror + "." dialogutils.warning_message(primary_txt, secondary_txt, linker_window, is_info=False) return # Relink and save _relink_project_media_paths() persistance.save_project(target_project, target_project.last_save_path) dialogutils.info_message(_("Relinked version of the Project saved!"), _("To test the project, close this tool and open the relinked version in Flowblade."), linker_window) else: dialog.destroy()
def _cover_blank_from_prev(data): clip, track, item_id, item_data = data clip_index = movemodes.selected_range_in - 1 if clip_index < 0: # we're not getting legal clip index return cover_clip = track.clips[clip_index] # Check that clip covers blank area total_length = 0 for i in range(movemodes.selected_range_in, movemodes.selected_range_out + 1): total_length += track.clips[i].clip_length() clip_handle = cover_clip.get_length() - cover_clip.clip_out - 1 if total_length > clip_handle: # handle not long enough to cover blanks primary_txt = _( "Previous clip does not have enough material to cover blank area") secondary_txt = _("Requested edit can't be done.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return # Do edit movemodes.clear_selected_clips() data = {"track": track, "clip": cover_clip, "clip_index": clip_index} action = edit.trim_end_over_blanks(data) action.do_edit()
def _check_transition_handles(from_req, from_handle, to_req, to_handle, length): if from_req > from_handle or to_req > to_handle: SPACE_TAB = " " info_text = _("To create a rendered transition you need enough media overlap from both clips!\n\n") if from_req > from_handle: info_text = info_text + \ _("More media overlap needed from <b>first</b> clip:\n\n") + \ SPACE_TAB + _("<b>Available:</b> ") + str(from_handle) + _(" frame(s)\n") + \ SPACE_TAB + _("<b>Required:</b> ") + str(from_req) + _(" frame(s)\n\n") + \ SPACE_TAB + _("Cut ") + str(from_req - from_handle) + _(" frame(s) from the <b>end</b> of first clip.") if to_req > to_handle: info_text = info_text + "\n\n" info_text = info_text + \ _("More media overlap needed from <b>second</b> clip:\n\n") + \ SPACE_TAB + _("<b>Available:</b> ") + str(to_handle) + _(" frame(s)\n") + \ SPACE_TAB + _("<b>Required:</b> ") + str(to_req) + _(" frame(s)\n\n") + \ SPACE_TAB + _("Cut ") + str(to_req - to_handle) + _(" frame(s) from the <b>beginning</b> of the second clip.") dialogutils.info_message(_("More media overlap needed to create transition!"), info_text, gui.editor_window.window) return False return True
def quick_reference(): try: url = "file://" + respaths.HELP_DOC print(url) #webbrowser.open('http://code.google.com/p/flowblade/wiki/FlowbladeReference') webbrowser.open(url) except: dialogutils.info_message(_("Help page not found!"), _("Unfortunately the webresource containing help information\nfor this application was not found."), None)
def quick_reference(): try: url = "file://" + respaths.HELP_DOC print url #webbrowser.open('http://code.google.com/p/flowblade/wiki/FlowbladeReference') webbrowser.open(url) except: dialogutils.info_message(_("Help page not found!"), _("Unfortunately the webresource containing help information\nfor this application was not found."), None)
def _add_image_sequence_callback(dialog, response_id, data): if response_id == Gtk.ResponseType.CANCEL: dialog.destroy() return file_chooser, spin = data frame_file = file_chooser.get_filename() dialog.destroy() if frame_file == None: dialogutils.info_message(_("No file was selected"), _("Select a numbered file to add an Image Sequence to Project."), gui.editor_window.window) return (folder, file_name) = os.path.split(frame_file) try: number_parts = re.findall("[0-9]+", file_name) number_part = number_parts[-1] # we want the last number part except: dialogutils.info_message(_("Not a sequence file!"), _("Selected file does not have a number part in it,\nso it can't be an image sequence file."), gui.editor_window.window) return # Create resource name with MLT syntax for MLT producer number_index = file_name.find(number_part) path_name_part = file_name[0:number_index] end_part = file_name[number_index + len(number_part):len(file_name)] # The better version with "?begin=xxx" only available after 0.8.7 if editorstate.mlt_version_is_equal_or_greater("0.8.5"): resource_name_str = utils.get_img_seq_resource_name(frame_file, True) else: resource_name_str = utils.get_img_seq_resource_name(frame_file, False) # detect highest file # FIX: this fails if two similarily numbered sequences in same dir and both have same substring in frame name onlyfiles = [ f for f in listdir(folder) if isfile(join(folder,f)) ] highest_number_part = int(number_part) for f in onlyfiles: try: file_number_part = int(re.findall("[0-9]+", f)[-1]) # -1, we want the last number part except: continue if f.find(path_name_part) == -1: continue if file_number_part > highest_number_part: highest_number_part = file_number_part dialog.destroy() resource_path = folder + "/" + resource_name_str length = highest_number_part - int(number_part) PROJECT().add_image_sequence_media_object(resource_path, file_name + "(img_seq)", length) gui.media_list_view.fill_data_model() gui.bin_list_view.fill_data_model() editorpersistance.prefs.last_opened_media_dir = os.path.dirname(resource_path) editorpersistance.save()
def quick_reference(): try: url = "file://" + respaths.HELP_DOC webbrowser.open(url) except: dialogutils.info_message( _("Help page not found!"), _("Unfortunately the webresource containing help information\nfor this application was not found." ), None)
def three_point_overwrite_pressed(): # Check that state is good for edit if movemodes.selected_track == -1: primary_txt = _("No Clips are selected!") secondary_txt = _( "You need to select clips to overwrite to perform this edit.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return # Get data track = get_track(movemodes.selected_track) if editevent.track_lock_check_and_user_info(track, three_point_overwrite_pressed, "3 point overwrite"): return range_start_frame = track.clip_start(movemodes.selected_range_in) out_clip = track.clips[movemodes.selected_range_out] out_start = track.clip_start(movemodes.selected_range_out) range_end_frame = out_start + out_clip.clip_out - out_clip.clip_in range_length = range_end_frame - range_start_frame + 1 # calculated end is incl. over_clip = _get_new_clip_from_clip_monitor() if over_clip == None: no_monitor_clip_info(gui.editor_window.window) return over_length = over_clip.mark_out - over_clip.mark_in + 1 # + 1 out incl ?????????? what if over_clip.mark_out == -1 ?????????? if over_length < range_length: monitor_clip_too_short(gui.editor_window.window) return over_clip_out = over_clip.mark_in + range_length - 1 # -1 out incl range_in = movemodes.selected_range_in range_out = movemodes.selected_range_out movemodes.clear_selected_clips() # edit consumes selection updater.save_monitor_frame = False # hack to not get wrong value saved in MediaFile.current_frame data = { "track": track, "clip": over_clip, "clip_in": over_clip.mark_in, "clip_out": over_clip_out, "in_index": range_in, "out_index": range_out } action = edit.three_point_overwrite_action(data) action.do_edit() if not editorstate.timeline_visible(): updater.display_sequence_in_monitor() updater.display_tline_cut_frame(track, range_in)
def _show_failed_environment_info(): primary_txt = "Environment detection failed!" secondary_txt = "You will probably be presented with filters, transitions\nand rendering options that are not available on your system." + \ "\n---\nYou may experience sudden crashes when adding filters or\nattempting rendering." + \ "\n---\nYour MLT Version is: "+ editorstate.mlt_version + "\n" + \ "Only report this as a bug if the MLT version above is >= 0.7.6." dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return False
def _preferences_dialog_callback(dialog, response_id, all_widgets): if response_id == Gtk.ResponseType.ACCEPT: editorpersistance.update_prefs_from_widgets(all_widgets) editorpersistance.save() dialog.destroy() primary_txt = _("Restart required for some setting changes to take effect.") secondary_txt = _("If requested change is not in effect, restart application.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return dialog.destroy()
def open_recent_project(widget, index): path = editorpersistance.recent_projects.projects[index] if not os.path.exists(path): editorpersistance.recent_projects.projects.pop(index) editorpersistance.fill_recents_menu_widget(gui.editor_window.uimanager.get_widget('/MenuBar/FileMenu/OpenRecent'), open_recent_project) primary_txt = _("Project not found on disk") secondary_txt = _("Project can't be loaded.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return actually_load_project(path)
def splice_out_button_pressed(): """ Removes 1 - n long continuous clip range from track and closes the created gap. """ if movemodes.selected_track == -1: return # Edit consumes selection, so clear selected from clips movemodes.set_range_selection(movemodes.selected_track, movemodes.selected_range_in, movemodes.selected_range_out, False) track = get_track(movemodes.selected_track) if editevent.track_lock_check_and_user_info(track, splice_out_button_pressed, "splice out"): movemodes.clear_selection_values() return # A single clip delete can trigger a special clip cover delete # See if such delete should be attempted. # Exit if done succesfully, do normal splice out and report if failed cover_delete_failed = False if editorpersistance.prefs.trans_cover_delete == True: if movemodes.selected_range_out == movemodes.selected_range_in: clip = track.clips[movemodes.selected_range_in] if hasattr(clip, "rendered_type") and ( track.id >= current_sequence().first_video_index): cover_delete_success = _attempt_clip_cover_delete( clip, track, movemodes.selected_range_in) if cover_delete_success: return # A successful cover delete happened else: cover_delete_failed = True # A successful cover delete failed, do normal delete and gove info # Do delete data = { "track": track, "from_index": movemodes.selected_range_in, "to_index": movemodes.selected_range_out } edit_action = edit.remove_multiple_action(data) edit_action.do_edit() _splice_out_done_update() if cover_delete_failed == True: dialogutils.info_message( _("Fade/Transition cover delete failed!"), _("There wasn't enough material available in adjacent clips.\nA normal Splice Out was done instead." ), gui.editor_window.window)
def launch_gmic(): if _gmic_found == False: primary_txt = _("G'Mic not found!") secondary_txt = _("G'Mic binary was not present at <b>/usr/bin/gmic</b>.\nInstall G'MIC to use this tool.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return print "Launch gmic..." gui.save_current_colors() FLOG = open(utils.get_hidden_user_dir_path() + "log_gmic", 'w') subprocess.Popen([sys.executable, respaths.LAUNCH_DIR + "flowbladegmic"], stdin=FLOG, stdout=FLOG, stderr=FLOG)
def range_overwrite_pressed(): # Get data track = current_sequence().get_first_active_track() if editevent.track_lock_check_and_user_info(track, range_overwrite_pressed, "range overwrite"): return # tractor is has mark in and mark mark_in_frame = current_sequence().tractor.mark_in mark_out_frame = current_sequence().tractor.mark_out range_length = mark_out_frame - mark_in_frame + 1 # end is incl. if mark_in_frame == -1 or mark_out_frame == -1: primary_txt = _("Timeline Range not set!") secondary_txt = _( "You need to set Timeline Range using Mark In and Mark Out buttons\nto perform this edit." ) dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return # Get over clip and check it overwrite range area over_clip = _get_new_clip_from_clip_monitor() if over_clip == None: no_monitor_clip_info(gui.editor_window.window) return over_length = over_clip.mark_out - over_clip.mark_in + 1 # + 1 out incl if over_length < range_length: monitor_clip_too_short(gui.editor_window.window) return over_clip_out = over_clip.mark_in + range_length - 1 movemodes.clear_selected_clips() # edit consumes selection updater.save_monitor_frame = False # hack to not get wrong value saved in MediaFile.current_frame data = { "track": track, "clip": over_clip, "clip_in": over_clip.mark_in, "clip_out": over_clip_out, "mark_in_frame": mark_in_frame, "mark_out_frame": mark_out_frame + 1 } # +1 because mark is displayed and end of frame end this # confirms to user expectation of # of how this should work action = edit.range_overwrite_action(data) action.do_edit() updater.display_tline_cut_frame(track, track.get_clip_index_at(mark_in_frame))
def shutdown(): if queue_runner_thread != None: primary_txt = _("Application is rendering and cannot be closed!") secondary_txt = _("Stop rendering before closing the application.") dialogutils.info_message(primary_txt, secondary_txt, batch_window.window) return True # Tell callsite (inside GTK toolkit) that event is handled, otherwise it'll destroy window anyway. while(Gtk.events_pending()): Gtk.main_iteration() if _dbus_service != None: _dbus_service.remove_from_dbus() Gtk.main_quit()
def shutdown(): if queue_runner_thread != None: primary_txt = _("Application is rendering and cannot be closed!") secondary_txt = _("Stop rendering before closing the application.") dialogutils.info_message(primary_txt, secondary_txt, batch_window.window) return True # Tell callsite (inside GTK toolkit) that event is handled, otherwise it'll destroy window anyway. while (gtk.events_pending()): gtk.main_iteration() if _dbus_service != None: _dbus_service.remove_from_dbus() gtk.main_quit()
def launch_natron_animations_tool(): if _natron_found == False: primary_txt = _("Natron not found!") secondary_txt = _("Natron was not present in the system.") # TODO: more info dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return gui.save_current_colors() current_profile_name = PROJECT().profile.description().replace(" ", "_") print current_profile_name print "Launch Natron tool..." FLOG = open(utils.get_hidden_user_dir_path() + "log_natron_tool", 'w') subprocess.Popen([sys.executable, respaths.LAUNCH_DIR + "flowbladenatron", current_profile_name], stdin=FLOG, stdout=FLOG, stderr=FLOG)
def show_titler(): global _titler_data if _titler_data == None: _titler_data = TitlerData() global _titler if _titler != None: primary_txt = _("Titler is already open") secondary_txt = _("Only single instance of Titler can be opened.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return _titler = Titler() _titler.load_titler_data() _titler.show_current_frame()
def three_point_overwrite_pressed(): # Check that state is good for edit if movemodes.selected_track == -1: primary_txt = _("No Clips are selected!") secondary_txt = _("You need to select clips to overwrite to perform this edit.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return # Get data track = get_track(movemodes.selected_track) if editevent.track_lock_check_and_user_info(track, three_point_overwrite_pressed, "3 point overwrite"): return range_start_frame = track.clip_start(movemodes.selected_range_in) out_clip = track.clips[movemodes.selected_range_out] out_start = track.clip_start(movemodes.selected_range_out) range_end_frame = out_start + out_clip.clip_out - out_clip.clip_in range_length = range_end_frame - range_start_frame + 1 # calculated end is incl. over_clip = _get_new_clip_from_clip_monitor() if over_clip == None: no_monitor_clip_info(gui.editor_window.window) return over_length = over_clip.mark_out - over_clip.mark_in + 1 # + 1 out incl ?????????? what if over_clip.mark_out == -1 ?????????? if over_length < range_length: monitor_clip_too_short(gui.editor_window.window) return over_clip_out = over_clip.mark_in + range_length - 1 # -1 out incl range_in = movemodes.selected_range_in range_out = movemodes.selected_range_out movemodes.clear_selected_clips() # edit consumes selection updater.save_monitor_frame = False # hack to not get wrong value saved in MediaFile.current_frame data = {"track":track, "clip":over_clip, "clip_in":over_clip.mark_in, "clip_out":over_clip_out, "in_index":range_in, "out_index":range_out} action = edit.three_point_overwrite_action(data) action.do_edit() updater.display_tline_cut_frame(track, range_in)
def screenshot_export(): length = current_sequence().tractor.get_length() if length < 2: dialogutils.info_message(_("Sequence is too short"), _("Sequence needs to be at least 2 frames long to allow frame export."), None) return frame = PLAYER().current_frame() # Can't get last frame to render easily, so just force range. if frame > length - 2: frame = length - 2 render_screen_shot(frame, get_displayed_image_render_path(), "png") export_screenshot_dialog(_export_screenshot_dialog_callback, frame, gui.editor_window.window, PROJECT().name) PLAYER().seek_frame(frame)
def screenshot_export(): length = current_sequence().tractor.get_length() if length < 2: dialogutils.info_message("Sequence is too short", "Sequence needs to be at least 2 frames long to allow frame export.", None) return frame = PLAYER().current_frame() # Can't get last frame to render easily, so just force range. if frame > length - 2: frame = length - 2 render_screen_shot(frame, get_displayed_image_render_path(), "png") export_screenshot_dialog(_export_screenshot_dialog_callback, frame, gui.editor_window.window, PROJECT().name) PLAYER().seek_frame(frame)
def splice_out_button_pressed(): """ Removes 1 - n long continuous clip range from track and closes the created gap. """ if movemodes.selected_track == -1: return # Edit consumes selection, so clear selected from clips movemodes.set_range_selection(movemodes.selected_track, movemodes.selected_range_in, movemodes.selected_range_out, False) track = get_track(movemodes.selected_track) if editevent.track_lock_check_and_user_info(track, splice_out_button_pressed, "splice out"): movemodes.clear_selection_values() return # A single clip delete can trigger a special clip cover delete # See if such delete should be attempted. # Exit if done succesfully, do normal splice out and report if failed cover_delete_failed = False if editorpersistance.prefs.trans_cover_delete == True: if movemodes.selected_range_out == movemodes.selected_range_in: clip = track.clips[movemodes.selected_range_in] if hasattr(clip, "rendered_type") and (track.id >= current_sequence().first_video_index): cover_delete_success = _attempt_clip_cover_delete(clip, track, movemodes.selected_range_in) if cover_delete_success: return # A successful cover delete happened else: cover_delete_failed = True # A successful cover delete failed, do normal delete and gove info # Do delete data = {"track":track, "from_index":movemodes.selected_range_in, "to_index":movemodes.selected_range_out} edit_action = edit.remove_multiple_action(data) edit_action.do_edit() _splice_out_done_update() if cover_delete_failed == True: dialogutils.info_message(_("Fade/Transition cover delete failed!"), _("There wasn't enough material available in adjacent clips.\nA normal Splice Out was done instead."), gui.editor_window.window)
def _save_as_dialog_callback(dialog, response_id): if response_id == gtk.RESPONSE_ACCEPT: filenames = dialog.get_filenames() dialog.destroy() target_project.last_save_path = filenames[0] target_project.name = os.path.basename(filenames[0]) _relink_project_media_paths() persistance.save_project(target_project, target_project.last_save_path) dialogutils.info_message(_("Relinked version of the Project saved!"), _("To test the project, close this tool and open the relinked version in Flowblade."), linker_window) else: dialog.destroy()
def sync_compositor(compositor): track = current_sequence().tracks[compositor.transition.b_track] # b_track is source track where origin clip is origin_clip = None for clip in track.clips: if clip.id == compositor.origin_clip_id: origin_clip = clip if origin_clip == None: dialogutils.info_message(_("Origin clip not found!"), _("Clip used to create this Compositor has been removed\nor moved to different track."), gui.editor_window.window) return clip_index = track.clips.index(origin_clip) clip_start = track.clip_start(clip_index) clip_end = clip_start + origin_clip.clip_out - origin_clip.clip_in data = {"compositor":compositor,"clip_in":clip_start,"clip_out":clip_end} action = edit.move_compositor_action(data) action.do_edit()
def _save_as_dialog_callback(dialog, response_id): if response_id == Gtk.ResponseType.ACCEPT: filenames = dialog.get_filenames() dialog.destroy() target_project.last_save_path = filenames[0] target_project.name = os.path.basename(filenames[0]) _relink_project_media_paths() persistance.save_project(target_project, target_project.last_save_path) dialogutils.info_message(_("Relinked version of the Project saved!"), _("To test the project, close this tool and open the relinked version in Flowblade."), linker_window) else: dialog.destroy()
def range_overwrite_pressed(): # Get data track = current_sequence().get_first_active_track() if editevent.track_lock_check_and_user_info(track, range_overwrite_pressed, "range overwrite"): return # tractor is has mark in and mark mark_in_frame = current_sequence().tractor.mark_in mark_out_frame = current_sequence().tractor.mark_out range_length = mark_out_frame - mark_in_frame + 1 # end is incl. if mark_in_frame == -1 or mark_out_frame == -1: primary_txt = _("Timeline Range not set!") secondary_txt = _("You need to set Timeline Range using Mark In and Mark Out buttons\nto perform this edit.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return # Get over clip and check it overwrite range area over_clip = _get_new_clip_from_clip_monitor() if over_clip == None: no_monitor_clip_info(gui.editor_window.window) return over_length = over_clip.mark_out - over_clip.mark_in + 1 # + 1 out incl if over_length < range_length: monitor_clip_too_short(gui.editor_window.window) return over_clip_out = over_clip.mark_in + range_length - 1 movemodes.clear_selected_clips() # edit consumes selection updater.save_monitor_frame = False # hack to not get wrong value saved in MediaFile.current_frame data = {"track":track, "clip":over_clip, "clip_in":over_clip.mark_in, "clip_out":over_clip_out, "mark_in_frame":mark_in_frame, "mark_out_frame":mark_out_frame + 1} # +1 because mark is displayed and end of frame end this # confirms to user expectation of # of how this should work action = edit.range_overwrite_action(data) action.do_edit() updater.display_tline_cut_frame(track, track.get_clip_index_at(mark_in_frame))
def _save_backup_snapshot_dialog_callback(dialog, response_id, project_folder, name_entry): if response_id == Gtk.ResponseType.ACCEPT: root_path = project_folder.get_filenames()[0] if not (os.listdir(root_path) == []): dialog.destroy() primary_txt = _("Selected folder contains files") secondary_txt = _("When saving a back-up snapshot of the project, the selected folder\nhas to be empty.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return name = name_entry.get_text() dialog.destroy() GLib.idle_add(lambda : _do_snapshot_save(root_path + "/", name)) else: dialog.destroy()
def _duplicates_info(duplicates): primary_txt = _("Media files already present in project were opened!") MAX_DISPLAYED_ITEMS = 3 items = MAX_DISPLAYED_ITEMS if len(duplicates) < MAX_DISPLAYED_ITEMS: items = len(duplicates) secondary_txt = _("Files already present:\n\n") for i in range(0, items): secondary_txt = secondary_txt + "<b>" + duplicates[i] + "</b>" + "\n" if len(duplicates) > MAX_DISPLAYED_ITEMS: secondary_txt = secondary_txt + "\n" + "and " + str(len(duplicates) - MAX_DISPLAYED_ITEMS) + " other items.\n" secondary_txt = secondary_txt + "\nNo duplicate media items were added to project." dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return False
def _check_transition_handles(from_req, from_handle, to_req, to_handle): if from_req > from_handle: info_text = _("There is not enough material available in the FROM clip after the cut") + \ _("\nto create the transition.\n\n") + \ _("<b>Available:</b> ") + str(from_handle) + _(" frame(s)\n") + \ _("<b>Required:</b> ") + str(from_req) + _(" frame(s)") dialogutils.info_message(_("FROM Clip Handle is too short!"), info_text, gui.editor_window.window) return False if to_req > to_handle: info_text = _("There is not enough material available in the TO clip before the cut") + \ _("\nto create the transition.\n\n") + \ _("<b>Available:</b> ") + str(to_handle) + _(" frame(s)\n") + \ _("<b>Required:</b> ") + str(to_req) + _(" frame(s)") dialogutils.info_message(_("TO Clip Handle is too short!"), info_text, gui.editor_window.window) return False return True
def _save_profile_clicked(widgets, user_profiles_view): load_profile_combo, description, f_rate_num, f_rate_dem, width, height, \ s_rate_num, s_rate_dem, d_rate_num, d_rate_dem, progressive = widgets profile_file_name = description.get_text().lower().replace(os.sep, "_").replace(" ","_") file_contents = "description=" + description.get_text() + "\n" file_contents += "frame_rate_num=" + f_rate_num.get_text() + "\n" file_contents += "frame_rate_den=" + f_rate_dem.get_text() + "\n" file_contents += "width=" + width.get_text() + "\n" file_contents += "height=" + height.get_text() + "\n" if progressive.get_active() == True: prog_val = "1" else: prog_val = "0" file_contents += "progressive=" + prog_val + "\n" file_contents += "sample_aspect_num=" + s_rate_num.get_text() + "\n" file_contents += "sample_aspect_den=" + s_rate_dem.get_text() + "\n" file_contents += "display_aspect_num=" + d_rate_num.get_text() + "\n" file_contents += "display_aspect_den=" + d_rate_dem.get_text() + "\n" profile_path = utils.get_hidden_user_dir_path() + mltprofiles.USER_PROFILES_DIR + profile_file_name if os.path.exists(profile_path): dialogutils.warning_message(_("Profile '") + description.get_text() + _("' already exists!"), \ _("Delete profile and save again."), gui.editor_window.window) return profile_file = open(profile_path, "w") profile_file.write(file_contents) profile_file.close() dialogutils.info_message(_("Profile '") + description.get_text() + _("' saved."), \ _("You can now create a new project using the new profile."), gui.editor_window.window) mltprofiles.load_profile_list() render.reload_profiles() user_profiles_view.fill_data_model(mltprofiles.get_user_profiles())
def _cover_blank_from_prev(data): clip, track, item_id, item_data = data clip_index = movemodes.selected_range_in - 1 if clip_index < 0: # we're not getting legal clip index return cover_clip = track.clips[clip_index] # Check that clip covers blank area total_length = 0 for i in range(movemodes.selected_range_in, movemodes.selected_range_out + 1): total_length += track.clips[i].clip_length() clip_handle = cover_clip.get_length() - cover_clip.clip_out - 1 if total_length > clip_handle: # handle not long enough to cover blanks primary_txt = _("Previous clip does not have enough material to cover blank area") secondary_txt = _("Requested edit can't be done.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return # Do edit movemodes.clear_selected_clips() data = {"track":track, "clip":cover_clip, "clip_index":clip_index} action = edit.trim_end_over_blanks(data) action.do_edit()
def set_oneroll_mode(track, current_frame=-1, editing_to_clip=None): """ Sets one roll mode """ if track == None: return False if track.id < 1 or (track.id >= len(current_sequence().tracks) - 1): return False if current_frame == -1: # from button, ctrl + mouse calls with frame current_frame = PLAYER().producer.frame() + 1 # +1 because cut frame selects previous clip if current_frame >= track.get_length(): return False edit_frame, to_side_being_edited = _get_trim_edit(track, current_frame) if edit_frame == -1: return False # hack fix for last clip out trim. If frame pointer not at very end of clip # the other functions for getting trim frame given +1 too much if edit_frame > track.get_length(): edit_frame = track.get_length() if editing_to_clip != None: # This is set when mode reset after edit or after undo or redo # _get_trim_edit() might give different(wrong) clip being edited # because cut is now at a different place. to_side_being_edited = editing_to_clip _set_edit_data(track, edit_frame, True) global edit_data # Set side being edited to default to-side edit_data["to_side_being_edited"] = to_side_being_edited current_sequence().clear_hidden_track() # Cant't trim a blank clip. Blank clips are special in MLT and can't be # made to do things that are needed in trim. if _trimmed_clip_is_blank(): set_exit_mode_func() primary_txt = _("Cant ONE ROLL TRIM blank clips.") secondary_txt = _("You can use MOVE OVERWRITE or TWO ROLL TRIM edits instead\nto get the desired change.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window) return False # Give timeline widget needed data tlinewidgets.set_edit_mode(edit_data, tlinewidgets.draw_one_roll_overlay) # Set clip as special producer on hidden track and display current frame # from it. trim_limits = edit_data["trim_limits"] if edit_data["to_side_being_edited"]: clip = edit_data["to_clip"] clip_start = trim_limits["to_start"] else: clip = edit_data["from_clip"] clip_start = trim_limits["from_start"] # Display trim clip if clip.media_type != appconsts.PATTERN_PRODUCER: current_sequence().display_trim_clip(clip.path, clip_start) # file producer else: current_sequence().display_trim_clip(None, clip_start, clip.create_data) # pattern producer PLAYER().seek_frame(edit_frame) return True
def _tworoll_init_failed_window(): primary_txt = _("Initializing TWO ROLL TRIM failed") secondary_txt = _("You are attempting TWO ROLL TRIM at a position in the timeline\nwhere it can't be performed.") dialogutils.info_message(primary_txt, secondary_txt, gui.editor_window.window)
def _show_length_error_dialog(): parent_window = gui.editor_window.window primary_txt = _("Clip too short!") secondary_txt = _("The Clip is too short to add the requested fade.") dialogutils.info_message(primary_txt, secondary_txt, parent_window)
def _show_defaults_length_error_dialog(): parent_window = gui.editor_window.window primary_txt = _("Clip too short for Auto Fades!") secondary_txt = _("The Clip is too short to add the user set default fades on Compositor creation.") dialogutils.info_message(primary_txt, secondary_txt, parent_window)