import sys
import gi

gi.require_version('Gst', '1.0')
gi.require_version('GstNet', '1.0')
from gi.repository import Gst, GstNet, GObject, GLib

Gst.init([])
mainloop = GLib.MainLoop()

# audiotestsrc to aes67
pipelineString = """
audiotestsrc freq=480 volume=0.1 !
audioconvert !
audio/x-raw, format=S24BE, channels=2, rate=48000 !
rtpL24pay name=rtppay min-ptime=1000000 max-ptime=1000000 !
application/x-rtp, clock-rate=48000, channels=2, payload=98 !
udpsink host=239.69.0.121 port=5004 qos=true qos-dscp=34 multicast-iface=eth0
"""


if GstNet.ptp_init(GstNet.PTP_CLOCK_ID_NONE, ['eth0']):
	print('PTP initialized')
else:
	print('PTP failed to initialize')
	sys.exit()


ptpClock = GstNet.PtpClock.new('PTP-Master', 0)
if ptpClock != None:
	print('PTP clock obtained')
else:
	print('PTP failed to obtain clock')
	sys.exit()

def ptpstats(domain, stats, userdata):
	t = stats.get_name()

	if t == GstNet.PTP_STATISTICS_NEW_DOMAIN_FOUND:
		print('PTP new domain found')
	elif t == GstNet.PTP_STATISTICS_BEST_MASTER_CLOCK_SELECTED:
		print("PTP master clock selected")
	elif t == GstNet.PTP_STATISTICS_PATH_DELAY_MEASURED:
		print('PTP path delay measured')
	elif t == GstNet.PTP_STATISTICS_TIME_UPDATED:
		print('PTP time updated')
		if ptpClock.is_synced():
			calcOffset = (round((ptpClock.get_time()) * (48 / 1000000)) & 0xffffffff)
			currentOffset = pipeline.get_by_name('rtppay').get_property("timestamp")
			diff = (currentOffset - calcOffset)
			print("Difference of", diff, "samples")
			if diff < 0:
				pipeline.set_state(Gst.State.PAUSED)
				pipeline.set_state(Gst.State.READY)
				calcOffset = (round((ptpClock.get_time()) * (48 / 1000000)) & 0xffffffff) - diff + 96
				pipeline.get_by_name('rtppay').set_property("timestamp-offset", calcOffset)
				pipeline.set_state(Gst.State.PLAYING)
	return True

GstNet.ptp_statistics_callback_add(ptpstats, None)

print('PTP Syncing to Master')
ptpClock.wait_for_sync(Gst.CLOCK_TIME_NONE)
print('PTP successfully synced to Master')

pipeline = Gst.parse_launch(pipelineString)
pipeline.use_clock(ptpClock)

# calculate intial offset (gstreamer uses random offset as default)
ptpOffset = (round((ptpClock.get_time()) * (48000 / 1000000000)) & 0xffffffff) # convert ptp nanosecond timestamp to mediaclock add 72 (1.5ms) as offset for time alignment
# ptpOffset = (round((ptpClock.get_time()) * (48000 / 1000000000)) & 0xffffffff) + round(20*48) # convert ptp nanosecond timestamp to mediaclock add 72 (1.5ms) as offset for time alignment
pipeline.get_by_name('rtppay').set_property("timestamp-offset", ptpOffset)

pipeline.set_state(Gst.State.PLAYING)

print('starting mainloop')
mainloop.run()