#!/usr/bin/env python3
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, Gtk
from time import sleep
from threading import Thread

Gst.init(None)
GObject.threads_init()


class Player():
    def __init__(self):
        self.status = False  # status of player
        self.thread_status = False

        # Create player
        self.player = Gst.ElementFactory.make("playbin", None)

        # Create bin for eq and load eq into bin
        self.bin = Gst.Bin()
        self.equaliser = Gst.ElementFactory.make("equalizer-10bands", None)
        self.bin.add(self.equaliser)

        # Load Eq into player
        pad = self.equaliser.get_static_pad("sink")
        self.ghostpad = Gst.GhostPad.new("sink", pad)
        self.bin.add_pad(self.ghostpad)

        # Load audiosink into bin
        self.audiosink = Gst.ElementFactory.make("autoaudiosink", None)
        self.bin.add(self.audiosink)

        # Link eq and audiosink
        self.equaliser.link(self.audiosink)

        # Add bin as audio-sink of player
        self.player.set_property("audio-sink", self.bin)

        # Provide clock
        self.player.provide_clock()

        # Link bus and enable emission
        self.bus = self.player.get_bus()
        self.bus.enable_sync_message_emission()

    @property
    def duration(self):
        if self.status:  # Check player is playing
            # Return position from player
            return int(self.player.query_duration(Gst.Format.TIME)[1])
        else:
            return 0

    def monitor(self):
        # While thread is alive and track is playing
        while self.thread_status and self.status:
            if self.player.clock is not None:  # Check gst clock is up
                # Check that the player is playing
                if self.status:
                    # Get position and duration
                    pos_int = self.position
                    dur_int = self.duration

            # sleep(0.25)  # Wait for next loop
            sleep(0.001)  # Wait for short period to emphasize mem leak

    @property
    def position(self):
        if self.status:  # Check the player is playing
            # Return position from player
            return int(self.player.query_position(Gst.Format.TIME)[1])
        else:
            return 0

    def start(self, filepath):
        # Load uri and set to play
        self.player.set_property("uri", filepath)
        self.player.set_state(Gst.State.PLAYING)

        # Set status
        self.status = True
        self.thread_status = True

        # Start monitor thread
        self.play_thread = Thread(target=self.monitor)
        self.play_thread.setDaemon(True)
        self.play_thread.start()

player = Player()
player.start("file:///path/to/file.flac")

Gtk.main()

