def on_btnAdd_clicked(self, widget, *args): replace_clip_with = self.frmAddFiles.get_filename() try: #does the new file already exist in the project? file_object = self.project.project_folder.FindFile( replace_clip_with) if not file_object: #add the file to the project self.project.project_folder.AddFile(replace_clip_with) #this method does the actual replacement and modifies the project self.form.replace_clip(self.clip, replace_clip_with) except: messagebox.show( _("Error"), _("There was an error importing the selected file(s).")) #set the last used folder current_folder = self.frmAddFiles.get_current_folder() if current_folder is None: current_folder = "None" preferences.Settings.app_state["import_folder"] = current_folder self.frmAddFiles.destroy()
def on_btnUpload_clicked(self, widget, *args): print "on_btnUpload_clicked" _ = self._ if self.cboUploadService.get_active_text(): # get upload service service_name = str(self.cboUploadService.get_active_text()) service = self.upload_services[service_name] if service.validate(self): print "form is valid!" # start upload status = service.start_upload(self) # did upload succeed? if status == True: # prompt user that export is completed if has_py_notify: try: # Use libnotify to show the message (if possible) if pynotify.init("OpenShot Video Editor"): n = pynotify.Notification(_("Upload Successful!"), _("Your video has been successfully uploaded!")) n.show() except: # use a GTK messagebox messagebox.show(_("Upload Successful!"), _("Your video has been successfully uploaded!")) else: # use a GTK messagebox messagebox.show(_("Upload Successful!"), _("Your video has been successfully uploaded!")) # close the window self.frmUploadVideo.destroy()
def on_btnCreateProject_clicked(self, widget, *args): print "on_btnCreateProject_clicked called with self.%s" % widget.get_name() localName = str.strip(self.txtProjectName.get_text()) localFolder = str.strip(self.fileProjectFolder.get_filename()) localType = self.cmbProjectType.get_active_text() localLength = str.strip(self.spinProjectLength.get_text()) # Validate the the form is valid if (len(localName) == 0): # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid project name.")) elif (localType == - 1): # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid project type.")) else: # check if mode is 'New Project' if (self.mode == "new"): # Re-init / clear the current project object (to reset all exisint data) self.project = project.project() self.project.form = self.form self.project.form.project = self.project # clear history (since we are opening a new project) self.project.form.history_stack = [] self.project.form.history_index = -1 self.project.form.refresh_history() self.project.set_project_modified(is_modified=True, refresh_xml=False, type=_("New project")) # set the project properties self.project.name = localName self.project.project_type = localType self.project.folder = localFolder self.project.sequences[0].length = float(localLength) * 60 # convert to seconds self.project.set_project_modified(is_modified=False, refresh_xml=True) # stop video self.project.form.MyVideo.pause() # set the profile settings in the video thread self.project.form.MyVideo.set_project(self.project, self.project.form, os.path.join(self.project.USER_DIR, "sequence.mlt"), mode="preview") self.project.form.MyVideo.set_profile(localType) self.project.form.MyVideo.load_xml() # Save the project self.project.Save("%s/%s.osp" % (localFolder, localName)) # Is openshot existing? if self.project.form.is_exiting: self.project.form.frmMain.destroy() # Update the main form self.project.form.refresh() # close the window self.frmNewProject.destroy()
def on_btnCreate_clicked(self,widget): #prompt the user for a file name self.filename = self.setTitleName() if self.filename == "": messagebox.show(_("OpenShot Error"), _("The Title name cannot be blank, the title file has not been created.")) return #load the template doc to read xml self.load_svg_template(self.template_name) #set the new filename (fileBaseName, fileExtension)=os.path.splitext(self.template_name) self.filename = self.filename + fileExtension #write the new file self.writeToFile(self.xmldoc) #show the text editor if self.noTitles == False: if not self.on_btnEditText_clicked(widget): return #set edit button states self.btnEditText.set_sensitive(True) self.btnFont.set_sensitive(True) self.btnFontColor.set_sensitive(True) self.btnBackgroundColor.set_sensitive(True) self.btnAdvanced.set_sensitive(True) #preview the file self.set_img_pixbuf(self.filename) #turn off the create button once we have created the new file self.btnCreate.set_sensitive(False) self.cmbTemplate.set_sensitive(False) if self.noTitles == True: self.btnEditText.set_sensitive(False) self.btnFont.set_sensitive(False) self.btnFontColor.set_sensitive(False)
def import_transition(self): # get translation method _ = self._ # Create user directory / transitions folders for the new icon files if not os.path.exists(self.project.USER_TRANSITIONS_DIR): os.makedirs(self.project.USER_TRANSITIONS_DIR) try: # init file paths (dirName, filename) = os.path.split(self.transition_file) (simple_filename, file_extention) = os.path.splitext(filename) new_transition_path = os.path.join( self.project.USER_TRANSITIONS_DIR, filename) # copy transition & icon into .libreshot folder shutil.copyfile(self.transition_file, new_transition_path) # Refresh the main screen, to show the new transition self.form.on_btnTransFilterAll_toggled(None) # Switch to transitions tab self.form.nbFiles.set_current_page(0) # switch to files self.form.nbFiles.set_current_page( 1) # and then back to transitions messagebox.show("Openshot", _("Transition Imported successfully!")) self.frmImportTransitions.destroy() except: messagebox.show(_("Error!"), _("There was an error importing the Transition!"))
def import_transition(self): # get translation method _ = self._ # Create user directory / transitions folders for the new icon files if not os.path.exists(self.project.USER_TRANSITIONS_DIR): os.makedirs(self.project.USER_TRANSITIONS_DIR) try: # init file paths (dirName, filename) = os.path.split(self.transition_file) (simple_filename, file_extention) = os.path.splitext(filename) new_transition_path = os.path.join(self.project.USER_TRANSITIONS_DIR, filename) # copy transition & icon into .openshot folder shutil.copyfile(self.transition_file, new_transition_path) # Refresh the main screen, to show the new transition self.form.on_btnTransFilterAll_toggled(None) # Switch to transitions tab self.form.nbFiles.set_current_page(0) # switch to files self.form.nbFiles.set_current_page(1) # and then back to transitions messagebox.show("Openshot", _("Transition Imported successfully!")) self.frmImportTransitions.destroy() except: messagebox.show(_("Error!"), _("There was an error importing the Transition!"))
def delete_profile(self): #get the active profile model = self.cmbProjectType.get_model() iter = self.cmbProjectType.get_active_iter() file_name = model.get_value(iter, 0) if os.path.exists(os.path.join(self.project.USER_PROFILES_DIR, file_name)): os.remove(os.path.join(self.project.USER_PROFILES_DIR, file_name)) #clear the combo & repopulate model.clear() self.get_profiles_list() #set the default profile self.set_project_type_dropdown(self.form.settings.general["default_profile"]) if not self.cmbProjectType.get_active_text(): self.set_project_type_dropdown("DV/DVD NTSC") self.parent.set_default_profile("DV/DVD NTSC") # reload parent window's list of profiles self.parent.populate_profiles() # re-select the default profile self.parent.set_default_profile(self.form.settings.general["default_profile"]) else: messagebox.show("Openshot Error!", _("The profile %s cannot be deleted." % file_name))
def on_btnOpenProject_clicked(self, widget, *args): #print "on_btnOpenProject_clicked called with self.%s" % widget.get_name() # Get selected file name file_to_open = self.frmOpenProject.get_filename() try: # open the project (and re-serialize the project object) self.project.Open(file_to_open) # Update the main form self.project.form.refresh() # stop video self.project.form.MyVideo.pause() # set the profile settings in the video thread self.project.form.MyVideo.set_profile(self.project.project_type) self.project.form.MyVideo.set_project(self.project, self.project.form, os.path.join(self.project.USER_DIR, "sequence.mlt"), mode="preview") self.project.form.MyVideo.load_xml() # stop video self.project.form.MyVideo.play() self.project.form.MyVideo.pause() # close window self.frmOpenProject.destroy() except: # show the error message messagebox.show(_("Error!"), _("There was an error opening this project file. Please be sure you open the correct *.osp file."))
def delete_profile(self): #get the active profile model = self.cmbProjectType.get_model() iter = self.cmbProjectType.get_active_iter() file_name = model.get_value(iter, 0) if os.path.exists( os.path.join(self.project.USER_PROFILES_DIR, file_name)): os.remove(os.path.join(self.project.USER_PROFILES_DIR, file_name)) #clear the combo & repopulate model.clear() self.get_profiles_list() #set the default profile self.set_project_type_dropdown( self.form.settings.general["default_profile"]) if not self.cmbProjectType.get_active_text(): self.set_project_type_dropdown("DV/DVD NTSC") self.parent.set_default_profile("DV/DVD NTSC") # reload parent window's list of profiles self.parent.populate_profiles() # re-select the default profile self.parent.set_default_profile( self.form.settings.general["default_profile"]) else: messagebox.show("Openshot Error!", _("The profile %s cannot be deleted." % file_name))
def update_progress(self, new_percentage): # get correct gettext method _ = self._ # update the percentage complete self.progressExportVideo.set_fraction(new_percentage) # if progress bar is 100%, close window if new_percentage == 1 and self.export_in_progress: # remove the MODAL property from the window (sicne we are done) self.frmExportVideo.set_modal(False) if not self.cancelled: title = _("Export Complete") message = _("The video has been successfully exported to\n%s") % self.export_path # prompt user that export is completed if has_py_notify: # Use libnotify to show the message (if possible) if pynotify.init("OpenShot Video Editor"): n = pynotify.Notification(title, message) n.show() else: # use a GTK messagebox messagebox.show(title, message) # flag export as completed self.export_in_progress = False
def get_formats(self, format=None): #this is the equivalant of running this command inthe terminal: #melt noise -consumer avformat f=list command = [self.melt_command, "noise", "-consumer", "avformat", "f=list"] output = '' formats_raw=[] try: process = subprocess.Popen(args=command,stdout=subprocess.PIPE, stdin=subprocess.PIPE,stderr=subprocess.STDOUT) output = str(process.stdout.read(20000)) except: pass output_lines=output.split('\n') for line in output_lines: if " - " in line and "..." not in line and len(line.strip()) > 0: formats_raw.append(line.lstrip(' - ')) # sort list formats_raw.sort() # Alert user that no formats were found (this is bad) if len(formats_raw) == 0: print _("No formats or codecs were found. Please check the OpenShot preferences and configure the 'melt' command name.") messagebox.show(_("Error!"), _("No formats or codecs were found. Please check the OpenShot preferences and configure the 'melt' command name.")) return formats_raw
def save_settings_to_xml(self): settings_path = os.path.join(self.project.USER_DIR, "config.xml") #update each xml element with the current dictionary values if os.path.exists(settings_path): try: xmldoc = xml.parse(settings_path) except xml.xml.parsers.expat.ExpatError: # Invalid or empty config file, create new blank dom messagebox.show( _("LibreShot Warning"), _("Invalid or empty preferences file found, loaded default values" )) xmldoc = xml.Document() root_node = xmldoc.createElement("settings") xmldoc.appendChild(root_node) # create a node for each section for section, section_dict in self.sections.iteritems(): section_node = xmldoc.createElement(section) root_node.appendChild(section_node) else: # missing config file, create new blank dom xmldoc = xml.Document() root_node = xmldoc.createElement("settings") xmldoc.appendChild(root_node) # create a node for each section for section, section_dict in self.sections.iteritems(): section_node = xmldoc.createElement(section) root_node.appendChild(section_node) for section, section_dict in self.sections.iteritems(): for key, value in section_dict.iteritems(): try: element = xmldoc.getElementsByTagName(key) if element: # does text node exist? if not element[0].childNodes: txt = xmldoc.createTextNode(str(value)) element[0].appendChild(txt) else: # update existing text node element[0].childNodes[0].data = str( section_dict[key]) else: #there is no matching element in the xml, #we need to add one new_element = xmldoc.createElement(key) parent = xmldoc.getElementsByTagName(section) parent[0].appendChild(new_element) txt = xmldoc.createTextNode(str(value)) new_element.appendChild(txt) except IndexError: pass # save settings self.write_to_settings_file(xmldoc)
def restore_project_state(project_object, state): # open the serialized file old_form = project_object.form old_play_head = project_object.sequences[0].play_head old_ruler_time = project_object.sequences[0].ruler_time old_thumbnailer = project_object.thumbnailer old_play_head_line = project_object.sequences[0].play_head_line old_theme = project_object.theme # update the form reference on the new project file state.seek(0,0) project_object = pickle.load(state) # re-attach some variables (that aren't pickleable) project_object.form = old_form project_object.sequences[0].play_head = old_play_head project_object.sequences[0].ruler_time = old_ruler_time project_object.sequences[0].play_head_line = old_play_head_line project_object.thumbnailer = old_thumbnailer #project_object.sequences[0].play_head_position = 0.0 project_object.theme = old_theme project_object.mlt_profile = None # update the thumbnailer's project reference project_object.thumbnailer.set_project(project_object) # update project reference to menus project_object.form.mnuTrack1.project = project_object project_object.form.mnuClip1.project = project_object project_object.form.mnuTransition1.project = project_object # update the project reference on the form variable project_object.form.project = project_object # update project references in the menus project_object.form.mnuTrack1.project = project_object.form.project project_object.form.mnuClip1.project = project_object.form.project project_object.form.mnuMarker1.project = project_object.form.project project_object.form.mnuTransition1.project = project_object.form.project project_object.form.mnuAnimateSubMenu1.project = project_object.form.project project_object.form.mnuPositionSubMenu1.project = project_object.form.project # mark XML as refreshable project_object.set_project_modified(is_modified=True, refresh_xml=True) #check project files still exist in the same location missing_files = "" items = project_object.project_folder.items for item in items: if isinstance(item, files.OpenShotFile): if not os.path.exists(item.name) and "%" not in item.name: missing_files += item.name + "\n" if missing_files: messagebox.show("OpenShot", _("The following file(s) no longer exist." + "\n" + "Please restore them or remove them from your project:" + "\n\n" + missing_files))
def on_cboSimpleQuality_changed(self, widget, *args): # get reference to gettext _ = self._ #don't do anything if the combo has been cleared if self.cboSimpleQuality.get_active_text(): # reset the invalid codecs list self.invalid_codecs = [] # Get the quality quality = str(self.cboSimpleQuality.get_active_text()) #set the attributes in the advanced tab #video format self.set_dropdown_values(self.videoformat, self.cboVIdeoFormat) #videocodec self.set_dropdown_values(self.videocodec, self.cboVideoCodec) #audiocode self.set_dropdown_values(self.audiocodec, self.cboAudioCodec) #samplerate self.set_dropdown_values(self.samplerate, self.cboSampleRate) #audiochannels self.set_dropdown_values(self.audiochannels, self.cboChannels) #video bit rate self.cboBitRate.insert_text(0,self.vbr[quality]) self.cboBitRate.set_active(0) #audio bit rate self.cboAudioBitRate.insert_text(0,self.abr[quality]) self.cboAudioBitRate.set_active(0) #check for any invalid codecs and disable #the export button if required. if self.invalid_codecs: if self.use_infobar: self.label.set_markup(_("The following codec(s) are missing from your system:\n\n{missing_codecs}\n\nYou may need to install packages such as libavformat-extra to enable the missing codecs.\n<a href='https://answers.launchpad.net/libreshot/+faq/1040'>Learn More</a>".format(missing_codecs = "\n".join(self.invalid_codecs)))) self.infobar.show_all() else: # no infobar available (use messagebox) if self.last_error != self.invalid_codecs: messagebox.show(_("Error!"), _("The following codec(s) are missing from your system:\n\n{missing_codecs}\n\nYou may need to install packages such as libavformat-extra to enable the missing codecs.".format(missing_codecs = "\n".join(self.invalid_codecs)))) self.last_error = self.invalid_codecs self.btnExportVideo.set_sensitive(False) else: # hide the missing codec message again if self.use_infobar: self.last_error = None self.infobar.hide()
def on_btnClose_clicked(self, widget, *args): if self.save_prompt == True: messagebox.show("Openshot", _("Do you want to save this profile?."), gtk.BUTTONS_YES_NO, self.save_profile, self.close_window) else: self.close_window()
def on_cboSimpleQuality_changed(self, widget, *args): # get reference to gettext _ = self._ #don't do anything if the combo has been cleared if self.cboSimpleQuality.get_active_text(): # reset the invalid codecs list self.invalid_codecs = [] # Get the quality quality = str(self.cboSimpleQuality.get_active_text()) #set the attributes in the advanced tab #video format self.set_dropdown_values(self.videoformat, self.cboVIdeoFormat) #videocodec self.set_dropdown_values(self.videocodec, self.cboVideoCodec) #audiocode self.set_dropdown_values(self.audiocodec, self.cboAudioCodec) #samplerate self.set_dropdown_values(self.samplerate, self.cboSampleRate) #audiochannels self.set_dropdown_values(self.audiochannels, self.cboChannels) #video bit rate self.cboBitRate.insert_text(0,self.vbr[quality]) self.cboBitRate.set_active(0) #audio bit rate self.cboAudioBitRate.insert_text(0,self.abr[quality]) self.cboAudioBitRate.set_active(0) #check for any invalid codecs and disable #the export button if required. if self.invalid_codecs: if self.use_infobar: self.label.set_markup(_("The following codec(s) are missing from your system:\n\n{missing_codecs}\n\nYou may need to install packages such as libavformat-extra to enable the missing codecs.\n<a href='https://answers.launchpad.net/openshot/+faq/1040'>Learn More</a>".format(missing_codecs = "\n".join(self.invalid_codecs)))) self.infobar.show_all() else: # no infobar available (use messagebox) if self.last_error != self.invalid_codecs: messagebox.show(_("Error!"), _("The following codec(s) are missing from your system:\n\n{missing_codecs}\n\nYou may need to install packages such as libavformat-extra to enable the missing codecs.".format(missing_codecs = "\n".join(self.invalid_codecs)))) self.last_error = self.invalid_codecs self.btnExportVideo.set_sensitive(False) else: # hide the missing codec message again if self.use_infobar: self.last_error = None self.infobar.hide()
def save_settings_to_xml(self): settings_path = os.path.join(self.project.USER_DIR, "config.xml") #update each xml element with the current dictionary values if os.path.exists(settings_path): try: xmldoc = xml.parse(settings_path) except xml.xml.parsers.expat.ExpatError: # Invalid or empty config file, create new blank dom messagebox.show(_("OpenShot Warning"), _("Invalid or empty preferences file found, loaded default values")) xmldoc = xml.Document() root_node = xmldoc.createElement("settings") xmldoc.appendChild(root_node) # create a node for each section for section, section_dict in self.sections.iteritems(): section_node = xmldoc.createElement(section) root_node.appendChild(section_node) else: # missing config file, create new blank dom xmldoc = xml.Document() root_node = xmldoc.createElement("settings") xmldoc.appendChild(root_node) # create a node for each section for section, section_dict in self.sections.iteritems(): section_node = xmldoc.createElement(section) root_node.appendChild(section_node) for section, section_dict in self.sections.iteritems(): for key, value in section_dict.iteritems(): try: element = xmldoc.getElementsByTagName(key) if element: # does text node exist? if not element[0].childNodes: txt = xmldoc.createTextNode(str(value)) element[0].appendChild(txt) else: # update existing text node element[0].childNodes[0].data = str(section_dict[key]) else: #there is no matching element in the xml, #we need to add one new_element = xmldoc.createElement(key) parent = xmldoc.getElementsByTagName(section) parent[0].appendChild(new_element) txt = xmldoc.createTextNode(str(value)) new_element.appendChild(txt) except IndexError: pass # save settings self.write_to_settings_file(xmldoc)
def GetImageSequenceDetails(self, file_path, session=None): """ Determine if this image is part of an image sequence, and if so, return the regular expression to match this image sequence, else return None. """ # get a reference to the language translate method _ = self.project.translate # Get just the file name (dirName, fileName) = os.path.split(file_path) extensions = ["png", "jpg", "jpeg", "gif"] match = re.findall(r"(.*[^\d])?(0*)(\d+)\.(%s)" % "|".join(extensions), fileName, re.I) if not match: # File name does not match an image sequence return None else: # Get the parts of image name base_name = match[0][0] fixlen = match[0][1] > "" number = int(match[0][2]) digits = len(match[0][1] + match[0][2]) extension = match[0][3] full_base_name = os.path.join(dirName, base_name) # Check for images which the file names have the different length fixlen = fixlen or not (glob.glob("%s%s.%s" % (full_base_name, "[0-9]" * (digits + 1), extension)) or glob.glob("%s%s.%s" % (full_base_name, "[0-9]" * ((digits - 1) if digits > 1 else 3), extension))) # Check for previous or next image for x in range(max(0, number - 100), min(number + 101, 50000)): if x != number and os.path.exists("%s%s.%s" % (full_base_name, str(x).rjust(digits, "0") if fixlen else str(x), extension)): is_sequence = True break else: is_sequence = False parameters = {"file_path":file_path, "folder_path":dirName, "base_name":base_name, "fixlen":fixlen, "digits":digits, "extension":extension} # if sibling images were found... if is_sequence: # prevent repeat messageboxes... only prompt user about the first image sequence found in a single drag n drop action if session not in self.project.form.file_drop_messages: # mark this session, so no more dialogs are shown for these drag n drop files if session: self.project.form.file_drop_messages.append(session) # prompt user messagebox.show("LibreShot", _("Would you like to import %s as an image sequence?") % fileName, gtk.BUTTONS_NONE, self.import_image_sequence, self.dont_import_image_sequence, gtk.MESSAGE_QUESTION, "", gtk.STOCK_YES, gtk.RESPONSE_YES, gtk.STOCK_NO, gtk.RESPONSE_NO, parameters) return parameters return None else: return None
def write_to_settings_file(self, xmldoc): # write the updated xml document to the config file filename = os.path.join(self.project.USER_DIR, "config.xml") try: file = open(filename, "wb") file.write(xmldoc.toxml("UTF-8")) # xmldoc.writexml(file, indent='', addindent=' ', newl='', encoding='UTF-8') file.close() except IOError, inst: messagebox.show(_("OpenShot Error"), _("Unexpected Error '%s' while writing to '%s'." % (inst, filename)))
def on_btnDelete_clicked(self, widget, *args): # get correct gettext method _ = self._ #get the active profile model = self.cmbProjectType.get_model() iter = self.cmbProjectType.get_active_iter() file_name = model.get_value(iter, 0) messagebox.show("Openshot", _("Are you sure you want to delete the profile %s?" % file_name), gtk.BUTTONS_YES_NO, self.delete_profile)
def on_btnSave_clicked(self, widget, *args): file_name = self.txtProfileName.get_text() #first check if this name already exists in the 'preset' profiles #or USER_PROFILES_DIR if profiles.mlt_profiles(self.project).profile_exists(file_name): messagebox.show("Openshot", _("A profile with this name already exists. Please use another name.")) return True else: self.save_profile()
def update_progress(self, new_percentage): # get correct gettext method _ = self._ # update the percentage complete self.progressExportVideo.set_fraction(new_percentage) # if progress bar is 100%, close window if new_percentage == 1 and self.export_in_progress: # show message if not self.cancelled: title = _("Export Complete") message = _("The video has been successfully exported to\n%s") % self.export_path # prompt user that export is completed if has_py_notify: try: # Use libnotify to show the message (if possible) if pynotify.init("OpenShot Video Editor"): n = pynotify.Notification(title, message) n.show() except: # use a GTK messagebox messagebox.show(title, message) else: # use a GTK messagebox messagebox.show(title, message) # Re-enable the controls on the screen self.btnExportVideo.set_sensitive(True) self.vbox1.set_sensitive(True) # Show Upload screen (if needed) export_type = self.cboExportType.get_active_text() if export_type == _("Upload to Web"): localUploadService = self.cboUploadServices.get_active_text() localfileExportFolder = self.project.USER_DIR localtxtFileName = "%s-upload" % str.strip(self.txtFileName.get_text()) localtxtVideoFormat = self.cboVIdeoFormat.get_active_text() # close this window self.frmExportVideo.destroy() # show upload screen frmUploadVideo = UploadVideo.frmUploadVideo(form=self.form, project=self.project, filename=os.path.join(localfileExportFolder, "%s.%s" % (localtxtFileName, localtxtVideoFormat)), service_name=localUploadService) frmUploadVideo.frmUploadVideo.show() else: # export is now finished, so close window self.frmExportVideo.destroy() # flag export as completed self.export_in_progress = False
def update_progress(self, new_percentage): # get correct gettext method _ = self._ # update the percentage complete self.progressExportVideo.set_fraction(new_percentage) # if progress bar is 100%, close window if new_percentage == 1 and self.export_in_progress: # show message if not self.cancelled: title = _("Export Complete") message = _("The video has been successfully exported to\n%s") % self.export_path # prompt user that export is completed if has_py_notify: try: # Use libnotify to show the message (if possible) if pynotify.init("LibreShot Video Editor"): n = pynotify.Notification(title, message) n.show() except: # use a GTK messagebox messagebox.show(title, message) else: # use a GTK messagebox messagebox.show(title, message) # Re-enable the controls on the screen self.btnExportVideo.set_sensitive(True) self.vbox1.set_sensitive(True) # Show Upload screen (if needed) export_type = self.cboExportType.get_active_text() if export_type == _("Upload to Web"): localUploadService = self.cboUploadServices.get_active_text() localfileExportFolder = self.project.USER_DIR localtxtFileName = "%s-upload" % str.strip(self.txtFileName.get_text()) localtxtVideoFormat = self.cboVIdeoFormat.get_active_text() # close this window self.frmExportVideo.destroy() # show upload screen frmUploadVideo = UploadVideo.frmUploadVideo(form=self.form, project=self.project, filename=os.path.join(localfileExportFolder, "%s.%s" % (localtxtFileName, localtxtVideoFormat)), service_name=localUploadService) frmUploadVideo.frmUploadVideo.show() else: # export is now finished, so close window self.frmExportVideo.destroy() # flag export as completed self.export_in_progress = False
def on_btnAdvanced_clicked(self, widget): #use an external editor to edit the image try: prog = "inkscape" #check if inkscape is installed if os.system('which ' + prog + ' 2>/dev/null') == 0: # launch Inkscape os.system("%s '%s'" % (prog, self.filename)) else: messagebox.show(_("OpenShot Error"), _("Please install %s to use this function." % (prog.capitalize()))) except: messagebox.show(_("OpenShot Error"), _("There was an error opening '%s', is it installed?" % (prog)))
def on_btnDelete_clicked(self, widget, *args): # get correct gettext method _ = self._ #get the active profile model = self.cmbProjectType.get_model() iter = self.cmbProjectType.get_active_iter() file_name = model.get_value(iter, 0) messagebox.show( "Openshot", _("Are you sure you want to delete the profile %s?" % file_name), gtk.BUTTONS_YES_NO, self.delete_profile)
def write_to_settings_file(self, xmldoc): #write the updated xml document to the config file filename = os.path.join(self.project.USER_DIR, "config.xml") try: file = open(filename, "wb") file.write(xmldoc.toxml("UTF-8")) #xmldoc.writexml(file, indent='', addindent=' ', newl='', encoding='UTF-8') file.close() except IOError, inst: messagebox.show( _("LibreShot Error"), _("Unexpected Error '%s' while writing to '%s'." % (inst, filename)))
def on_btnSave_clicked(self, widget, *args): file_name = self.txtProfileName.get_text() #first check if this name already exists in the 'preset' profiles #or USER_PROFILES_DIR if profiles.mlt_profiles(self.project).profile_exists(file_name): messagebox.show( "Openshot", _("A profile with this name already exists. Please use another name." )) return True else: self.save_profile()
def validate(self, form): """ Validate the upload form... check for missing values. """ # get reference to gettext _ = self._ # get settings title = form.txtTitle.get_text() start, end = form.txtDescription.get_buffer().get_bounds() description = form.txtDescription.get_buffer().get_text(start, end) username = form.txtUsername.get_text() password = form.txtPassword.get_text() # Validate the the form is valid if not os.path.isfile(str(self.filename)): # Show error message messagebox.show( _("Validation Error!"), _("Please choose a valid video file.")) return False if not title: # Show error message messagebox.show( _("Validation Error!"), _("Please enter a valid title.")) return False if not description: # Show error message messagebox.show( _("Validation Error!"), _("Please enter a valid description.")) return False if not username: # Show error message messagebox.show( _("Validation Error!"), _("Please enter a valid username.")) return False else: # save username self.settings.app_state["upload_username"] = username if not password: # Show error message messagebox.show( _("Validation Error!"), _("Please enter a valid password.")) return False # form is valid return True
def validate(self, form): """ Validate the upload form... check for missing values. """ # get reference to gettext _ = self._ # get settings title = form.txtTitle.get_text() start, end = form.txtDescription.get_buffer().get_bounds() description = form.txtDescription.get_buffer().get_text(start, end) username = form.txtUsername.get_text() password = form.txtPassword.get_text() # Validate the the form is valid if not os.path.isfile(str(self.filename)): # Show error message messagebox.show(_("Validation Error!"), _("Please choose a valid video file.")) return False if not title: # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid title.")) return False if not description: # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid description.")) return False if not username: # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid username.")) return False else: # save username self.settings.app_state["upload_username"] = username if not password: # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid password.")) return False # form is valid return True
def on_btnExportXML_clicked(self, widget, *args): #print "on_btnExportXML_clicked called with self.%s" % widget.get_name() # Get selected file name file_to_save = self.frmExportXML.get_filename() try: # Call the GenerateXML method on the project self.project.GenerateXML(file_to_save) # close window self.frmExportXML.destroy() except: # show the error message messagebox.show(_("Error!"), _("There was an error saving this project as XML."))
def AddFolder(self, folder_name, project=None): """Add a new folder to the current folder""" #does this folder name already exist? if self.FindFolder(folder_name): messagebox.show(_("OpenShot Error"), _("The folder %s already exists in this project." % folder_name)) return newFolder = OpenShotFolder(project) newFolder.name = folder_name self.items.append(newFolder) #set the modified status self.project.set_project_modified(is_modified=True, refresh_xml=False, type=_("Added folder")) self.project.form.refresh()
def on_btnOpenProject_clicked(self, widget, *args): #print "on_btnOpenProject_clicked called with self.%s" % widget.get_name() # Get selected file name file_to_open = self.frmOpenProject.get_filename() try: # Call the Open method on the main form self.form.open_project(file_to_open) # close window self.frmOpenProject.destroy() except: # show the error message messagebox.show(_("Error!"), _("There was an error opening this project file. Please be sure you open the correct *.osp file."))
def on_btnAuthorize_clicked(self, widget, *args): print "on_btnAuthorize_clicked" # get translation object _ = self._ if self.cboUploadService.get_active_text(): service_name = str(self.cboUploadService.get_active_text()) service = self.upload_services[service_name] try: # launch verification URL in webbrowser import webbrowser webbrowser.open(service.get_authorization_url()) except: messagebox.show(_("Error!"), _("Unable to open the verification web page."))
def on_cboSimpleQuality_changed(self, widget, *args): # get reference to gettext _ = self._ #don't do anything if the combo has been cleared if self.cboSimpleQuality.get_active_text(): # reset the invalid codecs list self.invalid_codecs = [] # Get the quality quality = str(self.cboSimpleQuality.get_active_text()) #set the attributes in the advanced tab #video format self.set_dropdown_values(self.videoformat, self.cboVIdeoFormat) #videocodec self.set_dropdown_values(self.videocodec, self.cboVideoCodec) #audiocode self.set_dropdown_values(self.audiocodec, self.cboAudioCodec) #samplerate self.set_dropdown_values(self.samplerate, self.cboSampleRate) #audiochannels self.set_dropdown_values(self.audiochannels, self.cboChannels) #video bit rate self.cboBitRate.insert_text(0,self.vbr[quality]) self.cboBitRate.set_active(0) #audio bit rate self.cboAudioBitRate.insert_text(0,self.abr[quality]) self.cboAudioBitRate.set_active(0) #check for any invalid codecs and disable #the export button if required. if self.invalid_codecs: missing_codecs = "" for codec in self.invalid_codecs: missing_codecs += codec + "\n" messagebox.show(_("Openshot Error"), _("The following formats/codecs are missing from your system:" + "\n\n" + "%s" % missing_codecs + "\nYou will not be able to use the selected export profile. You will need to install the missing formats/codecs or choose a different export profile.")) self.btnExportVideo.set_sensitive(False)
def on_btnImport_clicked(self, widget, *args): file_open = gtk.FileChooserDialog(title="Select Profile" , action=gtk.FILE_CHOOSER_ACTION_OPEN , buttons=(gtk.STOCK_CANCEL , gtk.RESPONSE_CANCEL , gtk.STOCK_OPEN , gtk.RESPONSE_OK)) #add the file filters filter = gtk.FileFilter() filter.set_name("tar archives") filter.add_pattern("*.tar.gz") filter.add_pattern("*.tar.bz2") file_open.add_filter(filter) #add the 'all files' filter""" filter = gtk.FileFilter() filter.set_name("All files") filter.add_pattern("*") file_open.add_filter(filter) if file_open.run() == gtk.RESPONSE_OK: file_name = file_open.get_filename() (dirName, filename) = os.path.split(file_name) (fileBaseName, fileExtension)=os.path.splitext(filename) if ".bz2" in fileExtension or ".gz" in fileExtension: #extract the file(s) try: tar = tarfile.open(file_name) tar.extractall(self.project.USER_PROFILES_DIR) tar.close() messagebox.show("Openshot", _("The profile has been successfully imported.")) except: messagebox.show("Openshot Error!", _("There was an error extracting the file %s" % filename)) else: #regular file - just copy it to the user profiles folder # get file name, path, and extention try: shutil.copyfile(file_name, os.path.join(self.project.USER_PROFILES_DIR, fileBaseName)) messagebox.show("Openshot", _("The profile has been successfully imported.")) except: messagebox.show("Openshot Error!", _("There was an error copying the file %s" % filename)) #add the new profile to the dropdown #clear the combo & repopulate - we can't just add the filename if it was a tar.gz model = self.cmbProjectType.get_model() model.clear() self.get_profiles_list() #set the default profile self.set_project_type_dropdown(fileBaseName) file_open.destroy()
def error_with_blender(self, version=None, command_output=None): """ Show a friendly error message regarding the blender executable or version. """ _ = self._ version_message = "" if version: version_message = _("\n\nVersion Detected:\n%s") % version if command_output: version_message = _("\n\nError Output:\n%s") % command_output # show error message blender_version = "2.62" messagebox.show(_("Blender Error"), _("Blender, the free open source 3D content creation suite is required for this action (http://www.blender.org).\n\nPlease check the preferences in OpenShot and be sure the Blender executable is correct. This setting should be the path of the 'blender' executable on your computer. Also, please be sure that it is pointing to Blender version %s or greater.\n\nBlender Path:\n%s%s") % (blender_version, self.form.settings.general["blender_command"], version_message)) # Enable the Render button again self.btnRender.set_sensitive(True)
def initialize(self, form): """ Prepare the upload form for this service """ # test the authentication if self.token: try: self.v = VimeoClient( token=self.token, token_secret=self.token_secret, verifier=self.verifier) self.v.cache_timeout = 0 self.uploader = self.v.get_uploader() except: # failed to authenticate, erase tokens self.token = None self.token_secret = None self.verifier = None self.settings.app_state["vimeo_token"] = "" self.settings.app_state["vimeo_token_secret"] = "" self.settings.app_state["vimeo_verifier"] = "" # Show error message messagebox.show( _("Validation Error!"), _("Vimeo authentication has expired.")) self.form = form form.lblUsername.set_property("visible", False) form.txtUsername.set_property("visible", False) form.lblPassword.set_property("visible", False) form.txtPassword.set_property("visible", False) if self.token: # already authorized form.login_divider.set_property("visible", False) form.btnAuthorize.set_property("visible", False) form.lblVerification.set_property("visible", False) form.txtVerification.set_property("visible", False) else: # user needs to authorize OpenShot form.login_divider.set_property("visible", True) form.btnAuthorize.set_property("visible", True) form.lblVerification.set_property("visible", True) form.txtVerification.set_property("visible", True) form.lnkForgot.set_label("http://www.vimeo.com") form.lnkForgot.set_uri("http://www.vimeo.com")
def writeToFile(self, xmldoc): '''writes a new svg file containing the user edited data''' project_path = os.path.join(self.project.folder, "thumbnail") if not self.filename.endswith("svg"): self.filename = self.filename + ".svg" try: if self.filename.startswith(project_path) == False: file = open(os.path.join(project_path,self.filename), "wb") #wb needed for windows support self.filename = os.path.join(project_path, self.filename) else: file = open(self.filename, "wb") #wb needed for windows support file.write(xmldoc.toxml()) file.close() #Now the file is ready to import into the project. self.btnApply.set_sensitive(True) except IOError, inst: messagebox.show(_("OpenShot Error"), _("Unexpected Error '%s' while writing to '%s'." % (inst, self.filename)))
def on_cboSimpleVideoProfile_changed(self, widget, *args): # get reference to gettext _ = self._ #don't do anything if the combo has been cleared if self.cboSimpleVideoProfile.get_active_text(): profile = str(self.cboSimpleVideoProfile.get_active_text()) #does this profile exist? p = profiles.mlt_profiles(self.project).get_profile(profile) if str(p.description()) != profile: messagebox.show(_("Error!"), _("%s is not a valid OpenShot profile. Profile settings will not be applied." % profile)) self.init_properties(profile) #set the value of the project type dropdown on the advanced tab self.set_dropdown_values(profile,self.cmbProjectType)
def on_btnOpenProject_clicked(self, widget, *args): #print "on_btnOpenProject_clicked called with self.%s" % widget.get_name() # Get selected file name file_to_open = self.frmOpenProject.get_filename() try: # Call the Open method on the main form self.form.open_project(file_to_open) # close window self.frmOpenProject.destroy() except: # show the error message messagebox.show( _("Error!"), _("There was an error opening this project file. Please be sure you open the correct *.osp file." ))
def AddFolder(self, folder_name, project=None): # get a reference to the language translate method _ = self.project.translate """Add a new folder to the current folder""" #does this folder name already exist? if self.FindFolder(folder_name): messagebox.show(_("LibreShot Error"), _("The folder %s already exists in this project." % folder_name)) return newFolder = LibreShotFolder(project) newFolder.name = folder_name self.items.append(newFolder) #set the modified status self.project.set_project_modified(is_modified=True, refresh_xml=False, type=_("Added folder")) self.project.form.refresh_files()
def initialize(self, form): """ Prepare the upload form for this service """ # test the authentication if self.token: try: self.v = VimeoClient(token=self.token, token_secret=self.token_secret, verifier=self.verifier) self.v.cache_timeout = 0 self.uploader = self.v.get_uploader() except: # failed to authenticate, erase tokens self.token = None self.token_secret = None self.verifier = None self.settings.app_state["vimeo_token"] = "" self.settings.app_state["vimeo_token_secret"] = "" self.settings.app_state["vimeo_verifier"] = "" # Show error message messagebox.show(_("Validation Error!"), _("Vimeo authentication has expired.")) self.form = form form.lblUsername.set_property("visible", False) form.txtUsername.set_property("visible", False) form.lblPassword.set_property("visible", False) form.txtPassword.set_property("visible", False) if self.token: # already authorized form.login_divider.set_property("visible", False) form.btnAuthorize.set_property("visible", False) form.lblVerification.set_property("visible", False) form.txtVerification.set_property("visible", False) else: # user needs to authorize OpenShot form.login_divider.set_property("visible", True) form.btnAuthorize.set_property("visible", True) form.lblVerification.set_property("visible", True) form.txtVerification.set_property("visible", True) form.lnkForgot.set_label("http://www.vimeo.com") form.lnkForgot.set_uri("http://www.vimeo.com")
def on_cboSimpleVideoProfile_changed(self, widget, *args): # get reference to gettext _ = self._ #don't do anything if the combo has been cleared if self.cboSimpleVideoProfile.get_active_text(): profile = str(self.cboSimpleVideoProfile.get_active_text()) #does this profile exist? p = profiles.mlt_profiles(self.project).get_profile(profile) if str(p.description()) != profile: messagebox.show(_("Error!"), _("%s is not a valid LibreShot profile. Profile settings will not be applied." % profile)) self.init_properties(profile) #set the value of the project type dropdown on the advanced tab self.set_dropdown_values(profile,self.cmbProjectType)
def on_btnUpload_clicked(self, widget, *args): print "on_btnUpload_clicked" _ = self._ if self.cboUploadService.get_active_text(): # get upload service service_name = str(self.cboUploadService.get_active_text()) service = self.upload_services[service_name] if service.validate(self): print "form is valid!" # start upload status = service.start_upload(self) # did upload succeed? if status == True: # prompt user that export is completed if has_py_notify: try: # Use libnotify to show the message (if possible) if pynotify.init("LibreShot Video Editor"): n = pynotify.Notification( _("Upload Successful!"), _("Your video has been successfully uploaded!" )) n.show() except: # use a GTK messagebox messagebox.show( _("Upload Successful!"), _("Your video has been successfully uploaded!") ) else: # use a GTK messagebox messagebox.show( _("Upload Successful!"), _("Your video has been successfully uploaded!")) # close the window self.frmUploadVideo.destroy()
def on_btnCreate_clicked(self,widget): # get translation method _ = self._ #prompt the user for a file name self.filename = self.setTitleName() if self.filename == "": messagebox.show(_("LibreShot Error"), _("The Title name cannot be blank, the title file has not been created.")) return #load the template doc to read xml self.load_svg_template(self.template_name) self.update_font_color_button() self.update_background_color_button() #set the new filename (fileBaseName, fileExtension)=os.path.splitext(self.template_name) self.filename = self.filename + fileExtension #write the new file self.writeToFile(self.xmldoc) #show the text editor if self.noTitles == False: if not self.on_btnEditText_clicked(widget): return #set edit button states self.btnEditText.set_sensitive(True) self.btnFont.set_sensitive(True) self.btnFontColor.set_sensitive(True) self.btnBackgroundColor.set_sensitive(True) self.btnAdvanced.set_sensitive(True) #preview the file self.set_img_pixbuf(self.filename) #turn off the create button once we have created the new file self.btnCreate.set_sensitive(False) self.cmbTemplate.set_sensitive(False) if self.noTitles == True: self.btnEditText.set_sensitive(False) self.btnFont.set_sensitive(False) self.btnFontColor.set_sensitive(False)
def on_btnAdd_clicked(self, widget, *args): files_to_add = self.frmAddFiles.get_filenames() try: for file in files_to_add: # add each file self.project.project_folder.AddFile(file) #set the project as modified self.project.set_project_modified(is_modified=True, refresh_xml=False) # refresh the main form self.form.refresh() except: messagebox.show(_("Error"), _("There was an error importing the selected files")) #set the last used folder preferences.Settings.app_state["import_folder"] = self.frmAddFiles.get_current_folder() self.frmAddFiles.destroy()
def writeToFile(self, xmldoc): '''writes a new svg file containing the user edited data''' project_path = os.path.join(self.project.folder, "thumbnail") # get translation method _ = self._ if not self.filename.endswith("svg"): self.filename = self.filename + ".svg" try: if self.filename.startswith(project_path) == False: file = open(os.path.join(project_path,self.filename), "wb") #wb needed for windows support self.filename = os.path.join(project_path, self.filename) else: file = open(self.filename, "wb") #wb needed for windows support file.write(xmldoc.toxml()) file.close() #Now the file is ready to import into the project. self.btnApply.set_sensitive(True) except IOError, inst: messagebox.show(_("LibreShot Error"), _("Unexpected Error '%s' while writing to '%s'." % (inst, self.filename)))
def on_btnCreateProject_clicked(self, widget, *args): print "on_btnCreateProject_clicked called with self.%s" % widget.get_name() extension = ".osp" localName = str.strip(self.txtProjectName.get_text()) localFolder = str.strip(self.fileProjectFolder.get_filename()) localType = self.cmbProjectType.get_active_text() # Validate the the form is valid if (len(localName) == 0): # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid project name.")) elif (localType == - 1): # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid project type.")) else: path = os.path.join(localFolder, localName + extension) # Control if the file already exists if os.path.exists(path): # Show confirm box messagebox.show(_("Confirm Overwrite"), _("There is already a project named %s%s in the selected folder. Would you like to overwrite it?") % (localName, extension), gtk.BUTTONS_YES_NO, self.create_project) else: self.create_project()
def on_btnCreateProject_clicked(self, widget, *args): print "on_btnCreateProject_clicked called with self.%s" % widget.get_name( ) extension = ".osp" localName = str.strip(self.txtProjectName.get_text()) localFolder = str.strip(self.fileProjectFolder.get_filename()) localType = self.cmbProjectType.get_active_text() # Validate the the form is valid if (len(localName) == 0): # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid project name.")) elif (localType == -1): # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid project type.")) else: path = os.path.join(localFolder, localName + extension) # Control if the file already exists if os.path.exists(path): # Show confirm box messagebox.show( _("Confirm Overwrite"), _("There is already a project named %s%s in the selected folder. Would you like to overwrite it?" ) % (localName, extension), gtk.BUTTONS_YES_NO, self.create_project) else: self.create_project()
def error_with_blender(self, version=None, command_output=None): """ Show a friendly error message regarding the blender executable or version. """ _ = self._ version_message = "" if version: version_message = _("\n\nVersion Detected:\n%s") % version if command_output: version_message = _("\n\nError Output:\n%s") % command_output # show error message blender_version = "2.62" messagebox.show( _("Blender Error"), _("Blender, the free open source 3D content creation suite is required for this action (http://www.blender.org).\n\nPlease check the preferences in LibreShot and be sure the Blender executable is correct. This setting should be the path of the 'blender' executable on your computer. Also, please be sure that it is pointing to Blender version %s or greater.\n\nBlender Path:\n%s%s" ) % (blender_version, self.form.settings.general["blender_command"], version_message)) # Enable the Render button again self.btnRender.set_sensitive(True)
def on_btnAdvanced_clicked(self, widget): # get translation method _ = self._ #use an external editor to edit the image try: prog = "inkscape" #check if inkscape is installed if subprocess.call('which ' + prog + ' 2>/dev/null', shell=True) == 0: # launch Inkscape p=subprocess.Popen([prog, self.filename]) # wait for process to finish (so we can updated the preview) p.communicate() # update image preview self.set_img_pixbuf(self.filename) else: messagebox.show(_("OpenShot Error"), _("Please install %s to use this function.") % prog.capitalize()) except OSError: messagebox.show(_("OpenShot Error"), _("There was an error opening '%s', is it installed?") % prog)
def on_btnAdvanced_clicked(self, widget): # get translation method _ = self._ #use an external editor to edit the image try: prog = "inkscape" #check if inkscape is installed if subprocess.call('which ' + prog + ' 2>/dev/null', shell=True) == 0: # launch Inkscape p=subprocess.Popen([prog, self.filename]) # wait for process to finish (so we can updated the preview) p.communicate() # update image preview self.set_img_pixbuf(self.filename) else: messagebox.show(_("LibreShot Error"), _("Please install %s to use this function.") % prog.capitalize()) except OSError: messagebox.show(_("LibreShot Error"), _("There was an error opening '%s', is it installed?") % prog)
def validate(self, form): """ Validate the upload form... check for missing values. """ # get reference to gettext _ = self._ # get code verification_code = form.txtVerification.get_text() title = form.txtTitle.get_text() start, end = form.txtDescription.get_buffer().get_bounds() description = form.txtDescription.get_buffer().get_text(start, end) # Validate the the form is valid if not os.path.isfile(str(self.filename)): # Show error message messagebox.show(_("Validation Error!"), _("Please choose a valid video file.")) return False if not title: # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid title.")) return False if not self.token: if not description: # Show error message messagebox.show(_("Validation Error!"), _("Please enter a valid description.")) return False if not verification_code: # Show error message messagebox.show( _("Validation Error!"), _("Please enter a valid verification code. Click the 'Authorize' button and login to the website. Confirm the authorization, and copy the verification code." )) return False # form is valid return True
def on_btnAdd_clicked(self, widget, *args): print "on_btnAdd_clicked" # get reference to gettext _ = self._ # get settings new_clip = None start_time = self.txtStartTime.get_value() trackA_name = self.cboTrackA.get_active_text() trackA_object = None trackB_name = self.cboTrackB.get_active_text() trackB_object = None fade_name = self.cboFade.get_active_text() fade_length = self.txtFadeLength.get_value() transition_name = self.cboTransition.get_active_text() transition_file_path = None transition_length = self.txtTransitionLength.get_value() #animation = self.cboAnimation.get_active_text() use_transitions = True use_random = False if transition_name == _("No Transition"): # do not use a transition use_transitions = False elif transition_name == _("Random Transition"): # random transitions use_random = True else: # get the file path of the transition transition_file_path = self.transitions[transition_name] # get actual track objects for track in self.project.sequences[0].tracks: if trackA_name == track.name: trackA_object = track if trackB_name == track.name: trackB_object = track # Validate the the top track is above the bottom track if self.project.sequences[0].tracks.index( trackA_object) >= self.project.sequences[0].tracks.index( trackB_object): # Show error message messagebox.show( _("Validation Error!"), _("The top track must be higher than the bottom track.")) return # init the start position / time position = start_time location = "top" current_track = trackA_object # loop through all files (in tree order) for file in self.selected_files: # Get filename (dirName, fileName) = os.path.split(file.name) # Add clips to track 1 new_clip = current_track.AddClip(fileName, "Gold", position, float(0.0), float(file.length), file) # Apply Fade settings if fade_name == _("Fade In"): new_clip.audio_fade_in = True new_clip.video_fade_in = True new_clip.audio_fade_in_amount = fade_length new_clip.video_fade_in_amount = fade_length elif fade_name == _("Fade Out"): new_clip.audio_fade_out = True new_clip.video_fade_out = True new_clip.audio_fade_out_amount = fade_length new_clip.video_fade_out_amount = fade_length elif fade_name == _("Fade In & Out"): new_clip.audio_fade_in = True new_clip.video_fade_in = True new_clip.audio_fade_out = True new_clip.video_fade_out = True new_clip.audio_fade_in_amount = fade_length new_clip.audio_fade_out_amount = fade_length new_clip.video_fade_in_amount = fade_length new_clip.video_fade_out_amount = fade_length # increment position if use_transitions: # adjust the position based on the transition length position = position + new_clip.length() - transition_length else: position = position + new_clip.length() # Add transition (if needed) if use_transitions: # if a random transition, choose a random one if use_random: random_transition = random.choice(self.transitions.items()) transition_name = random_transition[0] transition_file_path = random_transition[1] # add the transition new_trans = trackA_object.AddTransition( transition_name, position, transition_length, transition_file_path) if location == "top": new_trans.reverse = True # change tracks (if needed) if use_transitions: if current_track == trackA_object: location = "bottom" current_track = trackB_object else: current_track = trackA_object location = "top" # Does timeline need to be expanded? if new_clip: self.form.expand_timeline(new_clip) #mark the project as modified self.project.set_project_modified(is_modified=True, refresh_xml=True, type="Added files to timeline") # close this window self.frmAddToTimeline.destroy() # refresh the main form & timeline self.form.refresh()
def GetFile(self, file_location, only_thumbnail=True, new_file_base_name=None, start_time=0.00, end_time=None): """ Use this method to generate an LibreShotFile object based on the URL (or file location) of a video or audio file. Each time you call this method, it will lock this thread (and LibreShot's main thread) until it has finished. """ """ file_location: The location of the file on the hard drive, including the name and extension. only_thumbnail: True if only a thumbnail should be grabbed from the file, False if image sequence. new_file_base_name: The name of the folder and the base for the image sequence name, not including the path. start_time: The time to start grabbing frames from the file, in seconds. end_time: The time to end grabbing frames from the file, in seconds. None = To the last frame. """ try: # determine name and location of thumbnail image self.file_name = file_location self.thumbnail_path = "" self.file_type = "video" self.label = "" self.unique_id = str(uuid.uuid1()) project_path = self.project.folder (dirName, fileName) = os.path.split(file_location) (fileBaseName, fileExtension) = os.path.splitext(fileName) fileExtension = fileExtension.replace(".", "") uniqueFileBaseName = self.unique_id actual_thumbnail_path = project_path + "/thumbnail/" + uniqueFileBaseName + "_" + fileExtension + "_1.png" if only_thumbnail: # just get 1 thumbnail frame self.thumbnail_path = project_path + "/thumbnail/" + uniqueFileBaseName + "_" + fileExtension + "_%d.png" # set the profile self.profile = mlt.Profile("quarter_ntsc") else: if new_file_base_name == None or new_file_base_name == fileBaseName: # choose the same folder as the name (without extension) as default self.thumbnail_path = os.path.join( dirName, fileBaseName, fileBaseName + "_%d.png") else: # export a part of the video to a folder under the folder with the same name as the file. self.thumbnail_path = os.path.join( dirName, fileBaseName, new_file_base_name, new_file_base_name + "_%d.png") # re-init the mlt factory mlt.Factory.init() # Create the producer self.p = mlt.Producer(self.profile, '%s' % file_location) # Check if clip is valid (otherwise a seg fault) if self.p.is_valid() == False: return None # Check for invalid files - badly generated video files can have # a length of 0 or -1, e.g. # https://bugs.launchpad.net/ubuntu/+source/libreshot/+bug/927755, https://bugs.launchpad.net/kazam/+bug/925238 if self.p.get_length() < 1 or self.p.get_length() == 0x7fffffff: return None # check the 'seekable' property # If it is zero, then MLT is likely to have problems with this file. if self.p.get("seekable") == '0': messagebox.show( _("Warning!"), _("The file %s has properties that may prevent it working properly in LibreShot.\nYou may need to transcode it to another format." ) % (self.file_name)) # create the consumer self.c = mlt.Consumer(self.profile, "avformat", self.thumbnail_path) # set some consumer properties self.c.set("real_time", 0) self.c.set("vcodec", "png") # determine length of clip in seconds producer_fps = float(self.p.get_fps()) first_frame = int(round(producer_fps * start_time)) # Whole clip if end_time = None if end_time == None: last_frame = self.p.get_length() else: last_frame = int(round(producer_fps * end_time)) max_frames = last_frame - first_frame # determine dimensions height = 0 width = 0 if self.p.get("height"): height = int(self.p.get("height")) if self.p.get("width"): width = int(self.p.get("width")) audio_index = self.p.get_int("audio_index") video_index = self.p.get_int("video_index") audio_property = "meta.media.%s.codec.long_name" % audio_index if self.p.get(audio_property): self.audio_codec = self.p.get(audio_property) else: self.audio_codec = "" video_property = "meta.media.%s.codec.long_name" % video_index if self.p.get(video_property): self.video_codec = self.p.get(video_property) else: self.video_codec = "" if self.p.get_frame(): frame = self.p.get_frame() self.audio_frequency = frame.get_int("frequency") self.audio_channels = frame.get_int("channels") # determine if this is an image is_image = False if self.p.get_length( ) == 15000 and video_index == 0 and audio_index == 0: # images always have exactly 15000 frames is_image = True self.file_type = "image" # set the max length of the image to 300 seconds (i.e. 5 minutes) max_frames = producer_fps * 300 # get actual height & width of image (since MLT defaults to 1 x 1) width, height = self.get_image_size(file_location) # determine length if only_thumbnail: calculate_length = self.p.get_length() / producer_fps else: calculate_length = max_frames / producer_fps if is_image: # set the length to 300 seconds (i.e. 5 minutes) calculate_length = float(300) # set thumbnail image (if no height & width are detected) if (height == False or width == False) and (is_image == False): self.thumbnail_path = "" self.file_type = "audio" # get the 1st frame (if not exporting all frames) if only_thumbnail: max_frames = float(self.p.get_length()) - 1.0 self.p = self.p.cut(1, 1) # get the frames in an interval else: self.p = self.p.cut(first_frame, last_frame) # mark as image seq self.label = "Image Sequence" self.file_type = "image sequence" # Check if clip is valid (otherwise a seg fault) if self.p.is_valid() == False: return None # connect the producer and consumer self.c.connect(self.p) # Start the consumer, and lock the thread until it's done (to prevent crazy seg fault errors) # Only start if the media item has a thumbnail location (i.e. no audio thumbnails) if self.thumbnail_path: self.c.run() # create an libreshot file object newFile = files.LibreShotFile(self.project) # thumbnails and image sequences are stored at different locations if only_thumbnail: newFile.name = file_location else: newFile.name = self.thumbnail_path newFile.length = calculate_length newFile.thumb_location = actual_thumbnail_path newFile.videorate = (self.p.get_fps(), 0) newFile.height = height newFile.width = width newFile.max_frames = max_frames newFile.fps = producer_fps newFile.file_type = self.file_type newFile.label = self.label newFile.audio_channels = self.audio_channels newFile.audio_codec = self.audio_codec newFile.audio_frequency = self.audio_frequency newFile.video_codec = self.video_codec # return the LibreShotFile object return newFile except Exception: print "Failed to import file: %s" % file_location
def save_profile(self): #check we have all the data populated if self.txtProfileName.get_text() == "": messagebox.show("Openshot Error!", _("Please enter a profile name.")) self.txtProfileName.grab_focus() return if self.spnSizeHeight.get_text() == "0" or self.spnSizeWidth == "0": messagebox.show("Openshot Error!", _("Please enter a valid size.")) return ####create the profile file#### filename = self.txtProfileName.get_text() if self.chkProgressive.get_active(): progressive = '1' else: progressive = '0' f = open(os.path.join(self.project.USER_PROFILES_DIR, filename), 'w') f.write("description=" + filename + '\n') f.write("frame_rate_num=" + self.spnFrameRate1.get_text() + '\n') f.write("frame_rate_den=" + self.spnFrameRate2.get_text() + '\n') f.write("width=" + self.spnSizeWidth.get_text() + '\n') f.write("height=" + self.spnSizeHeight.get_text() + '\n') f.write("progressive=" + progressive + '\n') f.write("sample_aspect_num=" + self.spnPixelRatio1.get_text() + '\n') f.write("sample_aspect_den=" + self.spnPixelRatio2.get_text() + '\n') f.write("display_aspect_num=" + self.spnAspect1.get_text() + '\n') f.write("display_aspect_den=" + self.spnAspect2.get_text() + '\n') f.close() # reload parent window's list of profiles self.parent.populate_profiles() #check for default profile if self.chkDefaultProfile.get_active(): # change default profile self.parent.set_default_profile(filename) else: # re-select the default profile self.parent.set_default_profile( self.form.settings.general["default_profile"]) #reactivate the drop down self.cmbProjectType.set_sensitive(False) self.btnSave.set_sensitive(False) #disable the spinbuttons self.spnSizeHeight.set_sensitive(False) self.spnSizeWidth.set_sensitive(False) self.lblSize.set_sensitive(False) self.spnAspect1.set_sensitive(False) self.spnAspect2.set_sensitive(False) self.lblAspect.set_sensitive(False) self.spnPixelRatio1.set_sensitive(False) self.spnPixelRatio2.set_sensitive(False) self.lblPixel.set_sensitive(False) self.chkProgressive.set_sensitive(False) self.chkDefaultProfile.set_sensitive(False) self.txtProfileName.set_sensitive(False) self.lblProfile.set_sensitive(False) self.spnFrameRate1.set_sensitive(False) self.spnFrameRate2.set_sensitive(False) self.lblFrame.set_sensitive(False) self.btnSave.set_sensitive(False) #enable the drop down self.cmbProjectType.set_sensitive(True) #add the newly saved profile to the combo self.cmbProjectType.append_text(filename) self.set_project_type_dropdown(filename) self.save_prompt = False
def on_btnImport_clicked(self, widget, *args): file_open = gtk.FileChooserDialog( title="Select Profile", action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) #add the file filters filter = gtk.FileFilter() filter.set_name("tar archives") filter.add_pattern("*.tar.gz") filter.add_pattern("*.tar.bz2") file_open.add_filter(filter) #add the 'all files' filter""" filter = gtk.FileFilter() filter.set_name("All files") filter.add_pattern("*") file_open.add_filter(filter) if file_open.run() == gtk.RESPONSE_OK: file_name = file_open.get_filename() (dirName, filename) = os.path.split(file_name) (fileBaseName, fileExtension) = os.path.splitext(filename) if ".bz2" in fileExtension or ".gz" in fileExtension: #extract the file(s) try: tar = tarfile.open(file_name) tar.extractall(self.project.USER_PROFILES_DIR) tar.close() messagebox.show( "Openshot", _("The profile has been successfully imported.")) except: messagebox.show( "Openshot Error!", _("There was an error extracting the file %s" % filename)) else: #regular file - just copy it to the user profiles folder # get file name, path, and extention try: shutil.copyfile( file_name, os.path.join(self.project.USER_PROFILES_DIR, fileBaseName)) messagebox.show( "Openshot", _("The profile has been successfully imported.")) except: messagebox.show( "Openshot Error!", _("There was an error copying the file %s" % filename)) #add the new profile to the dropdown #clear the combo & repopulate - we can't just add the filename if it was a tar.gz model = self.cmbProjectType.get_model() model.clear() self.get_profiles_list() #set the default profile self.set_project_type_dropdown(fileBaseName) file_open.destroy()
def on_btnAdd_clicked(self, widget, *args): files_to_add = self.frmAddFiles.get_filenames() # get a reference to the language translate method _ = self.project.translate # create a unique session id, to prevent duplicate prompts session = str(time.time()) # The total number of ok files selected (not folders) total_ok_files = 0 # The total number of broken files selected (could not be imported) total_broken_files = 0 # The total number of files already imported selected total_duplicate_files = 0 # The total number of folders selected total_folders = 0 try: for file in files_to_add: # add each file result = self.project.project_folder.AddFile(file, session=session) # parse the results and add to the total total_ok_files += result[0] total_broken_files += result[1] total_duplicate_files += result[2] total_folders += result[3] # The number of total selected files, not including folders total_files = total_ok_files + total_broken_files + total_duplicate_files # print error messages (if needed) if total_files == 0: if total_folders == 1: messagebox.show(_("Empty Folder "), _("The selected folder was empty.")) else: messagebox.show(_("Empty Folders"), _("The selected folders were empty.")) else: if total_files == total_broken_files: if total_files == 1: messagebox.show( _("Unsupported File Type"), _("LibreShot does not support this file type.")) else: messagebox.show( _("Unsupported File Types"), _("LibreShot supports none of the file types of the selected files." )) elif total_files == total_duplicate_files: if total_files == 1: messagebox.show( _("Already Imported File"), _("The selected file has already been imported to the project." )) else: messagebox.show( _("Already Imported Files"), _("All of the selected files have already been imported to the project." )) elif total_ok_files == 0: messagebox.show( _("File Import Error"), _("The selected files either have an unsupported file type or have already been imported to the project." )) # set the project as modified self.project.set_project_modified(is_modified=True, refresh_xml=False) # refresh the main form self.form.refresh_files() except: messagebox.show( _("Error"), _("There was an error importing the selected file(s).")) #set the last used folder current_folder = self.frmAddFiles.get_current_folder() if current_folder is None: current_folder = "None" preferences.Settings.app_state["import_folder"] = current_folder # clear and destroy this dialog self.form.import_files_dialog = None self.frmAddFiles.destroy()