#!/usr/bin/env python

import sys
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst, GLib

if len(sys.argv) != 2:
	print "usage: " + sys.argv[0] + " file:///path/to/file.mp3"
	sys.exit(1)

GLib.threads_init()
Gst.init([])

p = Gst.Pipeline()

# sink bin:
ob = Gst.parse_bin_from_description("capsfilter caps=audio/x-raw,format=S16LE,channels=2,rate=44100,layout=interleaved ! audioconvert ! audioresample ! volume ! autoaudiosink", True)
oa = Gst.ElementFactory.make("adder", "outputadder")

# silent stream used to keep the pipeline running
sb = Gst.parse_bin_from_description("audiotestsrc wave=silence ! audioconvert ! capsfilter caps=audio/x-raw,format=S16LE,channels=2,rate=44100,layout=interleaved", True)

p.add(oa)
p.add(ob)
p.add(sb)
oa.link(ob)
sb.link(oa)

# start the sink
for e in (ob, oa, sb):
	e.set_state(Gst.State.PAUSED)
ob.get_state(2.0)
for e in (ob, oa, sb):
	e.set_state(Gst.State.PLAYING)
p.set_state(Gst.State.PLAYING)

# stream decoder bin:
stream = Gst.Bin()
udb = Gst.ElementFactory.make("uridecodebin", "udb")
sac = Gst.ElementFactory.make("audioconvert", "sac")
sar = Gst.ElementFactory.make("audioresample", "sar")
scf = Gst.ElementFactory.make("capsfilter", "scf")
sq = Gst.ElementFactory.make("queue", "sq")
for e in (udb, sac, sar, scf, sq):
	stream.add(e)
p.add(stream)

udb.props.uri = sys.argv[1]
scf.props.caps = Gst.Caps.from_string("audio/x-raw,format=S16LE,channels=2,rate=44100,layout=interleaved")

# link stream bin when the decoder produces an output pad
def link_udb(udb, pad, stream):
	print "linking stream"
	udb.link(sac)
	sac.link(sar)
	sar.link(scf)
	scf.link(sq)
	
	ss = sq.get_static_pad("src")
	gp = Gst.GhostPad.new("src", ss)
	gp.set_active(True)
	stream.add_pad(gp)

udb.connect("pad-added", link_udb, stream)

# link stream to adder when it's prerolled
linked = False
def blocked(pad, info, stream):
	print "linking.."
	sp = stream.get_static_pad("src")
	ap = oa.get_request_pad("sink_%u")
	if sp.link(ap) is False:
		print "SHIT"
		sys.exit(5)
	stream.set_state(Gst.State.PLAYING)
	linked = True
	pad.remove_probe(pad_probe_id)

pad = sac.get_static_pad("src")
pad_probe_id = pad.add_probe(Gst.PadProbeType.BLOCK_DOWNSTREAM, blocked, stream)

# start prerolling
stream.set_state(Gst.State.PAUSED)

def message_cb(bus, message):
	s = message.get_structure()
	if s.get_name() != 'GstMessageStateChanged':
		print message.get_structure().to_string()

bus = p.get_bus()
bus.add_signal_watch()
bus.connect('message', message_cb)

ml = GLib.MainLoop()
ml.run()
