[farsight2/master] Document python test gui a bit

Olivier Crête olivier.crete at collabora.co.uk
Tue Dec 23 15:21:18 PST 2008


---
 tests/gui/fs2-gui.py |  135 ++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 104 insertions(+), 31 deletions(-)

diff --git a/tests/gui/fs2-gui.py b/tests/gui/fs2-gui.py
index 032abb1..067d519 100644
--- a/tests/gui/fs2-gui.py
+++ b/tests/gui/fs2-gui.py
@@ -75,6 +75,7 @@ gladefile = os.path.join(os.path.dirname(__file__),"fs2-gui.glade")
 
 
 def make_video_sink(pipeline, xid, name):
+    "Make a bin with a video sink in it, that will be displayed on xid."
     bin = gst.Bin("videosink_%d" % xid)
     sink = gst.element_factory_make("ximagesink", name)
     bin.add(sink)
@@ -90,12 +91,14 @@ def make_video_sink(pipeline, xid, name):
 
 
 class FsUIPipeline:
+    "Object to wrap the GstPipeline"
     
     def __init__(self, elementname="fsrtpconference"):
         self.pipeline = gst.Pipeline()
         self.pipeline.get_bus().set_sync_handler(self.sync_handler)
         self.pipeline.get_bus().add_watch(self.async_handler)
         self.conf = gst.element_factory_make(elementname)
+        # Sets lets our own cname
         self.conf.set_property("sdes-cname", mycname)
         self.pipeline.add(self.conf)
         if VIDEO:
@@ -110,10 +113,13 @@ class FsUIPipeline:
         self.pipeline.set_state(gst.STATE_NULL)
 
     def sync_handler(self, bus, message):
+        "Message handler to get the prepare-xwindow-id event"
         if message.type == gst.MESSAGE_ELEMENT and \
                message.structure.has_name("prepare-xwindow-id"):
             xid = None
             element = message.src
+            # We stored the XID on the element or its parent on the expose event
+            # Now lets look it up
             while not xid and element:
                 xid = element.get_data("xid")
                 element = element.get_parent()
@@ -123,13 +129,12 @@ class FsUIPipeline:
         return gst.BUS_PASS
 
     def async_handler(self, bus, message):
+        "Async handler to print messages"
         if message.type != gst.MESSAGE_STATE_CHANGED \
                and message.type != gst.MESSAGE_ASYNC_DONE:
             print message.type
         if message.type == gst.MESSAGE_ERROR:
             print message.parse_error()
-            #message.src.set_state(gst.STATE_NULL)
-            #message.src.set_state(gst.STATE_PLAYING)
         elif message.type == gst.MESSAGE_WARNING:
             print message.parse_warning()
         elif message.type == gst.MESSAGE_ELEMENT:
@@ -138,9 +143,11 @@ class FsUIPipeline:
         return True
 
     def make_video_preview(self, xid, newsize_callback):
+        "Creates the preview sink"
         self.previewsink = make_video_sink(self.pipeline, xid,
                                            "previewvideosink")
         self.pipeline.add(self.previewsink)
+        #Add a probe to wait for the first buffer to find the image size
         self.havesize = self.previewsink.get_pad("sink").add_buffer_probe(self.have_size,
                                                           newsize_callback)
                                                           
@@ -150,6 +157,7 @@ class FsUIPipeline:
         return self.previewsink
 
     def have_size(self, pad, buffer, callback):
+        "Callback on the first buffer to know the drawingarea size"
         x = buffer.caps[0]["width"]
         y = buffer.caps[0]["height"]
         callback(x,y)
@@ -157,6 +165,7 @@ class FsUIPipeline:
         return True
 
     def link_audio_sink(self, pad):
+        "Link the audio sink to the pad"
         print >>sys.stderr, "LINKING AUDIO SINK"
         self.audiosink = gst.element_factory_make("alsasink")
         self.pipeline.add(self.audiosink)
@@ -165,6 +174,8 @@ class FsUIPipeline:
             
 
 class FsUISource:
+    "An abstract generic class for media sources"
+
     def __init__(self, pipeline):
         self.pipeline = pipeline
         self.tee = gst.element_factory_make("tee")
