pitivi r1329 - in trunk: . pitivi



Author: edwardrv
Date: Thu Oct 16 14:20:48 2008
New Revision: 1329
URL: http://svn.gnome.org/viewvc/pitivi?rev=1329&view=rev

Log:
	* pitivi/objectfactory.py:
	* pitivi/stream.py:
	* pitivi/Makefile.am:
	Use python properties.
	Move MultimediaStream to separate module.
	Comments and cleanups.
	* pitivi/discoverer.py:
	Update code for modifications in objectfactory

Added:
   trunk/pitivi/stream.py
Modified:
   trunk/ChangeLog
   trunk/pitivi/Makefile.am
   trunk/pitivi/discoverer.py
   trunk/pitivi/objectfactory.py

Modified: trunk/pitivi/Makefile.am
==============================================================================
--- trunk/pitivi/Makefile.am	(original)
+++ trunk/pitivi/Makefile.am	Thu Oct 16 14:20:48 2008
@@ -30,6 +30,7 @@
 	signalgroup.py	\
 	signalinterface.py \
 	sourcelist.py 	\
+	stream.py	\
 	threads.py	\
 	thumbnailer.py	\
 	utils.py

Modified: trunk/pitivi/discoverer.py
==============================================================================
--- trunk/pitivi/discoverer.py	(original)
+++ trunk/pitivi/discoverer.py	Thu Oct 16 14:20:48 2008
@@ -312,7 +312,8 @@
 
             if caps and caps.is_fixed():
                 if not self.currentfactory:
-                    self.currentfactory = FileSourceFactory(self.current, self.project)
+                    self.currentfactory = FileSourceFactory(filename=self.current,
+                                                            project=self.project)
                     self.emit("new_sourcefilefactory", self.currentfactory)
                 if caps.to_string().startswith("audio/x-raw") and not self.currentfactory.audio_info:
                     self.currentfactory.audio_info = caps
@@ -407,12 +408,14 @@
         gst.info("pad:%s caps:%s is_last:%s" % (pad, capsstr, is_last))
         if capsstr.startswith("video/x-raw"):
             if not self.currentfactory:
-                self.currentfactory = FileSourceFactory(self.current, self.project)
+                self.currentfactory = FileSourceFactory(filename=self.current,
+                                                        project=self.project)
                 self.emit("new_sourcefilefactory", self.currentfactory)
             self._newVideoPadCb(element, pad)
         elif capsstr.startswith("audio/x-raw"):
             if not self.currentfactory:
-                self.currentfactory = FileSourceFactory(self.current, self.project)
+                self.currentfactory = FileSourceFactory(filename=self.current,
+                                                        project=self.project)
                 self.emit("new_sourcefilefactory", self.currentfactory)
             self._newAudioPadCb(element, pad)
         else:

Modified: trunk/pitivi/objectfactory.py
==============================================================================
--- trunk/pitivi/objectfactory.py	(original)
+++ trunk/pitivi/objectfactory.py	Thu Oct 16 14:20:48 2008
@@ -34,6 +34,7 @@
 
 from serializable import Serializable
 from settings import ExportSettings
+from stream import get_stream_for_caps
 
 from gettext import gettext as _
 
@@ -54,10 +55,12 @@
 
     # FIXME : Use Setter/Getter for internal values !
 
