#!/usr/bin/python3
# -*- coding: utf-8 -*-

import os
import sys
import time
import argparse

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

GObject.threads_init()
Gst.init(None)


class ObPriorityStream (object):
    def __init__(self):
        parser = argparse.ArgumentParser(prog='priority_stream', formatter_class=argparse.ArgumentDefaultsHelpFormatter, description="Stream audio to an icecast server only when audio is playing.")
        parser.add_argument('-D', '--alsa-device', type=str, help='Name of the ALSA device to monitor.', default='default')
        parser.add_argument('-i', '--ip', type=str, help='Icecast server IP address.', default='127.0.0.1')
        parser.add_argument('-P', '--port', type=str, help='Icecast server port number.', default='8000')
        parser.add_argument('-p', '--password', type=str, help='Icecast server password.', default='')
        parser.add_argument('-m', '--mount', type=str, help='Icecast mountpoint to send to.', default='stream')

        self.args = parser.parse_args()

        self.create_pipeline()

    def create_pipeline(self):
        self.pipeline = Gst.Pipeline()

        self.input_pipe = [ ]

        self.audio_input = Gst.ElementFactory.make("alsasrc", "alsasrc")
        self.audio_input.set_property('device', self.args.alsa_device)
        self.input_pipe.append(self.audio_input)

        self.level = Gst.ElementFactory.make("level", "level")
        self.level.set_property('message', True)
        self.level.set_property('interval', int(1.0 * Gst.SECOND))
        self.input_pipe.append(self.level)

        self.selector = Gst.ElementFactory.make("valve", "selector")
        self.input_pipe.append(self.selector)

        self.build_pipeline(self.input_pipe)


        self.output_pipe = [ ]
        self.encoder = Gst.ElementFactory.make("lamemp3enc", "lamemp3enc")
        self.output_pipe.append(self.encoder)

        self.shout2send = Gst.ElementFactory.make("shout2send", "shout2send")
        self.shout2send.set_property('ip', self.args.ip)
        self.shout2send.set_property('port', int(self.args.port))
        self.shout2send.set_property('password', self.args.password)
        self.shout2send.set_property('mount', self.args.mount)
        self.output_pipe.append(self.shout2send)

        self.build_pipeline(self.output_pipe)

        self.selector.link(self.encoder)


        """
        self.fake_pipe = [ ]
        self.fakesink = Gst.ElementFactory.make("fakesink", "fakesink")
        self.fake_pipe.append(self.fakesink)

        self.build_pipeline(self.fake_pipe)

        self.selector.link(self.fakesink)
        """


        #self.selector.set_property('active-pad', self.selector.get_request_pad('sink0'))

        self.is_dropping = True
        self.selector.set_property('drop', True)

        self.pipeline.get_bus().add_signal_watch()
        self.pipeline.get_bus().connect('message::element', self.detect_silence)

    def build_pipeline(self, elements):
        for element in elements:
            #print "adding element to bin: " + element.get_name()
            self.pipeline.add(element)
        for index in range(0, len(elements) - 1):
            elements[index].link(elements[index + 1])

    def start(self):
        self.pipeline.set_state(Gst.State.PLAYING)

    def stop(self):
        self.pipeline.set_state(Gst.State.NULL)

    def detect_silence(self, bus, message, *args):
        peak = message.get_structure().get_value('peak')
        if peak[0] < -28:
            if not self.is_dropping:
                self.is_dropping = True
                self.selector.set_property('drop', True)
                print "now dropping buffers"
        else:
            if self.is_dropping:
                self.is_dropping = False
                self.selector.set_property('drop', False)
                print "now outputting buffers"
        return True


def main():
    mainloop = GObject.MainLoop()

    stream = ObPriorityStream()
    stream.start()

    try:
        mainloop.run()
    except KeyboardInterrupt:
        pass

    stream.stop()
    sys.exit(0)

main()

