~timo-jyrinki/ubuntu/trusty/pitivi/backport_utopic_fixes

« back to all changes in this revision

Viewing changes to pitivi/application.py

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2014-03-29 15:22:50 UTC
  • mto: (3.1.23 experimental)
  • mto: This revision was merged to the branch mainline in revision 44.
  • Revision ID: package-import@ubuntu.com-20140329152250-flg9onx416bqf3e3
Tags: upstream-0.93
Import upstream version 0.93

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 
24
24
"""
25
25
Main application
 
26
 
 
27
Hierarchy of the whole thing:
 
28
 
 
29
Pitivi
 
30
    InteractivePitivi
 
31
    GuiPitivi
 
32
        ProjectCreatorGuiPitivi
 
33
        ProjectLoaderGuiPitivi
 
34
        StartupWizardGuiPitivi
26
35
"""
27
36
import os
28
37
import sys
 
38
 
29
39
from gi.repository import GES
30
40
from gi.repository import Gio
31
41
from gi.repository import GLib
34
44
from gettext import gettext as _
35
45
from optparse import OptionParser
36
46
 
37
 
import pitivi.instance as instance
38
 
 
39
47
from pitivi.effects import EffectsHandler
40
 
from pitivi.configure import APPNAME, pitivi_version, RELEASES_URL
 
48
from pitivi.configure import VERSION, RELEASES_URL
41
49
from pitivi.settings import GlobalSettings
42
50
from pitivi.utils.threads import ThreadMaster
43
51
from pitivi.mainwindow import PitiviMainWindow
54
62
#from pitivi.undo.timeline import TimelineLogObserver
55
63
 
56
64
 
57
 
"""
58
 
Hierarchy of the whole thing:
59
 
 
60
 
Pitivi
61
 
    InteractivePitivi
62
 
    GuiPitivi
63
 
        ProjectCreatorGuiPitivi
64
 
        ProjectLoaderGuiPitivi
65
 
        StartupWizardGuiPitivi
66
 
"""
67
 
 
68
 
 
69
65
class Pitivi(Loggable, Signallable):
70
66
    """
71
67
    Pitivi's main application class.
76
72
     - C{new-project-loading} : Pitivi is attempting to load a new project.
77
73
     - C{new-project-loaded} : A new L{Project} has been loaded, and the UI should refresh it's view.
78
74
     - C{new-project-failed} : A new L{Project} failed to load.
79
 
     - C{closing-project} :  pitivi would like to close a project. handlers should return false
80
 
     if they do not want this project to close. by default, assumes
81
 
     true. This signal should only be used by classes that might want to abort
82
 
     the closing of a project.
83
75
     - C{project-closed} : The project is closed, it will be freed when the callback returns.
84
76
     Classes should connect to this instance when they want to know that
85
77
     data related to that project is no longer going to be used.
97
89
        "new-project-created": ["project"],
98
90
        "new-project-loaded": ["project"],
99
91
        "new-project-failed": ["uri", "exception"],
100
 
        "closing-project": ["project"],
101
92
        "project-closed": ["project"],
102
93
        "missing-uri": ["formatter", "uri"],
103
94
        "version-info-received": ["versions"],
104
95
        "shutdown": None}
105
96
 
106
97
    def __init__(self):
107
 
        """
108
 
        initialize pitivi with the command line arguments
