Gstreamer+python: adding and removing audio sources while pipeline is running
Question: I'm working on a sample **python** script, originally found here: [Adding and
removing audio sources to/from GStreamer pipeline on-the-
go](http://stackoverflow.com/questions/3899666/adding-and-removing-audio-
sources-to-from-gstreamer-pipeline-on-the-go). The aim is to make a script
such as the one above, able to **insert and remove audio sources while the
pipeline is running** but with an **audioconvert** element between the source
and the adder. This is because in a more general case **Adder** wants the
incoming streams to be of the same format.

So here's the code; we create 2 generators (buzzers). The first emits a 1000Hz
tone and waits for a return key. The second is a 500Hz tone, which is summed
to the first one after the key press. Again, by pressing the return key, only
the second generator is heard.

    
    
    #!/usr/bin/python
    
    import gobject;
    gobject.threads_init()
    import gst
    
    # THE FOLLOWING FUNCTION IS A REWORK OF THE ORIGINAL, STILL DOING THE JOB
    
    def create_raw_audiotest_signal(pipe, freq, adder):
      # create buzzer of a given freq
      buzzer = gst.element_factory_make("audiotestsrc","buzzer%d" % freq)
      buzzer.set_property("freq",freq)
      pipe.add(buzzer)
      buzzersrc=buzzer.get_pad("src")
      # Gather a request sink pad on the mixer
      sinkpad=adder.get_request_pad("sink%d")
      # .. and connect it to the buzzer
      buzzersrc.link(sinkpad)
      return buzzer, buzzersrc, sinkpad
    
    # THIS IS A MODIFIED VERSION, NOT WORKING, THAT JUST PUTS AN AUDIOCONVERT
    # ELEMENT BETWEEN THE GENERATOR AND THE ADDER.
    
    def create_audiotest_signal_with_converter(pipe, freq, adder):
        # create buzzer of a given freq
        buzzer = gst.element_factory_make("audiotestsrc","buzzer%d" % freq)
        buzzer.set_property("freq",freq)
        # add a converter because adder wants inputs with the same format.
        ac = gst.element_factory_make("audioconvert", "ac%d" % freq)
        pipe.add(buzzer, ac)
        # link the buzzer with the converter ...
        buzzer.link(ac)
        buzzersrc=buzzer.get_pad("src")
        # Gather a request sink pad on the mixer
        sinkpad=adder.get_request_pad("sink%d")
        # and then the converter to the adder
        ac.get_pad('src').link(sinkpad)
        return buzzer, buzzersrc, sinkpad
    
    if __name__ == "__main__":
      # First create our pipeline
      pipe = gst.Pipeline("mypipe")
    
      # Create a software mixer with "Adder"
      adder = gst.element_factory_make("adder","audiomixer")
      pipe.add(adder)
    
      # Create the first buzzer..
      #buzzer1, buzzersrc1, sinkpad1 = create_raw_audiotest_signal(pipe, 1000, adder)
      buzzer1, buzzersrc1, sinkpad1 = create_audiotest_signal_with_converter(pipe, 1000, adder)
    
      # Add some output
      output = gst.element_factory_make("autoaudiosink", "audio_out")
      pipe.add(output)
      adder.link(output)
    
      # Start the playback
      pipe.set_state(gst.STATE_PLAYING)
    
      raw_input("1kHz test sound. Press <ENTER> to continue.")
    
      # Get another generator
      #buzzer2, buzzersrc2, sinkpad2 = create_raw_audiotest_signal(pipe, 500, adder)
      buzzer2, buzzersrc2, sinkpad2 = create_audiotest_signal_with_converter(pipe, 500, adder)
    
      # Start the second buzzer (other ways streaming stops because of starvation)
      buzzer2.set_state(gst.STATE_PLAYING)
    
      raw_input("1kHz + 500Hz test sound playing simoultenously. Press <ENTER> to continue.")
    
      # Before removing a source, we must use pad blocking to prevent state changes
      buzzersrc1.set_blocked(True)
      # Stop the first buzzer
      buzzer1.set_state(gst.STATE_NULL)
      # Unlink from the mixer
      buzzersrc1.unlink(sinkpad2)
      # Release the mixers first sink pad
      adder.release_request_pad(sinkpad1)
      # Because here none of the Adder's sink pads block, streaming continues
    
      raw_input("Only 500Hz test sound. Press <ENTER> to stop.")
    

If you use **create_raw_audiotest_signal** in place of
**create_audiotest_signal_with_converter** in both the calls of course it
works. If you use a mixture of the two, it works, but with an unwanted extra
delay inbetween. The most interesting case is when you use the audioconvert in
both the calls, but gtk blocks at the first return key.

Does anybody have any suggestion? What am I doing wrong? Thank you in advance.


Answer: I found the answer myself, it was simple indeed... I added other components,
but they live in the pipeline and keep having an independent play status. So
the solution is set all the pipeline to playing, which in turn sets the status
to all the children.

**pipe.set_state(gst.STATE_PLAYING)**

instead of:

**buzzer2.set_state(gst.STATE_PLAYING)**

and it works again.

