def get_args_vals_list_for_current_selections(): profile = get_current_profile() encoding_option_index = widgets.encoding_panel.encoding_selector.widget.get_active() quality_option_index = widgets.encoding_panel.quality_selector.widget.get_active() if widgets.render_type_panel.type_combo.get_active() == 1: # Preset encodings -1) encoding_option = renderconsumer.non_user_encodings[widgets.render_type_panel.presets_selector.widget.get_active()] args_vals_list = encoding_option.get_args_vals_tuples_list(profile) elif widgets.args_panel.use_args_check.get_active() == False: # User encodings args_vals_list = renderconsumer.get_args_vals_tuples_list_for_encoding_and_quality( profile, encoding_option_index, quality_option_index) args_vals_list.append(("ar", str(widgets.encoding_panel.sample_rate_selector.get_selected_rate()))) else: # Manual args encodings if widgets.args_panel.text_buffer == None: # Normal height args panel buf = widgets.args_panel.opts_view.get_buffer() else: # Small heights with dialog for setting args buf = widgets.args_panel.text_buffer args_vals_list, error = renderconsumer.get_ffmpeg_opts_args_vals_tuples_list(buf) if error != None: dialogutils.warning_message("FFMPeg Args Error", error, gui.editor_window.window) return None return args_vals_list
def delete_selected_bin(): """ Deletes current bin if it's empty and at least one will be left. """ if len(current_bin().file_ids) != 0: dialogutils.warning_message(_("Can't remove a non-empty bin"), _("You must remove all files from the bin before deleting it."), gui.editor_window.window) return # Get iter and index for (current) selected bin selection = gui.bin_list_view.treeview.get_selection() model, iter = selection.get_selected() if len(model) < 2: dialogutils.warning_message(_("Can't remove last bin"), _("There must always exist at least one bin."), gui.editor_window.window) return (model, rows) = selection.get_selected_rows() row = max(rows[0]) # Remove from gui and project data model.remove(iter) PROJECT().bins.pop(row) # Set first bin selected, listener 'bin_selection_changed' updates editorstate.project.c_bin selection.select_path("0") _enable_save()
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 launch_render(self): same_paths = render_queue.check_for_same_paths() if len(same_paths) > 0: primary_txt = _("Multiple items with same render target file!") secondary_txt = _("Later items will render on top of earlier items if this queue is rendered.\n") + \ _("Delete or unqueue some items with same paths:\n\n") for k,v in same_paths.iteritems(): secondary_txt = secondary_txt + str(v) + _(" items with path: ") + str(k) + "\n" dialogutils.warning_message(primary_txt, secondary_txt, batch_window.window) return # GUI pattern for rendering self.render_button.set_sensitive(False) self.reload_button.set_sensitive(False) self.stop_render_button.set_sensitive(True) self.est_time_left.set_text("") self.items_rendered.set_text("") start_time = datetime.datetime.now() start_str = start_time.strftime(' %H:%M, %d %B, %Y') self.render_started_label.set_text(start_str) self.remove_selected.set_sensitive(False) self.remove_finished.set_sensitive(False) global queue_runner_thread queue_runner_thread = QueueRunnerThread() queue_runner_thread.start()
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 copy_project(render_item, file_name): try: shutil.copyfile(render_item.get_project_filepath(), file_name) except Exception as e: primary_txt = _("Render Item Project File Copy failed!") secondary_txt = _("Error message: ") + str(e) dialogutils.warning_message(primary_txt, secondary_txt, batch_window.window)
def _shutdown_dialog_callback(dialog, response_id): dialog.destroy() if response_id == Gtk.ResponseType.CLOSE:# "Don't Save" pass elif response_id == Gtk.ResponseType.YES:# "Save" if editorstate.PROJECT().last_save_path != None: persistance.save_project(editorstate.PROJECT(), editorstate.PROJECT().last_save_path) else: dialogutils.warning_message(_("Project has not been saved previously"), _("Save project with File -> Save As before closing."), gui.editor_window.window) return else: # "Cancel" return # --- APP SHUT DOWN --- # print "Exiting app..." # No more auto saving stop_autosave() # Save window dimensions on exit alloc = gui.editor_window.window.get_allocation() x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height editorpersistance.prefs.exit_allocation = (w, h) editorpersistance.prefs.app_v_paned_position = gui.editor_window.app_v_paned.get_position() editorpersistance.prefs.top_paned_position = gui.editor_window.top_paned.get_position() editorpersistance.prefs.mm_paned_position = gui.editor_window.mm_paned.get_position() editorpersistance.save() # Block reconnecting consumer before setting window not visible updater.player_refresh_enabled = False gui.editor_window.window.set_visible(False) # Close and destroy app when gtk finds time to do it after hiding window GLib.idle_add(_app_destroy)
def set_track_normal_height(track_index, is_retry=False): track = get_track(track_index) track.height = appconsts.TRACK_HEIGHT_NORMAL # Check that new height tracks can be displayed and cancel if not. new_h = current_sequence().get_tracks_height() allocation = gui.tline_canvas.widget.get_allocation() x, y, w, h = allocation.x, allocation.y, allocation.width, allocation.height if new_h > h and is_retry == False: current_paned_pos = gui.editor_window.app_v_paned.get_position() new_paned_pos = current_paned_pos - (new_h - h) - 5 gui.editor_window.app_v_paned.set_position(new_paned_pos) GObject.timeout_add(200, lambda: set_track_normal_height(track_index, True)) return False allocation = gui.tline_canvas.widget.get_allocation() x, y, w, h = allocation.x, allocation.y, allocation.width, allocation.height if new_h > h: track.height = appconsts.TRACK_HEIGHT_SMALL dialogutils.warning_message(_("Not enough vertical space on Timeline to expand track"), _("Maximize or resize application window to get more\nspace for tracks if possible."), gui.editor_window.window, True) return False tlinewidgets.set_ref_line_y(gui.tline_canvas.widget.get_allocation()) gui.tline_column.init_listeners() updater.repaint_tline() return False
def get_render_consumer(): file_path = get_file_path() if file_path == None: return None profile = get_current_profile() if widgets.render_type_panel.type_combo.get_active() == 1: # Preset encodings encoding_option = renderconsumer.non_user_encodings[ widgets.render_type_panel.presets_selector.widget.get_active() ] if encoding_option.type != "img_seq": consumer = renderconsumer.get_render_consumer_for_encoding(file_path, profile, encoding_option) else: # Image Sequence rendering consumers need to be created a bit differently consumer = renderconsumer.get_img_seq_render_consumer(file_path, profile, encoding_option) return consumer if widgets.args_panel.use_args_check.get_active() == False: # Using options comboboxes encoding_option_index = widgets.encoding_panel.encoding_selector.widget.get_active() quality_option_index = widgets.encoding_panel.quality_selector.widget.get_active() consumer = renderconsumer.get_render_consumer_for_encoding_and_quality( file_path, profile, encoding_option_index, quality_option_index ) else: buf = widgets.args_panel.opts_view.get_buffer() consumer, error = renderconsumer.get_render_consumer_for_text_buffer(file_path, profile, buf) if error != None: dialogutils.warning_message("FFMPeg Args Error", error, gui.editor_window.window) return None return consumer
def get_args_vals_list_for_current_selections(): profile = get_current_profile() encoding_option_index = widgets.encoding_panel.encoding_selector.widget.get_active( ) quality_option_index = widgets.encoding_panel.quality_selector.widget.get_active( ) if widgets.render_type_panel.type_combo.get_active( ) == 1: # Preset encodings args_vals_list = renderconsumer.get_args_vals_tuples_list_for_encoding_and_quality( profile, encoding_option_index, -1) elif widgets.args_panel.use_args_check.get_active( ) == False: # User encodings args_vals_list = renderconsumer.get_args_vals_tuples_list_for_encoding_and_quality( profile, encoding_option_index, quality_option_index) else: # Manual args encodings buf = widgets.args_panel.opts_view.get_buffer() args_vals_list, error = renderconsumer.get_ffmpeg_opts_args_vals_tuples_list( buf) if error != None: dialogutils.warning_message("FFMPeg Args Error", error, gui.editor_window.window) return None return args_vals_list
def no_good_rander_range_info(): primary_txt = _("Render range not defined!") secondary_txt = _( "Define render range using Mark In and Mark Out points\nor select range option 'Sequence length' to start rendering." ) dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window)
def _delete_confirm_callback(dialog, response_id): if response_id != Gtk.ResponseType.ACCEPT: dialog.destroy() return dialog.destroy() selection = gui.sequence_list_view.treeview.get_selection() model, iter = selection.get_selected() # Have to have one sequence. if len(model) < 2: dialogutils.warning_message(_("Can't remove last sequence"), _("There must always exist at least one sequence."), gui.editor_window.window) return (model, rows) = selection.get_selected_rows() row = max(rows[0]) current_index = PROJECT().sequences.index(current_sequence()) # Remove sequence from gui and project data model.remove(iter) PROJECT().sequences.pop(row) # If we deleted current sequence, open first sequence if row == current_index: app.change_current_sequence(0) _enable_save()
def _save_project_in_last_saved_path(): updater.set_info_icon(Gtk.STOCK_SAVE) try: persistance.save_project(PROJECT(), PROJECT().last_save_path) #<----- HERE except IOError as ioe: updater.set_info_icon(None) primary_txt = "I/O error({0})".format(ioe.errno) secondary_txt = ioe.strerror + "." dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window, is_info=False) return PROJECT().events.append( projectdata.ProjectEvent(projectdata.EVENT_SAVED, PROJECT().last_save_path)) global save_icon_remove_event_id save_icon_remove_event_id = GObject.timeout_add(500, remove_save_icon) global save_time save_time = time.clock() projectinfogui.update_project_info()
def launch_render(self): same_paths = render_queue.check_for_same_paths() if len(same_paths) > 0: primary_txt = _("Multiple items with same render target file!") secondary_txt = _("Later items will render on top of earlier items if this queue is rendered.\n") + \ _("Delete or unqueue some items with same paths:\n\n") for k, v in same_paths.iteritems(): secondary_txt = secondary_txt + str(v) + _( " items with path: ") + str(k) + "\n" dialogutils.warning_message(primary_txt, secondary_txt, batch_window.window) return # GUI pattern for rendering self.render_button.set_sensitive(False) self.reload_button.set_sensitive(False) self.stop_render_button.set_sensitive(True) self.est_time_left.set_text("") self.items_rendered.set_text("") start_time = datetime.datetime.now() start_str = start_time.strftime(' %H:%M, %d %B, %Y') self.render_started_label.set_text(start_str) self.remove_selected.set_sensitive(False) self.remove_finished.set_sensitive(False) global queue_runner_thread queue_runner_thread = QueueRunnerThread() queue_runner_thread.start()
def run(self): action_object = containeractions.get_action_object( self.container_clip_data) is_valid, err_msg = action_object.validate_program() time.sleep(0.5) # To make sure text is seen. Gdk.threads_enter() self.dialog.destroy() if is_valid == True: container_clip = ContainerClipMediaItem( PROJECT().next_media_file_id, self.container_clip_data.get_unrendered_media_name(), self.container_clip_data) PROJECT().add_container_clip_media_object(container_clip) _update_gui_for_media_object_add() else: primary_txt = _("G'Mic Container Clip Validation Error") dialogutils.warning_message(primary_txt, err_msg, gui.editor_window.window) Gdk.threads_leave()
def set_track_normal_height(track_index, is_retry=False): track = get_track(track_index) track.height = appconsts.TRACK_HEIGHT_NORMAL # Check that new height tracks can be displayed and cancel if not. new_h = current_sequence().get_tracks_height() allocation = gui.tline_canvas.widget.get_allocation() x, y, w, h = allocation.x, allocation.y, allocation.width, allocation.height if new_h > h and is_retry == False: current_paned_pos = gui.editor_window.app_v_paned.get_position() new_paned_pos = current_paned_pos - (new_h - h) - 5 gui.editor_window.app_v_paned.set_position(new_paned_pos) GObject.timeout_add(200, lambda: set_track_normal_height(track_index, True)) return False allocation = gui.tline_canvas.widget.get_allocation() x, y, w, h = allocation.x, allocation.y, allocation.width, allocation.height if new_h > h: track.height = appconsts.TRACK_HEIGHT_SMALL dialogutils.warning_message( _("Not enough vertical space on Timeline to expand track"), _("Maximize or resize application window to get more\nspace for tracks if possible." ), gui.editor_window.window, True) return False tlinewidgets.set_ref_line_y(gui.tline_canvas.widget.get_allocation()) gui.tline_column.init_listeners() updater.repaint_tline() return False
def main(root_path, force_launch=False): init_dirs_if_needed() gtk_version = "%s.%s.%s" % (Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()) editorstate.gtk_version = gtk_version try: editorstate.mlt_version = mlt.LIBMLT_VERSION except: editorstate.mlt_version = "0.0.99" # magic string for "not found" # Set paths. respaths.set_paths(root_path) # Load editor prefs and list of recent projects editorpersistance.load() # Init translations module with translations data translations.init_languages() translations.load_filters_translations() mlttransitions.init_module() # Init gtk threads Gdk.threads_init() Gdk.threads_enter() repo = mlt.Factory().init() # Set numeric locale to use "." as radix, MLT initilizes this to OS locale and this causes bugs locale.setlocale(locale.LC_NUMERIC, 'C') # Check for codecs and formats on the system mltenv.check_available_features(repo) renderconsumer.load_render_profiles() # Load filter and compositor descriptions from xml files. mltfilters.load_filters_xml(mltenv.services) mlttransitions.load_compositors_xml(mltenv.transitions) # Create list of available mlt profiles mltprofiles.load_profile_list() global render_queue render_queue = RenderQueue() render_queue.load_render_items() global batch_window batch_window = BatchRenderWindow() if render_queue.error_status != None: primary_txt = _("Error loading render queue items!") secondary_txt = _("Message:\n") + render_queue.get_error_status_message() dialogutils.warning_message(primary_txt, secondary_txt, batch_window.window) DBusGMainLoop(set_as_default=True) global _dbus_service _dbus_service = BatchRenderDBUSService() Gtk.main() Gdk.threads_leave()
def _display_no_audio_on_video_msg(track): dialogutils.warning_message( _("Can't put an audio clip on a video track."), _("Track ") + utils.get_track_name(track, current_sequence()) + _(" is a video track and can't display audio only material."), gui.editor_window.window, )
def show_warning(self, size_str): primary_txt = _("Disk Cache Size Exceeds Current Warning Level!") secondary_txt = _("Flowblade currently uses ") + size_str + _(" of disk space.") + "\n\n" + \ _("You can either delete saved data using dialog opened with <b>Edit->Disk Cache</b> or") + "\n" + \ _("change warning level in <b>Edit->Preferences 'General Options'</b> panel.") dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window, is_info=False)
def _shutdown_dialog_callback(dialog, response_id): dialog.destroy() if response_id == Gtk.ResponseType.CLOSE:# "Don't Save" pass elif response_id == Gtk.ResponseType.YES:# "Save" if editorstate.PROJECT().last_save_path != None: persistance.save_project(editorstate.PROJECT(), editorstate.PROJECT().last_save_path) else: dialogutils.warning_message(_("Project has not been saved previously"), _("Save project with File -> Save As before closing."), gui.editor_window.window) return else: # "Cancel" return # --- APP SHUT DOWN --- # print "Exiting app..." # Sep-2018 - SvdB - Stop wave form threads for thread_termination in threading.enumerate(): # We only terminate threads with a 'process', as these are launched # by the audiowaveformrenderer try: thread_termination.process.terminate() except: None # No more auto saving stop_autosave() # Save window dimensions on exit alloc = gui.editor_window.window.get_allocation() x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height editorpersistance.prefs.exit_allocation = (w, h) if gui.editor_window.window2 != None: alloc = gui.editor_window.window2.get_allocation() pos_x, pos_y = gui.editor_window.window2.get_position() editorpersistance.prefs.exit_allocation_window_2 = (alloc.width, alloc.height, pos_x, pos_y) editorpersistance.prefs.app_v_paned_position = gui.editor_window.app_v_paned.get_position() editorpersistance.prefs.top_paned_position = gui.editor_window.top_paned.get_position() try: # This fails if preference for top row layout changed, we just ignore saving these values then. if editorwindow.top_level_project_panel() == True: editorpersistance.prefs.mm_paned_position = 200 # This is not used until user sets preference to not have top level project panel else: editorpersistance.prefs.mm_paned_position = gui.editor_window.mm_paned.get_position() except: pass editorpersistance.save() # Block reconnecting consumer before setting window not visible updater.player_refresh_enabled = False gui.editor_window.window.set_visible(False) if gui.editor_window.window2 != None: gui.editor_window.window2.set_visible(False) # Close and destroy app when gtk finds time to do it after hiding window GLib.idle_add(_app_destroy)
def track_lock_check_and_user_info(track, calling_function="this ain't used anymore", actionname="this ain't used anymore"): if track.edit_freedom == appconsts.LOCKED: track_name = utils.get_track_name(track, current_sequence()) # No edits on locked tracks. primary_txt = _("Can't edit a locked track") secondary_txt = _("Track ") + track_name + _(" is locked. Unlock track to edit it.") dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window) return True return False
def reload_queue(self): global render_queue render_queue = RenderQueue() render_queue.load_render_items() if render_queue.error_status != None: primary_txt = _("Error loading render queue items!") secondary_txt = _("Message:\n") + render_queue.get_error_status_message() dialogutils.warning_message(primary_txt, secondary_txt, batch_window.window) return self.queue_view.fill_data_model(render_queue)
def _blender_clip_create_dialog_callback(dialog, response_id, data): dialog.destroy() if response_id != Gtk.ResponseType.ACCEPT: dialog.destroy() else: project_select = data[0] project_file = project_select.get_filename() dialog.destroy() if project_file == None: _show_not_all_data_info() return container_clip_data = ContainerClipData( appconsts.CONTAINER_CLIP_BLENDER, project_file, None) action_object = containeractions.get_action_object(container_clip_data) is_valid, err_msg = action_object.validate_program() if is_valid == False: primary_txt = _("Blender Container Clip Validation Error") dialogutils.warning_message(primary_txt, err_msg, gui.editor_window.window) return action_object.initialize_project( project_file) # blocks until info data written project_edit_info_path = userfolders.get_cache_dir( ) + "blender_container_projectinfo.json" if editorstate.app_running_from == editorstate.RUNNING_FROM_FLATPAK: project_edit_info_path = userfolders.get_user_home_cache_for_flatpak( ) + "blender_container_projectinfo.json" info_file = open(project_edit_info_path, "r") project_edit_info = json.load(info_file) length = int(project_edit_info["frame_end"]) - int( project_edit_info["frame_start"]) container_clip_data.data_slots["project_edit_info"] = project_edit_info container_clip_data.editable = True container_clip_data.unrendered_length = length blender_unrendered_media_image = respaths.IMAGE_PATH + "unrendered_blender.png" window_text = _("Creating Container for Blender Project") containeractions.create_unrendered_clip( length, blender_unrendered_media_image, container_clip_data, _blender_unredered_media_creation_complete, window_text)
def _track_is_locked(track): global drag_disabled if track.edit_freedom == appconsts.LOCKED: track_name = utils.get_track_name(track, current_sequence()) # No edits on locked tracks. primary_txt = _("Can't do edit on a locked track") secondary_txt = _("Track ") + track_name + _(" is locked. Unlock track to edit it.\n") dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window) drag_disabled = True return True return False
def render_timeline(): if len(widgets.file_panel.movie_name.get_text()) == 0: primary_txt = _("Render file name entry is empty") secondary_txt = _("You have to provide a name for the file to be rendered.") dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window) return if os.path.exists(get_file_path()): primary_txt = _("File: ") + get_file_path() + _(" already exists!") secondary_txt = _("Do you want to overwrite existing file?") dialogutils.warning_confirmation(_render_overwrite_confirm_callback, primary_txt, secondary_txt, gui.editor_window.window) else: _do_rendering()
def add_to_render_queue(): args_vals_list = render.get_args_vals_list_for_current_selections() render_path = render.get_file_path() # Get render start and end points if render.widgets.range_cb.get_active() == 0: start_frame = 0 end_frame = -1 # renders till finish else: start_frame = current_sequence().tractor.mark_in end_frame = current_sequence().tractor.mark_out # Only do if range defined. if start_frame == -1 or end_frame == -1: if render.widgets.range_cb.get_active() == 1: rendergui.no_good_rander_range_info() return # Create render data object if render.widgets.args_panel.use_args_check.get_active() == False: enc_index = render.widgets.encoding_panel.encoding_selector.widget.get_active( ) quality_index = render.widgets.encoding_panel.quality_selector.widget.get_active( ) user_args = False else: # This is not implemented enc_index = render.widgets.encoding_panel.encoding_selector.widget.get_active( ) quality_index = render.widgets.encoding_panel.quality_selector.widget.get_active( ) user_args = False profile = render.get_current_profile() profile_text = guicomponents.get_profile_info_text(profile) fps = profile.fps() profile_name = profile.description() r_data = batchrendering.RenderData(enc_index, quality_index, user_args, profile_text, profile_name, fps) # Add item try: batchrendering.add_render_item(PROJECT(), render_path, args_vals_list, start_frame, end_frame, r_data) except Exception as e: primary_txt = _("Adding item to render queue failed!") secondary_txt = _("Error message: ") + str(e) dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window, is_info=False) return
def reload_queue(self): global render_queue render_queue = RenderQueue() render_queue.load_render_items() if render_queue.error_status != None: primary_txt = _("Error loading render queue items!") secondary_txt = _( "Message:\n") + render_queue.get_error_status_message() dialogutils.warning_message(primary_txt, secondary_txt, batch_window.window) return self.queue_view.fill_data_model(render_queue)
def _shutdown_dialog_callback(dialog, response_id): dialog.destroy() if response_id == Gtk.ResponseType.CLOSE: # "Don't Save" pass elif response_id == Gtk.ResponseType.YES: # "Save" if editorstate.PROJECT().last_save_path != None: persistance.save_project(editorstate.PROJECT(), editorstate.PROJECT().last_save_path) else: dialogutils.warning_message( _("Project has not been saved previously"), _("Save project with File -> Save As before closing."), gui.editor_window.window) return else: # "Cancel" return # --- APP SHUT DOWN --- # print "Exiting app..." # No more auto saving stop_autosave() # Save window dimensions on exit alloc = gui.editor_window.window.get_allocation() x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height editorpersistance.prefs.exit_allocation = (w, h) if gui.editor_window.window2 != None: alloc = gui.editor_window.window2.get_allocation() pos_x, pos_y = gui.editor_window.window2.get_position() editorpersistance.prefs.exit_allocation_window_2 = (alloc.width, alloc.height, pos_x, pos_y) editorpersistance.prefs.app_v_paned_position = gui.editor_window.app_v_paned.get_position( ) editorpersistance.prefs.top_paned_position = gui.editor_window.top_paned.get_position( ) editorpersistance.prefs.mm_paned_position = gui.editor_window.mm_paned.get_position( ) editorpersistance.save() # Block reconnecting consumer before setting window not visible updater.player_refresh_enabled = False gui.editor_window.window.set_visible(False) if gui.editor_window.window2 != None: gui.editor_window.window2.set_visible(False) # Close and destroy app when gtk finds time to do it after hiding window GLib.idle_add(_app_destroy)
def change_edit_sequence(): selection = gui.sequence_list_view.treeview.get_selection() (model, rows) = selection.get_selected_rows() row = max(rows[0]) current_index = PROJECT().sequences.index(current_sequence()) if row == current_index: dialogutils.warning_message(_("Selected sequence is already being edited"), _("Select another sequence. Press Add -button to create a\nnew sequence if needed."), gui.editor_window.window) return # Clear clips selection at exit. This is transient user focus state and # therefore is not saved. movemodes.clear_selected_clips() app.change_current_sequence(row)
def _save_as_dialog_callback(dialog, response_id): if response_id == Gtk.ResponseType.ACCEPT: filenames = dialog.get_filenames() PROJECT().last_save_path = filenames[0] PROJECT().name = unicode(os.path.basename(filenames[0]), "utf-8") updater.set_info_icon(Gtk.STOCK_SAVE) try: persistance.save_project(PROJECT(), PROJECT().last_save_path) #<----- HERE except IOError as ioe: dialog.destroy() updater.set_info_icon(None) primary_txt = "I/O error({0})".format(ioe.errno) secondary_txt = ioe.strerror + "." dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window, is_info=False) return if len(PROJECT().events) == 0: # Save as... with 0 project events is considered Project creation p_event = projectdata.ProjectEvent(projectdata.EVENT_CREATED_BY_SAVING, PROJECT().last_save_path) PROJECT().events.append(p_event) else: p_event = projectdata.ProjectEvent(projectdata.EVENT_SAVED_AS, (PROJECT().name, PROJECT().last_save_path)) PROJECT().events.append(p_event) app.stop_autosave() app.start_autosave() global save_icon_remove_event_id save_icon_remove_event_id = GObject.timeout_add(500, remove_save_icon) global save_time save_time = time.clock() gui.editor_window.window.set_title(PROJECT().name + " - Flowblade") gui.editor_window.uimanager.get_widget("/MenuBar/FileMenu/Save").set_sensitive(False) gui.editor_window.uimanager.get_widget("/MenuBar/EditMenu/Undo").set_sensitive(False) gui.editor_window.uimanager.get_widget("/MenuBar/EditMenu/Redo").set_sensitive(False) editorpersistance.add_recent_project_path(PROJECT().last_save_path) editorpersistance.fill_recents_menu_widget(gui.editor_window.uimanager.get_widget('/MenuBar/FileMenu/OpenRecent'), open_recent_project) projectinfogui.update_project_info() dialog.destroy() else: dialog.destroy()
def select_sync_clip_mouse_pressed(event, frame): sync_clip = _get_sync_tline_clip(event, frame) if sync_clip == None: return # selection wasn't good if utils.is_mlt_xml_file(sync_clip.path) == True: # This isn't translated because 1.14 translation window is close, translation coming for 1.16 dialogutils.warning_message( _("Cannot Timeline Audio Sync with MLT XML Container Clips!"), _("Audio syncing for MLT XML Container Clips is not supported."), gui.editor_window.window, True) return sync_track = tlinewidgets.get_track(event.y) sync_clip_index = sync_track.clips.index(sync_clip) _tline_sync_data.sync_clip = sync_clip _tline_sync_data.sync_track = sync_track _tline_sync_data.sync_clip_index = sync_clip_index # TImeline media offset for clips sync_clip_start_in_tline = sync_track.clip_start(sync_clip_index) _tline_sync_data.origin_clip_start_in_tline = _tline_sync_data.origin_track.clip_start( _tline_sync_data.origin_clip_index) _tline_sync_data.clip_tline_media_offset = ( sync_clip_start_in_tline - sync_clip.clip_in) - (_tline_sync_data.origin_clip_start_in_tline - _tline_sync_data.origin_clip.clip_in) gdk_window = gui.tline_display.get_parent_window() gdk_window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR)) global _compare_dialog_thread _compare_dialog_thread = AudioCompareActiveThread() _compare_dialog_thread.start() # This or GUI freezes, we really can't do Popen.wait() in a Gtk thread clapperless_thread = ClapperlesLaunchThread( _tline_sync_data.origin_clip.path, sync_clip.path, _tline_sync_offsets_computed_callback) clapperless_thread.start() # Edit consumes selection movemodes.clear_selected_clips() updater.repaint_tline()
def select_thumbnail_dir_callback(dialog, response_id, data): file_select, retry_add_media = data folder = file_select.get_filenames()[0] dialog.destroy() if response_id == Gtk.ResponseType.YES: if folder == os.path.expanduser("~"): dialogutils.warning_message(_("Can't make home folder thumbnails folder"), _("Please create and select some other folder then \'") + os.path.expanduser("~") + _("\' as thumbnails folder"), gui.editor_window.window) else: editorpersistance.prefs.thumbnail_folder = folder editorpersistance.save() if retry_add_media == True: add_media_files(True)
def _load_compositor_values_dialog_callback(dialog, response_id): if response_id == Gtk.ResponseType.ACCEPT: load_path = dialog.get_filenames()[0] compositor_data = utils.unpickle(load_path) if compositor_data.data_applicable(compositor.transition.info): compositor_data.set_values(compositor) set_compositor(compositor) else: saved_name_comp_name = mlttransitions.name_for_type[compositor_data.info.name] current_comp_name = mlttransitions.name_for_type[compositor.transition.info.name] primary_txt = _("Saved Compositor data not applicaple for this compositor!") secondary_txt = _("Saved data is for ") + saved_name_comp_name + " compositor,\n" + _(", current compositor is ") + current_comp_name + "." dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window) dialog.destroy()
def _set_sync_parent_clip(event, frame): child_clip, child_index, child_clip_track = parent_selection_data parent_track = tlinewidgets.get_track(event.y) if parent_track != current_sequence().tracks[current_sequence().first_video_index]: dialogutils.warning_message( _("Sync parent clips must be on track V1"), _("Selected sync parent clip is on track ") + utils.get_track_name(parent_track, current_sequence()) + _(".\nYou can only sync to clips that are on track V1."), gui.editor_window.window, True, ) return # this can't have parent clip already if child_clip.sync_data != None: return if parent_track == None: return parent_clip_index = current_sequence().get_clip_index(parent_track, frame) if parent_clip_index == -1: return # Parent and child can't be on the same track. # Now that all parent clips must be on track V1 this is no longer shoild be possible. if parent_track == child_clip_track: print "parent_track == child_clip_track" return parent_clip = parent_track.clips[parent_clip_index] # These cannot be chained. # Now that all parent clips must be on track V1 this is no longer shoild be possible. if parent_clip.sync_data != None: print "parent_clip.sync_data != None" return data = { "child_index": child_index, "child_track": child_clip_track, "parent_index": parent_clip_index, "parent_track": parent_track, } action = edit.set_sync_action(data) action.do_edit()
def add_to_render_queue(): args_vals_list = render.get_args_vals_list_for_current_selections() render_path = render.get_file_path() # Get render start and end points if render.widgets.range_cb.get_active() == 0: start_frame = 0 end_frame = -1 # renders till finish else: start_frame = current_sequence().tractor.mark_in end_frame = current_sequence().tractor.mark_out # Only do if range defined. if start_frame == -1 or end_frame == -1: if render.widgets.range_cb.get_active() == 1: rendergui.no_good_rander_range_info() return # Create render data object if render.widgets.args_panel.use_args_check.get_active() == False: enc_index = render.widgets.encoding_panel.encoding_selector.widget.get_active() quality_index = render.widgets.encoding_panel.quality_selector.widget.get_active() user_args = False else: # This is not implemented enc_index = render.widgets.encoding_panel.encoding_selector.widget.get_active() quality_index = render.widgets.encoding_panel.quality_selector.widget.get_active() user_args = False profile = render.get_current_profile() profile_text = guicomponents.get_profile_info_text(profile) fps = profile.fps() profile_name = profile.description() r_data = batchrendering.RenderData(enc_index, quality_index, user_args, profile_text, profile_name, fps) # Add item try: batchrendering.add_render_item(PROJECT(), render_path, args_vals_list, start_frame, end_frame, r_data) except Exception as e: primary_txt = _("Adding item to render queue failed!") secondary_txt = _("Error message: ") + str(e) dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window, is_info=False) return
def _load_compositor_values_dialog_callback(dialog, response_id): if response_id == Gtk.ResponseType.ACCEPT: load_path = dialog.get_filenames()[0] f = open(load_path) compositor_data = pickle.load(f) if compositor_data.data_applicable(compositor.transition.info): compositor_data.set_values(compositor) set_compositor(compositor) else: saved_name_comp_name = mlttransitions.name_for_type[compositor_data.info.name] current_comp_name = mlttransitions.name_for_type[compositor.transition.info.name] primary_txt = _("Saved Compositor data not applicaple for this compositor!") secondary_txt = _("Saved data is for ") + saved_name_comp_name + " compositor,\n" + _(", current compositor is ") + current_comp_name + "." dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window) dialog.destroy()
def render_timeline(): if len(widgets.file_panel.movie_name.get_text()) == 0: primary_txt = _("Render file name entry is empty") secondary_txt = _( "You have to provide a name for the file to be rendered.") dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window) return if os.path.exists(get_file_path()): primary_txt = _("File: ") + get_file_path() + _(" already exists!") secondary_txt = _("Do you want to overwrite existing file?") dialogutils.warning_confirmation(_render_overwrite_confirm_callback, primary_txt, secondary_txt, gui.editor_window.window) else: _do_rendering()
def _set_sync_parent_clip(event, frame): child_clip, child_index, child_clip_track = parent_selection_data parent_track = tlinewidgets.get_track(event.y) if parent_track != current_sequence().tracks[ current_sequence().first_video_index]: dialogutils.warning_message( _("Sync parent clips must be on track V1"), _("Selected sync parent clip is on track ") + utils.get_track_name(parent_track, current_sequence()) + _(".\nYou can only sync to clips that are on track V1."), gui.editor_window.window, True) return # this can't have parent clip already if child_clip.sync_data != None: return if parent_track == None: return parent_clip_index = current_sequence().get_clip_index(parent_track, frame) if parent_clip_index == -1: return # Parent and child can't be on the same track. # Now that all parent clips must be on track V1 this is no longer shoild be possible. if parent_track == child_clip_track: print "parent_track == child_clip_track" return parent_clip = parent_track.clips[parent_clip_index] # These cannot be chained. # Now that all parent clips must be on track V1 this is no longer shoild be possible. if parent_clip.sync_data != None: print "parent_clip.sync_data != None" return data = { "child_index": child_index, "child_track": child_clip_track, "parent_index": parent_clip_index, "parent_track": parent_track } action = edit.set_sync_action(data) action.do_edit()
def create_audio_sync_compound_clip(): selection = gui.media_list_view.get_selected_media_objects() if len(selection) != 2: return video_file = selection[0].media_file audio_file = selection[1].media_file # Can't sync coumpound clips if utils.is_mlt_xml_file(video_file.path) == True or utils.is_mlt_xml_file( audio_file.path) == True: dialogutils.warning_message( _("Cannot Create Audio Sync Clip from MLT XML Container Clips!"), _("Audio syncing MLT XML Container Clips is not supported."), gui.editor_window.window, True) return # Can't sync 2 audio clips if video_file.type == appconsts.AUDIO and audio_file.type == appconsts.AUDIO: dialogutils.warning_message( _("Cannot Create Audio Sync Container Clip from 2 Audio Clips!"), _("One of the media items needs to be a video clip."), gui.editor_window.window, True) return if video_file.type == appconsts.VIDEO and audio_file.type == appconsts.AUDIO: pass elif video_file.type == appconsts.AUDIO and audio_file.type == appconsts.VIDEO: video_file, audio_file = audio_file, video_file else: print( "2 video files, video audio assignments determined by selection order" ) global _compare_dialog_thread _compare_dialog_thread = AudioCompareActiveThread() _compare_dialog_thread.start() # This or GUI freezes, we really can't do Popen.wait() in a Gtk thread clapperless_thread = ClapperlesLaunchThread(video_file.path, audio_file.path, _compound_offsets_complete) clapperless_thread.start()
def _get_sync_tline_clip(event, frame): sync_track = tlinewidgets.get_track(event.y) if sync_track == None: return None if sync_track == _tline_sync_data.origin_track: dialogutils.warning_message( _("Audio Sync parent clips must be on differnt tracks "), _("Selected audio sync clip is on the sametrack as the sync action origin clip." ), gui.editor_window.window, True) return None sync_clip_index = current_sequence().get_clip_index(sync_track, frame) if sync_clip_index == -1: return None return sync_track.clips[sync_clip_index]
def set_track_normal_height(track_index): track = get_track(track_index) track.height = appconsts.TRACK_HEIGHT_NORMAL # Check that new height tracks can be displayed and cancel if not. new_h = current_sequence().get_tracks_height() x, y, w, h = gui.tline_canvas.widget.allocation if new_h > h: track.height = appconsts.TRACK_HEIGHT_SMALL dialogutils.warning_message( _("Not enough vertical space on Timeline to expand track"), _("Maximize or resize application window to get more\nspace for tracks if possible." ), gui.editor_window.window, True) return tlinewidgets.set_ref_line_y(gui.tline_canvas.widget.allocation) gui.tline_column.init_listeners() updater.repaint_tline()
def _get_sync_tline_clip(event, frame): sync_track = tlinewidgets.get_track(event.y) if sync_track == None: return None if sync_track == _tline_sync_data.origin_track: dialogutils.warning_message(_("Audio Sync parent clips must be on differnt tracks "), _("Selected audio sync clip is on the sametrack as the sync action origin clip."), gui.editor_window.window, True) return None sync_clip_index = current_sequence().get_clip_index(sync_track, frame) if sync_clip_index == -1: return None return sync_track.clips[sync_clip_index]
def run(self): action_object = containeractions.get_action_object( self.container_clip_data) is_valid, err_msg = action_object.validate_program() # Media plugins have plugin data created with user set values, scripts loaded from file system # do not and just had it created in 'action_object.validate_program()' if self.plugin_data != None: # For media plugins use provided user edited creation data. self.container_clip_data.data_slots[ "fluxity_plugin_edit_data"] = self.plugin_data time.sleep(0.5) # To make sure text is seen. if self.dialog != None: Gdk.threads_enter() self.dialog.destroy() if is_valid == False: primary_txt = _( "Flowblade Media Plugin Container Clip Validation Error") dialogutils.warning_message(primary_txt, err_msg, gui.editor_window.window) Gdk.threads_leave() if is_valid == False: Gdk.threads_enter() primary_txt = _( "Flowblade Media Plugin Container Clip Validation Error") dialogutils.warning_message(primary_txt, err_msg, gui.editor_window.window) Gdk.threads_leave() return data_object = self.container_clip_data.data_slots[ "fluxity_plugin_edit_data"] length = data_object["length"] fluxity_unrendered_media_image = respaths.IMAGE_PATH + "unrendered_fluxity.png" window_text = _("Creating Container for Flowblade Media Plugin...") containeractions.create_unrendered_clip( length, fluxity_unrendered_media_image, self.container_clip_data, _fluxity_unredered_media_creation_complete, window_text)
def _hide_selected_clicked(visible_view, hidden_view): visible_indexes = visible_view.get_selected_indexes_list() prof_names = [] default_profile = mltprofiles.get_default_profile() for i in visible_indexes: pname, profile = mltprofiles.get_factory_profiles()[i] if profile == default_profile: dialogutils.warning_message("Can't hide default Profile", "Profile '"+ profile.description() + "' is default profile and can't be hidden.", None) return prof_names.append(pname) editorpersistance.prefs.hidden_profile_names += prof_names editorpersistance.save() mltprofiles.load_profile_list() visible_view.fill_data_model(mltprofiles.get_factory_profiles()) hidden_view.fill_data_model(mltprofiles.get_hidden_profiles())
def select_sync_clip_mouse_pressed(event, frame): sync_clip = _get_sync_tline_clip(event, frame) if sync_clip == None: return # selection wasn't good if utils.is_mlt_xml_file(sync_clip.path) == True: # This isn't translated because 1.14 translation window is close, translation coming for 1.16 dialogutils.warning_message(_("Cannot Timeline Audio Sync with Compound Clips!"), _("Audio syncing for Compound Clips is not supported."), gui.editor_window.window, True) return sync_track = tlinewidgets.get_track(event.y) sync_clip_index = sync_track.clips.index(sync_clip) _tline_sync_data.sync_clip = sync_clip _tline_sync_data.sync_track = sync_track _tline_sync_data.sync_clip_index = sync_clip_index # TImeline media offset for clips sync_clip_start_in_tline = sync_track.clip_start(sync_clip_index) _tline_sync_data.origin_clip_start_in_tline = _tline_sync_data.origin_track.clip_start(_tline_sync_data.origin_clip_index) _tline_sync_data.clip_tline_media_offset = (sync_clip_start_in_tline - sync_clip.clip_in) - (_tline_sync_data.origin_clip_start_in_tline - _tline_sync_data.origin_clip.clip_in) gdk_window = gui.tline_display.get_parent_window(); gdk_window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR)) global _compare_dialog_thread _compare_dialog_thread = AudioCompareActiveThread() _compare_dialog_thread.start() # This or GUI freezes, we really can't do Popen.wait() in a Gtk thread clapperless_thread = ClapperlesLaunchThread(_tline_sync_data.origin_clip.path, sync_clip.path, _tline_sync_offsets_computed_callback) clapperless_thread.start() # Edit consumes selection movemodes.clear_selected_clips() updater.repaint_tline()
def set_track_normal_height(track_index): track = get_track(track_index) track.height = appconsts.TRACK_HEIGHT_NORMAL # Check that new height tracks can be displayed and cancel if not. new_h = current_sequence().get_tracks_height() x, y, w, h = gui.tline_canvas.widget.allocation if new_h > h: track.height = appconsts.TRACK_HEIGHT_SMALL dialogutils.warning_message( _("Not enough vertical space on Timeline to expand track"), _("Maximize or resize application window to get more\nspace for tracks if possible."), gui.editor_window.window, True, ) return tlinewidgets.set_ref_line_y(gui.tline_canvas.widget.allocation) gui.tline_column.init_listeners() updater.repaint_tline()
def _load_effect_values_dialog_callback(dialog, response_id): if response_id == Gtk.ResponseType.ACCEPT: load_path = dialog.get_filenames()[0] f = open(load_path) effect_data = pickle.load(f) filter_object = clip.filters[current_filter_index] if effect_data.data_applicable(filter_object.info): effect_data.set_effect_values(filter_object) effect_selection_changed() else: # Info window saved_effect_name = effect_data.info.name current_effect_name = filter_object.info.name primary_txt = _("Saved Filter data not applicaple for this Filter!") secondary_txt = _("Saved data is for ") + saved_effect_name + " Filter,\n" + _("current edited Filter is ") + current_effect_name + "." dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window) dialog.destroy()
def _close_dialog_callback(dialog, response_id): dialog.destroy() if response_id == Gtk.ResponseType.CLOSE:# "Don't Save" pass elif response_id == Gtk.ResponseType.YES:# "Save" if editorstate.PROJECT().last_save_path != None: persistance.save_project(editorstate.PROJECT(), editorstate.PROJECT().last_save_path) else: dialogutils.warning_message(_("Project has not been saved previously"), _("Save project with File -> Save As before closing."), gui.editor_window.window) return else: # "Cancel" return # This is the same as opening default project sequence.AUDIO_TRACKS_COUNT = 4 sequence.VIDEO_TRACKS_COUNT = 5 new_project = projectdata.get_default_project() app.open_project(new_project)
def create_audio_sync_compound_clip(): selection = gui.media_list_view.get_selected_media_objects() if len(selection) != 2: return video_file = selection[0].media_file audio_file = selection[1].media_file # Can't sync coumpound clips if utils.is_mlt_xml_file(video_file.path) == True or utils.is_mlt_xml_file(audio_file.path) == True: # This isn't translated because 1.14 translation window is close, translation coming for 1.16 dialogutils.warning_message(_("Cannot Create Audio Sync Compound Clip from Compound Clips!"), _("Audio syncing Compound Clips is not supported."), gui.editor_window.window, True) return # Can't sync 2 audio clips if video_file.type == appconsts.AUDIO and audio_file.type == appconsts.AUDIO: # This isn't translated because 1.14 translation window is close, translation coming for 1.16 dialogutils.warning_message(_("Cannot Create Audio Sync Compound Clip from 2 Audio Clips!"), _("One of the media items needs to be a video clip."), gui.editor_window.window, True) return if video_file.type == appconsts.VIDEO and audio_file.type == appconsts.AUDIO: pass elif video_file.type == appconsts.AUDIO and audio_file.type == appconsts.VIDEO: video_file, audio_file = audio_file, video_file else: print "2 video files, video audio assignments determined by selection order" global _compare_dialog_thread _compare_dialog_thread = AudioCompareActiveThread() _compare_dialog_thread.start() # This or GUI freezes, we really can't do Popen.wait() in a Gtk thread clapperless_thread = ClapperlesLaunchThread(video_file.path, audio_file.path, _compound_offsets_complete) clapperless_thread.start()
def get_args_vals_list_for_current_selections(): profile = get_current_profile() encoding_option_index = widgets.encoding_panel.encoding_selector.widget.get_active() quality_option_index = widgets.encoding_panel.quality_selector.widget.get_active() if widgets.render_type_panel.type_combo.get_active() == 1: # Preset encodings args_vals_list = renderconsumer.get_args_vals_tuples_list_for_encoding_and_quality( profile, encoding_option_index, -1) elif widgets.args_panel.use_args_check.get_active() == False: # User encodings args_vals_list = renderconsumer.get_args_vals_tuples_list_for_encoding_and_quality( profile, encoding_option_index, quality_option_index) else: # Manual args encodings buf = widgets.args_panel.opts_view.get_buffer() args_vals_list, error = renderconsumer.get_ffmpeg_opts_args_vals_tuples_list(buf) if error != None: dialogutils.warning_message("FFMPeg Args Error", error, gui.editor_window.window) return None return args_vals_list