[pitivi/ges: 1/287] Implement import and playback of 1 clip or project using GES



commit 1dbb504a9d9ebba54a48a0e30afd087c692fd591
Author: Mathieu Duponchelle <seeed laposte net>
Date:   Sun Aug 28 23:21:22 2011 +0200

    Implement import and playback of 1 clip or project using GES
    
    * Disconnect observer, need to be reconnect. Start making changes to get it ready for GES
    * Disconnect selection changed, needs to be handled with/by GES
    * Unconnect the track names recenter when adding track
    * Effects are not handled anymore
    
    Almost everything is broken now!

 pitivi/application.py            |    9 ++-
 pitivi/project.py                |   21 +++----
 pitivi/projectmanager.py         |    8 ---
 pitivi/timeline/timeline_undo.py |   14 +++--
 pitivi/ui/clipproperties.py      |   13 +++--
 pitivi/ui/mainwindow.py          |   45 ++++-----------
 pitivi/ui/startupwizard.py       |    5 +-
 pitivi/ui/timeline.py            |   98 +++++--------------------------
 pitivi/ui/timelinecanvas.py      |   10 +--
 pitivi/ui/timelinecontrols.py    |   23 ++++---
 pitivi/ui/track.py               |   79 ++++++++++++++++---------
 pitivi/ui/trackobject.py         |   76 +++++++++++++++---------
 pitivi/ui/viewer.py              |  118 +++++++++++++++++++++-----------------
 pitivi/utils.py                  |    4 +-
 14 files changed, 245 insertions(+), 278 deletions(-)
---
diff --git a/pitivi/application.py b/pitivi/application.py
index 094e51c..f28315c 100644
--- a/pitivi/application.py
+++ b/pitivi/application.py
@@ -133,7 +133,8 @@ class Pitivi(Loggable, Signallable):
         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)
+        # TODO reimplement the observing after GES port
+        #self.timelineLogObserver = TimelineLogObserver(self.action_log)
         self.projectLogObserver = ProjectLogObserver(self.action_log)
         self.sourcelist_log_observer = SourceListLogObserver(self.action_log)
 
@@ -184,7 +185,7 @@ class Pitivi(Loggable, Signallable):
     def _projectManagerNewProjectLoaded(self, projectManager, project):
         self.current = project
         self.action_log.clean()
-        self.timelineLogObserver.startObserving(project.timeline)
+        #self.timelineLogObserver.startObserving(project.timeline)
         self.projectLogObserver.startObserving(project)
         self.sourcelist_log_observer.startObserving(project.sources)
         self._newProjectLoaded(project)
@@ -197,7 +198,7 @@ class Pitivi(Loggable, Signallable):
         return self.emit("closing-project", project)
 
     def _projectManagerProjectClosed(self, projectManager, project):
-        self.timelineLogObserver.stopObserving(project.timeline)
+        #self.timelineLogObserver.stopObserving(project.timeline)
         self.projectLogObserver.stopObserving(project)
         self.current = None
         self.emit("project-closed", project)
@@ -369,6 +370,8 @@ class StartupWizardGuiPitivi(FullGuiPitivi):
 
     def __init__(self, debug=False):
         FullGuiPitivi.__init__(self, debug)
+        self.projectManager.newBlankProject()
+        self.gui.viewer.setPipeline()
 
     def _createGui(self):
         self.wizard = StartUpWizard(self)
