Commit 2c0c361c authored by Edward Hervey's avatar Edward Hervey

* __init__.py:

* bin/pitivi.in:
* pitivi/__init__.py:
* pitivi/bin.py:
* pitivi/discoverer.py:
* pitivi/dnd.py:
* pitivi/objectfactory.py:
* pitivi/pitivi.py:
* pitivi/playground.py:
* pitivi/project.py:
* pitivi/sourcelist.py:
* pitivi/pixmaps/pitivi-file.png:
* pitivi/pixmaps/pitivi-sound.png:
* pitivi/pixmaps/pitivi-video.png:
* pitivi/ui/__init__.py:
* pitivi/ui/actions.xml:
* pitivi/ui/mainwindow.py:
* pitivi/ui/sourcefactories.py:
* pitivi/ui/sourcelist.py:
* pitivi/ui/timeline.py:
* pitivi/ui/viewer.py:
Initial python version commit


git-svn-id: svn+ssh://svn.gnome.org/svn/pitivi/trunk@628 d3729300-e425-0410-8a4c-d956edccc248
parent 4ddfd124
2005-05-02 Edward Hervey <bilboed@bilboed.com>
* __init__.py:
* bin/pitivi.in:
* pitivi/__init__.py:
* pitivi/bin.py:
* pitivi/discoverer.py:
* pitivi/dnd.py:
* pitivi/objectfactory.py:
* pitivi/pitivi.py:
* pitivi/playground.py:
* pitivi/project.py:
* pitivi/sourcelist.py:
* pitivi/pixmaps/pitivi-file.png:
* pitivi/pixmaps/pitivi-sound.png:
* pitivi/pixmaps/pitivi-video.png:
* pitivi/ui/__init__.py:
* pitivi/ui/actions.xml:
* pitivi/ui/mainwindow.py:
* pitivi/ui/sourcefactories.py:
* pitivi/ui/sourcelist.py:
* pitivi/ui/timeline.py:
* pitivi/ui/viewer.py:
Initial python version commit
2005-05-02 Edward Hervey <bilboed@bilboed.com>
* NEWS: indicated switch to python version
......
#!/usr/bin/python
# PiTiVi , Non-linear video editor
#
# pitivi
#
# Copyright (c) 2005, 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.
import os
import sys
# Check if we're in development or installed version
# Add the path of pitivi stuff
# TODO : change it when it's finally in cvs
def _add_pitivi_path():
dir = os.path.dirname(os.path.abspath(__file__))
root = os.path.split(dir)[0]
sys.path.insert(0, root)
def _init_gobject_gtk_gst():
try:
import pygtk
pygtk.require("2.0")
import gtk
import gobject
except ImportError:
raise SystemExit("PyGTK couldn't be found !")
try:
import gst
except ImportError:
raise SystemExit("Gst-Python couldn't be found!")
def _run_pitivi():
import pitivi.pitivi as pitivi
try:
sys.exit(pitivi.main(sys.argv))
except StandardError, e:
print "Error: ", e
sys.exit(1)
try:
_add_pitivi_path()
_init_gobject_gtk_gst()
_run_pitivi()
except KeyboardInterrupt:
print "Interrupted by user!"
# PiTiVi , Non-linear video editor
#
# pitivi/pitivi.py
#
# Copyright (c) 2005, 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.
import gobject
import gst
class SmartBin(gst.Bin):
"""
Self-contained Bin with playing/encoding ready places
It also has length information
"""
length = 0
has_video = False
has_audio = False
width = 0
height = 0
def __init__(self, name):
gobject.GObject.__init__(self)
self.name = name
self.set_name(name)
self.vtee = gst.element_factory_make("tee", "vtee")
self.atee = gst.element_factory_make("tee", "atee")
self.add_many(self.vtee, self.atee)
self.add_source()
self.connect_source()
self.set_state(gst.STATE_READY)
self.asinkthread = None
self.vsinkthread = None
def add_source(self):
""" add the source to self, implement in subclasses """
pass
def connect_source(self):
""" connect the source to the tee, implement in subclasses """
pass
def set_audio_sink_thread(self, asinkthread):
""" set the audio sink thread """
print "setting asinkthread in", self.name
if self.get_state() >= gst.STATE_PAUSED:
return False
if self.asinkthread:
return False
if self.has_audio:
self.asinkthread = asinkthread
self.add(self.asinkthread)
self.atee.get_pad("src%d").link(self.asinkthread.get_pad("sink"))
return True
def set_video_sink_thread(self, vsinkthread):
""" set the video sink thread """
print "setting vsinkthread in ", self.name
if self.get_state() >= gst.STATE_PAUSED:
return False
if self.vsinkthread:
return False
if self.has_video:
self.vsinkthread = vsinkthread
self.add(self.vsinkthread)
self.vtee.get_pad("src%d").link(self.vsinkthread.get_pad("sink"))
return True
def remove_audio_sink_thread(self):
""" remove the audio sink thread """
print "removing asinkthread in ", self.name
if self.get_state() >= gst.STATE_PAUSED:
return False
if not self.asinkthread:
return False
self.asinkthread.get_pad("sink").get_peer().unlink(self.asinkthread.get_pad("sink"))
self.remove(self.asinkthread)
self.asinkthread = None
return True
def remove_video_sink_thread(self):
""" remove the videos sink thread """
print "removing vsinkthread in ", self.name
if self.get_state() >= gst.STATE_PAUSED:
return False
if not self.vsinkthread:
return False
self.vsinkthread.get_pad("sink").get_peer().unlink(self.vsinkthread.get_pad("sink"))
self.remove(self.vsinkthread)
self.vsinkthread = None
return True
gobject.type_register(SmartBin)
class SmartFileBin(SmartBin):
"""
SmartBin for file sources from FileSourceFactory
"""
def __init__(self, factory):
self.factory = factory
self.has_video = factory.is_video
self.has_audio = factory.is_audio
self.length = factory.length
if self.factory.video_info:
struct = self.factory.video_info.get_structure(0)
self.height = struct["height"]
self.width = struct["width"]
self.source = self.factory.make_bin()
SmartBin.__init__(self, "smartfilebin-" + factory.name)
def add_source(self):
self.add(self.source)
def connect_source(self):
if self.has_video:
self.source.get_pad("vsrc").link(self.vtee.get_pad("sink"))
if self.has_audio:
self.source.get_pad("asrc").link(self.atee.get_pad("sink"))
def do_destroy(self):
print "do_destroy"
self.factory.bin_is_destroyed(self.source)
gobject.type_register(SmartFileBin)
class SmartTimelineBin(SmartBin):
"""
SmartBin for GnlTimeline
"""
gobject.type_register(SmartTimelineBin)
class SmartDefaultBin(SmartBin):
"""
SmartBin with videotestsrc and silenc output
Can be used as a default source
"""
def __init__(self):
print "Creating new smartdefaultbin"
self.videotestsrc = gst.element_factory_make("videotestsrc", "vtestsrc")
self.silence = gst.element_factory_make("silence", "silence")
self.has_audio = True
self.has_video = True
self.width = 320
self.height = 240
SmartBin.__init__(self, "smartdefaultbin")
def add_source(self):
self.add_many(self.videotestsrc, self.silence)
def connect_source(self):
print "connecting sources"
self.videotestsrc.get_pad("src").link(self.vtee.get_pad("sink"))
self.silence.get_pad("src").link(self.atee.get_pad("sink"))
print "finished connecting sources"
gobject.type_register(SmartDefaultBin)
## class SmartDefaultBin(SmartBin):
## """
## SmartBin with videotestsrc and silenc output
## Can be used as a default source
## """
## def __init__(self):
## print "Creating new smartdefaultbin"
## self.vthread = gst.Thread("vthread")
## self.athread = gst.Thread("athread")
## self.vqueue = gst.element_factory_make("queue", "vq")
## self.vqueue.set_property("max-size-buffers", 10)
## self.aqueue = gst.element_factory_make("queue", "aq")
## self.aqueue.set_property("max-size-buffers", 10)
## self.videotestsrc = gst.element_factory_make("videotestsrc", "vtestsrc")
## self.silence = gst.element_factory_make("silence", "silence")
## self.vthread.add_many(self.videotestsrc, self.vqueue)
## self.athread.add_many(self.silence, self.aqueue)
## self.videotestsrc.link_filtered(self.vqueue, gst.caps_from_string("video/x-raw-yuv,width=320,height=240"))
## self.silence.link_filtered(self.aqueue, gst.caps_from_string("audio/x-raw-int,rate=48000"))
## self.has_audio = True
## self.has_video = True
## self.width = 320
## self.height = 240
## SmartBin.__init__(self, "smartdefaultbin")
## def add_source(self):
## self.add_many(self.vthread)
## def connect_source(self):
## self.vqueue.get_pad("src").link(self.vtee.get_pad("sink"))
## #self.aqueue.get_pad("src").link(self.atee.get_pad("sink"))
## gobject.type_register(SmartDefaultBin)
class SmartTempUriBin(SmartBin):
"""
SmartBin for temporary uris
"""
def __init__(self, uri):
self.uri = uri
self.has_audio = True
self.has_video = True
SmartBin.__init__(self, "temp-" + uri)
def add_source(self):
filesrc = gst.element_factory_make("gnomevfssrc", "src")
filesrc.set_property("location", self.uri)
self.dbin = gst.element_factory_make("decodebin", "dbin")
self.dbin.connect("new-decoded-pad", self._bin_new_decoded_pad)
self.aident = gst.element_factory_make("identity", "aident")
self.vident = gst.element_factory_make("identity", "vident")
self.add_many(filesrc, self.dbin, self.aident, self.vident)
def connect_source(self):
print "connecting ident to tee"
print self.aident.get_pad("src").link(self.atee.get_pad("sink"))
print self.vident.get_pad("src").link(self.vtee.get_pad("sink"))
def _bin_new_decoded_pad(self, dbin, pad, is_last):
if "audio" in pad.get_caps().to_string():
pad.link(self.aident.get_caps("sink"))
elif "video" in pad.get_caps().to_string():
pad.link(self.vident.get_caps("sink"))
gobject.type_register(SmartTempUriBin)
#!/usr/bin/python
# PiTiVi , Non-linear video editor
#
# discoverer.py
#
# Copyright (c) 2005, 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.
import gobject
import gst
import gtk
import objectfactory
import gc
class Discoverer(gobject.GObject):
"""
Queues requests to discover information about given files.
The discovery is done in a very fragmented way, so that it appears to be
running in a separate thread.
The "new_sourcefilefactory" signal is triggered when a file is established
to be a media_file and the FileSourceFactory() is included in the signal.
The "not_media_file" signal is triggered if a file is not a media_file.
"""
__gsignals__ = {
"new_sourcefilefactory" : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT, )),
"not_media_file" : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_STRING, ))
}
def __init__(self):
gobject.GObject.__init__(self)
self.queue = []
self.working = False
self.currentfactory = None
self.current = None
self.videoprobe = None
self.audioprobe = None
self.pipeline = None
self.probepads = []
self.thumbnailing = False
# TODO create pipeline
def add_file(self, filename):
""" queue a filename to be discovered """
self.queue.append(filename)
while gtk.events_pending():
gtk.main_iteration(False)
if not self.working:
self._analyze()
def add_files(self, filenames):
""" queue a list of filenames to be discovered """
self.queue.extend(filenames)
while gtk.events_pending():
gtk.main_iteration(False)
if not self.working:
self._analyze()
def _analyze(self):
""" segmented loop for analyzing queued filenames """
self.working = True
while len(self.queue) > 0:
self.current = self.queue.pop(0)
print "Analyzing ", self.current
self.currentfactory = None
# setup graph and start analyzing
self.pipeline = gst.parse_launch("gnomevfssrc name=src location=\"%s\" ! decodebin name=dbin" % self.current)
if not self.pipeline:
self.emit("not_media_file", self.current)
self._del_analyze_data()
continue
dbin = self.pipeline.get_by_name("dbin")
dbin.connect("new-decoded-pad", self._new_decoded_pad_cb)
self.pipeline.set_state(gst.STATE_PLAYING)
print "starting loop"
for i in range(100):
if not self.pipeline.iterate():
break
if not i % 2:
while gtk.events_pending():
gtk.main_iteration(False)
print "finished loop"
#for probe, pad in self.probepads:
# pad.remove_probe(probe)
# probe.destroy()
#self.probepads = []
self.pipeline.set_state(gst.STATE_NULL)
print "finished setting pipeline to NULL"
if not self.currentfactory:
self.emit("not_media_file", self.current)
self._del_analyze_data()
self.working = False
def _new_video_pad_cb(self, element, pad):
""" a new video pad was found """
print "video pad", pad.get_caps().to_string()
if not self.currentfactory:
self.currentfactory = objectfactory.FileSourceFactory(self.current)
self.emit("new_sourcefilefactory", self.currentfactory)
self.currentfactory.set_video(True)
# Connect identity to fakesink at first
# This allows to check when the desired buffer number arrives
# When this happens we will connect the thumbnail-ing chain
self.thumbnailing = False
vident = gst.element_factory_make("identity")
fakesink = gst.element_factory_make("fakesink")
vcsp = gst.element_factory_make("ffmpegcolorspace")
vscale = gst.element_factory_make("videoscale")
vpng = gst.element_factory_make("jpegenc")
#vpng.set_property("snapshot", False)
vpngfakesink = gst.element_factory_make("fakesink")
vpngfakesink.set_property("signal-handoffs", True)
vident.connect("handoff", self._vident_handoff_cb,
(vident, fakesink, vcsp, vscale, vpng, vpngfakesink, pad))
vpngfakesink.connect("handoff", self._vpngsink_handoff_cb,
(vident, fakesink, vcsp, vscale, vpng, vpngfakesink, pad))
self.pipeline.set_state(gst.STATE_PAUSED)
self.pipeline.add_many(vident, fakesink, vcsp, vscale, vpng, vpngfakesink)
pad.link(vident.get_pad("sink"))
vident.link(fakesink)
self.pipeline.set_state(gst.STATE_PLAYING)
def _vident_handoff_cb(self, element, buffer, data):
""" cb on handoff on identity """
# If this is the first run,
# get video pad info
# if don't have length, get it
# if this is the right buffer
# disconnect fakesink and connect the correct pipeline
print "vident_handoff_cb"
if self.thumbnailing:
return
if not isinstance(buffer, gst.Event):
vident, fakesink, vcsp, vscale, vpng, vpngfakesink, pad = data
if not self.currentfactory.length:
# Get the length
length = pad.query(gst.QUERY_TOTAL, gst.FORMAT_TIME)
if length:
self.currentfactory.set_length(length)
# Get video info
# TODO, we should check if we already have it or not
caps = pad.get_caps()
struct = caps.get_structure(0)
rw = struct["width"]
he = struct["height"]
if not self.currentfactory.video_info:
self.currentfactory.set_video_info(caps)
height = 96 * he / rw #/ 16 * 16
# Connect correct pipeline
self.pipeline.set_state(gst.STATE_PAUSED)
element.unlink(fakesink)
#element.link(vcsp)
#vcsp.link(vscale)
element.link(vscale)
vscale.link_filtered(vpng, gst.caps_from_string("video/x-raw-yuv,width=(int)%d,height=(int)%d" % (96, height)))
vpng.link(vpngfakesink)
self.pipeline.set_state(gst.STATE_PLAYING)
print "set up new pipeline"
self.thumbnailing = True
def _vpngsink_handoff_cb(self, element, buffer, sinkpad, data):
""" cb on handoff on png fakesink """
print "pngsink_handoff"
if not self.thumbnailing:
print "ERROR !!! the png fakesink shouldn't be called here !!!"
return
vident, fakesink, vcsp, vscale, vpng, vpngfakesink, pad = data
# save the buffer to a file
filename = "/tmp/" + self.currentfactory.name.encode('base64').replace('\n','') + ".jpg"
pngfile = open(filename, "wb")
pngfile.write(buffer.get_data())
pngfile.close()
self.currentfactory.set_thumbnail(filename)
# disconnect this pipeline
self.pipeline.set_state(gst.STATE_PAUSED)
vident.unlink(vscale)
# reconnect the fakesink
vident.link(fakesink)
self.pipeline.set_state(gst.STATE_PLAYING)
# EVENTUALLY eos the pipeline
self.pipeline.set_eos()
self.thumbnailing = False
def _new_audio_pad_cb(self, element, pad):
""" a new audio pad was found """
print "audio pad", pad.get_caps().to_string()
if not self.currentfactory:
self.currentfactory = objectfactory.FileSourceFactory(self.current)
self.emit("new_sourcefilefactory", self.currentfactory)
self.currentfactory.set_audio(True)
cb = self._audio_handoff_cb
#self.audioprobe = gst.Probe(False, self._audio_probe_cb, pad)
#probe = self.audioprobe
#probe = gst.Probe(False, self._audio_probe_cb, pad)
#self.probepads.append((probe, pad))
fakesink = gst.element_factory_make("fakesink")
fakesink.set_property("signal-handoffs", True)
fakesink.connect("handoff", cb, pad)
self.pipeline.set_state(gst.STATE_PAUSED)
self.pipeline.add(fakesink)
pad.link(fakesink.get_pad("sink"))
#pad.add_probe(probe)
self.pipeline.set_state(gst.STATE_PLAYING)
def _new_decoded_pad_cb(self, element, pad, is_last):
# check out the type (audio/video)
# if we don't already have self.currentfactory
# create one, emit "new_sourcefile_factory"
if "video" in pad.get_caps().to_string():
self._new_video_pad_cb(element, pad)
elif "audio" in pad.get_caps().to_string():
self._new_audio_pad_cb(element, pad)
def _filesink_handoff_cb(self, filesink):
print "data outputted"
self.currentfactory.set_thumbnail(filesink.get_property("location"))
self.pipeline.set_eos()
def _video_handoff_cb(self, identity, data, pad):
print "video data"
if not isinstance(data, gst.Event):
if not self.currentfactory.length:
length = pad.query(gst.QUERY_TOTAL, gst.FORMAT_TIME)
if length:
self.currentfactory.set_length(length)
# link to vscale with the correct caps
width = 64
caps = pad.get_caps()
print "caps : ", caps
struct = caps.get_structure(0)
print "struct : ", struct
rw = struct["width"]
he = struct["height"]
height = width * he / rw
print "width: %d, height: %d" % (width, height)
identity.link_filtered(self.pngenc, gst.caps_from_string("video/x-raw-rgb,width=(int)%d,height=(int)%d" % (width, height)))
#self.currentfactory.set_thumbnail("/tmp/" + self.currentfactory.name.encode('base64').replace('\n','') + ".png")
#self.pipeline.set_eos()
def _audio_handoff_cb(self, fakesink, data, sinkpad, pad):
print "audio data"
if not isinstance(data, gst.Event):
if not self.currentfactory.audio_info:
self.currentfactory.set_audio_info(pad.get_caps())
if not self.currentfactory.length:
length = pad.query(gst.QUERY_TOTAL, gst.FORMAT_TIME)
if length:
self.currentfactory.set_length(length)
if not self.currentfactory.is_video:
# Only stop pipeline if there isn't any video to thumbnail
self.pipeline.set_eos()
def _video_probe_cb(self, probe, data, pad):
print "video data", data
if not isinstance(data, gst.Event):
length = pad.query(gst.QUERY_TOTAL, gst.FORMAT_TIME)
if length:
if not self.currentfactory.length:
self.currentfactory.set_length(length)
self.pipeline.set_eos()
return True
def _audio_probe_cb(self, probe, data, pad):
print "audio data", data
if not isinstance(data, gst.Event):
length = pad.query(gst.QUERY_TOTAL, gst.FORMAT_TIME)
if length:
if not self.currentfactory.length:
self.currentfactory.set_length(length)
self.pipeline.set_eos()
return True
def _del_analyze_data(self):
if self.audioprobe:
print "removing audioprobe"
print gc.get_referents(self.audioprobe)
self.audioprobe.destroy()
del self.audioprobe
self.audioprobe = None
print gc.get_referents(self.audioprobe)
if self.videoprobe:
print "removing videoprobe"
print gc.get_referents(self.videoprobe)
self.videoprobe.destroy()
del self.videoprobe
self.videoprobe = None
print gc.get_referents(self.videoprobe)
print "removing pipeline"
del self.pipeline
self.pipeline = None
self.currentfactory = None
self.current = None
gobject.type_register(Discoverer)
# PiTiVi , Non-linear video editor
#
# pitivi/pitivi.py
#
# Copyright (c) 2005, 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.
DND_TYPE_TEXT_PLAIN = 24
DND_TYPE_URI_LIST = 25
DND_TYPE_PITIVI_FILESOURCE = 26
DND_TYPE_PITIVI_EFFECT = 27
DND_TYPE_PITIVI_AUDIO_EFFECT = 28
DND_TYPE_PITIVI_VIDEO_EFFECT = 29
DND_TYPE_PITIVI_AUDIO_TRANSITION = 30
DND_TYPE_PITIVI_VIDEO_TRANSITION = 31
DND_FILE_TUPLE = ("text/plain", 0, DND_TYPE_TEXT_PLAIN)
DND_URI_TUPLE = ("text/uri-list", 0, DND_TYPE_URI_LIST)
DND_FILESOURCE_TUPLE = ("pitivi/file-source", 0, DND_TYPE_PITIVI_FILESOURCE)
DND_EFFECT_TUPLE = ("pitivi/effect", 0, DND_TYPE_PITIVI_EFFECT)
DND_AUDIO_EFFECT_TUPLE = ("pitivi/audio-effect", 0, DND_TYPE_PITIVI_AUDIO_EFFECT)
DND_VIDEO_EFFECT_TUPLE = ("pitivi/video-effect", 0, DND_TYPE_PITIVI_VIDEO_EFFECT)
DND_AUDIO_TRANSITION_TUPLE = ("pitivi/audio-transition", 0, DND_TYPE_PITIVI_AUDIO_TRANSITION)
DND_VIDEO_TRANSITION_TUPLE = ("pitivi/video-transition", 0, DND_TYPE_PITIVI_VIDEO_TRANSITION)
#!/usr/bin/python
# PiTiVi , Non-linear video editor
#
# objectfactory.py
#
# Copyright (c) 2005, 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.
import gobject
import gst
class ObjectFactory(gobject.GObject):
"""
base class for object factories which provide elements to use