109
 
        """
110
98
        Loggable.__init__(self)
111
99
 
112
 
        # init logging as early as possible so we can log startup code
113
 
        enable_color = os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '0')
 
100
        # Init logging as early as possible so we can log startup code
 
101
        enable_color = not os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '1')
114
102
        # Let's show a human-readable pitivi debug output by default, and only
115
103
        # show a crazy unreadable mess when surrounded by gst debug statements.
116
104
        enable_crack_output = "GST_DEBUG" in os.environ
118
106
 
119
107
        self.info('starting up')
120
108
 
121
 
        # store ourself in the instance global
122
 
        if instance.Pitivi:
123
 
            raise RuntimeWarning(_("There is already a %s instance, please inform "
124
 
                "the developers by filing a bug at "
125
 
                "http://bugzilla.gnome.org/enter_bug.cgi?product=pitivi")
126
 
                % APPNAME)
127
 
        instance.Pitivi = self
128
 
 
129
 
        self.current_project = None
130
 
 
131
 
        # get settings
132
109
        self.settings = GlobalSettings()
133
110
        self.threads = ThreadMaster()
134
 
        #self.screencast = False
135
 
 
136
111
        self.effects = EffectsHandler()
137
112
        self.system = getSystem()
138
113
 
 
114
        self.current_project = None
139
115
        self.projectManager = ProjectManager(self)
140
116
        self._connectToProjectManager(self.projectManager)
141
117
 
146
122
        #self.timelineLogObserver = TimelineLogObserver(self.action_log)
147
123
        self.projectLogObserver = ProjectLogObserver(self.action_log)
148
124
 
149
 
        self.version_information = {}
 
125
        self._version_information = {}
150
126
        self._checkVersion()
151
127
 
152
128
    def shutdown(self):
165
141
        self.threads.stopAllThreads()
166
142
        self.settings.storeSettings()
167
143
        self.current_project = None
168
 
        instance.Pitivi = None
169
144
        self.emit("shutdown")
170
145
        return True
171
146
 
175
150
        pm.connect("new-project-created", self._projectManagerNewProjectCreated)
176
151
        pm.connect("new-project-loaded", self._projectManagerNewProjectLoaded)
177
152
        pm.connect("new-project-failed", self._projectManagerNewProjectFailed)
178
 
        pm.connect("closing-project", self._projectManagerClosingProject)
179
153
        pm.connect("project-closed", self._projectManagerProjectClosed)
180
154
 
181
 
    def _projectManagerNewProjectLoading(self, projectManager, uri):
 
155
    def _projectManagerNewProjectLoading(self, unused_project_manager, uri):
182
156
        self.emit("new-project-loading", uri)
183
157
 
184
 
    def _projectManagerNewProjectCreated(self, projectManager, project):
 
158
    def _projectManagerNewProjectCreated(self, unused_project_manager, project):
185
159
        self.current_project = project
186
160
        self.emit("new-project-created", project)
187
161
 
188
 
    def _newProjectLoaded(self, project):
 
162
    def _newProjectLoaded(self, unused_project):
189
163
        pass
190
164
 
191
 
    def _projectManagerNewProjectLoaded(self, projectManager, project, unused_fully_loaded):
 
165
    def _projectManagerNewProjectLoaded(self, unused_project_manager, project, unused_fully_loaded):
192
166
        self.current_project = project
193
167
        self.action_log.clean()
194
168
        #self.timelineLogObserver.startObserving(project.timeline)
196
170
        self._newProjectLoaded(project)
197
171
        self.emit("new-project-loaded", project)
198
172
 
199
 
    def _projectManagerNewProjectFailed(self, projectManager, uri, exception):
 
173
    def _projectManagerNewProjectFailed(self, unused_project_manager, uri, exception):
200
174
        self.emit("new-project-failed", uri, exception)
201
175
 
202
 
    def _projectManagerClosingProject(self, projectManager, project):
203
 
        return self.emit("closing-project", project)
204
 
 
205
 
    def _projectManagerProjectClosed(self, projectManager, project):
 
176
    def _projectManagerProjectClosed(self, unused_project_manager, project):
206
177
        #self.timelineLogObserver.stopObserving(project.timeline)
207
178
        self.projectLogObserver.stopObserving(project)
208
179
        self.current_project = None
214
185
        self.info("Requesting version information")
215
186
        giofile.load_contents_async(None, self._versionInfoReceivedCb, None)
216
187
 
217
 
    def _versionInfoReceivedCb(self, giofile, result, data):
 
188
    def _versionInfoReceivedCb(self, giofile, result, user_data):
218
189
        try:
219
190
            raw = giofile.load_contents_finish(result)[1]
220
191
            raw = raw.split("\n")
224
195
 
225
196
            # search newest version and status
226
197
            status = "UNSUPPORTED"
 
198
            current_version = None
227
199
            for version, version_status in data:
228
 
                if pitivi_version == version:
 
200
                if VERSION == version:
229
201
                    status = version_status
230
202
                if version_status.upper() == "CURRENT":
 
203
                    # This is the latest.
231
204
                    current_version = version
232
205
 
233
206
            self.info("Latest software version is %s", current_version)
234
 
            if status is "UNSUPPORTED":
235
 
                self.warning("Using an outdated version of Pitivi (%s)" % pitivi_version)
 
207
            # Python is magical... comparing version *strings* always works,
 
208
            # even with different major.minor.nano version number schemes!
 
209
            if VERSION > current_version:
 
210
                status = "CURRENT"
 
211
                self.info("Running version %s, which is newer than the latest known version. Considering it as the latest current version.", VERSION)
 
212
            elif status is "UNSUPPORTED":
 
213
                self.warning("Using an outdated version of Pitivi (%s)", VERSION)
236
214
 
237
 
            self.version_information["current"] = current_version
238
 
            self.version_information["status"] = status
239
 
            self.emit("version-info-received", self.version_information)
 
215
            self._version_information["current"] = current_version
 
216
            self._version_information["status"] = status
 
217
            self.emit("version-info-received", self._version_information)
240
218
        except Exception, e:
241
 
            self.warning("Version info could not be read: %s" % e)
 
219
            self.warning("Version info could not be read: %s", e)
 
220
 
 
221
    def isLatest(self):
 
222
        """
 