-    def __init__(self, name="", displayname="",
+    def __init__(self, name="", displayname="", project=None,
                  **unused_kw):
-        self.name = name
-        self.displayname = displayname
+        gst.info("name:%s , project:%r" % (name, project))
+        self._project = project
+        self._name = name
+        self._displayname = displayname
         self._is_audio = False
         self._is_video = False
         self.is_effect = False
@@ -71,6 +74,9 @@
         self.artist = None
         self.uid = -1
 
+    def __repr__(self):
+        return "<%s: %s>" % (self.__class__.__name__, self._displayname or self._name)
+
     ## properties
 
     def _get_is_audio(self):
@@ -106,20 +112,37 @@
     video_info = property(_get_video_info, _set_video_info,
                           doc="Video information as gst.Caps")
 
-    def _get_audio_info_stream(self):
+    # read only properties
+    @property
+    def audio_info_stream(self):
+        """Audio information of a Stream"""
         return self._audio_info_stream
-    audio_info_stream = property(_get_audio_info_stream,
-                                 doc="Audio information as a Stream")
 
-    def _get_video_info_stream(self):
+    @property
+    def video_info_stream(self):
+        """Video information of a Stream"""
         return self._video_info_stream
-    video_info_stream = property(_get_video_info_stream,
-                                 doc="Video information as a Stream")
 
+    @property
+    def name(self):
+        """Name of the factory"""
+        return self._name
+
+    @property
+    def displayname(self):
+        """Name of the factory for display"""
+        return self._displayname
+
+    @property
+    def project(self):
+        """Project this factory is being used in"""
+        return self._project
 
     def __repr__(self):
         return "<%s: %s>" % (self.__class__.__name__, self.displayname or self.name)
 
+    # FIXME : Media Tags are only Source specific (or not ?)
+    # FIXME : if so, should be moved down
     def addMediaTags(self, tags=[]):
         """ Add the given gst.Tag or gst.TagList to the factory """
         gst.debug("tags:%s" % tags)
@@ -133,9 +156,9 @@
                 self._mediaTags[tag] = "%s/%s/%s" % (d.day, d.month, d.year)
         gst.debug("tags:%s" % self._mediaTags)
         if self.video_info_stream:
-            self.video_info_stream.set_codec(self._mediaTags.get(gst.TAG_VIDEO_CODEC))
+            self.video_info_stream.codec = self._mediaTags.get(gst.TAG_VIDEO_CODEC)
         if self.audio_info_stream:
-            self.audio_info_stream.set_codec(self._mediaTags.get(gst.TAG_AUDIO_CODEC))
+            self.audio_info_stream.codec = self._mediaTags.get(gst.TAG_AUDIO_CODEC)
         self.artist = self._mediaTags.get(gst.TAG_ARTIST)
         if self.artist:
             self.artist.strip()
@@ -143,6 +166,7 @@
         if self.title:
             self.title.strip()
 
+    # FIXME : Method can stay here, but implementation is wrong
     def getPrettyInfo(self):
         """ Returns a prettyfied information string """
         if self.is_effect:
@@ -154,6 +178,8 @@
         if not self.is_video and not self.is_audio:
             "Unknown"
         stl = []
+        # FIXME : file is FileSourceFactory specific !
+        # FIXME : and it might not be a file:// but maybe a http://
         filename = os.path.basename(unquote(self.name))
         if not self.title:
             stl.append(_("<b>%s</b><small>") % gobject.markup_escape_text(filename))
@@ -166,11 +192,12 @@
                 stl.append(_("<b>%s</b>") % gobject.markup_escape_text(self.title))
             stl.append(_("<small><b>File:</b> %s") % filename)
         if self.is_video and self.video_info_stream:
-            stl.append(self.video_info_stream.getMarkup())
+            stl.append(self.video_info_stream.markup)
         if self.is_audio and self.audio_info_stream:
-            stl.append(self.audio_info_stream.getMarkup())
+            stl.append(self.audio_info_stream.markup)
         return string.join(stl, "\n") + "</small>"
 
+    # FIXME : Too limited and ugly. What if we have non-AV streams ??
     def makeAudioBin(self):
         """ returns a audio only bin """
         raise NotImplementedError
@@ -180,6 +207,8 @@
         raise NotImplementedError
 
 
+    # FIXME : ALL the following methods will die once we switch to a saner
+    # FIXME : and more flexible way of doing file save/load
     # Serializable methods
 
     def toDataFormat(self):
@@ -193,10 +222,10 @@
 
     def fromDataFormat(self, obj):
         Serializable.fromDataFormat(self, obj)
-        self.name = obj["name"]
-        self.displayname = obj["displayname"]
-        self.is_audio = obj["is_audio"]
-        self.is_video = obj["is_video"]
+        self._name = obj["name"]
+        self._displayname = obj["displayname"]
+        self._is_audio = obj["is_audio"]
+        self._is_video = obj["is_video"]
         self.setUniqueID(obj["uid"])
 
     # Unique ID methods
@@ -273,6 +302,13 @@
 # FIXME : It might not just be files (network sources ?) !
 # FIMXE : It might not even had a URI ! (audio/video generators for ex)
 
+
+
+
+# FIXME : Figure out everything which is Source specific and put it here
+# FIXME : It might not just be files (network sources ?) !
+# FIMXE : It might not even had a URI ! (audio/video generators for ex)
+
 class SourceFactory(ObjectFactory):
     """
     Provides sources usable in a timeline
@@ -299,17 +335,22 @@
         """
         return self.duration
 
-    ## properties
+    ## read only properties
 
-    def __getDefaultDuration(self):
+    @property
+    def default_duration(self):
+        """Default duration of the source in nanoseconds"""
         return self._getDefaultDuration()
-    default_duration = property(__getDefaultDuration,
-                                doc = "Default duration of a source in nanoseconds")
 
-    def __getDuration(self):
+    @property
+    def duration(self):
+        """Maximum duration of the source in nanoseconds"""
         return self._getDuration()
-    duration = property(__getDuration,
-                        doc = "Maximum duration of the source in nanoseconds")
+
+
+
+# FIXME : What about non-file sources ???
+
 
 
 
@@ -322,12 +363,12 @@
 
     __data_type__ = "file-source-factory"
 
-    def __init__(self, filename="", project=None, **kwargs):
-        gst.info("filename:%s , project:%s" % (filename, project))
-        SourceFactory.__init__(self, **kwargs)
-        self.project = project
-        self.name = filename
-        self.displayname = os.path.basename(unquote(self.name))
+    # FIXME : filename is specific to this class and should be obvious
+    def __init__(self, filename="", **kwargs):
+        name = kwargs.pop("name", filename)
+        displayname = kwargs.pop("displayname", os.path.basename(unquote(filename)))
+        SourceFactory.__init__(self, name=name, displayname=displayname,
+                               **kwargs)
         self.lastbinid = 0
         self._length = 0
         self._thumbnail = ""
@@ -341,7 +382,7 @@
         gst.debug("length:%r" % length)
         self._length = length
     length = property(_get_length, _set_length,
-                      doc="Length in nanoseconds")
+                      doc="Length of the file in nanoseconds")
 
     def _get_thumbnail(self):
         return self._thumbnail