@@ -172,7 +183,6 @@ class FsUISource:
         self.tee.set_state(gst.STATE_PLAYING)
 
         self.source = self.make_source()
-#        self.source.set_locked_state(1)
         pipeline.add(self.source)
         self.source.link(self.tee)
         self.playcount = 0
@@ -185,13 +195,16 @@ class FsUISource:
         
         
     def make_source(self):
+        "Creates and returns the source GstElement"
         raise NotImplementedError()
 
 
     def get_type(self):
+        "Returns the FsMediaType of the source."
         raise NotImplementedError()
 
     def get_src_pad(self, name="src%d"):
+        "Gets a source pad from the source"
         queue = gst.element_factory_make("queue")
         requestpad = self.tee.get_request_pad(name)
         self.pipeline.add(queue)
@@ -202,11 +215,14 @@ class FsUISource:
         return pad
 
     def put_src_pad(self, pad):
+        "Puts the source pad from the source"
         self.pipeline.remove(pad.get_data("queue"))
         self.tee.release_request_pad(pad.get_data("requestpad"))
     
 
 class FsUIVideoSource(FsUISource):
+    "A Video source"
+    
     def get_type(self):
         return farsight.MEDIA_TYPE_VIDEO
 
@@ -228,7 +244,9 @@ class FsUIVideoSource(FsUISource):
             
       
 
-class FsUIAudioSource(FsUISource): 
+class FsUIAudioSource(FsUISource):
+    "An audio source"
+
     def get_type(self):
         return farsight.MEDIA_TYPE_AUDIO
 
@@ -241,13 +259,19 @@ class FsUIAudioSource(FsUISource):
 
 
 class FsUISession:
+    "This is one session (audio or video depending on the source)"
+    
     def __init__(self, conference, source):
         self.conference = conference
         self.source = source
         self.streams = weakref.WeakValueDictionary()
-        self.session = conference.new_session(source.get_type())
+        self.fssession = conference.new_session(source.get_type())
         if source.get_type() == farsight.MEDIA_TYPE_VIDEO:
-            self.session.set_property("local-codecs-config",
+            # We prefer H263-1998 because we know it works
+            # We don't know if the others do work
+            # We know H264 doesn't work for now or anything else
+            # that needs to send config data
+            self.fssession.set_property("local-codecs-config",
                                       [farsight.Codec(farsight.CODEC_ID_ANY,
                                                       "H263-1998",
                                                       farsight.MEDIA_TYPE_VIDEO,
@@ -257,7 +281,7 @@ class FsUISession:
                                                       farsight.MEDIA_TYPE_VIDEO,
                                                       0)])
         elif source.get_type() == farsight.MEDIA_TYPE_AUDIO:
-            self.session.set_property("local-codecs-config",
+            self.fssession.set_property("local-codecs-config",
                                       [farsight.Codec(farsight.CODEC_ID_ANY,
                                                       "PCMA",
                                                       farsight.MEDIA_TYPE_AUDIO,
@@ -266,16 +290,17 @@ class FsUISession:
                                                       "PCMU",
                                                       farsight.MEDIA_TYPE_AUDIO,
                                                       0)])
-        self.session.connect("new-negotiated-codecs",
+        self.fssession.connect("new-negotiated-codecs",
                              self.__new_negotiated_codecs)
         self.sourcepad = self.source.get_src_pad()
-        self.sourcepad.link(self.session.get_property("sink-pad"))
+        self.sourcepad.link(self.fssession.get_property("sink-pad"))
 
     def __del__(self):
         self.sourcepad(unlink)
         self.source.put_src_pad(self.sourcepad)
         
     def __new_negotiated_codecs(self, session):
+        "Callback from FsSession"
         for s in self.streams.valuerefs():
             try:
                 s().new_negotiated_codecs()
@@ -283,82 +308,109 @@ class FsUISession:
                 pass
             
             
-    def new_stream(self, id, connect, participant):
+    def new_stream(self, id, participant):
+        "Creates a new stream for a specific participant"
         transmitter_params = {}
+        # If its video, we start at port 9078, to make it more easy
+        # to differentiate it in a tcpdump log
         if self.source.get_type() == farsight.MEDIA_TYPE_VIDEO and \
                TRANSMITTER == "rawudp":
             cand = farsight.Candidate()
             cand.component_id = farsight.COMPONENT_RTP
             cand.port = 9078
             transmitter_params["preferred-local-candidates"] = [cand]
-        realstream = self.session.new_stream(participant.participant,
+        realstream = self.fssession.new_stream(participant.fsparticipant,
                                              farsight.DIRECTION_BOTH,
                                              TRANSMITTER, transmitter_params)
-        stream = FsUIStream(id, connect, self, participant, realstream)
+        stream = FsUIStream(id, self, participant, realstream)
         self.streams[id] = stream
         return stream
     
 
 class FsUIStream:
-    def __init__(self, id, connect, session, participant, stream):
+    "One participant in one session"
+
+    def __init__(self, id, session, participant, fsstream):
         self.id = id
         self.session = session
         self.participant = participant
-        self.stream = stream
-        self.connect = connect
-        self.stream.connect("local-candidates-prepared",
+        self.fsstream = fsstream
+        self.connect = participant.connect
+        self.fsstream.connect("local-candidates-prepared",
                             self.__local_candidates_prepared)
-        self.stream.connect("new-local-candidate",
+        self.fsstream.connect("new-local-candidate",
                             self.__new_local_candidate)
-        self.stream.connect("src-pad-added", self.__src_pad_added)
+        self.fsstream.connect("src-pad-added", self.__src_pad_added)
         self.newcodecs = []
-        
-    def __local_candidates_prepared(self, streem):
+
+    def __local_candidates_prepared(self, stream):
+        "Callback from FsStream"
         self.connect.send_candidates_done(self.participant.id, self.id)
     def __new_local_candidate(self, stream, candidate):
+        "Callback from FsStream"
         self.connect.send_candidate(self.participant.id, self.id, candidate)
     def __src_pad_added(self, stream, pad, codec):
+        "Callback from FsStream"
         if self.session.source.get_type() == farsight.MEDIA_TYPE_VIDEO:
             self.participant.link_video_sink(pad)
         else:
             self.participant.pipeline.link_audio_sink(pad)
 
     def candidate(self, candidate):
-        self.stream.add_remote_candidate(candidate)
+        "Callback for the network object."
+        self.fsstream.add_remote_candidate(candidate)
     def candidates_done(self):
-        self.stream.remote_candidates_added()
+        "Callback for the network object."
+        self.fsstream.remote_candidates_added()
     def codec(self, codec):
+        "Callback for the network object. Stores the codec"
+        
         self.newcodecs.append(codec)
+        
     def codecs_done(self):
+        """Callback for the network object.
+
+        When all the codecs have been received, we can set them on the stream.
+        """
         if len(self.newcodecs) > 0:
             self.codecs = self.newcodecs
             self.newcodecs = []
         try:
-            self.stream.set_remote_codecs(self.codecs)
+            self.fsstream.set_remote_codecs(self.codecs)
         except AttributeError:
             print "Tried to set codecs with 0 codec"
+            
     def send_local_codecs(self):
-        codecs = self.session.session.get_property("negotiated-codecs")
+        "Callback for the network object."
+        codecs = self.session.fssession.get_property("negotiated-codecs")
         if codecs is None or len(codecs) == 0:
-            codecs = self.session.session.get_property("local-codecs")
+            codecs = self.session.fssession.get_property("local-codecs")
         for codec in codecs:
             self.connect.send_codec(self.participant.id, self.id, codec)
         self.connect.send_codecs_done(self.participant.id, self.id)
+
     def new_negotiated_codecs(self):
+        """Callback for the network object.
+
+        We only send our negotiated codecs to the server (participant 1) or
+        to everyone if we are the server.
+        """
         if self.participant.id == 1 or self.connect.myid == 1:
-            for codec in self.session.session.get_property("negotiated-codecs"):
+            for codec in self.session.fssession.get_property("negotiated-codecs"):
                 self.connect.send_codec(self.participant.id, self.id, codec)
             self.connect.send_codecs_done(self.participant.id, self.id)
 
 
 class FsUIParticipant:
+    "Wraps one FsParticipant, is one user remote contact"
+    
     def __init__(self, connect, id, cname, pipeline, mainui):
         self.connect = connect
         self.id = id
         self.cname = cname
         self.pipeline = pipeline
         self.mainui = mainui
-        self.participant = pipeline.conf.new_participant(cname)
+        self.fsparticipant = pipeline.conf.new_participant(cname)
         self.outcv = threading.Condition()
         self.funnel = None
         self.make_widget()
@@ -366,26 +418,31 @@ class FsUIParticipant:
         if VIDEO:
             self.streams[int(farsight.MEDIA_TYPE_VIDEO)] = \
               pipeline.videosession.new_stream(
-                int(farsight.MEDIA_TYPE_VIDEO),
-                connect, self)
+                int(farsight.MEDIA_TYPE_VIDEO), self)
         if AUDIO:
             self.streams[int(farsight.MEDIA_TYPE_AUDIO)] = \
               pipeline.audiosession.new_stream(
-                int(farsight.MEDIA_TYPE_AUDIO),
-                connect, self)
+                int(farsight.MEDIA_TYPE_AUDIO), self)
         
     def candidate(self, media, candidate):
+        "Callback for the network object."
         self.streams[media].candidate(candidate)
     def candidates_done(self, media):
+        "Callback for the network object."
         self.streams[media].candidates_done()
     def codec(self, media, codec):
+        "Callback for the network object."
         self.streams[media].codec(codec)
     def codecs_done(self, media):
+        "Callback for the network object."
         self.streams[media].codecs_done()
     def send_local_codecs(self):
+        "Callback for the network object."
         for id in self.streams:
             self.streams[id].send_local_codecs()
+
     def make_widget(self):
+        "Make the widget of the participant's video stream."
         gtk.gdk.threads_enter()
         self.glade = gtk.glade.XML(gladefile, "user_frame")
         self.userframe = self.glade.get_widget("user_frame")
@@ -395,6 +452,10 @@ class FsUIParticipant:
         gtk.gdk.threads_leave()
 
     def exposed(self, widget, *args):
+        """From the exposed signal, used to create the video sink
+        The video sink will be created here, but will only be linked when the
+        pad arrives and link_video_sink() is called.
+        """
         if not VIDEO:
             return
         try:
@@ -419,6 +480,7 @@ class FsUIParticipant:
             
 
     def have_size(self, pad, buffer):
+        "Callback on the first buffer to know the drawingarea size"
         x = buffer.caps[0]["width"]
         y = buffer.caps[0]["height"]
         gtk.gdk.threads_enter()
@@ -431,6 +493,11 @@ class FsUIParticipant:
 
 
     def link_video_sink(self, pad):
+        """Link the video sink
+
+        Wait for the funnnel for the video sink to be created, when it has been
+        created, link it.
+        """
         try:
             self.outcv.acquire()
             while self.funnel is None:
@@ -462,6 +529,7 @@ class FsUIParticipant:
         gtk.gdk.threads_leave()
 
     def error(self):
+        "Callback for the network object."
         if self.id == 1:
             self.mainui.fatal_error("<b>Disconnected from server</b>")
         else:
@@ -470,6 +538,7 @@ class FsUIParticipant:
     
 
 class FsMainUI:
+    "The main UI and its different callbacks"
     
     def __init__(self, mode, ip, port):
         self.mode = mode
@@ -493,6 +562,7 @@ class FsMainUI:
         self.mainwindow.show()
 
     def exposed(self, widget, *args):
+        "Callback from the exposed event of the widget to make the preview sink"
         if not VIDEO:
             return
         try:
@@ -525,7 +595,10 @@ class FsMainUI:
         gtk.main_quit()
         gtk.gdk.threads_leave()
 
+
 class FsUIStartup:
+    "Displays the startup window and then creates the FsMainUI"
+    
     def __init__(self):
         self.glade = gtk.glade.XML(gladefile, "neworconnect_dialog")
         self.dialog = self.glade.get_widget("neworconnect_dialog")
-- 
1.5.6.5




More information about the farsight-commits mailing list