diff --git a/pitivi/project.py b/pitivi/project.py
index 298dc71..7dec97f 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -24,7 +24,6 @@ Project class
 """
 
 from pitivi.log.loggable import Loggable
-from pitivi.timeline.timeline import Timeline
 from pitivi.pipeline import Pipeline
 from pitivi.factories.timeline import TimelineSourceFactory
 from pitivi.sourcelist import SourceList
@@ -33,6 +32,7 @@ from pitivi.signalinterface import Signallable
 from pitivi.action import ViewAction
 from pitivi.utils import Seeker
 import gst
+import ges
 
 
 class ProjectError(Exception):
@@ -90,19 +90,20 @@ class Project(Signallable, Loggable):
 
         self._dirty = False
 
-        self.timeline = Timeline()
+        self.timeline = ges.timeline_new_audio_video()
+        self.layer = ges.TimelineLayer()
+        self.timeline.add_layer(self.layer)
 
-        self.factory = TimelineSourceFactory(self.timeline)
-        self.pipeline = Pipeline()
+        self.pipeline = ges.TimelinePipeline()
+        self.pipeline._setUp = False
+        self.pipeline.add_timeline(self.timeline)
         self.view_action = ViewAction()
-        self.view_action.addProducers(self.factory)
         self.seeker = Seeker(80)
 
         self.settings = ExportSettings()
         self._videocaps = self.settings.getVideoCaps()
 
     def release(self):
-        self.pipeline.release()
         self.pipeline = None
 
     #{ Settings methods
@@ -142,14 +143,12 @@ class Project(Signallable, Loggable):
     def _projectSettingsChanged(self):
         settings = self.getSettings()
         self._videocaps = settings.getVideoCaps()
-        if self.timeline:
-            self.timeline.updateVideoCaps(self._videocaps)
 
         for fact in self.sources.getSources():
             fact.setFilterCaps(self._videocaps)
-        if self.pipeline.getState() != gst.STATE_NULL:
-            self.pipeline.stop()
-            self.pipeline.pause()
+        if self.pipeline.get_state() != gst.STATE_NULL:
+            self.pipeline.set_state(gst.STATE_READY)
+            self.pipeline.set_state(gst.STATE_PAUSED)
 
     def _sourceAddedCb(self, sourcelist, factory):
         factory.setFilterCaps(self._videocaps)
diff --git a/pitivi/projectmanager.py b/pitivi/projectmanager.py
index 0497295..5f25a66 100644
--- a/pitivi/projectmanager.py
+++ b/pitivi/projectmanager.py
@@ -21,7 +21,6 @@
 
 from gettext import gettext as _
 import gobject
-import gst
 import os
 
 from urlparse import urlparse
@@ -37,7 +36,6 @@ from pitivi.stream import AudioStream, VideoStream
 from pitivi.timeline.track import Track
 from pitivi.undo import UndoableAction
 
-
 class ProjectSettingsChanged(UndoableAction):
 
     def __init__(self, project, old, new):
@@ -191,12 +189,6 @@ class ProjectManager(Signallable, Loggable):
         # the rendered content will have. Pitivi currently supports
         # projects with exactly one video track and one audio track.
         settings = project.getSettings()
-        video = VideoStream(gst.Caps(settings.getVideoCaps()))
-        track = Track(video)
-        project.timeline.addTrack(track)
-        audio = AudioStream(gst.Caps(settings.getAudioCaps()))
-        track = Track(audio)
-        project.timeline.addTrack(track)
         project.connect("project-changed", self._projectChangedCb)
 
         self.emit("new-project-loaded", self.current)
diff --git a/pitivi/timeline/timeline_undo.py b/pitivi/timeline/timeline_undo.py
index d9a5ede..33b5cb2 100644
--- a/pitivi/timeline/timeline_undo.py
+++ b/pitivi/timeline/timeline_undo.py
@@ -369,10 +369,11 @@ class TimelineLogObserver(object):
 
     def startObserving(self, timeline):
         self._connectToTimeline(timeline)
-        for timeline_object in timeline.timeline_objects:
-            self._connectToTimelineObject(timeline_object)
-            for track_object in timeline_object.track_objects:
-                self._connectToTrackObject(track_object)
+        for layer in timeline.get_layers():
+            for timeline_object in layer.get_objects():
+                self._connectToTimelineObject(timeline_object)
+                for track_object in timeline_object.track_objects:
+                    self._connectToTrackObject(track_object)
 
     def stopObserving(self, timeline):
         self._disconnectFromTimeline(timeline)
@@ -382,8 +383,9 @@ class TimelineLogObserver(object):
                 self._disconnectFromTrackObject(track_object)
 
     def _connectToTimeline(self, timeline):
-        timeline.connect("timeline-object-added", self._timelineObjectAddedCb)
-        timeline.connect("timeline-object-removed", self._timelineObjectRemovedCb)
+        for layer in timeline.get_layers():
+            layer.connect("object-added", self._timelineObjectAddedCb)
+            layer.connect("object-removed", self._timelineObjectRemovedCb)
 
     def _disconnectFromTimeline(self, timeline):
         timeline.disconnect_by_func(self._timelineObjectAddedCb)
diff --git a/pitivi/ui/clipproperties.py b/pitivi/ui/clipproperties.py
index 5bc8f85..5eb3a68 100644
--- a/pitivi/ui/clipproperties.py
+++ b/pitivi/ui/clipproperties.py
@@ -245,7 +245,8 @@ class EffectProperties(gtk.Expander, gtk.HBox):
 
     def _newProjectLoadedCb(self, app, project):
         self.clip_properties.project = project
-        self.selected_effects = self.timeline.selection.getSelectedTrackEffects()
+        #GES break, reimplement me
+        #self.selected_effects = self.timeline.selection.getSelectedTrackEffects()
         self._updateAll()
 
     def _vcontentNotifyCb(self, paned, gparamspec):
@@ -258,8 +259,9 @@ class EffectProperties(gtk.Expander, gtk.HBox):
 
     def _setTimeline(self, timeline):
         self._timeline = timeline
-        if timeline:
-            self.timeline.connect('selection-changed', self._selectionChangedCb)
+        #GES break, reimplement me
+        #if timeline:
+        #    self.timeline.connect('selection-changed', self._selectionChangedCb)
 
     timeline = property(_getTimeline, _setTimeline)
 
@@ -626,7 +628,8 @@ class TransformationProperties(gtk.Expander):
 
     def _setTimeline(self, timeline):
         self._timeline = timeline
-        if timeline:
-            self.timeline.connect('selection-changed', self._selectionChangedCb)
+        #TODO reimplement it in GES
+        #if timeline:
+        #    self.timeline.connect('selection-changed', self._selectionChangedCb)
 
     timeline = property(_getTimeline, _setTimeline)
diff --git a/pitivi/ui/mainwindow.py b/pitivi/ui/mainwindow.py
index 0b21e3b..5c8d092 100644
--- a/pitivi/ui/mainwindow.py
+++ b/pitivi/ui/mainwindow.py
@@ -364,7 +364,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
         vpaned.show()
 
         self.timeline = Timeline(instance, self.uimanager)
-        self.timeline.project = self.project
+        self.project = None
 
         vpaned.pack2(self.timeline, resize=True, shrink=False)
         self.timeline.show()
@@ -401,7 +401,6 @@ class PitiviMainWindow(gtk.Window, Loggable):
         #Clips properties
         self.propertiestabs = BaseTabs(instance, True)
         self.clipconfig = ClipProperties(instance, self.uimanager)
-        self.clipconfig.project = self.project
         self.propertiestabs.append_page(self.clipconfig,
                                         gtk.Label(_("Clip configuration")))
         self.clipconfig.show()
@@ -689,8 +688,11 @@ class PitiviMainWindow(gtk.Window, Loggable):
     def _projectManagerNewProjectLoadedCb(self, projectManager, project):
         self.log("A NEW project is loaded, update the UI!")
         self.project = project
+        self.timeline.project = self.project
+        self.clipconfig.project = self.project
         self._connectToProjectSources(project.sources)
-        can_render = project.timeline.duration > 0
+        duration = 0
+        can_render = duration > 0
         self.render_button.set_sensitive(can_render)
         self._syncDoUndo(self.app.action_log)
 
@@ -699,7 +701,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
             self.actiongroup.get_action("SaveProject").set_sensitive(True)
             self._missingUriOnLoading = False
 
-        if project.timeline.duration != 0:
+        if duration != 0:
             self.setBestZoomRatio()
         else:
             self._zoom_duration_changed = True
@@ -714,7 +716,10 @@ class PitiviMainWindow(gtk.Window, Loggable):
         ruler_width = self.timeline.ruler.get_allocation()[2]
         # Add gst.SECOND - 1 to the timeline duration to make sure the
         # last second of the timeline will be in view.
-        timeline_duration = self.project.timeline.duration + gst.SECOND - 1
+        tracks = self.project.timeline.get_tracks()
+        duration = max (tracks[0].props.duration, tracks[1].props.duration)
+        self.project.timeline.duration = duration
+        timeline_duration = duration + gst.SECOND - 1
         timeline_duration_s = int(timeline_duration / gst.SECOND)
 
         ideal_zoom_ratio = float(ruler_width) / timeline_duration_s
@@ -807,10 +812,6 @@ class PitiviMainWindow(gtk.Window, Loggable):
 
     def _projectManagerProjectClosedCb(self, projectManager, project):
         # we must disconnect from the project pipeline before it is released
-        self._disconnectFromProjectSources(project.sources)
-        self.viewer.setAction(None)
-        self.viewer.setPipeline(None)
-        project.seeker.disconnect_by_func(self._timelineSeekCb)
         return False
 
     def _projectManagerRevertingToSavedCb(self, projectManager, project):
@@ -958,14 +959,6 @@ class PitiviMainWindow(gtk.Window, Loggable):
                 self.clipconfig.project = self.project
                 self.app.timelineLogObserver.pipeline = self.project.pipeline
 
-    project = receiver(_setProject)
-
-    @handler(project, "settings-changed")
-    def _settingsChangedCb(self, project, old, new):
-        if self.viewer.action == self.project.view_action:
-            self.viewer.setDisplayAspectRatio(float(new.videopar *
-            new.videowidth) / float(new.videoheight))
-
     def _sourceListMissingPluginsCb(self, project, uri, factory,
             details, descriptions, missingPluginsCallback):
         res = self._installPlugins(details, missingPluginsCallback)
@@ -1081,26 +1074,12 @@ class PitiviMainWindow(gtk.Window, Loggable):
         context.finish(True, False, ctime)
 
     def _viewFactory(self, factory):
-        # FIXME: we change the viewer pipeline unconditionally for now
-        # we need a pipeline for playback
-        pipeline = Pipeline()
-        action = ViewAction()
-        action.addProducers(factory)
-        self.viewer.setPipeline(None)
-        self.viewer.showSlider()
-        # FIXME: why do I have to call viewer.setAction ?
-        self.viewer.setAction(action)
-        self.viewer.setPipeline(pipeline)
-        self.viewer.play()
+        #GES crazyness... remove it or implement something?
+        pass
 
     def _timelineSeekCb(self, ruler, position, format):
         self.debug("position:%s", gst.TIME_ARGS(position))
         if self.viewer.action != self.project.view_action:
-            self.viewer.setPipeline(None)
-            self.viewer.hideSlider()
-            self.viewer.setAction(self.project.view_action)
-            self.viewer.setPipeline(self.project.pipeline)
-            # get the pipeline settings and set the DAR of the viewer
             sett = self.project.getSettings()
             self.viewer.setDisplayAspectRatio(float(sett.videopar * sett.videowidth) / float(sett.videoheight))
         # everything above only needs to be done if the viewer isn't already
diff --git a/pitivi/ui/startupwizard.py b/pitivi/ui/startupwizard.py
index 6cf9e9d..96ef954 100644
--- a/pitivi/ui/startupwizard.py
+++ b/pitivi/ui/startupwizard.py
@@ -21,7 +21,6 @@
 
 import os
 import gtk
-import webbrowser
 
 from gettext import gettext as _
 
@@ -77,11 +76,11 @@ class StartUpWizard(object):
 
     def _loadCb(self, unused_recent_chooser):
         """Handle a double-click on the recent chooser."""
-        self.app.projectManager.loadProject(self._getFileName())
+        self.app.gui.viewer.loadProject(self._getFileName())
 
     def _getFileName(self):
         """Get the URI of the project selected in the recent chooser."""
-        uri = self.recent_chooser.get_current_uri()
+        uri = self.recent_chooser.get_current_uri()[7:]
         return unquote(uri)
 
     def _keyPressCb(self, widget, event):
diff --git a/pitivi/ui/timeline.py b/pitivi/ui/timeline.py
index 27c4b74..39c3dfc 100644
--- a/pitivi/ui/timeline.py
+++ b/pitivi/ui/timeline.py
@@ -30,6 +30,7 @@ import ruler
 import dnd
 import gst
 import gobject
+import ges
 
 from gettext import gettext as _
 from timelinecanvas import TimelineCanvas
@@ -390,9 +391,6 @@ class Timeline(gtk.Table, Loggable, Zoomable):
 ## Drag and Drop callbacks
 
     def _dragMotionCb(self, unused, context, x, y, timestamp):
-        self.warning("self._factories:%r, self._temp_objects:%r",
-                     not not self._factories,
-                     not not self._temp_objects)
 
         if self._factories is None:
             if  context.targets in DND_EFFECT_LIST:
@@ -405,12 +403,8 @@ class Timeline(gtk.Table, Loggable, Zoomable):
         else:
             if  context.targets not in DND_EFFECT_LIST:
                 if not self._temp_objects:
-                    self.timeline.disableUpdates()
-                    self._add_temp_source()
-                    focus = self._temp_objects[0]
-                    self._move_context = MoveContext(self.timeline,
-                            focus, set(self._temp_objects[1:]))
-                self._move_temp_source(self.hadj.props.value + x, y)
+                    #GES break,FIXME
+                    pass
         return True
 
     def _dragLeaveCb(self, unused_layout, context, unused_tstamp):
@@ -422,25 +416,18 @@ class Timeline(gtk.Table, Loggable, Zoomable):
                 self._temp_objects = None
 
         self.drag_unhighlight()
-        self.timeline.enableUpdates()
+        #FIXME, GES break, temporary hack
+        uris = self.selection_data.split("\n")
+        layer = self.app.projectManager.current.timeline.get_layers()[0]
+        for uri in uris :
+            src = ges.TimelineFileSource(uri)
+            layer.add_object(src)
 
     def _dragDropCb(self, widget, context, x, y, timestamp):
+            #FIXME GES break, reimplement me
         if  context.targets not in DND_EFFECT_LIST:
             self.app.action_log.begin("add clip")
-            self.timeline.disableUpdates()
-
-            self._add_temp_source()
-            self.timeline.selection.setSelection(self._temp_objects, SELECT)
-            focus = self._temp_objects[0]
-            self._move_context = MoveContext(self.timeline,
-                                             focus, set(self._temp_objects[1:]))
-            self._move_temp_source(self.hadj.props.value + x, y)
-            self._move_context.finish()
             self.app.action_log.commit()
-            context.drop_finish(True, timestamp)
-            self._factories = None
-            self._temp_objects = None
-            self.app.current.seeker.seek(self._position)
 
             return True
         elif context.targets in DND_EFFECT_LIST:
@@ -474,6 +461,7 @@ class Timeline(gtk.Table, Loggable, Zoomable):
         # tell current project to import the uri
         # wait for source-added signal, meanwhile ignore dragMotion signals
         # when ready, add factories to the timeline.
+        self.selection_data = selection.data
 
         if targetType not in [dnd.TYPE_PITIVI_FILESOURCE, dnd.TYPE_PITIVI_EFFECT]:
             context.finish(False, False, timestamp)
@@ -555,11 +543,14 @@ class Timeline(gtk.Table, Loggable, Zoomable):
         self._vscrollbar.set_value(self._vscrollbar.get_value() +
             self.vadj.props.page_size ** (2.0 / 3.0))
 
-    def _updateScrollPosition(self, adjustment):
+    def unsureVadjHeight (self):
         self._scroll_pos_ns = Zoomable.pixelToNs(self.hadj.get_value())
         self._root_item.set_simple_transform(-self.hadj.get_value(),
             -self.vadj.get_value(), 1.0, 0)
 
+    def _updateScrollPosition(self, adjustment):
+        self.unsureVadjHeight()
+
     def _zoomAdjustmentChangedCb(self, adjustment):
         # GTK crack
         self._updateZoom = False
@@ -643,6 +634,7 @@ class Timeline(gtk.Table, Loggable, Zoomable):
             self.timeline = self.project.timeline
             self._controls.timeline = self.timeline
             self._canvas.timeline = self.timeline
+            self._canvas.set_timeline()
             self._canvas.zoomChanged()
             self.ruler.setProjectFrameRate(self.project.getSettings().videorate)
             self.ruler.zoomChanged()
@@ -667,16 +659,6 @@ class Timeline(gtk.Table, Loggable, Zoomable):
 
         self._controls.timeline = self.timeline
 
-    timeline = receiver(_setTimeline)
-
-    @handler(timeline, "duration-changed")
-    def _timelineStartDurationChanged(self, unused_timeline, duration):
-        self._prev_duration = duration
-        self.ruler.setMaxDuration(duration + 60 * gst.SECOND)
-        self._canvas.setMaxDuration(duration + 60 * gst.SECOND)
-        self.ruler.setShadedDuration(duration)
-        self._updateScrollAdjustments()
-
     def _updateScrollAdjustments(self):
         a = self.get_allocation()
         size = Zoomable.nsToPixel(self.timeline.duration)
@@ -686,54 +668,6 @@ class Timeline(gtk.Table, Loggable, Zoomable):
         self.hadj.props.page_increment = size * 0.9
         self.hadj.props.step_increment = size * 0.1
 
-    @handler(timeline, "selection-changed")
-    def _timelineSelectionChanged(self, timeline):
-        delete = False
-        link = False
-        unlink = False
-        group = False
-        ungroup = False
-        align = False
-        split = False
-        keyframe = False
-        if timeline.selection:
-            delete = True
-            if len(timeline.selection) > 1:
-                link = True
-                group = True
-                align = AutoAligner.canAlign(timeline.selection)
-
-            start = None
-            duration = None
-            for obj in self.timeline.selection:
-                if obj.link:
-                    link = False
-                    unlink = True
-
-                if len(obj.track_objects) > 1:
-                    ungroup = True
-
-                if start is not None and duration is not None:
-                    if obj.start != start or obj.duration != duration:
-                        group = False
-                else:
-                    start = obj.start
-                    duration = obj.duration
-
-            keyframe = True
-
-        if (len(timeline.timeline_objects) > 0):
-            split = True
-
-        self.delete_action.set_sensitive(delete)
-        self.link_action.set_sensitive(link)
-        self.unlink_action.set_sensitive(unlink)
-        self.group_action.set_sensitive(group)
-        self.ungroup_action.set_sensitive(ungroup)
-        self.align_action.set_sensitive(align)
-        self.split_action.set_sensitive(split)
-        self.keyframe_action.set_sensitive(keyframe)
-
 ## ToolBar callbacks
     def _zoomFitCb(self, unused_action):
         self.app.gui.setBestZoomRatio()
diff --git a/pitivi/ui/timelinecanvas.py b/pitivi/ui/timelinecanvas.py
index 6941e96..e2b22b6 100644
--- a/pitivi/ui/timelinecanvas.py
+++ b/pitivi/ui/timelinecanvas.py
@@ -305,17 +305,16 @@ class TimelineCanvas(goocanvas.Canvas, Zoomable, Loggable):
 
 ## Timeline callbacks
 
-    def _set_timeline(self):
+    def set_timeline(self):
         while self._tracks:
             self._trackRemoved(None, 0)
         if self.timeline:
-            for track in self.timeline.tracks:
+            for track in self.timeline.get_tracks():
                 self._trackAdded(None, track)
+            self.timeline.connect ("track-added", self._trackAdded)
+            self.timeline.connect ("track-removed", self._trackRemoved)
         self.zoomChanged()
 
-    timeline = receiver(_set_timeline)
-
-    @handler(timeline, "track-added")
     def _trackAdded(self, timeline, track):
         track = Track(self.app, track, self.timeline)
         self._tracks.append(track)
@@ -323,7 +322,6 @@ class TimelineCanvas(goocanvas.Canvas, Zoomable, Loggable):
         self.tracks.add_child(track)
         self.regroupTracks()
 
-    @handler(timeline, "track-removed")
     def _trackRemoved(self, unused_timeline, position):
         track = self._tracks[position]
         del self._tracks[position]
diff --git a/pitivi/ui/timelinecontrols.py b/pitivi/ui/timelinecontrols.py
index 312f3b3..e83d545 100644
--- a/pitivi/ui/timelinecontrols.py
+++ b/pitivi/ui/timelinecontrols.py
@@ -31,11 +31,13 @@ class TrackControls(gtk.Label):
         if self.track:
             self._maxPriorityChanged(None, self.track.max_priority)
 
-    track = receiver(_setTrack)
-
-    @handler(track, "max-priority-changed")
-    def _maxPriorityChanged(self, track, max_priority):
-        self._setSize(max_priority + 1)
+    # FIXME Stop using the receiver
+    #
+    # TODO implement in GES
+    #track = receiver(_setTrack)
+    # handler(track, "max-priority-changed")
+    #def _maxPriorityChanged(self, track, max_priority):
+    #    self._setSize(max_priority + 1)
 
     def _setSize(self, layers_count):
         assert layers_count >= 1
@@ -44,12 +46,13 @@ class TrackControls(gtk.Label):
 
     @staticmethod
     def _getTrackName(track):
-        stream_type = type(track.stream)
-        if stream_type == stream.AudioStream:
+        track_name = ""
+        #FIXME check that it is the best way to check the type
+        if track.props.track_type.first_value_name == 'GES_TRACK_TYPE_AUDIO':
             track_name = _("Audio:")
-        elif stream_type == stream.VideoStream:
+        elif track.props.track_type.first_value_name == 'GES_TRACK_TYPE_VIDEO':
             track_name = _("Video:")
-        elif stream_type == stream.TextStream:
+        elif track.props.track_type.first_value_name == 'GES_TRACK_TYPE_TEXT':
             track_name = _("Text:")
         return "<b>%s</b>" % track_name
 
@@ -69,7 +72,7 @@ class TimelineControls(gtk.VBox):
         while self._tracks:
             self._trackRemoved(None, 0)
         if self.timeline:
-            for track in self.timeline.tracks:
+            for track in self.timeline.get_tracks():
                 self._trackAdded(None, track)
 
     timeline = receiver(_set_timeline)
diff --git a/pitivi/ui/track.py b/pitivi/ui/track.py
index caf21e8..272f337 100644
--- a/pitivi/ui/track.py
+++ b/pitivi/ui/track.py
@@ -4,7 +4,8 @@ from pitivi.timeline.track import TrackEffect
 from pitivi.receiver import receiver, handler
 from pitivi.ui.common import LAYER_HEIGHT_EXPANDED, LAYER_HEIGHT_COLLAPSED, LAYER_SPACING
 import goocanvas
-
+import ges
+import gobject
 
 class Transition(goocanvas.Rect, Zoomable):
 
@@ -26,20 +27,20 @@ class Transition(goocanvas.Rect, Zoomable):
 
     def _updateAll(self):
         transition = self.transition
-        start = transition.start
-        duration = transition.duration
-        priority = transition.priority
+        start = transition.get_start()
+        duration = transition.get_duration()
+        priority = transition.get_priority()
         self._updateStart(transition, start)
         self._updateDuration(transition, duration)
         self._updatePriority(transition, priority)
 
     transition = receiver(_setTransition)
 
-    @handler(transition, "start-changed")
+    @handler(transition, "notify::start")
     def _updateStart(self, transition, start):
         self.props.x = self.nsToPixel(start)
 
-    @handler(transition, "duration-changed")
+    @handler(transition, "notify::duration")
     def _updateDuration(self, transition, duration):
         width = max(0, self.nsToPixel(duration))
         if width == 0:
@@ -48,9 +49,9 @@ class Transition(goocanvas.Rect, Zoomable):
             self.props.visibility = goocanvas.ITEM_VISIBLE
         self.props.width = width
 
-    @handler(transition, "priority-changed")
+    @handler(transition, "notify::priority")
     def _updatePriority(self, transition, priority):
-        self.props.y = (LAYER_HEIGHT_EXPANDED + LAYER_SPACING) * priority
+        self.props.y = (LAYER_HEIGHT_EXPANDED + LAYER_SPACING) * transition.get_priority()
 
     def zoomChanged(self):
         self._updateAll()
@@ -80,8 +81,22 @@ class Track(goocanvas.Group, Zoomable):
             self.get_canvas().regroupTracks()
 
     def getHeight(self):
+        track_objects = self.track.get_objects()
+        max_priority = 0
+        for track_object in track_objects :
+            if isinstance (track_object, ges.TrackAudioTestSource):
+                break
+            if isinstance (track_object, ges.TrackVideoTestSource):
+                break
+            priority = track_object.get_priority()
+            if priority > max_priority:
+                max_priority = priority
+        self.track.max_priority = (max_priority) / 10
+        if self.track.max_priority < 0:
+            self.track.max_priority = 0
         if self._expanded:
             return (1 + self.track.max_priority) * (LAYER_HEIGHT_EXPANDED + LAYER_SPACING)
+            #return LAYER_HEIGHT_EXPANDED + LAYER_SPACING
         else:
             return LAYER_HEIGHT_COLLAPSED + LAYER_SPACING
 
@@ -93,41 +108,47 @@ class Track(goocanvas.Group, Zoomable):
 
     def _setTrack(self):
         if self.track:
-            for trackobj in self.track.track_objects:
+            for trackobj in self.track.get_objects():
                 self._objectAdded(None, trackobj)
-            for transition in self.track.transitions.itervalues():
-                self._transitionAdded(None, transition)
 
     track = receiver(_setTrack)
 
     @handler(track, "track-object-added")
     def _objectAdded(self, unused_timeline, track_object):
-        if not isinstance(track_object, TrackEffect):
-            w = TrackObject(self.app, track_object, self.track, self.timeline)
-            self.widgets[track_object] = w
+        if isinstance (track_object, ges.TrackParseLaunchEffect):
+            return
+        if isinstance (track_object, ges.TrackAudioTestSource):
+            return
+        if isinstance (track_object, ges.TrackVideoTestSource):
+            return
+        if isinstance (track_object, ges.TrackVideoTestSource):
+            return
+        if isinstance (track_object, ges.TrackAudioTransition):
+            self._transitionAdded (track_object)
+            return
+        if isinstance (track_object, ges.TrackVideoTransition):
+            self._transitionAdded (track_object)
+            return
+        gobject.timeout_add(1, self.check, track_object)
+
+    def check(self, tr_obj):
+        if tr_obj.get_timeline_object():
+            w = TrackObject(self.app, tr_obj, self.track, self.timeline)
+            self.widgets[tr_obj] = w
             self.add_child(w)
+            self.app.gui.setBestZoomRatio()
 
     @handler(track, "track-object-removed")
     def _objectRemoved(self, unused_timeline, track_object):
-        if not isinstance(track_object, TrackEffect):
+        if not isinstance(track_object, ges.TrackParseLaunchEffect):
             w = self.widgets[track_object]
             self.remove_child(w)
             del self.widgets[track_object]
             Zoomable.removeInstance(w)
 
-    @handler(track, "transition-added")
-    def _transitionAdded(self, unused_timeline, transition):
-        w = Transition(transition)
+    def _transitionAdded(self, transition):
+        w = TrackObject(self.app, transition, self.track, self.timeline, self, True)
         self.widgets[transition] = w
         self.add_child(w)
-
-    @handler(track, "transition-removed")
-    def _transitionRemoved(self, unused_timeline, transition):
-        w = self.widgets[transition]
-        self.remove_child(w)
-        del self.widgets[transition]
-        Zoomable.removeInstance(w)
-
-    @handler(track, "max-priority-changed")
-    def _maxPriorityChanged(self, track, max_priority):
-        self.get_canvas().regroupTracks()
+        self.transitions.append(w)
+        w.raise_(None)
diff --git a/pitivi/ui/trackobject.py b/pitivi/ui/trackobject.py
index b67e70b..9e5e0cd 100644
--- a/pitivi/ui/trackobject.py
+++ b/pitivi/ui/trackobject.py
@@ -240,7 +240,7 @@ class TrackObject(View, goocanvas.Group, Zoomable):
                 self._view.app.current.seeker.seek(Zoomable.pixelToNs(x))
                 timeline.setSelectionToObj(element, SELECT)
 
-    def __init__(self, instance, element, track, timeline):
+    def __init__(self, instance, element, track, timeline, is_transition = False):
         goocanvas.Group.__init__(self)
         View.__init__(self)
         Zoomable.__init__(self)
@@ -249,13 +249,12 @@ class TrackObject(View, goocanvas.Group, Zoomable):
         self.timeline = timeline
         self.namewidth = 0
         self.nameheight = 0
+        self.is_transition = is_transition
 
         self.bg = goocanvas.Rect(
             height=self.height,
             line_width=1)
 
-        self.content = Preview(self.app, element)
-
         self.name = goocanvas.Text(
             x=NAME_HOFFSET + NAME_PADDING,
             y=NAME_VOFFSET + NAME_PADDING,
@@ -278,12 +277,14 @@ class TrackObject(View, goocanvas.Group, Zoomable):
             line_width=0.0,
             height=self.height)
 
-        for thing in (self.bg, self.content, self.selection_indicator,
-            self.start_handle, self.end_handle, self.namebg, self.name):
-            self.add_child(thing)
-
-        for prop, interpolator in element.getInterpolators().itervalues():
-            self.add_child(Curve(instance, element, interpolator))
+        if not self.is_transition:
+            for thing in (self.bg, self.selection_indicator,
+                self.start_handle, self.end_handle, self.namebg, self.name):
+                self.add_child(thing)
+        else :
+            for thing in (self.bg, self.selection_indicator,
+                self.namebg, self.name):
+                self.add_child(thing)
 
         self.element = element
         self.settings = instance.settings
@@ -354,10 +355,10 @@ class TrackObject(View, goocanvas.Group, Zoomable):
     @handler(settings, "selectedColorChanged")
     @handler(settings, "clipFontDescChanged")
     def clipAppearanceSettingsChanged(self, *args):
-        if isinstance(self.element.stream, VideoStream):
-            color = self.settings.videoClipBg
-        elif isinstance(self.element.stream, AudioStream):
+        if self.element.get_track().props.track_type.first_value_name == 'GES_TRACK_TYPE_AUDIO':
             color = self.settings.audioClipBg
+        else:
+            color = self.settings.videoClipBg
         pattern = unpack_cairo_gradient(color)
         self.bg.props.fill_pattern = pattern
 
@@ -377,9 +378,8 @@ class TrackObject(View, goocanvas.Group, Zoomable):
 ## element signals
 
     def _setElement(self):
-        if self.element:
-            self.name.props.text = os.path.basename(unquote(
-                self.element.factory.name))
+        if self.element and not self.is_transition:
+            self.name.props.text = self.element.get_property ("uri")
             twidth, theight = text_size(self.name)
             self.namewidth = twidth
             self.nameheight = theight
@@ -387,32 +387,50 @@ class TrackObject(View, goocanvas.Group, Zoomable):
 
     element = receiver(_setElement)
 
-    @handler(element, "start-changed")
-    @handler(element, "duration-changed")
+    @handler(element, "notify::start")
+    @handler(element, "notify::duration")
     def startChangedCb(self, track_object, start):
         self._update()
 
-    @handler(element, "selected-changed")
-    def selected_changed(self, element, state):
-        if element.selected:
+    def selected_changed(self, unused_project, element):
+        self.timeline.selected = []
+        if isinstance(element, set):
+            for elem in element:
+                elem.selected = True
+                self.timeline.selected.append(elem)
+            for elem in element:
+                if elem == self.element:
+                    print elem.get_timeline_object().get_property("priority"), "la pute !!"
+                    self.selection_indicator.props.visibility = goocanvas.ITEM_VISIBLE
+                    elem.selected = True
+                elif self.element.selected == False:
+                    self.selection_indicator.props.visibility = \
+                        goocanvas.ITEM_INVISIBLE
+            for elem in element:
+                elem.selected = False
+            return
+
+        else:
+            self.timeline.selected.append(element)
+
+        if element == self.element:
             self.selection_indicator.props.visibility = goocanvas.ITEM_VISIBLE
         else:
             self.selection_indicator.props.visibility = \
                 goocanvas.ITEM_INVISIBLE
 
-    @handler(element, "priority-changed")
-    def priority_changed(self, element, priority):
-        self._update()
-
     def _update(self):
         try:
-            x = self.nsToPixel(self.element.start)
+            x = self.nsToPixel(self.element.get_start())
         except Exception, e:
-            print self.element.start
+            print self.element.get_start()
             raise Exception(e)
-        y = (self.height + LAYER_SPACING) * self.element.priority
+        priority = (self.element.get_priority()) / 10
+        if priority < 0 :
+            priority = 0
+        y = (self.height + LAYER_SPACING) * priority
         self.set_simple_transform(x, y, 1, 0)
-        width = self.nsToPixel(self.element.duration)
+        width = self.nsToPixel(self.element.get_duration())
         min_width = self.start_handle.props.width * 2
         if width < min_width:
             width = min_width
@@ -430,3 +448,5 @@ class TrackObject(View, goocanvas.Group, Zoomable):
                 self.namebg.props.visibility = goocanvas.ITEM_VISIBLE
             else:
                 self.namebg.props.visibility = goocanvas.ITEM_INVISIBLE
+        self.app.gui.timeline._canvas.regroupTracks()
+        self.app.gui.timeline.unsureVadjHeight()
diff --git a/pitivi/ui/viewer.py b/pitivi/ui/viewer.py
index c912695..3085445 100644
--- a/pitivi/ui/viewer.py
+++ b/pitivi/ui/viewer.py
@@ -26,6 +26,7 @@ from gtk import gdk
 import gst
 from math import pi
 import cairo
+import ges
 
 from gettext import gettext as _
 
@@ -108,7 +109,10 @@ class PitiviViewer(gtk.VBox, Loggable):
         self.seeker = Seeker(80)
         self.seeker.connect('seek', self._seekerSeekCb)
         self.action = action
-        self.pipeline = pipeline
+        self.pipeline = None
+
+        self.formatter = ges.PitiviFormatter()
+
         self.sink = None
         self.docked = True
 
@@ -122,7 +126,6 @@ class PitiviViewer(gtk.VBox, Loggable):
         self._createUi()
         self.target = self.internal
         self.setAction(action)
-        self.setPipeline(pipeline)
         self.undock_action = undock_action
         if undock_action:
             self.undock_action.connect("activate", self._toggleDocked)
@@ -130,7 +133,16 @@ class PitiviViewer(gtk.VBox, Loggable):
             if not self.settings.viewerDocked:
                 self.undock()
 
-    def setPipeline(self, pipeline):
+    def loadProject(self, uri):
+        self.app.projectManager.current.pipeline.set_state(gst.STATE_NULL)
+        self.timeline = self.app.projectManager.current.timeline
+        for layer in self.timeline.get_layers():
+            self.timeline.remove_layer(layer)
+        self.formatter.load_from_uri(self.timeline, uri)
+        self.app.projectManager.emit("new-project-loading", uri)
+        self.app.projectManager.current.pipeline.set_state(gst.STATE_PAUSED)
+
+    def setPipeline(self):
         """
         Set the Viewer to the given Pipeline.
 
