Gstreamer ruby handling TAG messages

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
(Plugins)
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/47bf578c13be7/”)
@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???

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:
gsWax/brains/Wax.rb at master · lljk/gsWax · GitHub (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

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

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 :wink:

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/47bf578c13be7/
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