Forum: Ruby-Gnome 2 gstreamer ruby handling TAG messages

5e2910753aa8d0b3a4060ccd0fd33b50?d=identicon&s=25 Michael K. (michael_k31)
on 2012-05-18 15:19
All,

I am not getting any audio tags from my gstreamer playbin2 ruby setup.
Not sure why.  I am trying to grab the ICV (title, artist, etc) from the
stream.  My message bus is handling messages as I am getting
STATE_CHANGED messages, but I never see a TAG message which, by all
documentation I can find
(http://gstreamer.freedesktop.org/data/doc/gstreame...)
says should happen by default with playbin2.  UPDATE: I do get the tag
messages, but I have to query get_state to get them.


##########################
require 'thread'
require 'gst'
Gst.init

#create a thread for a glib main loop
thread = Thread.new() do
  @mainloop = GLib::MainLoop.new
  @mainloop.run
end
#make a few queries
@query_position = Gst::QueryPosition.new(Gst::Format::TIME)
@query_duration = Gst::QueryDuration.new(Gst::Format::TIME)

#make the playbin
@playbin = Gst::ElementFactory.make("playbin2")

bin = Gst::Bin.new()
@eq = Gst::ElementFactory.make("equalizer-10bands")
autosink = Gst::ElementFactory.make("autoaudiosink")

bin.add(@eq)
bin.add(autosink)
@eq >> autosink

eqpad = @eq.get_pad("sink")
gpad = Gst::GhostPad.new("gpad", eqpad)   # playbin2 requires a ghost
pad, not sure why
bin.add_pad(gpad)

@playbin.audio_sink = bin

#get the playbins bus
bus = @playbin.bus
#watch the bus for messages
bus.add_watch do |bus, message|
  p message
  case message.type

    when  Gst::Message::Type::TAG
      puts ("Got a TAG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
      tag_list = message.parse()
      #we need to get the key and value from the tag
      tag_list.each do |key,val|
        p "key: " + key
        p "val: " + val
        #handle this
      end
  end
  true

end

@playbin.set_property("uri","http://streampoint.radioio.com/streams/56/47bf578c...)
@playbin.play

##########################

So... not TAGs yet... but, if you call

@playbin.get_state

We get the messages dumped to the screen.  What am I missing???
5e3ddca8ea910cea06245c7b3c38007a?d=identicon&s=25 jake kaiden (lljk)
on 2012-05-21 00:47
hi Michael,

  sorry it took me a while to see this post...  i had a similarly hard
time working with tags in gstreamer.

  i don't have time to test the code right now, but you might try
changing this:

case message.type
    when  Gst::Message::Type::TAG
    ...

  to this:

case message.type
    when Gst::Message::TAG
    ...

  i also seem to remember having a problem with the #parse method on the
message, so i used:

message.structure.entries

  ...to grab the tag information.

  i'll give your code a try when i get some more time.

  you can check out the tag handling in my player here:
https://github.com/lljk/gsWax/blob/master/brains/Wax.rb (lines 95 - 109)

  it's basically the first thing i ever wrote in ruby, so the code's
kinda "funny" (got to get in there and clean it up,) but you can see how
i handle the tags anyway...

  good luck, keep rockin...

  - j
5e2910753aa8d0b3a4060ccd0fd33b50?d=identicon&s=25 Michael K. (michael_k31)
on 2012-05-21 01:31
Jake,

Thanks for the response.  I have made some headway on this.  I have
mostly working code now.  I say MOSTLY because this all works EXCEPT for
when the the signal handler for the ICYdemux src pad added event is
fired.  When that happens, all audio stops playing and I still don't get
any TAG messages from the ICYdemux.  Take a peek, I appreciate any and
all help!  BTW: Changing Gst::Message::Type::TAG to Gst::Message::TAG
had no effect.   They are identical anyway, just run
Gst::Message::Type::TAG == Gst::Message::TAG in ruby ;)


Here is my current code:

require 'thread'
require 'gst'
Gst.init

#create a thread for a glib main loop
thread = Thread.new() do
  @mainloop = GLib::MainLoop.new
  @mainloop.run
end

# Here is the gst-launch we are going for:
# gst-launch souphttpsrc
location=http://streampoint.radioio.com/streams/56/47bf578c13be7/
iradio-mode=true ! tee name=t ! queue2 ! decodebin2 ! audioconvert !
autoaudiosink  t. ! queue2 ! icydemux ! fakesink -t
#
# To do this we'll do 4 things:
#   1. Create a SRC element that feeds a TEE
#   2. Create an AUDIO OUT element array
#   3. Create a DECODER for the audio
#   4. Create an ICYDEMUX element to decode ICY messages
#   5. Link the TEE src pads to the DECODER and the ICYDEMUX
respectively


apipeline = Gst::Pipeline.new("ArydioPipeline")

##########  Step 1, create the SRC Bin

httpsrc = Gst::ElementFactory.make("souphttpsrc")
httpsrc.location     =
"http://streampoint.radioio.com/streams/56/47bf578c...
httpsrc.live         = true
httpsrc.do_timestamp = false
httpsrc.iradio_mode  = true

audiotee = Gst::ElementFactory.make("tee")
audiotee.name = "audiotee"

apipeline.add(httpsrc)
apipeline.add(audiotee)


########### Step 2, create the audio out pipeline. We'll link to the
decoder with the src is ready
audioconv = Gst::ElementFactory.make("audioconvert")
@eq = Gst::ElementFactory.make("equalizer-10bands")
autosink = Gst::ElementFactory.make("autoaudiosink")

apipeline.add(audioconv)
apipeline.add(@eq)
apipeline.add(autosink)

audioconv >> @eq >> autosink


########### Step 3, create the DECODER bin
queue1 = Gst::ElementFactory.make("queue2")
decoder = Gst::ElementFactory.make("decodebin2")
## decodebin2 does not expose a SRC pad by default, we need to look for
the signal and then construct the pipeline
decoder.signal_connect("pad-added") do |element, pad, data|
  puts "a new pad #{pad.name} was created!"
  if pad.caps.to_s.match('audio')
    element >> audioconv
  else
    fakesink = Gst::ElementFactory.make('fakesink')
    apipeline.add(fakesink)
    element >> fakesink
  end
  true
end

apipeline.add(queue1)
apipeline.add(decoder)

httpsrc >> audiotee
queue1 >> decoder


########### Step 4, create the ICYDEMUX element

queue2 = Gst::ElementFactory.make("queue2")
icydemx = Gst::ElementFactory.make("icydemux")

icydemx.signal_connect("pad-added") do |element, pad, data|
  puts "a new pad #{pad.name} was created for
ICY!!!!!!!!!!!!!!!!!!!!!!!!"
  fakesink = Gst::ElementFactory.make('fakesink')
  fakesink.set_property("dump", true)
  apipeline.add(fakesink)
  element >> fakesink
  true
end

apipeline.add(queue2)
apipeline.add(icydemx)

queue2 >> icydemx


############  Step 5, Link the TEE to the two paths
teesrc0 = audiotee.get_request_pad("src%d")
queue1sink = queue1.get_pad("sink")
teesrc0.link(queue1sink)

teesrc1 = audiotee.get_request_pad("src%d")
queue2sink = queue2.get_pad("sink")
teesrc1.link(queue2sink)





#get the apipeline bus
bus = apipeline.bus
#watch the bus for messages
bus.add_watch do |bus, message|
  case message.type

    when  Gst::Message::TAG
      puts ("Got a TAG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
      tag_list = message.parse()
      #we need to get the key and value from the tag
      tag_list.each do |key,val|
        p "key: " + key
        p "val: " + val
        #handle this
      end
  end
  true

end


apipeline.play

loop = true
sleep 1
while loop
  puts "type 'quit' to quit"
  s = $stdin.gets.chomp
  if s.eql? "quit"
    loop = false
  end
  if s.eql? "rock"
    @eq.band0 = 10
    @eq.band1 = 10
    @eq.band2 = 10
    @eq.band3 = 10
    @eq.band4 = 5
    @eq.band5 = 0
    @eq.band6 = -3
    @eq.band7 = -3
    @eq.band8 = -3
    @eq.band9 = -3
  end
  if s.eql? "jazz"
    @eq.band0 = 10
    @eq.band1 = 10
    @eq.band2 = 5
    @eq.band3 = 0
    @eq.band4 = -5
    @eq.band5 = -5
    @eq.band6 = -5
    @eq.band7 = 5
    @eq.band8 = 10
    @eq.band9 = 10
  end
  if s.eql? "normal"
    @eq.band0 = 0
    @eq.band1 = 0
    @eq.band2 = 0
    @eq.band3 = 0
    @eq.band4 = 0
    @eq.band5 = 0
    @eq.band6 = 0
    @eq.band7 = 0
    @eq.band8 = 0
    @eq.band9 = 0
  end

end
5e3ddca8ea910cea06245c7b3c38007a?d=identicon&s=25 jake kaiden (lljk)
on 2012-05-21 16:13
Michael K. wrote in post #1061447:
> Jake,
>
>   ...I say MOSTLY because this all works EXCEPT for
> when the the signal handler for the ICYdemux src pad added event is
> fired.  When that happens, all audio stops playing and I still don't get
> any TAG messages from the ICYdemux.

hi Michael,

  well, i've been playing around with your snippet a bit and with a
couple of changes i get the tags to show up, but the playback still
stops.  bummer.  i've got to head off to work (real bummer,) but i'll
keep fiddling with the thing when i can.

  the changes i made are these:

bus.add_watch do |bus, message|
  case message.type
    when  Gst::Message::TAG
      puts ("Got a TAG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
      tag_list = message.parse()
      #we need to get the key and value from the tag
      tag_list.each do |key,val|
        #p "key: " + key
        #p "val: " + val

        p "key: #{key}"  #changed this
        p "val: #{val}"   #and this, as sometimes these values are
integers

        #handle this
      end
  end
  true
end

  ...i also had to add

thread.join

  ...to the end.  running this i get some tag output, although as i
mentioned the sound still cuts out...  odd.  hopefully we'll get it
working...

  here's the output i get:

Got a TAG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
"key: organization"
"val: io80's Pop. An ioWorldMedia Production."
"key: genre"
"val: 80's Pop"
"key: location"
"val: http://www.radioio.com"
a new pad src was created for
ICY!!!!!!!!!!!!!!!!!!!!!!!!
a new pad src0 was created!
Got a TAG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
"key: audio-codec"
"val: MPEG 2 Audio, Layer 3 (MP3)"
Got a TAG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
"key: bitrate"
"val: 64000"
"key: has-crc"
"val: false"
"key: channel-mode"
"val: joint-stereo"
Got a TAG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
"key: audio-codec"
"val: MPEG 2 Audio, Layer 3 (MP3)"
Got a TAG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
"key: bitrate"
"val: 64000"


  - j
This topic is locked and can not be replied to.