@@ -139,24 +151,17 @@ class PitiviViewer(gtk.VBox, Loggable):
         @param pipeline: The Pipeline to switch to.
         @type pipeline: L{Pipeline}.
         """
-        self.debug("self.pipeline:%r, pipeline:%r", self.pipeline, pipeline)
-
-        if pipeline is not None and pipeline == self.pipeline:
-            return
+        self.debug("self.pipeline:%r", self.pipeline)
 
+        self.pipeline = self.app.projectManager.current.pipeline
         if self.pipeline != None:
-            # remove previously set Pipeline
-            self._disconnectFromPipeline()
-            # make ui inactive
-            self._setUiActive(False)
-            # finally remove previous pipeline
-            self.pipeline = None
+            bus = self.pipeline.get_bus()
+            bus.add_signal_watch()
+            bus.connect('message', self._busMessageCb)
+            bus.set_sync_handler(self._elementMessageCb)
+            self.pipeline.set_state(gst.STATE_PAUSED)
             self.currentState = gst.STATE_PAUSED
-            self.playpause_button.setPause()
-        self._connectToPipeline(pipeline)
-        self.pipeline = pipeline
-        if self.pipeline is not None:
-            self._setUiActive()
+        self._setUiActive()
 
     def setAction(self, action):
         """