223
        Whether the app's version is the latest as far as we know.
 
224
        """
 
225
        status = self._version_information.get("status")
 
226
        return status is None or status.upper() == "CURRENT"
 
227
 
 
228
    def getLatest(self):
 
229
        """
 
230
        Get the latest version of the app or None.
 
231
        """
 
232
        return self._version_information.get("current")
242
233
 
243
234
 
244
235
class InteractivePitivi(Pitivi):
249
240
    def __init__(self, debug=False):
250
241
        Pitivi.__init__(self)
251
242
        self.mainloop = GLib.MainLoop()
252
 
        self.actioner = None
253
243
        self.gui = None
254
244
        if debug:
255
245
            sys.excepthook = self._excepthook
256
246
 
257
 
    def _excepthook(self, exc_type, value, tback):
 
247
    def _excepthook(self, unused_exc_type, unused_value, tback):
258
248
        import traceback
259
249
        import pdb
260
250
        traceback.print_tb(tback)
261
251
        pdb.post_mortem(tback)
262
252
 
263
 
    def _setActioner(self, actioner):
264
 
        self.actioner = actioner
265
 
        if self.actioner:
266
 
            self.actioner.connect("eos", self._eosCb)
267
 
            # On error, all we need to do is shutdown which
268
 
            # is the same as we do for EOS
269
 
            self.actioner.connect("error", self._eosCb)
270
 
            # Configure the actioner and start acting!
271
 
            self.actioner.startAction()
272
 
 
273
 
    def _eosCb(self, unused_obj):
274
 
        raise NotImplementedError()
275
 
 
276
 
    def _loadProject(self, project_filename):
277
 
        self.projectManager.loadProject(quote_uri(os.path.abspath(project_filename)))
278
 
 
279
253
    def run(self):
280
254
        """Runs the main loop."""
281
255
        self.mainloop.run()
294
268
        self._showGui()
295
269
 
296
270
    def _showStartupError(self, message, detail):
297
 
        dialog = Gtk.MessageDialog(type=Gtk.MessageType.ERROR,
 
271
        dialog = Gtk.MessageDialog(message_type=Gtk.MessageType.ERROR,
298
272
                                   buttons=Gtk.ButtonsType.OK)
299
273
        dialog.set_markup("<b>" + message + "</b>")
300
274
        dialog.format_secondary_text(detail)
301
275
        dialog.run()
302
276
 
303
 
    def _eosCb(self, unused_obj):
304
 
        self.shutdown()
305
 
 
306
277
    def _createGui(self):
307
278
        """Returns a Gtk.Widget which represents the UI."""
308
279
        return PitiviMainWindow(self)
338
309
        lib.connect("discovery-error", self._discoveryErrorCb, uris)
339
310
        lib.addUris(uris)
340
311
 
341
 
    def _sourceAddedCb(self, medialibrary, info, startup_uris, add_to_timeline):
 
312
    def _sourceAddedCb(self, unused_media_library, info, startup_uris, add_to_timeline):
342
313
        if self._maybePopStartupUri(startup_uris, info.get_uri()) \
343
314
                and add_to_timeline:
344
315
            self.action_log.begin("add clip")
347
318
            self.current_project.timeline.get_layers()[0].add_clip(src)
348
319
            self.action_log.commit()
349
320
 
350
 
    def _discoveryErrorCb(self, medialibrary, uri, error, debug, startup_uris):
 
321
    def _discoveryErrorCb(self, unused_media_library, uri, unused_error, unused_debug, startup_uris):
351
322
        self._maybePopStartupUri(startup_uris, uri)
352
323
 
353
324
    def _maybePopStartupUri(self, startup_uris, uri):
376
347
        if not os.path.exists(project_filename):
377
348
            self.error("Project file does not exist: %s" % project_filename)
378
349
            sys.exit(1)
379
 
        else:
380
 
            self._loadProject(project_filename)
 
350
        self.projectManager.loadProject(quote_uri(os.path.abspath(project_filename)))
381
351
 
382
352
 
383
353
class StartupWizardGuiPitivi(GuiPitivi):
392
362
        self.projectManager.newBlankProject(emission=False)
393
363
 
394
364
    def _createGui(self):
395
 
        # Prevent the main window to go fullscreen because at least
396
 
        # the Metacity window manager will refuse to bring
397
 
        # the startup wizard window in front of the main window.
398
 
        return PitiviMainWindow(self, allow_full_screen=False)
 
365
        return PitiviMainWindow(self)
399
366
 
400
367
    def _showGui(self):
401
368
        GuiPitivi._showGui(self)