30
from timeline.timeline import Timeline
31
from sourcelist import SourceList
32
from bin import SmartTimelineBin
33
from settings import ExportSettings
34
from configure import APPNAME
36
30
from gettext import gettext as _
38
class Project(gobject.GObject):
39
""" The base class for PiTiVi projects """
42
"settings-changed" : ( gobject.SIGNAL_RUN_LAST,
31
from pitivi.log.loggable import Loggable
32
from pitivi.timeline.timeline import Timeline
33
from pitivi.timeline.track import Track
34
from pitivi.stream import AudioStream, VideoStream
35
from pitivi.pipeline import Pipeline
36
from pitivi.factories.timeline import TimelineSourceFactory
37
from pitivi.sourcelist import SourceList
38
from pitivi.settings import ExportSettings
39
from pitivi.configure import APPNAME
40
from pitivi.signalinterface import Signallable
41
from pitivi.action import ViewAction
42
from pitivi.formatters.format import save_project
44
class ProjectError(Exception):
48
class ProjectSaveLoadError(ProjectError):
49
"""Error while loading/saving project"""
52
class Project(Signallable, Loggable):
53
"""The base class for PiTiVi projects
55
@ivar name: The name of the project
57
@ivar description: A description of the project
58
@type description: C{str}
59
@ivar sources: The sources used by this project
60
@type sources: L{SourceList}
61
@ivar timeline: The timeline
62
@type timeline: L{Timeline}
63
@ivar pipeline: The timeline's pipeline
64
@type pipeline: L{Pipeline}
65
@ivar factory: The timeline factory
66
@type factory: L{TimelineSourceFactory}
67
@ivar format: The format under which the project is currently stored.
68
@type format: L{FormatterClass}
69
@ivar loaded: Whether the project is fully loaded or not.
73
- C{missing-plugins} : A plugin is missing for the given uri
74
- C{loaded} : The project is now fully loaded.
78
"settings-changed" : None,
79
"missing-plugins": ["uri", "detail", "description"],
47
def __init__(self, name="", uri=None):
83
def __init__(self, name="", uri=None, **kwargs):
49
85
name : the name of the project
50
86
uri : the uri of the project
52
gst.log("name:%s, uri:%s" % (name, uri))
53
gobject.GObject.__init__(self)
88
Loggable.__init__(self)
89
self.log("name:%s, uri:%s", name, uri)
55
91
self.settings = None
56
92
self.description = ""
94
self.urichanged = False
58
96
self.sources = SourceList(self)
60
self.timelinebin = None
61
98
self.settingssigid = 0
65
""" loads the project from a file """
68
self.timeline = Timeline(self)
70
raise NotImplementedError
73
""" returns the SmartTimelineBin of the project """
76
if not self.timelinebin:
77
self.timelinebin = SmartTimelineBin(self)
78
return self.timelinebin
80
def _save(self, filename):
81
""" internal save function """
86
""" Saves the project to the project's current file """
89
def saveAs(self, filename):
90
""" Saves the project to the given file name """
101
self.sources.connect('missing-plugins', self._sourceListMissingPluginsCb)
103
self.timeline = Timeline()
105
self.factory = TimelineSourceFactory(self.timeline)
106
self.pipeline = Pipeline()
107
self.view_action = ViewAction()
108
self.view_action.addProducers(self.factory)
110
# the loading formatter will set this accordingly
114
self.pipeline.release()
94
119
def _settingsChangedCb(self, unused_settings):
95
120
self.emit('settings-changed')
107
133
Sets the given settings as the project's settings.
108
134
If settings is None, the current settings will be unset
110
gst.log("Setting %s as the project's settings" % settings)
136
self.log("Setting %s as the project's settings", settings)
111
137
if self.settings:
112
138
self.settings.disconnect(self.settingssigid)
113
139
self.settings = settings
114
140
self.emit('settings-changed')
115
self.settingssigid = self.settings.connect('settings-changed', self._settingsChangedCb)
141
self.settingssigid = self.settings.connect('settings-changed',
142
self._settingsChangedCb)
117
144
def unsetSettings(self, unused_settings):
118
145
""" Remove the currently configured settings."""
125
152
If it has more than one, it will return the largest setting that suits
126
153
all contained sources.
155
settings = ExportSettings()
128
156
if not self.timeline:
129
gst.warning("project doesn't have a timeline, returning default settings")
130
return ExportSettings()
131
settings = self.timeline.getAutoSettings()
133
gst.warning("Timeline didn't return any auto settings, return default settings")
134
return ExportSettings()
136
# add the encoders and muxer of the default settings
137
curset = self.settings or ExportSettings()
138
settings.vencoder = curset.vencoder
139
settings.aencoder = curset.aencoder
140
settings.muxer = curset.muxer
157
self.warning("project doesn't have a timeline, returning default settings")
160
# FIXME: this is ugly, but rendering for now assumes at most one audio
161
# and one video tracks
162
have_audio = have_video = False
163
for track in self.timeline.tracks:
164
if isinstance(track.stream, VideoStream) and track.duration != 0:
166
elif isinstance(track.stream, AudioStream) and track.duration != 0:
170
settings.aencoder = None
173
settings.vencoder = None
144
def file_is_project(uri):
145
""" returns True if the given uri is a PitiviProject file"""
147
if not gst.uri_get_protocol(uri) == "file":
148
raise NotImplementedError(_("%s doesn't yet handle non local projects") % APPNAME)
149
return os.path.isfile(gst.uri_get_location(uri))
179
def _sourceListMissingPluginsCb(self, source_list, uri, detail, description):
180
return self.emit('missing-plugins', uri, detail, description)
182
#{ Save and Load features
184
def save(self, location=None, overwrite=False):
186
Save the project to the given location.
188
@param location: The location to write to. If not specified, the
189
current project location will be used (if set).
190
@type location: C{URI}
191
@param overwrite: Whether to overwrite existing location.
192
@type overwrite: C{bool}
194
@raises ProjectSaveLoadError: If no uri was provided and none was set
197
self.log("saving...")
198
location = location or self.uri
201
raise ProjectSaveLoadError("Location unknown")
203
save_project(self, location or self.uri, self.format,
208
def setModificationState(self, state):
211
def hasUnsavedModifications(self):
214
def markLoaded(self):
216
Mark the project as loaded.
218
Will emit the 'loaded' signal. Only meant to be used by