@@ -179,24 +184,19 @@ class PitiviViewer(gtk.VBox, Loggable):
         self._connectToAction(action)
         self.showControls()
 
-    def _connectToPipeline(self, pipeline):
-        self.debug("pipeline:%r", pipeline)
-        if self.pipeline != None:
-            raise ViewerError("previous pipeline wasn't disconnected")
-        self.pipeline = pipeline
-        if self.pipeline == None:
-            return
-        self.pipeline.connect('position', self._posCb)
-        self.pipeline.activatePositionListener()
-        self.pipeline.connect('state-changed', self._currentStateCb)
-        self.pipeline.connect('element-message', self._elementMessageCb)
-        self.pipeline.connect('duration-changed', self._durationChangedCb)
-        self.pipeline.connect('eos', self._eosCb)
-        self.pipeline.connect("state-changed", self.internal.currentStateCb)
-        # if we have an action set it to that new pipeline
-        if self.action:
-            self.pipeline.setAction(self.action)
-            self.action.activate()
+    def _busMessageCb(self, unused_bus, message):
+        if message.type == gst.MESSAGE_EOS:
+            print "eos"
+        elif message.type == gst.MESSAGE_STATE_CHANGED:
+            prev, new, pending = message.parse_state_changed()
+
+            if message.src == self.pipeline:
+                self.debug("Pipeline change state prev:%r, new:%r, pending:%r", prev, new, pending)
+
+                state_change = pending == gst.STATE_VOID_PENDING
+
+                if state_change:
+                    self._currentStateCb(new)
 
     def _disconnectFromPipeline(self):
         self.debug("pipeline:%r", self.pipeline)