@@ -355,7 +396,6 @@
     def _getDuration(self):
         return self._length
 
-
     def makeBin(self):
         """ returns a source bin with all pads """
         bin = gst.Bin("%s-%d" % (self.name, self.lastbinid))
@@ -406,12 +446,14 @@
             return
         bin.remove_pad(mypad)
 
+    # WTF, code used nowhere ???
     def binIsDestroyed(self, bin):
         """ Remove the given bin from the list of instances """
         if bin in self.instances:
             self.instances.remove(bin)
 
 
+    # FIXME : Shouldn't this be in a parent class ???
     def getExportSettings(self):
         """ Returns the ExportSettings corresponding to this source """
         if self.settings:
@@ -439,13 +481,11 @@
 
     def toDataFormat(self):
         ret = ObjectFactory.toDataFormat(self)
-        ret["filename"] = self.name
         ret["length"] = self._length
         return ret
 
     def fromDataFormat(self, obj):
         ObjectFactory.fromDataFormat(self, obj)
-        self.name = obj["filename"]
         self._length = obj["length"]
 
 
@@ -471,9 +511,9 @@
 
     def __init__(self, elementfactory, **kwargs):
         """ elementfactory is the GstElementFactory """
-        OperationFactory.__init__(self, **kwargs)
-        self.name = elementfactory.get_name()
-        self.displayname = elementfactory.get_longname()
+        OperationFactory.__init__(self, name=elementfactory.get_name(),
+                                  displayname=elementfactory.get_longname(),
+                                  **kwargs)
         # check what type the output pad is (AUDIO/VIDEO)
         for padt in elementfactory.get_pad_templates():
             if padt.direction == gst.PAD_SRC:
@@ -504,177 +544,8 @@
     def __init__(self, **kwargs):
         TransitionFactory.__init__(self, **kwargs)
 
