def _startupCb(self, unused_app): # Init logging as early as possible so we can log startup code enable_color = not os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '1') # Let's show a human-readable Pitivi debug output by default, and only # show a crazy unreadable mess when surrounded by gst debug statements. enable_crack_output = "GST_DEBUG" in os.environ log.init('PITIVI_DEBUG', enable_color, enable_crack_output) self.info('starting up') self.settings = GlobalSettings() self.threads = ThreadMaster() self.effects = EffectsManager() self.system = getSystem() self.action_log.connect("commit", self._actionLogCommit) self.action_log.connect("undo", self._actionLogUndo) self.action_log.connect("redo", self._actionLogRedo) self.action_log.connect("cleaned", self._actionLogCleaned) self.timeline_log_observer = TimelineLogObserver(self.action_log) self.project_log_observer = ProjectLogObserver(self.action_log) self.project_manager.connect("new-project-loaded", self._newProjectLoaded) self.project_manager.connect("project-closed", self._projectClosed) self._createActions() self._checkVersion()
def __create_settings(proxyingStrategy=ProxyingStrategy.NOTHING, numTranscodingJobs=4, **additional_settings): settings = GlobalSettings() settings.proxyingStrategy = proxyingStrategy settings.numTranscodingJobs = numTranscodingJobs for key, value in additional_settings.items(): setattr(settings, key, value) return settings
def test_read_config_file(self): GlobalSettings.addConfigSection("section-1") GlobalSettings.addConfigOption("section1OptionA", section="section-1", key="option-a", default=50) GlobalSettings.addConfigOption("section1OptionB", section="section-1", key="option-b", default=False) GlobalSettings.addConfigOption("section1OptionC", section="section-1", key="option-c", default="") self.assertEqual(GlobalSettings.section1OptionA, 50) self.assertEqual(GlobalSettings.section1OptionB, False) self.assertEqual(GlobalSettings.section1OptionC, "") conf_file_content = ("[section-1]\n" "option-a = 10\n" "option-b = True\n" "option-c = Pigs fly\n") with mock.patch("pitivi.settings.xdg_config_home") as xdg_config_home,\ tempfile.TemporaryDirectory() as temp_dir: with open(os.path.join(temp_dir, "pitivi.conf"), "w") as tmp_file: tmp_file.write(conf_file_content) xdg_config_home.return_value = temp_dir settings = GlobalSettings() self.assertEqual(settings.section1OptionA, 10) self.assertEqual(settings.section1OptionB, True) self.assertEqual(settings.section1OptionC, "Pigs fly")
def test_add_config_option(self): def add_option(): GlobalSettings.addConfigOption("optionA1", section="section-a", key="option-a-1", default=False) # "section-a" does not exist. with self.assertRaises(ConfigError): add_option() GlobalSettings.addConfigSection("section-a") add_option() self.assertFalse(GlobalSettings.optionA1) with self.assertRaises(ConfigError): add_option()
def _setup(self): self.settings = GlobalSettings() self.threads = ThreadMaster() self.effects = EffectsManager() self.proxy_manager = ProxyManager(self) self.system = get_system() self.project_manager.connect("new-project-loading", self._newProjectLoadingCb) self.project_manager.connect("new-project-loaded", self._newProjectLoaded) self.project_manager.connect("project-closed", self._projectClosed) self._createActions() self._syncDoUndo()
def _startupCb(self, unused_app): # Init logging as early as possible so we can log startup code enable_color = not os.environ.get( 'PITIVI_DEBUG_NO_COLOR', '0') in ('', '1') # Let's show a human-readable Pitivi debug output by default, and only # show a crazy unreadable mess when surrounded by gst debug statements. enable_crack_output = "GST_DEBUG" in os.environ log.init('PITIVI_DEBUG', enable_color, enable_crack_output) self.info('starting up') self.settings = GlobalSettings() self.threads = ThreadMaster() self.effects = EffectsManager() self.system = getSystem() self.action_log.connect("commit", self._actionLogCommit) self.action_log.connect("undo", self._actionLogUndo) self.action_log.connect("redo", self._actionLogRedo) self.action_log.connect("cleaned", self._actionLogCleaned) self.timeline_log_observer = TimelineLogObserver(self.action_log) self.project_log_observer = ProjectLogObserver(self.action_log) self.project_manager.connect( "new-project-loading", self._newProjectLoadingCb) self.project_manager.connect( "new-project-loaded", self._newProjectLoaded) self.project_manager.connect("project-closed", self._projectClosed) self._createActions() self._checkVersion()
def __init__(self): Loggable.__init__(self) # Init logging as early as possible so we can log startup code enable_color = not os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '1') # Let's show a human-readable pitivi debug output by default, and only # show a crazy unreadable mess when surrounded by gst debug statements. enable_crack_output = "GST_DEBUG" in os.environ log.init('PITIVI_DEBUG', enable_color, enable_crack_output) self.info('starting up') self.settings = GlobalSettings() self.threads = ThreadMaster() self.effects = EffectsHandler() self.system = getSystem() self.current_project = None self.projectManager = ProjectManager(self) self._connectToProjectManager(self.projectManager) self.action_log = UndoableActionLog() self.debug_action_log_observer = DebugActionLogObserver() self.debug_action_log_observer.startObserving(self.action_log) # TODO reimplement the observing after GES port #self.timelineLogObserver = TimelineLogObserver(self.action_log) self.projectLogObserver = ProjectLogObserver(self.action_log) self._version_information = {} self._checkVersion()
def __init__(self): """ initialize pitivi with the command line arguments """ Loggable.__init__(self) # init logging as early as possible so we can log startup code enable_color = os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '0') # Let's show a human-readable pitivi debug output by default, and only # show a crazy unreadable mess when surrounded by gst debug statements. enable_crack_output = "GST_DEBUG" in os.environ log.init('PITIVI_DEBUG', enable_color, enable_crack_output) self.info('starting up') # store ourself in the instance global if instance.PiTiVi: raise RuntimeWarning( _("There is already a %s instance, please inform " "the developers by filing a bug at " "http://bugzilla.gnome.org/enter_bug.cgi?product=pitivi") % APPNAME) instance.PiTiVi = self self.current = None # get settings self.settings = GlobalSettings() self.threads = ThreadMaster() #self.screencast = False self.effects = EffectsHandler() self.system = getSystem() self.projectManager = ProjectManager(self) self._connectToProjectManager(self.projectManager) self.action_log = UndoableActionLog() self.debug_action_log_observer = DebugActionLogObserver() self.debug_action_log_observer.startObserving(self.action_log) # TODO reimplement the observing after GES port #self.timelineLogObserver = TimelineLogObserver(self.action_log) self.projectLogObserver = ProjectLogObserver(self.action_log) self.version_information = {} self._checkVersion()
def _setup(self): # pylint: disable=attribute-defined-outside-init self.settings = GlobalSettings() self.threads = ThreadMaster() self.effects = EffectsManager() self.proxy_manager = ProxyManager(self) self.system = get_system() self.plugin_manager = PluginManager(self) self.project_manager.connect("new-project-loaded", self._new_project_loaded_cb) self.project_manager.connect_after("project-closed", self._project_closed_cb) self.project_manager.connect("project-saved", self.__project_saved_cb) self._create_actions() self._sync_do_undo()
def test_write_config_file(self): GlobalSettings.addConfigSection("section-new") GlobalSettings.addConfigOption("sectionNewOptionA", section="section-new", key="option-a", default="elmo") with mock.patch("pitivi.settings.xdg_config_home") as xdg_config_home,\ tempfile.TemporaryDirectory() as temp_dir: xdg_config_home.return_value = temp_dir settings1 = GlobalSettings() settings1.sectionNewOptionA = "kermit" settings1.storeSettings() settings2 = GlobalSettings() self.assertEqual(settings2.sectionNewOptionA, "kermit")
def __init__(self): """ initialize pitivi with the command line arguments """ Loggable.__init__(self) # init logging as early as possible so we can log startup code enable_color = os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '0') log.init('PITIVI_DEBUG', enable_color) self.info('starting up') # store ourself in the instance global if instance.PiTiVi: raise RuntimeWarning( _("There is already a %s instance, please inform the developers by filing a bug at http://bugzilla.gnome.org/enter_bug.cgi?product=pitivi" ) % APPNAME) instance.PiTiVi = self self.projects = [] self.current = None # get settings self.settings = GlobalSettings() self.threads = ThreadMaster() #self.screencast = False self.plugin_manager = PluginManager( self.settings.get_local_plugin_path(), self.settings.get_plugin_settings_path()) self.effects = Magician() self.deviceprobe = get_probe() self.projectManager = ProjectManager() self._connectToProjectManager(self.projectManager) self.action_log = UndoableActionLog() self.debug_action_log_observer = DebugActionLogObserver() self.debug_action_log_observer.startObserving(self.action_log) self.timelineLogObserver = TimelineLogObserver(self.action_log) self.sourcelist_log_observer = SourceListLogObserver(self.action_log)
def _value_changed_cb(self, unused_fake_widget, real_widget, attrname): value = getattr(self.settings, attrname) if attrname not in self.original_values: self.original_values[attrname] = value if not GlobalSettings.notifies_config_option(attrname): self.restart_warning.show() self.revert_button.set_sensitive(True) value = real_widget.get_widget_value() setattr(self.settings, attrname, value) # adjust controls as appropriate self.resets[attrname].set_sensitive( not self.settings.is_default(attrname)) self.factory_settings.set_sensitive(True)
def _setup(self): self.settings = GlobalSettings() self.threads = ThreadMaster() self.effects = EffectsManager() self.proxy_manager = ProxyManager(self) self.system = get_system() self.project_manager.connect( "new-project-loading", self._newProjectLoadingCb) self.project_manager.connect( "new-project-loaded", self._newProjectLoaded) self.project_manager.connect("project-closed", self._projectClosed) self._createActions() self._syncDoUndo()
def _valueChanged(self, fake_widget, real_widget, attrname): value = getattr(self.settings, attrname) if attrname not in self.original_values: self.original_values[attrname] = value if attrname + "Changed" not in GlobalSettings.get_signals(): self.restart_warning.show() self.revert_button.set_sensitive(True) # convert the value of the widget to whatever type it is currently if value is not None: value = type(value)(real_widget.getWidgetValue()) setattr(self.settings, attrname, value) # adjust controls as appropriate self.resets[attrname].set_sensitive(not self.settings.isDefault(attrname)) self.factory_settings.set_sensitive(True)
def _valueChanged(self, fake_widget, real_widget, attrname): value = getattr(self.settings, attrname) if attrname not in self.original_values: self.original_values[attrname] = value if attrname + "Changed" not in GlobalSettings.get_signals(): self.restart_warning.show() self.revert_button.set_sensitive(True) # convert the value of the widget to whatever type it is currently if value is not None: value = type(value)(real_widget.getWidgetValue()) setattr(self.settings, attrname, value) # adjust controls as appropriate self.resets[attrname].set_sensitive( not self.settings.isDefault(attrname)) self.factory_settings.set_sensitive(True)
def __init__(self): """ initialize pitivi with the command line arguments """ Loggable.__init__(self) # init logging as early as possible so we can log startup code enable_color = os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '0') # Let's show a human-readable pitivi debug output by default, and only # show a crazy unreadable mess when surrounded by gst debug statements. enable_crack_output = "GST_DEBUG" in os.environ log.init('PITIVI_DEBUG', enable_color, enable_crack_output) self.info('starting up') # store ourself in the instance global if instance.PiTiVi: raise RuntimeWarning(_("There is already a %s instance, please inform " "the developers by filing a bug at " "http://bugzilla.gnome.org/enter_bug.cgi?product=pitivi") % APPNAME) instance.PiTiVi = self self.current = None # get settings self.settings = GlobalSettings() self.threads = ThreadMaster() #self.screencast = False self.effects = EffectsHandler() self.system = getSystem() self.projectManager = ProjectManager(self.effects) self._connectToProjectManager(self.projectManager) self.action_log = UndoableActionLog() self.debug_action_log_observer = DebugActionLogObserver() self.debug_action_log_observer.startObserving(self.action_log) # TODO reimplement the observing after GES port #self.timelineLogObserver = TimelineLogObserver(self.action_log) self.projectLogObserver = ProjectLogObserver(self.action_log) self.medialibrary_log_observer = MediaLibraryLogObserver(self.action_log) self.version_information = {} self._checkVersion()
def _valueChangedCb(self, unused_fake_widget, real_widget, attrname): # Disable missing docstring # pylint: disable=C0111 value = getattr(self.settings, attrname) if attrname not in self.original_values: self.original_values[attrname] = value if not GlobalSettings.notifiesConfigOption(attrname): self.restart_warning.show() self.revert_button.set_sensitive(True) value = real_widget.getWidgetValue() setattr(self.settings, attrname, value) # adjust controls as appropriate self.resets[attrname].set_sensitive( not self.settings.isDefault(attrname)) self.factory_settings.set_sensitive(True)
def _valueChanged(self, unused_fake_widget, real_widget, attrname): # Disable missing docstring #pylint: disable=C0111 value = getattr(self.settings, attrname) if attrname not in self.original_values: self.original_values[attrname] = value if not GlobalSettings.notifiesConfigOption(attrname): self.restart_warning.show() self.revert_button.set_sensitive(True) # convert the value of the widget to whatever type it is currently if value is not None: value = type(value)(real_widget.getWidgetValue()) setattr(self.settings, attrname, value) # adjust controls as appropriate self.resets[attrname].set_sensitive(not self.settings.isDefault(attrname)) self.factory_settings.set_sensitive(True)
def __init__(self): """ initialize pitivi with the command line arguments """ Loggable.__init__(self) # init logging as early as possible so we can log startup code enable_color = os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '0') log.init('PITIVI_DEBUG', enable_color) self.info('starting up') # store ourself in the instance global if instance.PiTiVi: raise RuntimeWarning( _("There is already a %s instance, please inform the developers by filing a bug at http://bugzilla.gnome.org/enter_bug.cgi?product=pitivi") % APPNAME) instance.PiTiVi = self self.projects = [] self.current = None # get settings self.settings = GlobalSettings() self.threads = ThreadMaster() #self.screencast = False self.plugin_manager = PluginManager( self.settings.get_local_plugin_path(), self.settings.get_plugin_settings_path()) self.effects = Magician() self.deviceprobe = get_probe() self.projectManager = ProjectManager() self._connectToProjectManager(self.projectManager) self.action_log = UndoableActionLog() self.debug_action_log_observer = DebugActionLogObserver() self.debug_action_log_observer.startObserving(self.action_log) self.timelineLogObserver = TimelineLogObserver(self.action_log) self.projectLogObserver = ProjectLogObserver(self.action_log) self.sourcelist_log_observer = SourceListLogObserver(self.action_log)
def test_read_config_file(self): GlobalSettings.addConfigSection("section-1") GlobalSettings.addConfigOption("section1OptionA", section="section-1", key="option-a", default=50) GlobalSettings.addConfigOption("section1OptionB", section="section-1", key="option-b", default=False) GlobalSettings.addConfigOption("section1OptionC", section="section-1", key="option-c", default="") GlobalSettings.addConfigOption("section1OptionD", section="section-1", key="option-d", default=[]) GlobalSettings.addConfigOption("section1OptionE", section="section-1", key="option-e", default=["foo"]) GlobalSettings.addConfigOption("section1OptionF", section="section-1", key="option-f", default=Gdk.RGBA()) self.assertEqual(GlobalSettings.section1OptionA, 50) self.assertEqual(GlobalSettings.section1OptionB, False) self.assertEqual(GlobalSettings.section1OptionC, "") self.assertEqual(GlobalSettings.section1OptionD, []) self.assertEqual(GlobalSettings.section1OptionE, ["foo"]) self.assertEqual(GlobalSettings.section1OptionF, Gdk.RGBA()) self.assertIs(GlobalSettings.options["section-1"]["section1OptionA"][0], int) self.assertIs(GlobalSettings.options["section-1"]["section1OptionB"][0], bool) self.assertIs(GlobalSettings.options["section-1"]["section1OptionC"][0], str) self.assertIs(GlobalSettings.options["section-1"]["section1OptionD"][0], list) self.assertIs(GlobalSettings.options["section-1"]["section1OptionE"][0], list) self.assertIs(GlobalSettings.options["section-1"]["section1OptionF"][0], Gdk.RGBA) conf_file_content = ("[section-1]\n" "option-a = 10\n" "option-b = True\n" "option-c = Pigs fly\n" "option-d=\n" "option-e=\n" " elmo\n" " knows\n" " where you live\n" "option-f=rgba(51,102,255,0.4)") with mock.patch("pitivi.settings.xdg_config_home") as xdg_config_home,\ tempfile.TemporaryDirectory() as temp_dir: with open(os.path.join(temp_dir, "pitivi.conf"), "w") as tmp_file: tmp_file.write(conf_file_content) xdg_config_home.return_value = temp_dir settings = GlobalSettings() self.assertEqual(settings.section1OptionA, 10) self.assertEqual(settings.section1OptionB, True) self.assertEqual(settings.section1OptionC, "Pigs fly") self.assertEqual(settings.section1OptionD, []) expected_e_value = [ "elmo", "knows", "where you live" ] self.assertEqual(settings.section1OptionE, expected_e_value) self.assertEqual(settings.section1OptionF, Gdk.RGBA(0.2, 0.4, 1.0, 0.4))
from pitivi.medialibrary import MediaLibraryWidget from pitivi.perspective import Perspective from pitivi.project import ProjectSettingsDialog from pitivi.settings import GlobalSettings from pitivi.tabsmanager import BaseTabs from pitivi.timeline.previewers import ThumbnailCache from pitivi.timeline.timeline import TimelineContainer from pitivi.transitions import TransitionsListWidget from pitivi.utils.loggable import Loggable from pitivi.utils.misc import path_from_uri from pitivi.utils.ui import beautify_time_delta from pitivi.utils.ui import EDITOR_PERSPECTIVE_CSS from pitivi.utils.ui import info_name from pitivi.viewer.viewer import ViewerContainer GlobalSettings.add_config_section("main-window") GlobalSettings.add_config_option('mainWindowHPanePosition', section="main-window", key="hpane-position", type_=int) GlobalSettings.add_config_option('mainWindowMainHPanePosition', section="main-window", key="main-hpane-position", type_=int) GlobalSettings.add_config_option('mainWindowVPanePosition', section="main-window", key="vpane-position", type_=int) GlobalSettings.add_config_option('lastProjectFolder', section="main-window", key="last-folder",
def _createDefaultConfig(self, child_name): """ If they do not exist already, create default settings to save the state of a detachable widget. """ GlobalSettings.addConfigSection(child_name) GlobalSettings.addConfigOption(child_name + "docked", section=child_name, key="docked", default=True) GlobalSettings.addConfigOption(child_name + "width", section=child_name, key="width", default=320) GlobalSettings.addConfigOption(child_name + "height", section=child_name, key="height", default=400) GlobalSettings.addConfigOption(child_name + "x", section=child_name, key="x", default=0) GlobalSettings.addConfigOption(child_name + "y", section=child_name, key="y", default=0) GlobalSettings.readSettingSectionFromFile(self.settings, child_name)
try: # We can afford to scale the images here, the impact is negligible icon = GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(self._pixdir, effect_name + ".png"), ICON_WIDTH, ICON_WIDTH) # An empty except clause is bad, but "gi._glib.GError" is not helpful. except: icon = GdkPixbuf.Pixbuf.new_from_file( os.path.join(self._pixdir, "defaultthumbnail.svg")) return icon # ----------------------- UI classes to manage effects -------------------------# HIDDEN_EFFECTS = ["frei0r-filter-scale0tilt"] GlobalSettings.addConfigSection('effect-library') (COL_NAME_TEXT, COL_DESC_TEXT, COL_EFFECT_TYPE, COL_EFFECT_CATEGORIES, COL_FACTORY, COL_ELEMENT_NAME, COL_ICON) = list(range(7)) class EffectListWidget(Gtk.VBox, Loggable): """ Widget for listing effects """ def __init__(self, instance, unused_uiman):
from pitivi.settings import GlobalSettings import cairo from pitivi.stream import VideoStream, AudioStream, TextStream, \ MultimediaStream from xml.sax.saxutils import escape from urllib import unquote from gettext import gettext as _ from gettext import ngettext GlobalSettings.addConfigSection("user-interface") LAYER_HEIGHT_EXPANDED = 50 LAYER_HEIGHT_COLLAPSED = 15 LAYER_SPACING = 5 TRACK_SPACING = 5 def pack_color_32(red, green, blue, alpha=0xFFFF): red = red >> 8 green = green >> 8 blue = blue >> 8 alpha = alpha >> 8 return (red << 24 | green << 16 | blue << 8 | alpha) def pack_color_64(red, green, blue, alpha=0xFFFF): return (red << 48 | green << 32 | blue << 16 | alpha) def unpack_color(value): if not (value >> 32): return unpack_color_32(value)
# -*- coding: utf-8 -*- from pitivi.settings import GlobalSettings import cairo from pitivi.stream import VideoStream, AudioStream, TextStream, \ MultimediaStream from xml.sax.saxutils import escape from urllib import unquote from gettext import gettext as _ from gettext import ngettext import gst import gtk GlobalSettings.addConfigSection("user-interface") LAYER_HEIGHT_EXPANDED = 50 LAYER_HEIGHT_COLLAPSED = 15 LAYER_SPACING = 15 TRACK_SPACING = 8 SPACING = 6 PADDING = 6 def pack_color_32(red, green, blue, alpha=0xFFFF): """Packs the specified 16bit color values in a 32bit RGBA value.""" red = red >> 8 green = green >> 8 blue = blue >> 8 alpha = alpha >> 8 return (red << 24 | green << 16 | blue << 8 | alpha)
from pitivi.ui.filelisterrordialog import FileListErrorDialog from pitivi.configure import get_pixmap_dir from pitivi.signalgroup import SignalGroup from pitivi.stream import VideoStream, AudioStream, TextStream, \ MultimediaStream from pitivi.settings import GlobalSettings from pitivi.utils import beautify_length from pitivi.ui.common import beautify_factory, factory_name, \ beautify_stream, PADDING from pitivi.log.loggable import Loggable from pitivi.sourcelist import SourceListError SHOW_TREEVIEW = 1 SHOW_ICONVIEW = 2 GlobalSettings.addConfigSection('clip-library') GlobalSettings.addConfigOption('lastImportFolder', section='clip-library', key='last-folder', environment='PITIVI_IMPORT_FOLDER', default=os.path.expanduser("~")) GlobalSettings.addConfigOption('closeImportDialog', section='clip-library', key='close-import-dialog-after-import', default=True) GlobalSettings.addConfigOption('lastClipView', section='clip-library', key='last-clip-view', type_=int, default=SHOW_ICONVIEW)
class Pitivi(Loggable, Signallable): """ Pitivi's main application class. Signals: - C{new-project} : A new C{Project} is loaded and ready to use. - C{new-project-loading} : Pitivi is attempting to load a new project. - C{new-project-loaded} : A new L{Project} has been loaded, and the UI should refresh it's view. - C{new-project-failed} : A new L{Project} failed to load. - C{closing-project} : pitivi would like to close a project. handlers should return false if they do not want this project to close. by default, assumes true. This signal should only be used by classes that might want to abort the closing of a project. - C{project-closed} : The project is closed, it will be freed when the callback returns. Classes should connect to this instance when they want to know that data related to that project is no longer going to be used. - C{shutdown} : Used internally, do not use this signal.` @ivar settings: Application-wide settings. @type settings: L{GlobalSettings}. @ivar projects: List of used projects @type projects: List of L{Project}. @ivar current: Currently used project. @type current: L{Project}. """ __signals__ = { "new-project": ["project"], "new-project-loading": ["uri"], "new-project-created": ["project"], "new-project-loaded": ["project"], "new-project-failed": ["uri", "exception"], "closing-project": ["project"], "project-closed": ["project"], "missing-uri": ["formatter", "uri"], "shutdown": None} def __init__(self): """ initialize pitivi with the command line arguments """ Loggable.__init__(self) # init logging as early as possible so we can log startup code enable_color = os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '0') log.init('PITIVI_DEBUG', enable_color) self.info('starting up') # store ourself in the instance global if instance.PiTiVi: raise RuntimeWarning( _("There is already a %s instance, please inform the developers by filing a bug at http://bugzilla.gnome.org/enter_bug.cgi?product=pitivi") % APPNAME) instance.PiTiVi = self self.projects = [] self.current = None # get settings self.settings = GlobalSettings() self.threads = ThreadMaster() #self.screencast = False self.plugin_manager = PluginManager( self.settings.get_local_plugin_path(), self.settings.get_plugin_settings_path()) self.effects = EffectsHandler() self.projectManager = ProjectManager(self.effects) self._connectToProjectManager(self.projectManager) self.action_log = UndoableActionLog() self.debug_action_log_observer = DebugActionLogObserver() self.debug_action_log_observer.startObserving(self.action_log) self.timelineLogObserver = TimelineLogObserver(self.action_log) self.projectLogObserver = ProjectLogObserver(self.action_log) self.sourcelist_log_observer = SourceListLogObserver(self.action_log) def shutdown(self): """ Close PiTiVi. @return: C{True} if PiTiVi was successfully closed, else C{False}. @rtype: C{bool} """ self.debug("shutting down") # we refuse to close if we're running a user interface and the user # doesn't want us to close the current project. if self.current and not self.projectManager.closeRunningProject(): self.warning("Not closing since running project doesn't want to close") return False self.threads.stopAllThreads() self.settings.storeSettings() self.current = None instance.PiTiVi = None self.emit("shutdown") return True def _connectToProjectManager(self, projectManager): projectManager.connect("new-project-loading", self._projectManagerNewProjectLoading) projectManager.connect("new-project-created", self._projectManagerNewProjectCreated) projectManager.connect("new-project-loaded", self._projectManagerNewProjectLoaded) projectManager.connect("new-project-failed", self._projectManagerNewProjectFailed) projectManager.connect("closing-project", self._projectManagerClosingProject) projectManager.connect("project-closed", self._projectManagerProjectClosed) def _projectManagerNewProjectLoading(self, projectManager, uri): self.emit("new-project-loading", uri) def _projectManagerNewProjectCreated(self, projectManager, project): self.current = project self.emit("new-project-created", project) def _newProjectLoaded(self, project): pass def _projectManagerNewProjectLoaded(self, projectManager, project): self.current = project self.action_log.clean() self.timelineLogObserver.startObserving(project.timeline) self.projectLogObserver.startObserving(project) self.sourcelist_log_observer.startObserving(project.sources) self._newProjectLoaded(project) self.emit("new-project-loaded", project) def _projectManagerNewProjectFailed(self, projectManager, uri, exception): self.emit("new-project-failed", uri, exception) def _projectManagerClosingProject(self, projectManager, project): return self.emit("closing-project", project) def _projectManagerProjectClosed(self, projectManager, project): self.timelineLogObserver.stopObserving(project.timeline) self.projectLogObserver.stopObserving(project) self.current = None self.emit("project-closed", project)
from pitivi.check import missing_soft_deps from pitivi.configure import get_ui_dir, get_pixmap_dir from pitivi.dialogs.clipmediaprops import ClipMediaPropsDialog from pitivi.dialogs.filelisterrordialog import FileListErrorDialog from pitivi.mediafilespreviewer import PreviewWidget from pitivi.settings import GlobalSettings from pitivi.utils.loggable import Loggable from pitivi.utils.misc import PathWalker, quote_uri, path_from_uri from pitivi.utils.ui import beautify_info, beautify_length, info_name, \ URI_TARGET_ENTRY, FILE_TARGET_ENTRY, SPACING # Values used in the settings file. SHOW_TREEVIEW = 1 SHOW_ICONVIEW = 2 GlobalSettings.addConfigSection('clip-library') GlobalSettings.addConfigOption('lastImportFolder', section='clip-library', key='last-folder', environment='PITIVI_IMPORT_FOLDER', default=os.path.expanduser("~")) GlobalSettings.addConfigOption('closeImportDialog', section='clip-library', key='close-import-dialog-after-import', default=True) GlobalSettings.addConfigOption('lastClipView', section='clip-library', key='last-clip-view', type_=int, default=SHOW_ICONVIEW)
from pitivi.configure import get_pixmap_dir from pitivi.settings import GlobalSettings from pitivi.utils.loggable import Loggable from pitivi.utils.misc import uri_is_valid from pitivi.utils.ui import beautify_length, beautify_stream,\ SPACING from pitivi.viewer import ViewerWidget DEFAULT_AUDIO_IMAGE = os.path.join(get_pixmap_dir(), "pitivi-sound.png") PREVIEW_WIDTH = 250 PREVIEW_HEIGHT = 100 GlobalSettings.addConfigSection('filechooser-preview') GlobalSettings.addConfigOption('FCEnablePreview', section='filechooser-preview', key='do-preview-on-clip-import', default=True) GlobalSettings.addConfigOption('FCpreviewWidth', section='filechooser-preview', key='video-preview-width', default=PREVIEW_WIDTH) GlobalSettings.addConfigOption('FCpreviewHeight', section='filechooser-preview', key='video-preview-height', default=PREVIEW_HEIGHT) class PreviewWidget(gtk.VBox, Loggable):
RIGHT_SIDE = gtk.gdk.Cursor(gtk.gdk.RIGHT_SIDE) ARROW = gtk.gdk.Cursor(gtk.gdk.ARROW) TRIMBAR_PIXBUF = gtk.gdk.pixbuf_new_from_file( os.path.join(configure.get_pixmap_dir(), "trimbar-normal.png")) TRIMBAR_PIXBUF_FOCUS = gtk.gdk.pixbuf_new_from_file( os.path.join(configure.get_pixmap_dir(), "trimbar-focused.png")) NAME_HOFFSET = 10 NAME_VOFFSET = 5 NAME_PADDING = 2 NAME_PADDING2X = 2 * NAME_PADDING import gst GlobalSettings.addConfigOption('videoClipBg', section='user-interface', key='videoclip-background', default=0x3182bdC0, notify=True) PreferencesDialog.addColorPreference( 'videoClipBg', section=_("Appearance"), label=_("Clip Background (Video)"), description=_("The background color for clips in video tracks.")) GlobalSettings.addConfigOption('audioClipBg', section='user-interface', key='audioclip-background', default=0x3182bdC0, notify=True)
class Pitivi(Gtk.Application, Loggable): """Hello world. Attributes: action_log (UndoableActionLog): The undo/redo log for the current project. effects (EffectsManager): The effects which can be applied to a clip. gui (MainWindow): The main window of the app. recent_manager (Gtk.RecentManager): Manages recently used projects. project_manager (ProjectManager): The holder of the current project. settings (GlobalSettings): The application-wide settings. system (pitivi.utils.system.System): The system running the app. """ __gsignals__ = { "version-info-received": (GObject.SignalFlags.RUN_LAST, None, (object, )) } def __init__(self): Gtk.Application.__init__(self, application_id="org.pitivi.Pitivi", flags=Gio.ApplicationFlags.NON_UNIQUE | Gio.ApplicationFlags.HANDLES_OPEN) Loggable.__init__(self) self.settings = None self.threads = None self.effects = None self.system = None self.project_manager = ProjectManager(self) self.action_log = None self.project_observer = None self._last_action_time = Gst.util_get_timestamp() self.gui = None self.recent_manager = Gtk.RecentManager.get_default() self.__inhibit_cookies = {} self._version_information = {} self._scenario_file = None self._first_action = True Zoomable.app = self self.shortcuts = ShortcutsManager(self) def write_action(self, action, **kwargs): if self._scenario_file is None: return if self._first_action: self._scenario_file.write( "description, seek=true, handles-states=true\n") self._first_action = False now = Gst.util_get_timestamp() if now - self._last_action_time > 0.05 * Gst.SECOND: # We need to make sure that the waiting time was more than 50 ms. st = Gst.Structure.new_empty("wait") st["duration"] = float((now - self._last_action_time) / Gst.SECOND) self._scenario_file.write(st.to_string()) self._scenario_file.write("\n") self._last_action_time = now if not isinstance(action, Gst.Structure): structure = Gst.Structure.new_empty(action) for key, value in kwargs.items(): key = key.replace("_", "-") structure[key] = value action = structure self._scenario_file.write(action.to_string()) self._scenario_file.write("\n") self._scenario_file.flush() def do_startup(self): Gtk.Application.do_startup(self) # Init logging as early as possible so we can log startup code enable_color = os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') not in ('', '1') # Let's show a human-readable Pitivi debug output by default, and only # show a crazy unreadable mess when surrounded by gst debug statements. enable_crack_output = "GST_DEBUG" in os.environ loggable.init('PITIVI_DEBUG', enable_color, enable_crack_output) self.info('starting up') self._setup() self._check_version() def _setup(self): # pylint: disable=attribute-defined-outside-init self.settings = GlobalSettings() self.threads = ThreadMaster() self.effects = EffectsManager() self.proxy_manager = ProxyManager(self) self.system = get_system() self.plugin_manager = PluginManager(self) self.project_manager.connect("new-project-loaded", self._new_project_loaded_cb) self.project_manager.connect_after("project-closed", self._project_closed_cb) self.project_manager.connect("project-saved", self.__project_saved_cb) self._create_actions() self._sync_do_undo() def _create_actions(self): self.shortcuts.register_group("app", _("General"), position=10) # pylint: disable=attribute-defined-outside-init self.undo_action = Gio.SimpleAction.new("undo", None) self.undo_action.connect("activate", self._undo_cb) self.add_action(self.undo_action) self.shortcuts.add("app.undo", ["<Primary>z"], self.undo_action, _("Undo the most recent action")) self.redo_action = Gio.SimpleAction.new("redo", None) self.redo_action.connect("activate", self._redo_cb) self.add_action(self.redo_action) self.shortcuts.add("app.redo", ["<Primary><Shift>z"], self.redo_action, _("Redo the most recent action")) self.quit_action = Gio.SimpleAction.new("quit", None) self.quit_action.connect("activate", self._quit_cb) self.add_action(self.quit_action) self.shortcuts.add("app.quit", ["<Primary>q"], self.quit_action, _("Quit")) self.show_shortcuts_action = Gio.SimpleAction.new( "shortcuts_window", None) self.show_shortcuts_action.connect("activate", self._show_shortcuts_cb) self.add_action(self.show_shortcuts_action) self.shortcuts.add("app.shortcuts_window", ["<Primary>F1", "<Primary>question"], self.show_shortcuts_action, _("Show the Shortcuts Window")) def do_activate(self): if self.gui: # The app is already started and the window already created. # Present the already existing window. if self.system.has_x11(): # TODO: Use present() instead of present_with_time() when # https://bugzilla.gnome.org/show_bug.cgi?id=688830 is fixed. from gi.repository import GdkX11 x11_server_time = GdkX11.x11_get_server_time( self.gui.get_window()) self.gui.present_with_time(x11_server_time) else: # On Wayland or Quartz (Mac OS X) backend there is no GdkX11, # so just use present() directly here. self.gui.present() # No need to show the welcome wizard. return self.create_main_window() self.gui.show_perspective(self.gui.greeter) def create_main_window(self): if self.gui: return self.gui = MainWindow(self) self.gui.setup_ui() self.add_window(self.gui) def do_open(self, giofiles, unused_count, unused_hint): assert giofiles self.create_main_window() if len(giofiles) > 1: self.warning( "Opening only one project at a time. Ignoring the rest!") project_file = giofiles[0] self.project_manager.load_project(quote_uri(project_file.get_uri())) return True def shutdown(self): """Closes the app. Returns: bool: True if successful, False otherwise. """ self.debug("shutting down") # Refuse to close if we are not done with the current project. if not self.project_manager.close_running_project(): self.warning( "Not closing since running project doesn't want to close") return False if self.gui: self.gui.destroy() self.threads.wait_all_threads() self.settings.store_settings() self.quit() return True def _set_scenario_file(self, uri): if uri: project_path = path_from_uri(uri) else: # New project. project_path = None if 'PITIVI_SCENARIO_FILE' in os.environ: scenario_path = os.environ['PITIVI_SCENARIO_FILE'] else: cache_dir = xdg_cache_home("scenarios") scenario_name = str(time.strftime("%Y%m%d-%H%M%S")) if project_path: scenario_name += os.path.splitext( project_path.replace(os.sep, "_"))[0] scenario_path = os.path.join(cache_dir, scenario_name + ".scenario") scenario_path = path_from_uri(quote_uri(scenario_path)) self._scenario_file = open(scenario_path, "w") if project_path and not project_path.endswith(".scenario"): # It's an xges file probably. with open(project_path) as project: content = project.read().replace("\n", "") self.write_action("load-project", serialized_content=content) def _new_project_loaded_cb(self, unused_project_manager, project): uri = project.get_uri() if uri: # We remove the project from recent projects list # and then re-add it to this list to make sure it # gets positioned at the top of the recent projects list. try: self.recent_manager.remove_item(uri) except GLib.Error as e: if e.domain != "gtk-recent-manager-error-quark": raise e self.recent_manager.add_item(uri) self.action_log = UndoableActionLog() self.action_log.connect("pre-push", self._action_log_pre_push_cb) self.action_log.connect("commit", self._action_log_commit) self.action_log.connect("move", self._action_log_move_cb) self.project_observer = ProjectObserver(project, self.action_log) self._set_scenario_file(project.get_uri()) def __project_saved_cb(self, unused_project_manager, unused_project, uri): if uri: self.recent_manager.add_item(uri) def _project_closed_cb(self, unused_project_manager, project): if project.loaded: self.action_log = None self._sync_do_undo() if self._scenario_file: self.write_action("stop") self._scenario_file.close() self._scenario_file = None def _check_version(self): """Checks online for new versions of the app.""" self.info("Requesting version information async") giofile = Gio.File.new_for_uri(RELEASES_URL) giofile.load_contents_async(None, self._version_info_received_cb, None) def _version_info_received_cb(self, giofile, result, user_data): # pylint: disable=broad-except try: raw = giofile.load_contents_finish(result)[1] if not isinstance(raw, str): raw = raw.decode() raw = raw.split("\n") # Split line at '=' if the line is not empty or a comment line data = [ element.split("=") for element in raw if element and not element.startswith("#") ] # search newest version and status status = "UNSUPPORTED" current_version = None for version, version_status in data: if VERSION == version: status = version_status if version_status.upper() == "CURRENT": # This is the latest. current_version = version self.info("Latest software version is %s", current_version) version_split = [int(i) for i in VERSION.split(".")] current_version_split = [ int(i) for i in current_version.split(".") ] if version_split > current_version_split: status = "CURRENT" self.info( "Running version %s, which is newer than the latest known version. Considering it as the latest current version.", VERSION) elif status == "UNSUPPORTED": self.warning("Using an outdated version of Pitivi (%s)", VERSION) self._version_information["current"] = current_version self._version_information["status"] = status self.emit("version-info-received", self._version_information) except Exception as e: self.warning("Version info could not be read: %s", e) def is_latest(self): """Whether the app's version is the latest as far as we know.""" status = self._version_information.get("status") return status is None or status.upper() == "CURRENT" def get_latest(self): """Get the latest version of the app or None.""" return self._version_information.get("current") def _quit_cb(self, unused_action, unused_param): self.shutdown() def _undo_cb(self, unused_action, unused_param): self.action_log.undo() def _redo_cb(self, unused_action, unused_param): self.action_log.redo() def _show_shortcuts_cb(self, unused_action, unused_param): show_shortcuts(self) def _action_log_pre_push_cb(self, unused_action_log, action): scenario_action = action.as_scenario_action() if scenario_action: self.write_action(scenario_action) def _action_log_commit(self, action_log, unused_stack): if action_log.is_in_transaction(): return self._sync_do_undo() def _action_log_move_cb(self, action_log, unused_stack): self._sync_do_undo() def _sync_do_undo(self): can_undo = self.action_log and bool(self.action_log.undo_stacks) self.undo_action.set_enabled(bool(can_undo)) can_redo = self.action_log and bool(self.action_log.redo_stacks) self.redo_action.set_enabled(bool(can_redo)) if not self.project_manager.current_project: return dirty = self.action_log and self.action_log.dirty() self.project_manager.current_project.set_modification_state(dirty) # In the tests we do not want to create any gui if self.gui is not None: self.gui.editor.show_project_status() def simple_inhibit(self, reason, flags): """Informs the session manager about actions to be inhibited. Keeps track of the reasons received. A specific reason should always be accompanied by the same flags. Calling the method a second time with the same reason has no effect unless `simple_uninhibit` has been called in the meanwhile. Args: reason (str): The reason for which to perform the inhibition. flags (Gtk.ApplicationInhibitFlags): What should be inhibited. """ if reason in self.__inhibit_cookies: self.debug("Inhibit reason already active: %s", reason) return self.debug("Inhibiting %s for %s", flags, reason) cookie = self.inhibit(self.gui, flags, reason) self.__inhibit_cookies[reason] = cookie def simple_uninhibit(self, reason): """Informs the session manager that an inhibition is not needed anymore. Args: reason (str): The reason which is not valid anymore. """ try: cookie = self.__inhibit_cookies.pop(reason) except KeyError: self.debug("Inhibit reason not active: %s", reason) return self.debug("Uninhibiting %s", reason) self.uninhibit(cookie)
class Pitivi(Loggable, Signallable): """ Pitivi's main application class. Signals: - C{new-project} : A new C{Project} is loaded and ready to use. - C{new-project-loading} : Pitivi is attempting to load a new project. - C{new-project-loaded} : A new L{Project} has been loaded, and the UI should refresh it's view. - C{new-project-failed} : A new L{Project} failed to load. - C{closing-project} : pitivi would like to close a project. handlers should return false if they do not want this project to close. by default, assumes true. This signal should only be used by classes that might want to abort the closing of a project. - C{project-closed} : The project is closed, it will be freed when the callback returns. Classes should connect to this instance when they want to know that data related to that project is no longer going to be used. - C{shutdown} : Used internally, do not use this signal.` @ivar settings: Application-wide settings. @type settings: L{GlobalSettings}. @ivar current: Currently used project. @type current: L{Project}. """ __signals__ = { "new-project": ["project"], "new-project-loading": ["uri"], "new-project-created": ["project"], "new-project-loaded": ["project"], "new-project-failed": ["uri", "exception"], "closing-project": ["project"], "project-closed": ["project"], "missing-uri": ["formatter", "uri"], "version-info-received": ["versions"], "shutdown": None} def __init__(self): """ initialize pitivi with the command line arguments """ Loggable.__init__(self) # init logging as early as possible so we can log startup code enable_color = os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '0') # Let's show a human-readable pitivi debug output by default, and only # show a crazy unreadable mess when surrounded by gst debug statements. enable_crack_output = "GST_DEBUG" in os.environ log.init('PITIVI_DEBUG', enable_color, enable_crack_output) self.info('starting up') # store ourself in the instance global if instance.PiTiVi: raise RuntimeWarning(_("There is already a %s instance, please inform " "the developers by filing a bug at " "http://bugzilla.gnome.org/enter_bug.cgi?product=pitivi") % APPNAME) instance.PiTiVi = self self.current = None # get settings self.settings = GlobalSettings() self.threads = ThreadMaster() #self.screencast = False self.effects = EffectsHandler() self.system = getSystem() self.projectManager = ProjectManager(self.effects) self._connectToProjectManager(self.projectManager) self.action_log = UndoableActionLog() self.debug_action_log_observer = DebugActionLogObserver() self.debug_action_log_observer.startObserving(self.action_log) # TODO reimplement the observing after GES port #self.timelineLogObserver = TimelineLogObserver(self.action_log) self.projectLogObserver = ProjectLogObserver(self.action_log) self.medialibrary_log_observer = MediaLibraryLogObserver(self.action_log) self.version_information = {} self._checkVersion() def shutdown(self): """ Close PiTiVi. @return: C{True} if PiTiVi was successfully closed, else C{False}. @rtype: C{bool} """ self.debug("shutting down") # we refuse to close if we're running a user interface and the user # doesn't want us to close the current project. if self.current and not self.projectManager.closeRunningProject(): self.warning("Not closing since running project doesn't want to close") return False self.threads.stopAllThreads() self.settings.storeSettings() self.current = None instance.PiTiVi = None self.emit("shutdown") return True def _connectToProjectManager(self, projectManager): projectManager.connect("new-project-loading", self._projectManagerNewProjectLoading) projectManager.connect("new-project-created", self._projectManagerNewProjectCreated) projectManager.connect("new-project-loaded", self._projectManagerNewProjectLoaded) projectManager.connect("new-project-failed", self._projectManagerNewProjectFailed) projectManager.connect("closing-project", self._projectManagerClosingProject) projectManager.connect("project-closed", self._projectManagerProjectClosed) def _projectManagerNewProjectLoading(self, projectManager, uri): self.emit("new-project-loading", uri) def _projectManagerNewProjectCreated(self, projectManager, project): self.current = project self.emit("new-project-created", project) def _newProjectLoaded(self, project): pass def _projectManagerNewProjectLoaded(self, projectManager, project): self.current = project self.action_log.clean() #self.timelineLogObserver.startObserving(project.timeline) self.projectLogObserver.startObserving(project) self.medialibrary_log_observer.startObserving(project.medialibrary) self._newProjectLoaded(project) self.emit("new-project-loaded", project) def _projectManagerNewProjectFailed(self, projectManager, uri, exception): self.emit("new-project-failed", uri, exception) def _projectManagerClosingProject(self, projectManager, project): return self.emit("closing-project", project) def _projectManagerProjectClosed(self, projectManager, project): #self.timelineLogObserver.stopObserving(project.timeline) self.projectLogObserver.stopObserving(project) self.current = None self.emit("project-closed", project) # check if for version information online def _checkVersion(self): giofile = Gio.File.new_for_uri(RELEASES_URL) self.info("Requesting version information") giofile.load_contents_async(None, self._versionInfoReceivedCb, None) def _versionInfoReceivedCb(self, giofile, result, data): try: # split data in lines raw = giofile.load_contents_finish(result)[0].split("\n") # split line at '=' if not empty or comment data = [element.split("=") for element in raw if element and not element.startswith("#")] # search newest version and status status = "UNSUPPORTED" for version, version_status in data: if pitivi_version == version: status = version_status if version_status.upper() == "CURRENT": current_version = version self.info("Version information received") self.version_information["current"] = current_version self.version_information["status"] = status self.emit("version-info-received", self.version_information) except: self.warning("Version information could not be read")
from urllib.parse import unquote from gi.repository import Gio from gi.repository import Gtk from pitivi.configure import get_pixmap_dir from pitivi.dialogs.about import AboutDialog from pitivi.editorperspective import EditorPerspective from pitivi.greeterperspective import GreeterPerspective from pitivi.settings import GlobalSettings from pitivi.utils.loggable import Loggable from pitivi.utils.misc import show_user_manual GlobalSettings.addConfigOption('mainWindowX', section="main-window", key="X", default=0, type_=int) GlobalSettings.addConfigOption('mainWindowY', section="main-window", key="Y", default=0, type_=int) GlobalSettings.addConfigOption('mainWindowWidth', section="main-window", key="width", default=-1, type_=int) GlobalSettings.addConfigOption('mainWindowHeight', section="main-window", key="height",
from pitivi.ui.sourcelist import SourceList from pitivi.ui.effectlist import EffectList from pitivi.ui.clipproperties import ClipProperties from pitivi.ui.common import beautify_factory from pitivi.utils import beautify_length from pitivi.ui.zoominterface import Zoomable from pitivi.ui.startupwizard import StartUpWizard if HAVE_GCONF: D_G_INTERFACE = "/desktop/gnome/interface" for gconf_dir in (D_G_INTERFACE, ): gconf.client_get_default ().add_dir (gconf_dir, gconf.CLIENT_PRELOAD_NONE) GlobalSettings.addConfigOption("fileSupportEnabled", environment="PITIVI_FILE_SUPPORT", default=False) GlobalSettings.addConfigSection("main-window") GlobalSettings.addConfigOption('mainWindowFullScreen', section="main-window", key="full-screen", default=False) GlobalSettings.addConfigOption('mainWindowHPanePosition', section="main-window", key="hpane-position", type_=int) GlobalSettings.addConfigOption('mainWindowMainHPanePosition', section="main-window", key="main-hpane-position", type_=int)
from gi.repository import Gst from gi.repository import Gtk from gi.repository import Pango from pitivi.configure import get_ui_dir from pitivi.dialogs.prefs import PreferencesDialog from pitivi.settings import GlobalSettings from pitivi.utils.loggable import Loggable from pitivi.utils.timeline import SELECT from pitivi.utils.ui import argb_to_gdk_rgba from pitivi.utils.ui import fix_infobar from pitivi.utils.ui import gdk_rgba_to_argb GlobalSettings.addConfigOption('titleClipLength', section="user-interface", key="title-clip-length", default=5000, notify=True) PreferencesDialog.addNumericPreference('titleClipLength', section="timeline", label=_("Title clip duration"), description=_( "Default clip length (in milliseconds) of titles when inserting on the timeline."), lower=1) FOREGROUND_DEFAULT_COLOR = 0xFFFFFFFF # White BACKGROUND_DEFAULT_COLOR = 0x00000000 # Transparent DEFAULT_FONT_DESCRIPTION = "Sans 36" DEFAULT_VALIGNMENT = GES.TextVAlign.ABSOLUTE DEFAULT_HALIGNMENT = GES.TextHAlign.ABSOLUTE
class Pitivi(Loggable, Signallable): """ Pitivi's main application class. Signals: - C{new-project} : A new C{Project} is loaded and ready to use. - C{new-project-loading} : Pitivi is attempting to load a new project. - C{new-project-loaded} : A new L{Project} has been loaded, and the UI should refresh it's view. - C{new-project-failed} : A new L{Project} failed to load. - C{project-closed} : The project is closed, it will be freed when the callback returns. Classes should connect to this instance when they want to know that data related to that project is no longer going to be used. - C{shutdown} : Used internally, do not use this signal.` @ivar settings: Application-wide settings. @type settings: L{GlobalSettings}. @ivar current: Currently used project. @type current: L{Project}. """ __signals__ = { "new-project": ["project"], "new-project-loading": ["uri"], "new-project-created": ["project"], "new-project-loaded": ["project"], "new-project-failed": ["uri", "exception"], "project-closed": ["project"], "missing-uri": ["formatter", "uri"], "version-info-received": ["versions"], "shutdown": None} def __init__(self): Loggable.__init__(self) # Init logging as early as possible so we can log startup code enable_color = not os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '1') # Let's show a human-readable pitivi debug output by default, and only # show a crazy unreadable mess when surrounded by gst debug statements. enable_crack_output = "GST_DEBUG" in os.environ log.init('PITIVI_DEBUG', enable_color, enable_crack_output) self.info('starting up') self.settings = GlobalSettings() self.threads = ThreadMaster() self.effects = EffectsHandler() self.system = getSystem() self.current_project = None self.projectManager = ProjectManager(self) self._connectToProjectManager(self.projectManager) self.action_log = UndoableActionLog() self.debug_action_log_observer = DebugActionLogObserver() self.debug_action_log_observer.startObserving(self.action_log) # TODO reimplement the observing after GES port #self.timelineLogObserver = TimelineLogObserver(self.action_log) self.projectLogObserver = ProjectLogObserver(self.action_log) self._version_information = {} self._checkVersion() def shutdown(self): """ Close Pitivi. @return: C{True} if Pitivi was successfully closed, else C{False}. @rtype: C{bool} """ self.debug("shutting down") # we refuse to close if we're running a user interface and the user # doesn't want us to close the current project. if self.current_project and not self.projectManager.closeRunningProject(): self.warning("Not closing since running project doesn't want to close") return False self.threads.stopAllThreads() self.settings.storeSettings() self.current_project = None self.emit("shutdown") return True def _connectToProjectManager(self, projectManager): pm = projectManager pm.connect("new-project-loading", self._projectManagerNewProjectLoading) pm.connect("new-project-created", self._projectManagerNewProjectCreated) pm.connect("new-project-loaded", self._projectManagerNewProjectLoaded) pm.connect("new-project-failed", self._projectManagerNewProjectFailed) pm.connect("project-closed", self._projectManagerProjectClosed) def _projectManagerNewProjectLoading(self, unused_project_manager, uri): self.emit("new-project-loading", uri) def _projectManagerNewProjectCreated(self, unused_project_manager, project): self.current_project = project self.emit("new-project-created", project) def _newProjectLoaded(self, unused_project): pass def _projectManagerNewProjectLoaded(self, unused_project_manager, project, unused_fully_loaded): self.current_project = project self.action_log.clean() #self.timelineLogObserver.startObserving(project.timeline) self.projectLogObserver.startObserving(project) self._newProjectLoaded(project) self.emit("new-project-loaded", project) def _projectManagerNewProjectFailed(self, unused_project_manager, uri, exception): self.emit("new-project-failed", uri, exception) def _projectManagerProjectClosed(self, unused_project_manager, project): #self.timelineLogObserver.stopObserving(project.timeline) self.projectLogObserver.stopObserving(project) self.current_project = None self.emit("project-closed", project) def _checkVersion(self): # Check online for release versions information giofile = Gio.File.new_for_uri(RELEASES_URL) self.info("Requesting version information") giofile.load_contents_async(None, self._versionInfoReceivedCb, None) def _versionInfoReceivedCb(self, giofile, result, user_data): try: raw = giofile.load_contents_finish(result)[1] raw = raw.split("\n") # Split line at '=' if the line is not empty or a comment line data = [element.split("=") for element in raw if element and not element.startswith("#")] # search newest version and status status = "UNSUPPORTED" current_version = None for version, version_status in data: if VERSION == version: status = version_status if version_status.upper() == "CURRENT": # This is the latest. current_version = version self.info("Latest software version is %s", current_version) if status is "UNSUPPORTED": self.warning("Using an outdated version of Pitivi (%s)", VERSION) self._version_information["current"] = current_version self._version_information["status"] = status self.emit("version-info-received", self._version_information) except Exception, e: self.warning("Version info could not be read: %s", e)
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301, USA. """User preferences.""" import os from gettext import gettext as _ from gi.repository import Gtk from pitivi.configure import get_ui_dir from pitivi.settings import GlobalSettings from pitivi.utils import widgets from pitivi.utils.loggable import Loggable from pitivi.utils.ui import SPACING GlobalSettings.addConfigSection("user-interface") GlobalSettings.addConfigOption('prefsDialogWidth', section="user-interface", key="prefs-dialog-width", default=600) GlobalSettings.addConfigOption('prefsDialogHeight', section="user-interface", key="prefs-dialog-height", default=400) class PreferencesDialog(Loggable): """Preferences for how the app works."""
from pitivi.ui.zoominterface import Zoomable from pitivi.settings import GlobalSettings from pitivi.ui.prefs import PreferencesDialog from pitivi.ui.common import TRACK_SPACING, unpack_cairo_pattern, \ LAYER_HEIGHT_EXPANDED, LAYER_SPACING from pitivi.ui.controller import Controller from pitivi.ui.curve import KW_LABEL_Y_OVERFLOW # cursors to be used for resizing objects ARROW = gtk.gdk.Cursor(gtk.gdk.ARROW) # TODO: replace this with custom cursor PLAYHEAD_CURSOR = gtk.gdk.Cursor(gtk.gdk.SB_H_DOUBLE_ARROW) GlobalSettings.addConfigOption('edgeSnapDeadband', section = "user-interface", key = "edge-snap-deadband", default = 5, notify = True) PreferencesDialog.addNumericPreference('edgeSnapDeadband', section = _("Behavior"), label = _("Snap Distance (pixels)"), description = _("Threshold distance (in pixels) used for all snapping " "operations"), lower = 0) class PlayheadController(Controller, Zoomable): _cursor = PLAYHEAD_CURSOR
SAMPLE_DURATION = Gst.SECOND / 100 THUMB_MARGIN_PX = 3 # For the waveforms, ensures we always have a little extra surface when # scrolling while playing. MARGIN = 500 PREVIEW_GENERATOR_SIGNALS = { "done": (GObject.SIGNAL_RUN_LAST, None, ()), "error": (GObject.SIGNAL_RUN_LAST, None, ()), } THUMB_HEIGHT = EXPANDED_SIZE - 2 * THUMB_MARGIN_PX GlobalSettings.addConfigSection("previewers") GlobalSettings.addConfigOption("previewers_max_cpu", section="previewers", key="max-cpu-usage", default=90) class PreviewerBin(Gst.Bin, Loggable): """Baseclass for elements gathering datas to create previews.""" def __init__(self, bin_desc): Gst.Bin.__init__(self) Loggable.__init__(self) self.internal_bin = Gst.parse_bin_from_description(bin_desc, True) self.add(self.internal_bin)
from pitivi.configure import get_gstpresets_dir from pitivi.settings import GlobalSettings from pitivi.utils.loggable import Loggable # Make sure gst knowns about our own GstPresets Gst.preset_set_app_dir(get_gstpresets_dir()) class ProxyingStrategy: AUTOMATIC = "automatic" ALL = "all" NOTHING = "nothing" GlobalSettings.addConfigSection("proxy") GlobalSettings.addConfigOption('proxyingStrategy', section='proxy', key='proxying-strategy', default=ProxyingStrategy.AUTOMATIC) GlobalSettings.addConfigOption('numTranscodingJobs', section='proxy', key='num-proxying-jobs', default=4) GlobalSettings.addConfigOption("max_cpu_usage", section="proxy", key="max-cpu-usage", default=10) ENCODING_FORMAT_PRORES = "prores-raw-in-matroska.gep" ENCODING_FORMAT_JPEG = "jpeg-raw-in-matroska.gep"
import pitivi.utils as utils from pitivi.configure import get_pixmap_dir from pitivi.elements.singledecodebin import SingleDecodeBin from pitivi.elements.thumbnailsink import CairoSurfaceThumbnailSink from pitivi.elements.arraysink import ArraySink from pitivi.signalinterface import Signallable import pitivi.stream as stream from pitivi.settings import GlobalSettings from pitivi.ui.zoominterface import Zoomable from pitivi.log.loggable import Loggable from pitivi.factories.file import PictureFileSourceFactory from pitivi.thumbnailcache import ThumbnailCache from pitivi.ui.prefs import PreferencesDialog from pitivi.receiver import receiver, handler GlobalSettings.addConfigSection("thumbnailing") GlobalSettings.addConfigOption( "thumbnailSpacingHint", section="thumbnailing", key="spacing-hint", default=2, notify=True ) PreferencesDialog.addNumericPreference( "thumbnailSpacingHint", section=_("Appearance"), label=_("Thumbnail Gap (pixels)"), lower=0, description=_("The gap between thumbnails"), ) # this default works out to a maximum of ~ 1.78 MiB per factory, assuming: # 4:3 aspect ratio # 4 bytes per pixel
from gi.repository import Gio from gi.repository import Gtk from pitivi.configure import get_pixmap_dir from pitivi.dialogs.about import AboutDialog from pitivi.dialogs.prefs import PreferencesDialog from pitivi.editorperspective import EditorPerspective from pitivi.greeterperspective import GreeterPerspective from pitivi.settings import GlobalSettings from pitivi.utils.loggable import Loggable from pitivi.utils.misc import show_user_manual GlobalSettings.addConfigOption('mainWindowX', section="main-window", key="X", default=0, type_=int) GlobalSettings.addConfigOption('mainWindowY', section="main-window", key="Y", default=0, type_=int) GlobalSettings.addConfigOption('mainWindowWidth', section="main-window", key="width", default=-1, type_=int) GlobalSettings.addConfigOption('mainWindowHeight', section="main-window", key="height", default=-1, type_=int) GlobalSettings.addConfigSection('export') GlobalSettings.addConfigOption('lastExportFolder', section='export', key="last-export-folder",
from gi.repository import Gtk from gi.repository import Pango from pitivi.settings import GlobalSettings from pitivi.utils.loggable import Loggable from pitivi.utils.misc import uri_is_valid from pitivi.utils.pipeline import AssetPipeline from pitivi.utils.ui import beautify_length from pitivi.utils.ui import beautify_stream from pitivi.utils.ui import SPACING from pitivi.viewer.viewer import ViewerWidget PREVIEW_WIDTH = 250 PREVIEW_HEIGHT = 100 GlobalSettings.add_config_section('filechooser-preview') GlobalSettings.add_config_option('FCEnablePreview', section='filechooser-preview', key='do-preview-on-clip-import', default=True) GlobalSettings.add_config_option('FCpreviewWidth', section='filechooser-preview', key='video-preview-width', default=PREVIEW_WIDTH) GlobalSettings.add_config_option('FCpreviewHeight', section='filechooser-preview', key='video-preview-height', default=PREVIEW_HEIGHT) ACCEPTABLE_TAGS = [ Gst.TAG_ALBUM_ARTIST, Gst.TAG_ARTIST, Gst.TAG_TITLE, Gst.TAG_ALBUM,
from pitivi.sourcelist import SourceListError from pitivi.ui.sourcelist import SourceList from pitivi.ui.effectlist import EffectList from pitivi.ui.clipproperties import ClipProperties from pitivi.ui.common import beautify_factory from pitivi.utils import beautify_length from pitivi.ui.zoominterface import Zoomable if HAVE_GCONF: D_G_INTERFACE = "/desktop/gnome/interface" for gconf_dir in (D_G_INTERFACE, ): gconf.client_get_default ().add_dir (gconf_dir, gconf.CLIENT_PRELOAD_NONE) GlobalSettings.addConfigOption("fileSupportEnabled", environment="PITIVI_FILE_SUPPORT", default=False) GlobalSettings.addConfigSection("main-window") GlobalSettings.addConfigOption('mainWindowFullScreen', section="main-window", key="full-screen", default=False) GlobalSettings.addConfigOption('mainWindowHPanePosition', section="main-window", key="hpane-position", type_=int) GlobalSettings.addConfigOption('mainWindowMainHPanePosition', section="main-window", key="main-hpane-position", type_=int)
from pitivi.ui.trackobject import TrackObject from pitivi.ui.point import Point from pitivi.ui.zoominterface import Zoomable from pitivi.settings import GlobalSettings from pitivi.ui.prefs import PreferencesDialog from pitivi.ui.common import TRACK_SPACING, unpack_cairo_pattern, \ LAYER_HEIGHT_EXPANDED, LAYER_SPACING # cursors to be used for resizing objects ARROW = gtk.gdk.Cursor(gtk.gdk.ARROW) # TODO: replace this with custom cursor RAZOR_CURSOR = gtk.gdk.Cursor(gtk.gdk.XTERM) GlobalSettings.addConfigOption('edgeSnapDeadband', section = "user-interface", key = "edge-snap-deadband", default = 5, notify = True) PreferencesDialog.addNumericPreference('edgeSnapDeadband', section = _("Behavior"), label = _("Snap Distance (pixels)"), description = _("Threshold distance (in pixels) used for all snapping " "operations"), lower = 0) class TimelineCanvas(goocanvas.Canvas, Zoomable, Loggable): __gsignals__ = { "scroll-event":"override" }
SAMPLE_DURATION = Gst.SECOND / 100 THUMB_MARGIN_PX = 3 THUMB_HEIGHT = EXPANDED_SIZE - 2 * THUMB_MARGIN_PX THUMB_PERIOD = int(Gst.SECOND / 2) assert Gst.SECOND % THUMB_PERIOD == 0 # For the waveforms, ensures we always have a little extra surface when # scrolling while playing. MARGIN = 500 PREVIEW_GENERATOR_SIGNALS = { "done": (GObject.SIGNAL_RUN_LAST, None, ()), "error": (GObject.SIGNAL_RUN_LAST, None, ()), } GlobalSettings.addConfigSection("previewers") GlobalSettings.addConfigOption("previewers_max_cpu", section="previewers", key="max-cpu-usage", default=90) class PreviewerBin(Gst.Bin, Loggable): """Baseclass for elements gathering data to create previews.""" def __init__(self, bin_desc): Gst.Bin.__init__(self) Loggable.__init__(self) self.internal_bin = Gst.parse_bin_from_description(bin_desc, True) self.add(self.internal_bin)
import pitivi.utils as utils from pitivi.configure import get_pixmap_dir from pitivi.elements.singledecodebin import SingleDecodeBin from pitivi.elements.thumbnailsink import CairoSurfaceThumbnailSink from pitivi.elements.arraysink import ArraySink from pitivi.signalinterface import Signallable import pitivi.stream as stream from pitivi.settings import GlobalSettings from pitivi.ui.zoominterface import Zoomable from pitivi.log.loggable import Loggable from pitivi.factories.file import PictureFileSourceFactory from pitivi.thumbnailcache import ThumbnailCache from pitivi.ui.prefs import PreferencesDialog from pitivi.receiver import receiver, handler GlobalSettings.addConfigSection("thumbnailing") GlobalSettings.addConfigOption("thumbnailSpacingHint", section="thumbnailing", key="spacing-hint", default=2, notify=True) PreferencesDialog.addNumericPreference( "thumbnailSpacingHint", section=_("Appearance"), label=_("Thumbnail Gap (pixels)"), lower=0, description=_("The gap between thumbnails")) # this default works out to a maximum of ~ 1.78 MiB per factory, assuming: # 4:3 aspect ratio
from pitivi.utils.misc import asset_get_duration # Remove check when we depend on Gst >= 1.20 HAS_GST_1_19 = GstDependency("Gst", apiversion="1.0", version_required="1.19").check() # Make sure gst knowns about our own GstPresets Gst.preset_set_app_dir(get_gstpresets_dir()) class ProxyingStrategy: AUTOMATIC = "automatic" ALL = "all" NOTHING = "nothing" GlobalSettings.add_config_section("proxy") GlobalSettings.add_config_option('proxying_strategy', section='proxy', key='proxying-strategy', default=ProxyingStrategy.AUTOMATIC) GlobalSettings.add_config_option('num_transcoding_jobs', section='proxy', key='num-proxying-jobs', default=4, notify=True) PreferencesDialog.add_numeric_preference( 'num_transcoding_jobs', description="", section="_proxies", label=_("Max number of parallel transcoding jobs"),
# Private stuff # LEFT_SIDE = Gdk.Cursor.new(Gdk.CursorType.LEFT_SIDE) RIGHT_SIDE = Gdk.Cursor.new(Gdk.CursorType.RIGHT_SIDE) ARROW = Gdk.Cursor.new(Gdk.CursorType.ARROW) TRIMBAR_PIXBUF = GdkPixbuf.Pixbuf.new_from_file( os.path.join(configure.get_pixmap_dir(), "trimbar-normal.png")) TRIMBAR_PIXBUF_FOCUS = GdkPixbuf.Pixbuf.new_from_file( os.path.join(configure.get_pixmap_dir(), "trimbar-focused.png")) NAME_HOFFSET = 10 NAME_VOFFSET = 5 NAME_PADDING = 2 NAME_PADDING2X = 2 * NAME_PADDING GlobalSettings.addConfigOption('videoClipBg', section='user-interface', key='videoclip-background', default=993737707, notify=True) PreferencesDialog.addColorPreference('videoClipBg', section=_("Appearance"), label=_("Color for video clips"), description=_("The background color for clips in video tracks.")) GlobalSettings.addConfigOption('audioClipBg', section='user-interface', key='audioclip-background', default=996806336, notify=True) PreferencesDialog.addColorPreference('audioClipBg',
import pitivi.settings as settings from pitivi.settings import GlobalSettings from pitivi.configure import get_pixmap_dir import pitivi.utils as utils from pitivi.utils.misc import big_to_cairo_alpha_mask, big_to_cairo_red_mask, big_to_cairo_green_mask, big_to_cairo_blue_mask from pitivi.utils.receiver import receiver, handler from pitivi.utils.timeline import Zoomable from pitivi.utils.signal import Signallable from pitivi.utils.loggable import Loggable from pitivi.dialogs.prefs import PreferencesDialog GlobalSettings.addConfigSection("thumbnailing") GlobalSettings.addConfigOption("thumbnailSpacingHint", section="thumbnailing", key="spacing-hint", default=5, notify=True) GlobalSettings.addConfigOption("thumbnailPeriod", section="thumbnailing", key="thumbnail-period", default=gst.SECOND, notify=True) PreferencesDialog.addNumericPreference("thumbnailSpacingHint", section=_("Appearance"), label=_("Thumbnail gap"),
from math import pi import cairo from gettext import gettext as _ from pitivi.action import ViewAction from pitivi.stream import VideoStream from pitivi.utils import time_to_string, Seeker from pitivi.log.loggable import Loggable from pitivi.pipeline import PipelineError from pitivi.ui.common import SPACING, hex_to_rgb from pitivi.settings import GlobalSettings from pitivi.ui.dynamic import TimeWidget GlobalSettings.addConfigSection("viewer") GlobalSettings.addConfigOption("viewerDocked", section="viewer", key="docked", default=True) GlobalSettings.addConfigOption("viewerWidth", section="viewer", key="width", default=320) GlobalSettings.addConfigOption("viewerHeight", section="viewer", key="height", default=240) GlobalSettings.addConfigOption("viewerX", section="viewer", key="x-pos",
import cairo from gettext import gettext as _ from time import time from math import pi from pitivi.settings import GlobalSettings from pitivi.utils.loggable import Loggable from pitivi.utils.misc import format_ns from pitivi.utils.pipeline import AssetPipeline, Seeker from pitivi.utils.ui import SPACING, hex_to_rgb from pitivi.utils.widgets import TimeWidget import platform GlobalSettings.addConfigSection("viewer") GlobalSettings.addConfigOption("viewerDocked", section="viewer", key="docked", default=True) GlobalSettings.addConfigOption("viewerWidth", section="viewer", key="width", default=320) GlobalSettings.addConfigOption("viewerHeight", section="viewer", key="height", default=240) GlobalSettings.addConfigOption("viewerX", section="viewer", key="x-pos",
from gtk import gdk import gst from gettext import gettext as _ from pitivi.action import ViewAction from pitivi.stream import VideoStream from pitivi.utils import time_to_string, Seeker from pitivi.log.loggable import Loggable from pitivi.pipeline import PipelineError from pitivi.ui.common import SPACING from pitivi.settings import GlobalSettings from pitivi.ui.dynamic import TimeWidget GlobalSettings.addConfigSection("viewer") GlobalSettings.addConfigOption("viewerDocked", section="viewer", key="docked", default=True) GlobalSettings.addConfigOption("viewerWidth", section="viewer", key="width", default=320) GlobalSettings.addConfigOption("viewerHeight", section="viewer", key="height", default=240) GlobalSettings.addConfigOption("viewerX", section="viewer", key="x-pos",