@@ -418,7 +418,7 @@ class PitiviViewer(gtk.VBox, Loggable):
         self.info("button pressed")
         self.moving_slider = True
         self.valuechangedid = slider.connect("value-changed", self._sliderValueChangedCb)
-        self.pipeline.pause()
+        self.pipeline.set_state(gst.STATE_PAUSED)
         return False
 
     def _sliderButtonReleaseCb(self, slider, event):
@@ -431,9 +431,9 @@ class PitiviViewer(gtk.VBox, Loggable):
             self.valuechangedid = 0
         # revert to previous state
         if self.currentState == gst.STATE_PAUSED:
-            self.pipeline.pause()
+            self.pipeline.set_state(gst.STATE_PAUSED)
         else:
-            self.pipeline.play()
+            self.pipeline.set_state(gst.STATE_PLAYING)
         return False
 
     def _sliderValueChangedCb(self, slider):
@@ -510,8 +510,11 @@ class PitiviViewer(gtk.VBox, Loggable):
     def _backCb(self, unused_button):
         self.seekRelative(-gst.SECOND)
 
-    def _playButtonCb(self, unused_button, isplaying):
-        self.togglePlayback()
+    def _playButtonCb(self, unused_button, playing):
+        if playing:
+            self.pipeline.set_state(gst.STATE_PLAYING)
+        else:
+            self.pipeline.set_state(gst.STATE_PAUSED)
 
     def _forwardCb(self, unused_button):
         self.seekRelative(gst.SECOND)