-##
-## Multimedia streams, used for definition of media streams
-##
-
-
-class MultimediaStream:
-    """
-    Defines a media stream
-
-    Properties:
-    * raw (boolean) : True if the stream is a raw media format
-    * fixed (boolean) : True if the stream is entirely defined
-    * codec (string) : User-friendly description of the codec used
-    * caps (gst.Caps) : Caps corresponding to the stream
-    """
-
-    def __init__(self, caps):
-        gst.log("new with caps %s" % caps.to_string())
-        self.caps = caps
-        self.raw = False
-        self.fixed = True
-        self.codec = None
-        self._analyzeCaps()
-
-    def set_codec(self, codecstring=None):
-        if codecstring and codecstring.strip():
-            self.codec = codecstring.strip()
-
-    def _analyzeCaps(self):
-        raise NotImplementedError
-
-    def getMarkup(self):
-        """
-        Returns a pango-markup string definition of the stream
-        Subclasses need to implement this
-        """
-        raise NotImplementedError
-
-class VideoStream(MultimediaStream):
-    """
-    Video Stream
-    """
-
-    def _analyzeCaps(self):
-        if len(self.caps) > 1:
-            self.fixed = False
-
-        struct = self.caps[0]
-        self.videotype = struct.get_name()
-        if self.videotype.startswith("video/x-raw-"):
-            self.raw=True
-        else:
-            self.raw=False
 
-        try:
-            self.format = struct["format"]
-        except:
-            self.format = None
-        try:
-            self.width = struct["width"]
-        except:
-            self.width = None
-        try:
-            self.height = struct["height"]
-        except:
-            self.height = None
-        try:
-            self.framerate = struct["framerate"]
-        except:
-            # if no framerate was given, use 1fps
-            self.framerate = gst.Fraction(1,1)
-        try:
-            self.par = struct["pixel-aspect-ratio"]
-        except:
-            # use a default setting, None is not valid !
-            self.par = gst.Fraction(1,1)
 
-        if self.width and self.height and self.par:
-            self.dar = gst.Fraction(self.width * self.par.num, self.height * self.par.denom)
-        else:
-            if self.width and self.height:
-                self.dar = gst.Fraction(self.width, self.height)
-            else:
-                self.dar = gst.Fraction(4, 3)
 
-    def getMarkup(self):
-        if self.raw:
-            if self.framerate.num:
-                templ = _("<b>Video:</b> %d x %d <i>pixels</i> at %.2f<i>fps</i>")
-                templ = templ % (self.dar * self.height , self.height, float(self.framerate))
-            else:
-                templ = _("<b>Image:</b> %d x %d <i>pixels</i>")
-                templ = templ % (self.dar * self.height, self.height)
-            if self.codec:
-                templ = templ + _(" <i>(%s)</i>") % self.codec
-            return templ
-        return _("<b>Unknown Video format:</b> %s") % self.videotype
-
-class AudioStream(MultimediaStream):
-    """
-    Audio stream
-    """
-
-    def _analyzeCaps(self):
-        if len(self.caps) > 1:
-            self.fixed = False
-
-        struct = self.caps[0]
-        self.audiotype = struct.get_name()
-        if self.audiotype.startswith("audio/x-raw-"):
-            self.raw = True
-        else:
-            self.raw = False
 
-        if self.audiotype == "audio/x-raw-float":
-            self.float = True
-        else:
-            self.float = False
 