@@ -605,11 +608,11 @@ class PitiviViewer(gtk.VBox, Loggable):
     def _posCb(self, unused_pipeline, pos):
         self._newTime(pos)
 
-    def _currentStateCb(self, unused_pipeline, state):
+    def _currentStateCb(self, state):
         self.info("current state changed : %s", state)
-        if state == int(gst.STATE_PLAYING):
+        if int(state) == int(gst.STATE_PLAYING):
             self.playpause_button.setPause()
-        elif state == int(gst.STATE_PAUSED):
+        elif int(state) == int(gst.STATE_PAUSED):
             self.playpause_button.setPlay()
         else:
             self.sink = None
@@ -618,18 +621,21 @@ class PitiviViewer(gtk.VBox, Loggable):
     def _eosCb(self, unused_pipeline):
         self.playpause_button.setPlay()
 
-    def _elementMessageCb(self, unused_pipeline, message):
-        name = message.structure.get_name()
-        self.log('message:%s / %s', message, name)
-        if name == 'prepare-xwindow-id':
-            sink = message.src
-            self.sink = sink
-            self._switch_output_window()
+    def _elementMessageCb(self, unused_bus, message):
+        if message.type == gst.MESSAGE_ELEMENT:
+            name = message.structure.get_name()
+            self.log('message:%s / %s', message, name)
+            if name == 'prepare-xwindow-id':
+                sink = message.src
+                self.sink = sink
+                self._switch_output_window()
+        return gst.BUS_PASS
 
     def _switch_output_window(self):
         gtk.gdk.threads_enter()
         self.sink.set_xwindow_id(self.target.window_xid)