-        try:
-            self.channels = struct["channels"]
-        except:
-            self.channels = None
-        try:
-            self.rate = struct["rate"]
-        except:
-            self.rate = None
-        try:
-            self.width = struct["width"]
-        except:
-            self.width = None
-        try:
-            self.depth = struct["depth"]
-        except:
-            self.depth = self.width
-
-    def getMarkup(self):
-        if self.raw:
-            templ = _("<b>Audio:</b> %d channels at %d <i>Hz</i> (%d <i>bits</i>)")
-            templ = templ % (self.channels, self.rate, self.width)
-            if self.codec:
-                templ = templ + _(" <i>(%s)</i>") % self.codec
-            return templ
-        return _("<b>Unknown Audio format:</b> %s") % self.audiotype
-
-class TextStream(MultimediaStream):
-    """
-    Text media stream
-    """
-
-    def _analyzeCaps(self):
-        if len(self.caps) > 1:
-            self.fixed = False
-
-        self.texttype = self.caps[0].get_name()
-
-    def getMarkup(self):
-        return _("<b>Text:</b> %s") % self.texttype
-
-def get_stream_for_caps(caps):
-    """
-    Returns the appropriate MediaStream corresponding to the
-    given caps.
-    """
-    val = caps.to_string()
-    if val.startswith("video/"):
-        return VideoStream(caps)
-    elif val.startswith("audio/"):
-        return AudioStream(caps)
-    elif val.startswith("text/"):
-        return TextStream(caps)
-    else:
-        # FIXME : we should have an 'unknow' data stream class
-        return None