-        self.sink.expose()
+        #FIXME GES break
+        #self.sink.expose()
         gtk.gdk.threads_leave()
 
 
@@ -1115,6 +1121,9 @@ class PlayPauseButton(gtk.Button, Loggable):
         self.image = gtk.Image()
         self.add(self.image)
         self.playing = True
+
+        self.get_settings().props.gtk_button_images = True
+        self.playing = False
         self.setPlay()
         self.connect('clicked', self._clickedCb)
 
@@ -1122,6 +1131,7 @@ class PlayPauseButton(gtk.Button, Loggable):
         gtk.Button.set_sensitive(self, value)
 
     def _clickedCb(self, unused):
+        self.playing = not self.playing
         self.emit("play", self.playing)
 
     def setPlay(self):
@@ -1129,6 +1139,8 @@ class PlayPauseButton(gtk.Button, Loggable):
         self.log("setPlay")
         if self.playing:
             self.image.set_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON)
+        if not self.playing:
+            self.set_image(gtk.image_new_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON))
             self.set_tooltip_text(_("Play"))
             self.playing = False
 
@@ -1137,5 +1149,7 @@ class PlayPauseButton(gtk.Button, Loggable):
         """ display the pause image """
         if not self.playing:
             self.image.set_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_BUTTON)
+        if self.playing:
+            self.set_image(gtk.image_new_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_BUTTON))
             self.set_tooltip_text(_("Pause"))
             self.playing = True
diff --git a/pitivi/utils.py b/pitivi/utils.py
index 7767404..95df0f9 100644
--- a/pitivi/utils.py
+++ b/pitivi/utils.py
@@ -332,7 +332,7 @@ class PropertyChangeTracker(Signallable):
         self.obj = obj
         self.properties = self._takeCurrentSnapshot(obj)
         for property_name in self.property_names:
-            signal_name = property_name + '-changed'
+            signal_name = "notify::" + property_name
             self.__signals__[signal_name] = []
             obj.connect(signal_name,
                     self._propertyChangedCb, property_name)
@@ -341,7 +341,7 @@ class PropertyChangeTracker(Signallable):
         properties = {}
         for property_name in self.property_names:
             properties[property_name] = \
-                    getattr(obj, property_name.replace("-", "_"))
+                    obj.get_property (property_name.replace("-", "_"))
 
         return properties
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]