Added: trunk/pitivi/stream.py
==============================================================================
--- (empty file)
+++ trunk/pitivi/stream.py	Thu Oct 16 14:20:48 2008
@@ -0,0 +1,287 @@
+# PiTiVi , Non-linear video editor
+#
+#       pitivi/stream.py
+#
+# Copyright (c) 2008, Edward Hervey <bilboed bilboed com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""
+Multimedia stream, used for definition of media streams
+"""
+
+
+# FIXME : If theses streams stay, they should go in a different file/module
+
+##
+## Multimedia streams, used for definition of media streams
+##
+from gettext import gettext as _
+
+import gst
+
+class MultimediaStream:
+    """
+    Defines a media stream
+
+    Properties:
+    * raw (boolean) : True if the stream is a raw media format
+    * fixed (boolean) : True if the stream is entirely defined
+    * codec (string) : User-friendly description of the codec used
+    * caps (gst.Caps) : Caps corresponding to the stream
+    """
+
+    def __init__(self, caps):
+        gst.log("new with caps %s" % caps.to_string())
+        self._caps = caps
+        self._raw = False
+        if len(self._caps) > 1:
+            self._fixed = False
+        else:
+            self._fixed = True
+        self._codec = None
+        self._analyzeCaps()
+
+    ## read-only properties
+    def _get_caps(self):
+        return self._caps
+    caps = property(_get_caps,
+                    doc="Original gst.Caps")
+
+    def _get_raw(self):
+        return self._raw
+    raw = property(_get_raw,
+                   doc="True if the stream is a raw stream")
+
+    def _get_fixed(self):
+        return self._fixed
+    fixed = property(_get_fixed,
+                     doc="True if the stream has fixed caps")
+
+
+    def _get_codec(self):
+        return self._codec
+
+    def _set_codec(self, codecstring=None):
+        if codecstring and codecstring.strip():
+            self._codec = codecstring.strip()
+    codec = property(_get_codec, _set_codec,
+                     doc="Codec used in the stream")
+
+    @property
+    def markup(self):
+        """Pango-markup string definition"""
+        return self._getMarkup()
+
+    def _analyzeCaps(self):
+        raise NotImplementedError
+
+    def _getMarkup(self):
+        """
+        Returns a pango-markup string definition of the stream
+        Subclasses need to implement this
+        """
+        raise NotImplementedError
+
+    def __repr__(self):
+        return "%s" % self.caps
+
+class VideoStream(MultimediaStream):
+    """
+    Video Stream
+    """
+
+    # read-only properties
+    @property
+    def format(self):
+        """YUV format of the raw video stream"""
+        return self._format
+
+    @property
+    def width(self):
+        """Width of the video stream in pixels"""
+        return self._width
+
+    @property
+    def height(self):
+        """Height of the video stream in pixels"""
+        return self._height
+
+    @property
+    def framerate(self):
+        """Framerate"""
+        return self._framerate
+
+    @property
+    def par(self):
+        """Pixel Aspect Ratio in fraction"""
+        return self._par
+
+    @property
+    def dar(self):
+        """Display Aspect Ratio in fraction"""
+        return self._dar
+
+    def _analyzeCaps(self):
+        # WARNING/FIXME : Only analyses first structure !
+        struct = self.caps[0]
+        self.videotype = struct.get_name()
+        if self.videotype.startswith("video/x-raw-"):
+            self._raw=True
+        else:
+            self._raw=False
+
+        try:
+            self._format = struct["format"]
+        except:
+            self._format = None
+        try:
+            self._width = struct["width"]
+        except:
+            self._width = None
+        try:
+            self._height = struct["height"]
+        except:
+            self._height = None
+        try:
+            self._framerate = struct["framerate"]
+        except:
+            # if no framerate was given, use 1fps
+            self._framerate = gst.Fraction(1,1)
+        try:
+            self._par = struct["pixel-aspect-ratio"]
+        except:
+            # use a default setting, None is not valid !
+            self._par = gst.Fraction(1,1)
+
+        if self.width and self.height and self.par:
+            self._dar = gst.Fraction(self.width * self.par.num, self.height * self.par.denom)
+        else:
+            if self.width and self.height:
+                self._dar = gst.Fraction(self.width, self.height)
+            else:
+                self._dar = gst.Fraction(4, 3)
+
+    def _getMarkup(self):
+        if self._raw:
+            if self._framerate.num:
+                templ = _("<b>Video:</b> %d x %d <i>pixels</i> at %.2f<i>fps</i>")
+                templ = templ % (self.dar * self.height , self.height, float(self.framerate))
+            else:
+                templ = _("<b>Image:</b> %d x %d <i>pixels</i>")
+                templ = templ % (self.dar * self.height, self.height)
+            if self._codec:
+                templ = templ + _(" <i>(%s)</i>") % self.codec
+            return templ
+        return _("<b>Unknown Video format:</b> %s") % self.videotype
+
+class AudioStream(MultimediaStream):
+    """
+    Audio stream
+    """
+
+
+    @property
+    def float(self):
+        """True if the audio stream contains raw float data"""
+        return self._float
+
+    @property
+    def channels(self):
+        """Number of channels"""
+        return self._channels
+
+    @property
+    def rate(self):
+        """Rate in samples/seconds"""
+        return self._rate
+
+    @property
+    def width(self):
+        """Width of an individual sample (in bits)"""
+        return self._width
+
+    @property
+    def depth(self):
+        """Depth of an individual sample (in bits)"""
+        return self._depth
+
+    def _analyzeCaps(self):
+        # WARNING/FIXME : Only analyses first structure !
+        struct = self.caps[0]
+        self.audiotype = struct.get_name()
+        if self.audiotype.startswith("audio/x-raw-"):
+            self._raw = True
+        else:
+            self._raw = False
+
+        if self.audiotype == "audio/x-raw-float":
+            self._float = True
+        else:
+            self._float = False
+
+        try:
+            self._channels = struct["channels"]
+        except:
+            self._channels = None
+        try:
+            self._rate = struct["rate"]
+        except:
+            self._rate = None
+        try:
+            self._width = struct["width"]
+        except:
+            self._width = None
+        try:
+            self._depth = struct["depth"]
+        except:
+            self._depth = self.width
+
+    def _getMarkup(self):
+        if self.raw:
+            templ = _("<b>Audio:</b> %d channels at %d <i>Hz</i> (%d <i>bits</i>)")
+            templ = templ % (self.channels, self.rate, self.width)
+            if self.codec:
+                templ = templ + _(" <i>(%s)</i>") % self.codec
+            return templ
+        return _("<b>Unknown Audio format:</b> %s") % self.audiotype
+
+class TextStream(MultimediaStream):
+    """
+    Text media stream
+    """
+
+    def _analyzeCaps(self):
+        self.texttype = self.caps[0].get_name()
+
+    def _getMarkup(self):
+        return _("<b>Text:</b> %s") % self.texttype
+
+def get_stream_for_caps(caps):
+    """
+    Returns the appropriate MediaStream corresponding to the
+    given caps.
+    """
+    val = caps.to_string()
+    if val.startswith("video/"):
+        return VideoStream(caps)
+    elif val.startswith("audio/"):
+        return AudioStream(caps)
+    elif val.startswith("text/"):
+        return TextStream(caps)
+    else:
+        # FIXME : we should have an 'unknow' data stream class
+        return None



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